You are on page 1of 5

How To Set Up Your Arduino to Blink an LED With a Switch

Key Points:
-Latest CH340G driver from http://sparks.gogo.co.nz/ch340.html
-Tested CH340G drivers from http://web.mit.edu/6.101/www/s2017/drivers/
-Reading a button by polling
-Reading a button with interrupts
-Debouncing the button because interrupts are too fast

Install Arduino Software


Install the Arduino IDE. This is a complete environment that provides API’s and a compiler so
you can quickly get started developing and running code on your arduino.

Mac: Download it from the Arduino website. Unzip it and drag the Arduino App into your
Applications folder and run it from there.

Windows: Download it from the Arduino website. Run the installer and the Arduino IDE should
be accessible from the start menu.

Linux: This depends on which distribution you run. For Ubuntu or Debian (and Debathena), type
‘sudo apt-get install arduino’ in the terminal and press enter a few times to download and install
it. For other distributions of linux, google around because there is likely an active community
already on the internet. Otherwise find Yanni for help.

Run Arduino from the terminal by typing ‘arduino’. If it ever complains about permissions when
uploading a sketch, then quit and run ‘sudo arduino’ instead. Otherwise, find Yanni for help.

Install USB Serial Driver


The Arduino nano we use in 6.101 comes with a CH340G serial chip. This is a cheaper version
of the same chip that a company named FTDI sells for a lot of money. In order for your
computer to talk with our cheap Arduino (it was just $5!) you need to install a driver for the
CH340G.
Drivers on http://web.mit.edu/6.101/www/s2017/drivers/ have been tested.
- CH341SER_MAC: OSX Yosemite, El Capitan
- CH34x_Install_Windows_v3_4.zip: Windows 7
- CH340_LINUX.zip: Ubuntu 14.04.
Other drivers are available from http://sparks.gogo.co.nz/ch340.html If you run Linux, then you
probably already have it so don’t bother
If it asks you to restart, then do it or else the driver will not work (they are usually activated on
boot-up).

Acquire Materials
You are going to make a built-in LED on the Arduino nano turn on/off with a switch. Gim should
give you an Arduino and the USB cable for it. Next you need a breadboard and an official 6.101
Button™. It may look confusing because it has 6 pins on the bottom, but it is actually a common
Double Pole Double Throw (DPDT) button. Look at the circuit diagram on the datasheet. The
two rows are mirrors of each other and, when the button is pushed, it switches which pin is
connected to the center.

Assemble the Circuit


Pick a digital pin on the Arduino to use as an
input and assemble your circuit such that this pin
can read the state of the button. Since the button
produces either a short-circuit or an open-circuit it
will be necessary to use a pull up / pull down
resistor on your input pin. The Arduino Nano has
built-in 20K pull up resistors on every digital pin.
One elegant configuration is to position the button
so that it is centered on the D2 pin.

Program the Arduino


Open up the Arduino program and start a new
sketch. Arduinos, and most other
microcontrollers, are programmed in C.
Thankfully, the Arduino developers have done a
great job with the APIs so they’re very easy to
use and in-depth knowledge of C is not required.
It might be a good idea to open the Blinky
example sketch and just modify it instead of
starting from scratch.

There are 2 functions your Arduino must contain:


setup() and loop(). The setup() function contains
code that should only be run once when the
Arduino is turned on. This is because setup() is only called once. The loop() function gets called
as fast as possible for as long as the Arduino is on. You should assume that as soon as it
returns, it just gets called again.

There is code you can copy/paste below but you should try and write it out yourself because it’s
good practice.

Setup() Function
If you centered the button on the D2 pin, then there are just two pins to configure: the LED pin
and the D2 pin. In setup(), make D2 an input with a pull up resistor and make the LED an
output. You can use the predefined variable LED_BUILTIN to refer to the LED pin.
Loop() Function
The main job of the Arduino is to make the LED state follow the button state. This requires
reading the value of the button and then writing it out to the LED. The builtin functions
digitalRead() and digitalWrite() should prove useful.

Working Code
//----------------------------------------------------
void setup() {
// put your setup code here, to run once:

//make the on-board LED an output


pinMode(LED_BUILTIN, OUTPUT);

//make the pin connected to the button an input


//and turn on the internal pullup resistor
pinMode(2, INPUT_PULLUP);
}

void loop() {
// put your main code here, to run repeatedly:

//read the state of the switch


int val = digitalRead(2);

//write it out to the built-in LED


digitalWrite(LED_BUILTIN, val);
}
//----------------------------------------------------------

Upload Your Program


Go to Tools->Board and select Arduino Nano

Go to Tools->Processor and select ATmega328

Go to Tools->Port and select the correct serial port. A quick way to figure this out is to unplug
your usb cable and see which option disappeared.

Click the ‘Play’ button which is actually the upload button. If all goes well, you should be able to
push the button and have the LED blink.

Debugging
If your code has syntax errors then Arduino will tell you in red text down at the bottom. Your
code can still have bugs even if it has no syntax errors though. If you believe the code is correct
then the mistake must be in the wiring. Use a meter in continuity mode to make sure that your
circuit is connected in the way you expect. Refer to the circuit diagram of the button.

Interrupts
The most important feature of microcontrollers (like the Arduino) is interrupts, or responding to
an event exactly when it happens. If you coded the button like above then your Arduino is
spending 100% of its time reading the value of the input pin by polling it. This is OK when
there’s just one thing to do but it doesn’t work well when there’s lots of work to do. If the button
gets pushed and released before the Arduino reads the pin state, then that event is missed.

Interrupts are a hardware feature of most CPUs that allows them to temporarily leave their
current work and run some code in response to an event. For the Arduino, these events are
rising or falling edges on its input pins. Interrupts improve efficiency and performance because
they save your Arduino from doing unnecessary work polling a pin, but they increase code
complexity which leads to more bugs. Probably the only places you will not find interrupts used
are on satellites or in cars because reliability is more important than performance in those
systems.

Here is some code which toggles the LED with an interrupt.


//---------------------------------------------------------------
byte state=1;

void setup() {
// put your setup code here, to run once:

//make the on-board LED an output


pinMode(LED_BUILTIN, OUTPUT);

//make the pin connected to the button an input


//and turn on the internal pullup resistor
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), toggle, CHANGE);
}

void loop() {
// put your main code here, to run repeatedly:
}

void toggle() {
digitalWrite(LED_BUILTIN, state);
state=!state;
}
//------------------------------------------------------------------
Run this code and you will notice that the LED appears not to trigger sometimes when you
press the button. Quite the opposite is true! Here is a scope trace of what happens when you
press a button. With interrupts, the Arduino reacted to all those edges but sometimes missed
the last one. The way to solve this problem is called ‘debouncing’. There are ways to do it in
code and with circuits. Here is one way in code:

Debounced Interrupt Code


byte state=0;

void setup() {
// put your setup code here, to run once:

//make the on-board LED an output


pinMode(LED_BUILTIN, OUTPUT);

//make the pin connected to the button an input


//and turn on the internal pullup resistor
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), toggle, CHANGE);
}

void loop() {
// put your main code here, to run repeatedly:
if (state>0) {
int value=0;
//debounce the button a bit
//this essentially waits 10 clock cycles before reading the pin
for (volatile int i=0; i<10; i++) {
}
value=digitalRead(2);
digitalWrite(LED_BUILTIN, value);
state=0;
}
}

void toggle() {
state=1;
}

You might also like