Microcontrollers are immensely useful tools across an incredibly wide spectrum of applications, and have become more accessible through open-source community projects such as Arduino. In this workshop you will get to try a variety of simple, core functions of an Arduino microcontroller with circuit you build yourself!
Attention: If you have never worked with a breadboard before or would like to read a well written article about how to use them, check out Sparkfun's how to use a breadboard
modified from IEEE HOPE's microcontroller lab
installing arduino ide
Download and install:
Technically, the online IDE would work too, if that's more your cup of tea.
The Arduino language is built on a C++ base, and each "sketch" has two main functions:
loop . The code in
setup is run once whenever
the Arduino is turned on, and the code in
loop is run, well, forever in a loop after the setup completes.
Want to learn more about the Arduino programming environment/code? Take a look at the offical language reference
As you learned in lecture, microcontroller General Purpose Input/Output pins have a core set of pins called Digital I/O. We will use these pins on the Ardiuno to control an LED and make it blink at any chosen interval!
Analog VS Digital: In analog circuits, the circuit "understands" a continous range of voltages. In digital, there are only two possible states: 0 and 1. An analogy can be made with light switches. Digital circuits are analogous to classic flip switches, while analog circuits are analogous to dimmer switches.
Arduino Nano breadboard installation
If your group chose to use an Arduino Nano, you will need to install the Nano on the breadboard first. Carefully remove the Nano from its packaging. If you notice bent pins, please let an instructor know. Carefully insert the Nano into the breadboard across the split down the long center (called the "IC ravine"). Make sure to line up the outermost pins with the most extreme holes in the breadboard to allow yourself the most room for other components!
The Nano takes up 15 rows on the breadboard! If you would like to try making the complete circuit with a LED segment display by the end of the activity, it may be easier to arrange everything with a long breadboard, or two of the short ones.
power rails (optional but suggested)
To make distributing power from your Arduino to the circuits on your breadboard easier, you can connect your Arduino GND and +5V to the side "rails" of your breadboard. Please be careful not to short these two pins together!
led circuit assembly
You will need an LED and 1kΩ resistor to assemble this circuit.
- Connect the anode (positive terminal) of the LED to the resistor and the cathode (negative terminal) to ground.
- Connect the other end of the resistor to any one of the digital output pins of the Arduino numbered 2 to 13. If you have a Nano, use any of the pins labeled with a "D", which stands for digital.
the Blink sketch
Find and open the Blink example code in the Arduino IDE. (
File -> Examples -> 01.Basics -> Blink).
Make sure to change the
ledvariable to the pin number you've connected the LED to. The default value will blink a LED on the Arduino microcontroller board.
Upload your program by pressing the on screen upload or
Ctrl + U. When you press upload, Arduino actually first compiles your program. In other words, the Arduino IDE will let you know if there errors in your code before attempting to upload it. If you want to just compile, and not upload, then you can press the compile button in the toolbar or use the shortcut
Ctrl + R.
You may have a communication error between your computer and the Arduino board when you first try to upload. Click and bring down the "Tools" menu (button is at the top) and make sure you see...
- If you have a Uno: "Board: 'Arduino/Genuino Uno'. If you see any other board, change it to 'Arduino/Genuino Uno'.
- If you have a Nano: "Board: 'Arduino Nano'. If you see any other board, change it to 'Arduino Nano'.
Also in the "Tools" menu, click on "Port" and select a different COM, if there exists more than one. Feel free to ask an instructor for help.
Alter the delay on the program to change how many times the LED blinks, or whether it stays on longer or shorter (this is called the 'duty cycle').
How would you add more LEDs? Try adding one more LED and having it blink at a different rate than the first one.
You now have a sweet blinking LED circuit, but wouldn't it cooler if instead of blinking, the LED faded in and out instead? Let's learn about how we can achieve this behavior using only a digital output!
How can a digital signal, which can only be a high or low voltage, simulate an analog range of voltages? By doing something called pulse width modulation (PWM for short). It involves 2 basic ideas:
- We can flip the digital output between HIGH and LOW really fast, essentially creating a square wave.
- We can control how long the troughs and waves of the square wave are. The ratio of the time the output is on VS off is called the duty cycle.
Notice that we can easily control the average power per unit time by changing the duty cycle. When the unit time becomes very small, human eyes will not be able to percieve on-off switching, but rather just the average value! This means we can fake any value signal we want by simply adjusting the "on"-"off" time ratio of the PWM signal.
fun fact: this is exactly what is done with most adjustable brightness LED flashlights, slow fade Christmas lights, etc.
Luckily for us, the Arduino software has taken care of the hard part of controlling the PWM signal, wrapping it all up in a nice, abstracted function called
analogWrite (see the documentation for it here). It takes one input: an integer between 0 and 255 that represents the desired duty cycle.
You can use the same circuit that you used for blinking, but you may need to change the pin your LED is connected to with a PWM enabled pin, as well as upload new firmware to the Arduino microcontroller.
- Open up the built-in Fade example via
File -> Examples -> 03.Analog -> Fading
- Change the
ledvariable to the pin number that your LED is connected to. Make sure that that pin is PWM-enabled! Refer to the reference images above.
- Take a quick look at the code structure: what parts are the same as the blink code? What parts are new?
- Compile and upload the new sketch to your Arduino Uno or Nano, and see if your LED starts to fade in and out!
- Once it is working, try changing the code to...
- Make the LED fade in and out faster
- Make the LED fade faster in one direction, or only fade in one direction
- (2 LEDs) Make one LED blink and the other LED fade.
BONUS (2 LEDs): Have one LED fade with a linear ramp and the other LED fade with a quadratic ramp. Compare the actual lighting behavior of the two LEDs. Which one's brightness fading appears more linear?
inputs are important too
Have you noticed that all the sketches you've uploaded so far included a
pinMode(led, OUTPUT); line in the setup function? We've only gotten the microcontroller to output something, but have yet to give in external inputs. Let's change that trend with an INPUT POTENTIOMETER!
Potentiometers (or pots, for short) are essentially adjustable resistors. Twist the knob, and the resistance between two of its pins changes. Unfortunately, microcontrollers cannot read resistance directly, but they can read analog voltages through specially marked analog pins, which have an A before the (analog) pin number.
EE16A voltage dividers
To turn the adjustable resistor into an adjustable voltage that the microcontroller can read, we can use the trusty voltage divider circuit. For those of you who have not yet taken EE16A (or who just need a simple reminder), the voltage divider looks like so:
Let us call the top resistor R1 and the one on the bottom R2. The output is a simple function of the input voltage (voltage at the top of R1) and the resistances of the two resistors.
As if some miracle, the potentiometer actually implements the entirely of the voltage divider by itself! A potentiometer is like one big resistor that is "split" into two by a "wiper" pin.
potentiometer board setup
- Insert the potentiometer into a free area on your breadboard. Orient it such that the potentiometer's fat body legs are in the middle IC ravine; this will help it stay seated in the breadboard.
- Connect one of the pins on the end to GND (note that this may be easier if you had established power rails)
- Connect the other pin on the end to 5V.
- Connect the middle pin to any analog pin on your Arduino (these will be the pins with an 'A' before the pin number)
To get the analog voltage value from the potentiometer, we use the
analogRead function (read its documentation here). In short, it maps the analog value of the input (a voltage between 0-5V) to an integer between 0 and 1023.
Any guesses as to why 0-1023 is the range of values for analog reads?
We first have to make sure our sensor is sending data to the Arduino board before using the potentiometer for other, cooler things involving LEDs.
- Copy this code into your Arduino IDE, in either a new sketch or an existing sketch from before. Please change the value of
sensorPinto the analog pin you connected your potentiometer to.
- In the above provided program, we are taking the sensor information from pin A0 and displaying that data in the Serial Monitor. The Serial Monitor is a convenient feature of the Arduino IDE that enables simple communication with the microcontroller during its normal operation, and can be accessed by clicking on the magnifying glass icon in top right corner of the program or pressing
Ctrl + M(or
Command + Mfor you Mac folks).
Why do you think it is called the Serial Monitor?
- Compile and upload the program to your Arduino. Once you have, open the Serial Monitor. Make sure to set the baud rate to the value specificed in the setup section of the code. You should see values appearing on the screen vertically. You will know if your potentiometer is working the values change when you twist the potentiometer knob.
pot and fade
Now that you have a working analog input system, we can make microcontroller circuits that have both inputs and outputs. Let's try it by using the potentiometer to control the fade speed of your LEDs.
- Merge your previous two sketches (fading LED and potentiometer analogRead) into a new sketch.
- Use the value of the potentiometer to set the fade speed of the LED. You may find Arduino's built-in maps function to be very useful.
- BONUS: How could you use the pot and a couple LEDs to create a light-up "status" bar of sorts? It should fade both the LEDs and across the LEDs.
NOTE: the following is avaliable as an exercise for those particularly ambitious, if time allows
Now that you have a working LED control circuit, its time to spice it up with MORE leds! Ask one of the lab TAs for either more individual LEDs or some form of an LED grid. Now, it is a pain to have to set each pin manually, and that would also mean taking up more of the limited GPIO pins for basic on/off functionality! Thankfully, there exists these wonderful devices called integrated circuits: little black packages that house tiny but complete and robust circuits. Today, you will be working with the Texas Instruments SN74HC595N! Known as a shift register, this IC takes in Serial data and outputs Parallel Data!
You can read a lot more about how this works with the shift register here but the gist is that a serial string of binary data will go into the system, and the system outputs will be set according to the order of the input bits.
What this IC allows us to do is utilize SERIAL COMMUNICATION over a few data control lines to control lots of on/off outputs. In our case, we will be utlizing the Arduino built-in SPI library and the SPI communication protocol to "program" the shift registers to control an array of LEDs!
The 74HC595N does not actually use the SPI protocol "officially", but works on a serial input, clock, and enable signal, which the SPI protocal helpfully provides (in fact, the SPI protocol consists of exactly those three things).
It will be extremely helpful and informational to have the datasheet for the SN74HC595N open for the next section.
Adding the Shift Register
- Place the shift register IC across the DIP IC ravine on your breadboard.
- Make sure to have the datasheet open! Find the Pin Configuration and Functions section and use it to help you wire up the IC correctly. The first column is the pin on the IC, while the Target column is which pin on the Arduino it should be connected to.
|IC Pin||Target||What it's for|
|OE||GND||Output always Enabled|
|SRCLR||5V||Reclear pin, disabled|
|SER||11||Data Signal, in sync with Clock|
|RCLK||2-13||Chip Enable. Use any avaliable digital I/O|
The Qa and Qb or any Q pins on the 595 are the parallel outputs, with A being the first and Q being the last. For now, simply hook up the one LED you have to the Qa output, through an appropriate resistor of course.
Controlling the Shift Register
Start a new sketch in the Arduino IDE (or just stay with whatever you already have).
Complete the setup part of the sketch as shown below. Make sure to set the csPin to the number you connected the RCLK line too!
- For the actual communication to the device, create a helper function called
writeSPIas shown below. This declaration should be outside of the pre-existing functions of the Arduino sketch (the
To make sure that the serial communication is working properly, make sure an LED is connected to the first output of the shift register, and try writing a
1to the shift register (in
void setup). The LED should light up. If not, double check your connections, LED direction, etc.
- Which LEDs light up given an input value can be analyzed with an understanding of the BINARY NUMBER system. If you are unfamiliar with binary numbers, check out this helpful tutorial.
- The A-H outputs correspond respectively to the least -> most significant bits of the value you send to the 595 shift register (using the above code). If you wanted to make the LEDs attached at outputs A and Q to be the only ones that light up, what binary value would you have to send via SPI?
Once you've verified that your Arduino can properly communicate with the 74HC595 shift register, hook up LEDs to all the outputs (or use an LED segment bar) and try to make them light in a pattern, or even better, in response to an analog input, such as an ambient light sensor!