Pages

Sunday, September 22, 2013

Lab 3 - Arduino Material - Digital Input

Microprocessors can be used to read signals from the outside environment.

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??


  1. The Arduino board is used to supply both +5V and GND to the rails of the breadboard.
  2. The left pushbutton is used to light an LED in a simple electrical circuit. 
  3. 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. 
  4. 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.
There a a few more things that need to be explored and these will be covered in lab.

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.

    

/*
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
}
}
view raw PushOnce hosted with ❤ by GitHub

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...



/*
Arduino code - Example of how to use a single push-button to cycle through a number of choices. This example code uses functions to:
** debounce the button
** check the state of the button
** keep track of the current selection of the push button (in this case 1, 2, 3, 4, or 5)
** turn on an LED on the board that corresponds to the button selection
** a dummy function is included that can be used to set the condition of some device (motor speed, servo position, etc...) that corresponds to the button choice.
*/
// global variables
const int buttonPin = 2;
boolean currentState = LOW;
boolean lastState = LOW;
boolean stateChange = false;
int currentButton = 0;
int lastButton = 4;
int ledArray[] = {9, 10, 11, 12};
// setup
void setup() {
pinMode(buttonPin, INPUT);
for (int i=0; i<5; i++){
pinMode(ledArray[i],OUTPUT);
}
Serial.begin(9600);
}
// main loop
void loop(){
currentState = debounceButton();
stateChange = checkForChange(currentState, lastState);
currentButton = getButtonNumber(lastButton, currentState, stateChange);
indicatorLight(currentButton);
lastState = currentState;
lastButton = currentButton;
}
// function debounceButton
boolean debounceButton()
{
boolean firstCheck = LOW;
boolean secondCheck = LOW;
boolean current = LOW;
firstCheck = digitalRead(buttonPin);
delay(50);
secondCheck = digitalRead(buttonPin);
if (firstCheck == secondCheck){
current = firstCheck;
}
return current;
}
// function checkForChange
boolean checkForChange(boolean current, boolean last)
{
boolean change;
if (current != last){
change = true;
}
else {
change = false;
}
return change;
}
// function getButtonNumber
int getButtonNumber(int button, boolean state, boolean change)
{
if (change == true && state == LOW){
button++;
if (button > 4){
button = 0;
}
Serial.println(button);
}
return button;
}
// function indicatorLight
void indicatorLight(int button)
{
for (int i=0; i<5; i++) {
digitalWrite(ledArray[i], LOW);
}
digitalWrite(ledArray[button], HIGH);
}
// function itemControl

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.



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
view raw LED Wave hosted with ❤ by GitHub