Here I will add a state detecting button and integrate some other sensors.
I mentioned in my last post that I wanted to add a button to start and stop the program. Right now, the program starts running immediately when it receives power. That's good for starting, but I would rather it start with a button push and stop with one, so I can safetly remove the SD card without corrupting data. To do this, I need to add a button that can detect state changes.
For my initial test, I modified the code from the state-change-detection tutorial from Programming Electronics so that it changes an LED from on to off with every button push and resets the state tracking variable.
// constants const int buttonPin = 14; const int ledPin = 15; // changing variables int buttonCounter = 0; int buttonState =0; int lastButton = 0; void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); Serial.println("setup done, starting!"); } void loop() { buttonState = digitalRead(buttonPin); if(buttonState != lastButton){ if (buttonState == HIGH){ buttonCounter++; Serial.println("on!"); Serial.print("number of button pushes is "); Serial.println(buttonCounter); } else { Serial.println("off"); } delay(50); } lastButton = buttonState; if (buttonCounter % 2 == 0){ digitalWrite(ledPin, HIGH); buttonCounter = 0; // put your main code here, to run repeatedly: } else { digitalWrite(ledPin, LOW); } }
And my testing circuit diagram looks like so
Figure 1: State change test. Note LED polarity is wrong in this fritzing.
This works great, but it is a lot of code to do a relatively simple thing. It also polls the button state from within the loop, which can slow down larger programs or it wont detect the change immediately. A better solution would be to wrap the state change function in an interrupt.
The first step will be to shorten the previous code and wrap it in an interrupt function that checks and alters a global variable to track state.
I will set this variable to 0 at the beginning of the program's normal routine, this way whenever it is plugged in it is automatically set to off
and has to be manually started.
#include "Arduino.h" // constants const int interruptPin = 14; const int ledPin = 15; // changing variables volatile int buttonCounter = 0; void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(ledPin, OUTPUT); Serial.println("setup done, starting!"); attachInterrupt(digitalPinToInterrupt(interruptPin), button, RISING); } void loop() { Serial.println("no interrupt"); delay(1000); } void button(){ buttonCounter++; Serial.println("interrupt called"); if (buttonCounter % 2 == 0){ Serial.println("high loop"); digitalWrite(ledPin, HIGH); buttonCounter = 0; }else{ digitalWrite(ledPin, LOW); Serial.println("low loop!"); } }
That is much simpler and easier than I thought. I will probably improve the interrupt state checker as I go. The problem with this is that the debounce on the button is not great as it is a cheap button, so I used these instructions to control for the cheap hardware and only activate on a real push to control this.
#include "Arduino.h" // constants const int interruptPin = 14; const int ledPin = 15; // changing variables long lastDebounceTime = 0; long debounceDelay = 50; volatile int buttonCounter = 0; void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(ledPin, OUTPUT); Serial.println("setup done, starting!"); attachInterrupt(digitalPinToInterrupt(interruptPin), button, RISING); } void loop() { Serial.println("no interrupt"); delay(1000); } void button(){ if ((millis() - lastDebounceTime) > debounceDelay){ lastDebounceTime = millis(); buttonCounter++; Serial.println("interrupt called"); if (buttonCounter % 2 == 0){ Serial.println("high loop"); digitalWrite(ledPin, HIGH); buttonCounter = 0; }else{ digitalWrite(ledPin, LOW); Serial.println("low loop!"); } } }
The serial statements were useful for debugging, but I will remove them in the final project.
TODO More explanation on what debounce is, why we need to account for it and what exactly this code does.
that is all I had time for this weekend. Next weekend I will control the temperature logger with the button and start adding my other sensors.
Coming soon
Coming soon
Coming soon