Week 5: Microcontroller Programming

Programming LEDs in Sequence

Having tinkered with Arduino - and some JavaScript - before, I was excited by the prospect of diving right into object-oriented programming and attempting to synchronize multiple elements within one board. When working on the lab exercises, I conjured the idea of programming an Arduino "traffic light" with green, yellow, and red LEDs. My initial goal was to align the sequence of lights with the servo motor's speed, such that the motor would move fast during the green light, slow down during the yellow light, and stop during the red light.


Initial LED Tests

The lab materials were helpful in understanding how to sequence LED lights. Before reviewing a tutorial, I was able to program the red, yellow, and green LEDs to blink in sequence. However, since many of these examples used the delay() function, I wanted to try using millis() and class constructors.



Learning the Logic

As I searched for resources for how to time the LED and motor movement together, I came across a tutorial that built out a traffic light example in C++ at several levels of abstraction. Their process was similar to the examples from class, so I decided to give it a go. I coded along with the instructor, who ultimately taught me how to use a button to initialize the traffic light. Their logic was similar to when a pedestrian presses the crosswalk button and the stop light slows down traffic so they can cross the street.

  • Green LED is already on (base state).
  • User presses the button, inferring change.
  • Green LED turns off, yellow LED turns on (quickly).
  • Yellow LED turns off, red LED turns on (delayed).
  • Red LED turns off after delay, green LED turns on.


Arduino Schematic
Most Recent Demo

Setting the Timer

The timer code initialized a timer when the button is pressed, employing variables that drive the LED light sequence.


                    #ifndef _TIMER_H_
                    #define _TIMER_H_

                    class Timer {

                      // define timer start time and target time
                      // use these values to intiate the loop
                      long timerStart = 0;
                      long timerTarget = 0;

                      public:

                        // function to begin the timer using millis()
                        void startTimer(int msec) {
                          timerStart = millis();
                          timerTarget = msec;
                        }

                        // determine whether the timer is ready
                        bool isTimerReady() {
                          return (millis() - timerStart) > timerTarget;
                        } 
                      
                    };

                    #endif // _TIMER_H_
                
Setting the Button

The button code established a button pullup that, once read, instigates the traffic light code.


                    #ifndef _BUTTON_H_
                    #define _BUTTON_H_

                    class Button {

                      // set button pin variable
                      int _buttonPin;

                      public:

                      // define button object
                        Button(int buttonPin) {
                          // set variable to button input
                          _buttonPin = buttonPin;
                          // set button as pullup
                          pinMode(_buttonPin, INPUT_PULLUP);
                        }

                        // if button is pressed, read it
                        bool isPressed() {
                          return !digitalRead(_buttonPin);
                        }
                        
                    };
                    #endif // _BUTTON_H_
                

Adding the Motor?

As previously mentioned, It was my initial goal this week to align the speed of a servo or DC motor with the button-LED interaction. I troubleshot many different options, all of which disrupted the Green-Yellow-Red LED sequence. With some more time, I think I could make it work for the "Timer.h" and "Button.h" code to also correlate with the motor speed - to simplify things, I was thinking of just trying the analogWrite() function to turn the motor on when the light was green and off when the light was red, rather than utilizing the millis() and (for pos=0; pos <=180; pos+=1) syntax we used for the servo motors in order to avoid using delay(). Although I had executed those examples successfully, I got a bit confused when it came to applying it all in a multi-tasking program that involved buttons and light sequences. I hope to figure this out this week with some more help from the TFs.


Main Arduino File

            #include "TrafficLight.h"
            #include "Sweeper.h"
            #include "Timer.h"
            #include "Button.h"
            
            // determine LED data connections
            int pinGreen = 11;
            int pinYellow = 12;
            int pinRed = 13;
            
            // determine button data input
            int pinButton = 10;
            
            // create instance of the traffic light class
            trafficLight trafficLight(pinGreen, pinYellow, pinRed);
            
            // create instance of the button class
            Button button(pinButton);
            
            // create instance of the timer
            Timer timer;
            
            void setup(){
              // do not need
            }
            
            void loop(){
              // if in the middle of pressing the button
              if (button.isPressed()){
                // stop light sequence
                trafficLight.stop();
                // start timer
                timer.startTimer(1000);
              } else {
                // if timer is ready
                if (timer.isTimerReady()){
                  // start sequence
                  trafficLight.go();
                }
              }
              // else, loop through the lights
              trafficLight.loop();
            }
"TrafficLight.h" File

                    #ifndef _TRAFFIC_LIGHT_H
                    #define _TRAFFIC_LIGHT_H
                    
                    #include "Timer.h"
                    
                    // write LED class to be used thre times
                    class trafficLight {
                    
                      // define timer variables
                      long timerGreen = 2000;
                      long timerYellow = 1000;
                      long timerRed = 2000;
                    
                      // define class variables
                      int _greenLED;
                      int _yellowLED;
                      int _redLED;
                    
                      // define states
                      enum State {
                          GREEN,
                          YELLOW,
                          RED
                      };
                    
                      // define initial states
                      State _currentState = GREEN;
                      State _targetState = GREEN;
                      Timer timer;
                    
                      // constructor takes LEDs as parameters
                      public:
                        trafficLight (int greenLED, int yellowLED, int redLED){
                          _greenLED = greenLED;
                          _yellowLED = yellowLED;
                          _redLED = redLED;
                    
                          // set LEDs as output
                          pinMode(_greenLED, OUTPUT);
                          pinMode(_yellowLED, OUTPUT);
                          pinMode(_redLED, OUTPUT);
                    
                          // run the green function inside the object
                          green();
                        }
                    
                        // hitting go makes target state green
                        void go() {
                          _targetState = GREEN;
                        }
                    
                        // hitting stop makes target state red
                        void stop() {
                          _targetState = RED; 
                        }
                    
                        // if target state is green, loop through to make the LED green
                        // if the target state is red,loop through to make the LED red
                        void loop(){
                          if (_targetState == GREEN){
                            goToGreen();
                          } else {
                            goToRed();
                          }
                        }
                    
                      private:
                       
                        void goToGreen() {
                    
                          switch (_currentState){
                    
                            case RED:
                              _currentState = GREEN;
                              timer.startTimer(timerGreen);
                              break;
                    
                            case GREEN:
                              green();
                              break;
                          }
                        } 
                    
                        void goToRed () {
                    
                          switch (_currentState){
                    
                            // move from green to yellow
                            case GREEN:
                              _currentState = YELLOW;
                              timer.startTimer(timerYellow);
                              break;
                    
                            // move from yellow to red
                            case YELLOW:
                              yellow();
                              if (timer.isTimerReady()){
                                _currentState = RED;            
                              }
                              break;
                            
                            // stop at red
                            case RED:
                              red();
                              break;
                          }
                        } 
                    
                        // turn only yellow LED on
                        void yellow(){
                            digitalWrite(_greenLED, LOW);
                            digitalWrite(_yellowLED, HIGH);
                            digitalWrite(_redLED, LOW);
                          }
                    
                        // turn only red LED on
                        void red(){
                          digitalWrite(_greenLED, LOW);
                          digitalWrite(_yellowLED, LOW);
                          digitalWrite(_redLED, HIGH);
                        }
                    
                        // turn only green LED on
                        void green(){
                          digitalWrite(_greenLED, HIGH);
                          digitalWrite(_yellowLED, LOW);
                          digitalWrite(_redLED, LOW);
                        }
                    
                    };  
                    
                    #endif // _TRAFFIC_LIGHT_H
                    
ß