The command that can be used to read the state of a digital pin is digitalRead.
A simple way to see how this works is to use a pushbutton to toggle the voltage of an I/O pin between +5V and ground.
The following circuit created using Frizting shows one possible way that this can be accomplished.
So what's happening here??
- The Arduino board is used to supply both +5V and GND to the rails of the breadboard.
- The left pushbutton is used to light an LED in a simple electrical circuit.
- The right pushbutton is used to control the voltage state of digital I/O pin 2.
- Pin 2 is connected to both one leg of the pushbutton and to +5V through a 10k resistor. So when the button is open, pin 2 is HIGH.
- The other leg of the pushbutton is connected to GND. When the button is closed the voltage of Pin 2 is "pulled-down" to GND.
- The state of Pin 2 is determined using digitalRead in the program loop. When the program determines that the button has been pushed, it sends a digitalWrite(13, HIGH) this results in the other LED to turn on.
Using the above set-up explore the behavior of the example Sketches...
Button
StateChangeDetection
Debounce
After this exploration - take a look at the following code that combines some of these ideas together.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
PushOnce | |
Turns on and off a light emitting diode(LED) connected to digital | |
pin 13, when pressing a pushbutton attached to pin 2. | |
The circuit: | |
* LED attached from pin 13 to ground | |
* pin 2 is attached to one leg of pushbutton and to +5V through 10k resistor | |
* other leg uf pushbutton is attached to ground | |
* When button is pressed state of pin 2 chages from HIGH to LOW | |
*/ | |
// constants won't change. They're used here to | |
// set pin numbers: | |
const int buttonPin = 2; // the number of the pushbutton pin | |
const int ledPin = 13; // the number of the LED pin | |
// variables will change: | |
int buttonState1 = 0; // variables for reading the pushbutton status | |
int buttonState2 = 0; | |
int buttonState = 0; | |
int buttonCount = 0; // variable to record number of times button has been pushed | |
boolean lastButton = HIGH; // Boolean variable to hold last state of button | |
void setup() { | |
// initialize the LED pin as an output: | |
pinMode(ledPin, OUTPUT); | |
// initialize the pushbutton pin as an input: | |
pinMode(buttonPin, INPUT); | |
// Begin serial communication | |
Serial.begin(9600); | |
} | |
void loop(){ | |
/* | |
The loop processes so fast that it can read the state of the button many times during the | |
time interval it takes to physically push the button. The button can "bounce" during the | |
physical change and produce transients that the digital input can interpret as a | |
series of state changes from HIGH to LOW. | |
The button can be software "debounced" by checking the button state, waiting a short | |
amount of time, say 50 milliseconds, and then checking the state once again. If the state | |
hasn't changed then the reading of the button state can be consisdered valid. | |
*/ | |
buttonState1 = digitalRead(buttonPin); | |
delay(50); | |
buttonState2 = digitalRead(buttonPin); | |
if (buttonState1 == buttonState2){ // if a valid button state is detected proceed... | |
buttonState = buttonState2; | |
// check if the pushbutton is pressed. | |
// if it is, the buttonState is LOW: | |
if (buttonState == LOW) { | |
// turn LED on: | |
digitalWrite(ledPin, HIGH); | |
} | |
else { | |
// turn LED off: | |
digitalWrite(ledPin, LOW); | |
} | |
// check to see if button has changed state since last pass through loop | |
if (buttonState != lastButton) { | |
if (buttonState == LOW){ // if the state has changed and is now LOW | |
buttonCount++; // increment by 1 | |
Serial.println(buttonCount); // send count to serial monitor | |
} | |
} | |
lastButton = buttonState; // update value of lastButton | |
} | |
} |
Next steps...
Modify the circuit such that indicator LED's are connected to pins 9, 10, 11, and 12.The following code is a variation of the above code where functions are used to better define what is happening.
The Loop section only contains calls to a series of user defined functions and then updates to loop variables. The functions called are
debounceButton - this checks the current state of the button
checkForChange - this checks to see if the button has switched state (HIGH to LOW or LOW to HIGH)
getButtonNumber - this will increment the button counter it a change from a HIGH to LOW button state has been detected
indicatorLight - this turns on the LED associated with the button value. Either LED 1, 2, 3, or 4, on the 5th button push all LED's are tunred off.
The code for this setup is shown below the video...
Going even further...
One of the students in the class created a project that uses a sine wave to control an array of LED's. A pushbutton allows the user to toggle between different input modes and a potentiometer is used to adjust the parameter in each mode - phase, wave speed and brightness.This project introduces two new functions, analogWrite and analogRead. The analogWrite function names use of pulse-width modulation (PWM) to control the brightness of the LED's. The analogRead function is used to read the value of the potentiometer. You can explore these two functions using the Arduino Example sketches...
analogWrite: File... Examples... Analog... Fading
analogRead: File... Examples... Analog... AnalogInput
The code is also a very nice example of both how to use functions to make your code easier to read and the proper use of comments to provide clarity.
Here is a video of the system in action. The code used to create this set-up is listed after the video.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void setup(){ | |
//sets pins to OUTPUT | |
pinMode(11,OUTPUT);pinMode(10,OUTPUT);pinMode(9,OUTPUT); | |
pinMode(6,OUTPUT);pinMode(5,OUTPUT);pinMode(3,OUTPUT);} | |
// extern creates global variables | |
extern float p = 1; // phase shift constant | |
extern float s = .005; // angular velocity constant | |
extern float g = 1; // brightness threshold | |
extern int mode = 0 ; // operation mode | |
extern float x = 0 ; // clock variable | |
extern int lock = 0 ; // button lock | |
// analogWrite can only be used on pins 11,10,9,6,5,3 | |
// these pins contain pulse-width modulated output | |
void led1(){analogWrite(11,bright(0));} // led1() sets pin 11 to value returned by function bright() | |
void led2(){analogWrite(10,bright(p));} // p inputs phase shift | |
void led3(){analogWrite(9,bright(2*p));} | |
void led4(){analogWrite(6,bright(3*p));} | |
void led5(){analogWrite(5,bright(4*p));} | |
void led6(){analogWrite(3,bright(5*p));} | |
int bright(int xx){ // returns the sine of global x scaled between 0 and 255 | |
float b; | |
b = sin(x+xx)+g; // sin() input is in radians output is a float | |
b = (b )*(255/2); | |
if(b > 255){b = 255;} | |
else if(b < 0){b = 0;} // keeps output between 0 and 255 | |
return b;} | |
void tick(){ | |
if(x < 6.283){x = x + s;} // increments x variable from 0 to 2*pi | |
else{x = 0;}} // zeroes x variable | |
float phase(){if(mode == 0){p = analogRead(A0)/170; return p;};} // sets p = to analog input value if mode == 0 | |
float velocity(){if(mode == 1){s = (analogRead(A0)/10333.3)+.001; return s;};} // sets s = to analog input value if mode == 1 | |
float threshold(){if(mode == 2){g = (analogRead(A0)/341)-1; return g;};} // sets g = to analog input value if mode == 2 | |
void run(){led1(); led2(); led3(); led4(); led5(); led6();} //run function sets the brightness of the all LED's based on state of global variables | |
void test(){ // checks if button is pushed and increments mode by 1 | |
if(digitalRead(12)==LOW && lock == 0){mode = mode + 1; lock = 2;} // increments mode when pin goes LOW and sets lock to 2 | |
if(digitalRead(12)==HIGH && lock == 2){lock = 3;} // sets lock to 3 when pin goes high | |
if(digitalRead(12)==HIGH && lock == 3){lock = 0;} // sets lock back to 0 if pin is still high | |
if(mode >= 3){mode = 0;}} // keeps mode between 0 and 2 | |
void loop(){ // anything inside loop is run forever | |
run(); // set led brightness | |
tick(); // increment clock | |
phase(); // set global p if mode 0 | |
velocity(); // set global s if mode 1 | |
threshold(); // set global g if mode 2 | |
test();} // check button state, increment mode |