Today's objectives are getting used to the basic functions of your Arduino Uno. The following will be covered:
Used for communication between the Arduino board and a computer or other devices. All Arduino boards have at least one serial port (also known as a UART or USART): Serial. It communicates on digital pins 0 (RX) and 1 (TX) as well as with the computer via USB. Thus, if you use these functions, you cannot also use pins 0 and 1 for digital input or output.
You can use the Arduino environment's built-in serial monitor to communicate with an Arduino board. Click the serial monitor button in the toolbar and select the same baud rate used in the call to begin().
/* Echo Reads data from serial, when available, and prints the result to the serial monitor This example code is in the public domain. */ int incomingByte = 0; void setup() { //start serial communication with a baud rate of 9600 Serial.begin(9600); } void loop() { if(Serial.available() > 0) { //read the incoming byte incomingByte = Serial.read(); //NOTE: the byte you sent from serial monitor is considered of type char //the value of the character '0' is 48 //by subtracting 48 from the value returned by the Serial.read() function you get //the actual number you entered in serial monitor incomingByte = incomingByte - 48; //confirm the byte you just received Serial.print("I received "); Serial.println(incomingByte); }
Pushbuttons or switches connect two points in a circuit when you press them. When the pushbutton is open (unpressed) there is no connection between the two legs of the pushbutton, so the pin is connected to ground (through the pull-down resistor) and reads as LOW, or 0. When the button is closed (pressed), it makes a connection between its two legs, connecting the pin to 5 volts, so that the pin reads as HIGH, or 1.
If you disconnect the digital i/o pin from everything, the LED may blink erratically. This is because the input is “floating” - that is, it doesn't have a solid connection to voltage or ground, and it will randomly return either HIGH or LOW. That's why you need a pull-up resistor in the circuit. This can be done by attaching a resistor (usually 10K) between the floating pin of the pushbutton and 5V. It can also be done internally by enabling an integrated pull-up resistor in software for each pin we want to use as input.
Connect the pushbutton in your kit to digital pin 2, like in the picture below:
<imgcaption a center> </imgcaption>
In the program below, the very first thing that you do will in the setup function is to begin serial communications, at 9600 bits of data per second, between your Arduino and your computer with the line:
Serial.begin(9600);
Next, initialize digital pin 2, the pin that will read the output from your button, as an input:
pinMode(2,INPUT);
And we enable the internal pull-up resistor for pin 2, in order to read 5V when the button is not pressed. This is done by writing a digital “1” on a pin that was declared as an input:
digitalWrite(pushButton, HIGH);
Now that your setup has been completed, move into the main loop of your code. When your button is pressed, 5 volts will freely flow through your circuit, and when it is not pressed, the input pin will be connected to ground through the 10-kilohm resistor. This is a digital input, meaning that the switch can only be in either an on state (seen by your Arduino as a “1”, or HIGH) or an off state (seen by your Arduino as a “0”, or LOW), with nothing in between.
The first thing you need to do in the main loop of your program is to establish a variable to hold the information coming in from your switch. Since the information coming in from the switch will be either a “1” or a “0”, you can use an int datatype. Call this variable sensorValue, and set it to equal whatever is being read on digital pin 2. You can accomplish all this with just one line of code:
int sensorValue = digitalRead(2);
Once the Arduino has read the input, make it print this information back to the computer as a decimal (DEC) value. You can do this with the command Serial.println() in our last line of code:
Serial.println(sensorValue, DEC);
Now, when you open your Serial Monitor in the Arduino environment, you will see a stream of “1”s if your switch is open, or “0”s if your switch is closed.
/* DigitalReadSerial Reads a digital input on pin 2, prints the result to the serial monitor This example code is in the public domain. */ // digital pin 2 has a pushbutton attached to it. Give it a name: int pushButton = 2; // the setup routine runs once when you press reset: void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); // make the pushbutton's pin an input: pinMode(pushButton, INPUT); digitalWrite(pushButton, HIGH); // turn on pullup resistors } // the loop routine runs over and over again forever: void loop() { // read the input pin: int buttonState = digitalRead(pushButton); // print out the state of the button: Serial.println(buttonState); }
Connect the LED in your kit to digital pin 6, like in the picture below:
<imgcaption b center> </imgcaption>
We want to turn the LED on when we push the button. For this, we need to modify a bit the previous code:
/* DigitalReadSerial Reads a digital input on pin 2, prints the result to the serial monitor This example code is in the public domain. */ // digital pin 2 has a pushbutton attached to it. Give it a name: int pushButton = 2; int led = 6; // the setup routine runs once when you press reset: void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); // make the pushbutton's pin an input: pinMode(pushButton, INPUT); pinMode(led, OUTPUT); digitalWrite(pushButton, HIGH); // turn on pullup resistors digitalWrite(led, LOW); } // the loop routine runs over and over again forever: void loop() { // read the input pin: int buttonState = digitalRead(pushButton); // print out the state of the button: Serial.println(buttonState); if(buttonState==0) digitalWrite(led, HIGH); else digitalWrite(led, LOW); }
We've declared the LED on pin 6 as output and added a few lines in the loop() statement that check the state of the button and turn the LED on or off accordingly. Notice the LED is only ON when the button is pushed.
Exercise 1: Modify the code above to light up the LED when the pushbutton is pushed once and switch off when the pushbutton is pressed again. Send the button and led states as strings on the serial interface.
Exercise 2: Change the code to make the LED light up when the pushbutton is pressed twice and switch off after another two pushes.
An if statement allows you to choose between two discrete options, TRUE or FALSE. When there are more than two options, you can use multiple if statements, or you can use the switch statement. Switch allows you to choose between several discrete options.
This tutorial shows you how to use switch to turn on one of the two LEDs (pins 13 and 6) based on a byte of data received serially. The sketch listens for serial input, and turns on a different LED for the characters a, b, c, d.
/* Switch statement with serial input Demonstrates the use of a switch statement. The switch statement allows you to choose from among a set of discrete values of a variable. It's like a series of if statements. To see this sketch in action, open the Serial monitor and send any character. The characters a, b, c, d, will turn on or off the two LEDs. Any other character will turn the LEDs off. The circuit: * 2 LEDs attached to digital pins 13 and 6 through 220-ohm resistors created 1 Jul 2009 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/SwitchCase2 */ void setup() { // initialize serial communication: Serial.begin(9600); // initialize the LED pins: pinMode(13, OUTPUT); pinMode(6, OUTPUT); } void loop() { // read the sensor: if (Serial.available() > 0) { int inByte = Serial.read(); // do something different depending on the character received. // The switch statement expects single number values for each case; // in this exmaple, though, you're using single quotes to tell // the controller to get the ASCII value for the character. For // example 'a' = 97, 'b' = 98, and so forth: switch (inByte) { case 'a': digitalWrite(13, HIGH); digitalWrite(6, LOW); break; case 'b': digitalWrite(13, LOW); digitalWrite(6, HIGH); break; case 'c': digitalWrite(13, HIGH); digitalWrite(6, HIGH); break; case 'd': digitalWrite(13, LOW); digitalWrite(6, LOW); break; default: // turn all the LEDs off: digitalWrite(13, LOW); digitalWrite(6, LOW); } } }
LEDs can not only be switched on or off, but you can also vary their luminosity. This example demonstrates the use of the analogWrite() function in fading an LED off and on. AnalogWrite uses pulse width modulation (PWM), turning a digital pin on and off very quickly, to create a fading effect.
After declaring pin 6 to be your ledPin, there is nothing to do in the setup() function of your code.
The analogWrite() function that you will be using in the main loop of your code requires two arguments: One telling the function which pin to write to, and one indicating what PWM value to write.
In order to fade your LED off and on, gradually increase your PWM value from 0 (all the way off) to 255 (all the way on), and then back to 0 once again to complete the cycle. In the sketch below, the PWM value is set using a variable called brightness. Each time through the loop, it increases by the value of the variable fadeAmount.
If brightness is at either extreme of its value (either 0 or 255), then fadeAmount is changed to its negative. In other words, if fadeAmount is 5, then it is set to -5. If it's 55, then it's set to 5. The next time through the loop, this change causes brightness to change direction as well.
analogWrite() can change the PWM value very fast, so the delay at the end of the sketch controls the speed of the fade. Try changing the value of the delay and see how it changes the program.
/* Fade This example shows how to fade an LED on pin 6 using the analogWrite() function. This example code is in the public domain. */ int led = 6; // the pin that the LED is attached to int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by // the setup routine runs once when you press reset: void setup() { // declare pin 6 to be an output: pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { // set the brightness of pin 6: analogWrite(led, brightness); // change the brightness for next time through the loop: brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount ; } // wait for 30 milliseconds to see the dimming effect delay(30); }
Exercise 3: Using the code above, make the sketch send the brightness values through the serial port as integers from 0 to 255.
Exercise 4: Write a program that reads the LED brightness from the serial port and modifies it accordingly. Input values can range from 0 to 255. Other values are ignored by the program.
A pushbutton can only discern two states: on (5 volts) or off (0 volts). But what about all the other values in between? Can we read an analog value from, say a sensor and process it with our Arduino? This example shows how to read an analog input pin, map the result to a range from 0 to 255, and then use that result to set the pulsewidth modulation (PWM) of an output pin to dim or brighten an LED.
Leave the LED connected to port 6 and connect the potentiometer in the kit to analog pin 0, like in the picture below:
<imgcaption c center> </imgcaption>
In the program below, after declaring two pin assignments (analog 0 for your potentiometer and digital 9 for your LED) and two variables, sensorValue and outputValue, the only thing that you do will in the setup function is to begin serial communication.
Next, in the main loop of the code, sensorValue is assigned to store the raw analog value coming in from the potentiometer. Because the Arduino has an analogRead resolution of 0-1023, and an analogWrite resolution of only 0-255, this raw data from the potentiometer needs to be scaled before using it to dim the LED.
In order to scale this value, use a function called map()
outputValue = map(sensorValue, 0, 1023, 0, 255);
outputValue is assigned to equal the scaled value from the potentiometer. map() accepts five arguments: The value to be mapped, the low range and high range of the raw data, and the low and high values for that data to be scaled too. In this case, the sensor data is mapped down from its original range of 0 to 1023 to 0 to 255.
The newly mapped sensor data is then output to the analogOutPin dimming or brightening the LED as the potentiometer is turned. Finally, both the raw and scaled sensor values are sent to the Arduino serial window in a steady stream of data.
/* Analog input, analog output, serial output Reads an analog input pin, maps the result to a range from 0 to 255 and uses the result to set the pulsewidth modulation (PWM) of an output pin. Also prints the results to the serial monitor. The circuit: * potentiometer connected to analog pin 0. Center pin of the potentiometer goes to the analog pin. side pins of the potentiometer go to +5V and ground * LED connected from digital pin 6 to ground created 29 Dec. 2008 modified 30 Aug 2011 by Tom Igoe This example code is in the public domain. */ // These constants won't change. They're used to give names // to the pins used: const int analogInPin = A0; // Analog input pin that the potentiometer is attached to const int analogOutPin = 6; // Analog output pin that the LED is attached to int sensorValue = 0; // value read from the pot int outputValue = 0; // value output to the PWM (analog out) void setup() { // initialize serial communications at 9600 bps: Serial.begin(9600); } void loop() { // read the analog in value: sensorValue = analogRead(analogInPin); // map it to the range of the analog out: outputValue = map(sensorValue, 0, 1023, 0, 255); // change the analog out value: analogWrite(analogOutPin, outputValue); // wait 10 milliseconds before the next loop // for the analog-to-digital converter to settle // after the last reading: delay(10); }
Exercise 5: Add serial output to the code. It should print out sensorValue and outputValue on the serial interface. Convert the input value from the sensor to volts and print it.
This example shows you how to send a byte of data from the Arduino to a personal computer and graph the result. This is called serial communication because the connection appears to both the Arduino and the computer as a serial port, even though it may actually use a USB cable.
You can use the Arduino serial monitor to view the sent data, or it can be read by Processing.
For this exercise you will need to download Processing. You can get it from here: http://processing.org/download/ Simply unzip it into your Arduino folder and run the .exe in the root folder.
Keep the potentiometer connected to analog port 0 and upload the following code to the Arduino board:
/* Graph A simple example of communication from the Arduino board to the computer: the value of analog input 0 is sent out the serial port. We call this "serial" communication because the connection appears to both the Arduino and the computer as a serial port, even though it may actually use a USB cable. Bytes are sent one after another (serially) from the Arduino to the computer. You can use the Arduino serial monitor to view the sent data, or it can be read by Processing, PD, Max/MSP, or any other program capable of reading data from a serial port. The Processing code below graphs the data received so you can see the value of the analog input changing over time. The circuit: Any analog input sensor is attached to analog in pin 0. created 2006 by David A. Mellis modified 30 Aug 2011 by Tom Igoe and Scott Fitzgerald This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Graph */ void setup() { // initialize the serial communication: Serial.begin(9600); } void loop() { // send the value of analog input 0: Serial.println(analogRead(A0)); // wait a bit for the analog-to-digital converter // to stabilize after the last reading: delay(10); }
The code outputs the analog value of pin 0 to the serial port. You can see the raw values on your terminal, or you can plot them usong the following Processing sketch:
// Graphing sketch // This program takes ASCII-encoded strings // from the serial port at 9600 baud and graphs them. It expects values in the // range 0 to 1023, followed by a newline, or newline and carriage return // Created 20 Apr 2005 // Updated 18 Jan 2008 // by Tom Igoe // This example code is in the public domain. import processing.serial.*; Serial myPort; // The serial port int xPos = 1; // horizontal position of the graph void setup () { // set the window size: size(400, 300); // List all the available serial ports println(Serial.list()); // I know that the first port in the serial list on my mac // is always my Arduino, so I open Serial.list()[0]. // Open whatever port is the one you're using. myPort = new Serial(this, Serial.list()[3], 9600); // don't generate a serialEvent() unless you get a newline character: myPort.bufferUntil('\n'); // set inital background: background(0); } void draw () { // everything happens in the serialEvent() } void serialEvent (Serial myPort) { // get the ASCII string: String inString = myPort.readStringUntil('\n'); if (inString != null) { // trim off any whitespace: inString = trim(inString); // convert to an int and map to the screen height: float inByte = float(inString); inByte = map(inByte, 0, 1023, 0, height); // draw the line: stroke(127,34,255); line(xPos, height, xPos, height - inByte); // at the edge of the screen, go back to the beginning: if (xPos >= width) { xPos = 0; background(0); } else { // increment the horizontal position: xPos++; } } } /* Max/MSP v5 patch for this example ----------begin_max5_patcher---------- 1591.3oc0YszbaaCD9r7uBL5RalQUAO3CvdyS5zVenWZxs5NcfHgjPCIfJIT RTxj+6AOHkoTDooroUs0AQPR73a+1cwtK3WtZxzEpOwqlB9YveAlL4KWMYh6 Q1GLo99ISKXeJMmU451zTUQAWpmNy+NM+SZ2y+sR1l02JuU9t0hJvFlNcMPy dOuBv.U5Rgb0LPpRpYBooM3529latArTUVvzZdFPtsXAuDrrTU.f.sBffXxL vGE50lIHkUVJXq3fRtdaoDvjYfbgjujaFJSCzq4.tLaN.bi1tJefWpqbO0uz 1IjIABoluxrJ1guxh2JfPO2B5zRNyBCLDFcqbwNvuv9fHCb8bvevyyEU2JKT YhkBSWPAfq2TZ6YhqmuMUo0feUn+rYpY4YtY+cFw3lUJdCMYAapZqzwUHX8S crjAd+SIOU6UBAwIygy.Q1+HAA1KH6EveWOFQlitUK92ehfal9kFhUxJ3tWc sgpxadigWExbt1o7Ps5dk3yttivyg20W0VcSmg1G90qtx92rAZbH4ez.ruy1 nhmaDPidE07J+5n2sg6E6oKXxUSmc20o6E3SPRDbrkXnPGUYE.i5nCNB9TxQ jG.G0kCTZtH88f07Rt0ZMMWUw8VvbKVAaTk6GyoraPdZff7rQTejBN54lgyv HE0Ft7AvIvvgvIwO23jBdUkYOuSvIFSiNcjFhiSsUBwsUCh1AgfNSBAeNDBZ DIDqY.f8.YjfjV1HAn9XDTxyNFYatVTkKx3kcK9GraZpI5jv7GOx+Z37Xh82 LSKHIDmDXaESoXRngIZQDKVkpxUkMCyXCQhcCK1z.G457gi3TzMz4RFD515F G3bIQQwcP3SOF0zlkGhiCBQ1kOHHFFlXaEBQIQnCwv9QF1LxPZ.A4jR5cyQs vbvHMJsLll01We+rE2LazX6zYmCraRrsPFwKg1ANBZFY.IAihr8Ox.aH0oAL hB8nQVw0FSJiZeunOykbT6t3r.NP8.iL+bnwNiXuVMNJH9H9YCm89CFXPBER bz422p8.O4dg6kRxdyjDqRwMIHTbT3QFLskxJ8tbmQK4tm0XGeZWF7wKKtYY aTAF.XPNFaaQBinQMJ4QLF0aNHF0JtYuHSxoUZfZY6.UU2ejJTb8lQw8Fo5k Rv6e2PI+fOM71o2ecY1VgTYdCSxxUqLokuYq9jYJi6lxPgD2NIPePLB0mwbG YA9Rgxdiu1k5xiLlSU6JVnx6wzg3sYHwTesB8Z5D7RiGZpXyvDNJY.DQX3.H hvmcUN4bP1yCkhpTle2P37jtBsKrLWcMScEmltOPv22ZfAqQAdKr9HzATQwZ q18PrUGt6Tst2XMCRUfGuhXs6ccn23YloomMqcTiC5iMGPsHsHRWhWFlaenV XcqwgCQiGGJzptyS2ZMODBz6fGza0bzmXBj7+DA94bvpR01MffAlueO7HwcI pWCwmzJdvi9ILgflLAFmyXB6O7ML0YbD26lenmcGxjVsZUN+A6pUK7AtTrPg M+eRYG0qD9j4I7eEbco8Xh6WcO.or9XDC6UCiewbXHkh6xm5LiPEkzpJDRTu mEB44Fgz4NCtJvX.SM1vo2SlTCZGAe7GZu6ahdRyzFOhYZ+mbVVSYptBw.K1 tboIkatIA7c1cTKD1u.honLYV04VkluHsXe0szv9pQCE9Ro3jaVB1o15pz2X zYoBvO5KXCAe0LCYJybE8ZODf4fV8t9qW0zYxq.YJfTosj1bv0xc.SaC0+AV 9V9L.KKyV3SyTcRtmzi6rO.O16USvts4B5xe9EymDvebK0eMfW6+NIsNlE2m eqRyJ0utRq13+RjmqYKN1e.4d61jjdsauXe3.2p6jgi9hsNIv97CoyJ01xzl c3ZhUCtSHx3UZgjoEJYqNY+hYs5zZQVFW19L3JDYaTlMLqAAt1G2yXlnFg9a 53L1FJVcv.cOX0dh7mCVGCLce7GFcQwDdH5Ta3nyAS0pQbHxegr+tGIZORgM RnMj5vGl1Fs16drnk7Tf1XOLgv1n0d2iEsCxR.eQsNOZ4FGF7whofgfI3kES 1kCeOX5L2rifbdu0A9ae2X.V33B1Z+.Bj1FrP5iFrCYCG5EUWSG.hhunHJd. HJ5hhnng3h9HPj4lud02.1bxGw. -----------end_max5_patcher----------- */
Using the Processing sketch in the code sample above, you'll get a graph of the sensor's value. As you change the value of the analog sensor, you'll get a graph something like this:
In your kit you have two simple sensors: a light-dependent resistor, or LDR and a integrated temperature sensor. With them, you can measure ambiental light intensity and temperature. In order to do this, you must first connect the sensors to your Arduino. You can do that by following the pictures below:
<imgcaption c center> </imgcaption>
<imgcaption c center> </imgcaption>
Exercise 6: Connect the sensors to your board on analog inputs 0 and 1 and write a simple sketch that prints over the serial line the instantaneous values for light intensity and temperature. Plot them on your computer screen using the Processing sketch from the previous example.
Exercise 7: Write a sketch that turns on the LED connected to digital output 6 when temperature or luminosity goes over a predetermined threshold.
The LiquidCrystal library allows you to control LCD displays that are compatible with the Hitachi HD44780 driver. There are many of them out there, and you can usually tell them by the 16-pin interface.
This example sketch prints “Hello World!” to the LCD and shows the time in seconds since the Arduino was reset.
The LCDs have a parallel interface, meaning that the microcontroller has to manipulate several interface pins at once to control the display. The interface consists of the following pins:
A register select (RS) pin that controls where in the LCD's memory you're writing data to. You can select either the data register, which holds what goes on the screen, or an instruction register, which is where the LCD's controller looks for instructions on what to do next.
A Read/Write (R/W) pin that selects reading mode or writing mode
An Enable pin that enables writing to the registers
8 data pins (D0 -D7). The states of these pins (high or low) are the bits that you're writing to a register when you write, or the values you're reading when you read.
There's also a display constrast pin (Vo), power supply pins (+5V and Gnd) and LED Backlight (Bklt+ and BKlt-) pins that you can use to power the LCD, control the display contrast, and turn on and off the LED backlight, respectively.
The process of controlling the display involves putting the data that form the image of what you want to display into the data registers, then putting instructions in the instruction register. The LiquidCrystal Library simplifies this for you so you don't need to know the low-level instructions.
The Hitachi-compatible LCDs can be controlled in two modes: 4-bit or 8-bit. The 4-bit mode requires seven I/O pins from the Arduino, while the 8-bit mode requires 11 pins. For displaying text on the screen, you can do most everything in 4-bit mode, so example shows how to control a 2×16 LCD in 4-bit mode.
To wire your LED screen to your Arduino, connect the following pins:
LCD RS pin to digital pin 7 LCD Enable pin to digital pin 6 LCD D4 pin to digital pin 5 LCD D5 pin to digital pin 4 LCD D6 pin to digital pin 3 LCD D7 pin to digital pin 2
Additionally, wire a 10K pot to +5V and GND, with it's wiper (output) to LCD screens VO pin (pin3).
<imgcaption c center> </imgcaption>
/* LiquidCrystal Library - Hello World Demonstrates the use a 16x2 LCD display. The LiquidCrystal library works with all LCD displays that are compatible with the Hitachi HD44780 driver. There are many of them out there, and you can usually tell them by the 16-pin interface. This sketch prints "Hello World!" to the LCD and shows the time. The circuit: * LCD RS pin to digital pin 12 * LCD Enable pin to digital pin 11 * LCD D4 pin to digital pin 5 * LCD D5 pin to digital pin 4 * LCD D6 pin to digital pin 3 * LCD D7 pin to digital pin 2 * LCD R/W pin to ground * 10K resistor: * ends to +5V and ground * wiper to LCD VO pin (pin 3) Library originally added 18 Apr 2008 by David A. Mellis library modified 5 Jul 2009 by Limor Fried (http://www.ladyada.net) example added 9 Jul 2009 by Tom Igoe modified 22 Nov 2010 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/LiquidCrystal */ // include the library code: #include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins LiquidCrystal lcd(7, 6, 5, 4, 3, 2); void setup() { // set up the LCD's number of columns and rows: lcd.begin(16, 2); // Print a message to the LCD. lcd.print("hello, world!"); } void loop() { // set the cursor to column 0, line 1 // (note: line 1 is the second row, since counting begins with 0): lcd.setCursor(0, 1); // print the number of seconds since reset: lcd.print(millis()/1000); }