0

I am trying to run a program in Arduino Uno where the street light that has 3 colors, red, yellow and green, and when I press a button, the street light goes from green to yellow to red and then the pedestrian street light goes from red to green, just like a normal street light. Problem is my program does not read my button when it's pressed for some reason, I thought it was maybe the protoboard or the Arduino but when I try to run it on circuits.io the result is the same, leading me to the conclusion that my code is what is wrong. So here it is:

//libreria
#define EVENT_NONE 0
#define EVENT_EVERY 1
#define EVENT_OSCILLATE 2
#define MAX_NUMBER_OF_EVENTS (10)

#define TIMER_NOT_AN_EVENT (-2)
#define NO_TIMER_AVAILABLE (-1)
class Event {
public:
    Event(void);
    void update(void);
    void update(unsigned long now);
    int8_t eventType;
    unsigned long period;
    int repeatCount;
    uint8_t pin;
    uint8_t pinState;
    void (*callback)(void);
    unsigned long lastEventTime;
    int count;
};

Event::Event(void)
{
    eventType = EVENT_NONE;
}

void Event::update(void)
{
    unsigned long now = millis();
    update(now);
}

void Event::update(unsigned long now)
{
    if (now - lastEventTime >= period) {
        switch (eventType) {
        case EVENT_EVERY:
            (*callback)();
            break;

        case EVENT_OSCILLATE:
            pinState = !pinState;
            digitalWrite(pin, pinState);
            break;
        }
        lastEventTime = now;
        count++;
    }
    if (repeatCount > -1 && count >= repeatCount) {
        eventType = EVENT_NONE;
    }
}
//libreria timer

class Timer {

public:
    Timer(void);

    int8_t every(unsigned long period, void (*callback)(void));
    int8_t every(unsigned long period, void (*callback)(void), int repeatCount);
    int8_t after(unsigned long duration, void (*callback)(void));
    int8_t oscillate(uint8_t pin, unsigned long period, uint8_t startingValue);
    int8_t oscillate(uint8_t pin, unsigned long period, uint8_t startingValue, int repeatCount);

    /**
       * This method will generate a pulse of !startingValue, occuring period after the
       * call of this method and lasting for period. The Pin will be left in !startingValue.
       */
    int8_t pulse(uint8_t pin, unsigned long period, uint8_t startingValue);

    /**
       * This method will generate a pulse of pulseValue, starting immediately and of
       * length period. The pin will be left in the !pulseValue state
       */
    int8_t pulseImmediate(uint8_t pin, unsigned long period, uint8_t pulseValue);
    void stop(int8_t id);
    void update(void);
    void update(unsigned long now);

protected:
    Event _events[MAX_NUMBER_OF_EVENTS];
    int8_t findFreeEventIndex(void);
};

Timer::Timer(void)
{
}

int8_t Timer::every(unsigned long period, void (*callback)(), int repeatCount)
{
    int8_t i = findFreeEventIndex();
    if (i == -1)
        return -1;

    _events[i].eventType = EVENT_EVERY;
    _events[i].period = period;
    _events[i].repeatCount = repeatCount;
    _events[i].callback = callback;
    _events[i].lastEventTime = millis();
    _events[i].count = 0;
    return i;
}

int8_t Timer::every(unsigned long period, void (*callback)())
{
    return every(period, callback, -1); // - means forever
}

int8_t Timer::after(unsigned long period, void (*callback)())
{
    return every(period, callback, 1);
}

int8_t Timer::oscillate(uint8_t pin, unsigned long period, uint8_t startingValue, int repeatCount)
{
    int8_t i = findFreeEventIndex();
    if (i == NO_TIMER_AVAILABLE)
        return NO_TIMER_AVAILABLE;

    _events[i].eventType = EVENT_OSCILLATE;
    _events[i].pin = pin;
    _events[i].period = period;
    _events[i].pinState = startingValue;
    digitalWrite(pin, startingValue);
    _events[i].repeatCount = repeatCount * 2; // full cycles not transitions
    _events[i].lastEventTime = millis();
    _events[i].count = 0;
    return i;
}

int8_t Timer::oscillate(uint8_t pin, unsigned long period, uint8_t startingValue)
{
    return oscillate(pin, period, startingValue, -1); // forever
}

/**
     * This method will generate a pulse of !startingValue, occuring period after the
     * call of this method and lasting for period. The Pin will be left in !startingValue.
     */
int8_t Timer::pulse(uint8_t pin, unsigned long period, uint8_t startingValue)
{
    return oscillate(pin, period, startingValue, 1); // once
}

/**
     * This method will generate a pulse of startingValue, starting immediately and of
     * length period. The pin will be left in the !startingValue state
     */
int8_t Timer::pulseImmediate(uint8_t pin, unsigned long period, uint8_t pulseValue)
{
    int8_t id(oscillate(pin, period, pulseValue, 1));
    // now fix the repeat count
    if (id >= 0 && id < MAX_NUMBER_OF_EVENTS) {
        _events[id].repeatCount = 1;
    }
    return id;
}

void Timer::stop(int8_t id)
{
    if (id >= 0 && id < MAX_NUMBER_OF_EVENTS) {
        _events[id].eventType = EVENT_NONE;
    }
}

void Timer::update(void)
{
    unsigned long now = millis();
    update(now);
}

void Timer::update(unsigned long now)
{
    for (int8_t i = 0; i < MAX_NUMBER_OF_EVENTS; i++) {
        if (_events[i].eventType != EVENT_NONE) {
            _events[i].update(now);
        }
    }
}
int8_t Timer::findFreeEventIndex(void)
{
    for (int8_t i = 0; i < MAX_NUMBER_OF_EVENTS; i++) {
        if (_events[i].eventType == EVENT_NONE) {
            return i;
        }
    }
    return NO_TIMER_AVAILABLE;
}

This code was just a way to import the libraries since the circuits.io cannot use the #include Timer library

And this is the actual code:

// Street Light Code

int redCar = 12;
int yellowCar = 11;
int greenCar = 10;
int redWalk = 9;
int greenWalk = 8;
const int button = 2;
unsigned long lightChange = 1000;
volatile int buttonState = 0;
Timer t;

void setup() {
  pinMode(redCar, OUTPUT);
  pinMode(yellowCar, OUTPUT);
  pinMode(greenCar, OUTPUT);
  pinMode(redWalk, OUTPUT);
  pinMode(greenWalk, OUTPUT);
  pinMode(button, INPUT);
  attachInterrupt(0, interrupcion, RISING);
  digitalWrite(greenCar, HIGH);
  digitalWrite(redWalk, HIGH);
}

void loop() {
  t.update();
}

void interrupcion() {
  buttonState = digitalRead(button);
  start();
}

void start() {
  digitalWrite(greenCar, HIGH);
  digitalWrite(yellowCar, LOW);
  digitalWrite(redCar, LOW);
  digitalWrite(greenWalk, LOW);
  digitalWrite(redWalk, HIGH);
  t.after(lightChange, green_light_car);
}

void green_light_car() {
  t.oscillate(greenCar, 50, LOW, 10);
  digitalWrite(yellowCar, LOW);
  digitalWrite(redCar, LOW);
  digitalWrite(greenWalk, LOW);
  digitalWrite(redWalk, HIGH);
  t.after(lightChange, yellow_light_car);
}

void yellow_light_car() {
  digitalWrite(greenCar, LOW);
  digitalWrite(yellowCar, HIGH);
  digitalWrite(redCar, LOW);
  digitalWrite(greenWalk, LOW);
  digitalWrite(redWalk, HIGH);
  t.after(lightChange, red_light_car);
}

void red_light_car() {
  digitalWrite(greenCar, LOW);
  digitalWrite(yellowCar, LOW);
  digitalWrite(redCar, HIGH);
  digitalWrite(greenWalk, HIGH);
  digitalWrite(redWalk, LOW);
  t.after(lightChange, green_light_walk);
}

void green_light_walk() {
  digitalWrite(greenCar, LOW);
  digitalWrite(yellowCar, LOW);
  digitalWrite(redCar, HIGH);
  t.oscillate(greenWalk, 50, LOW, 10);
  digitalWrite(redWalk, LOW);
  t.after(lightChange, red_light_walk);
}

void red_light_walk() {
  digitalWrite(greenCar, HIGH);
  digitalWrite(yellowCar, LOW);
  digitalWrite(redCar, LOW);
  digitalWrite(greenWalk, LOW);
  digitalWrite(redWalk, HIGH);
  t.after(lightChange, interrupcion);
}
gre_gor
  • 6,669
  • 9
  • 47
  • 52
  • t.after(...) is not a good idea in an ISR. An ISR for a button is a bad idea anyway. An ISR with Arduino is something different than what you obviously think – datafiddler Nov 08 '16 at 13:11

1 Answers1

1

You are attaching the interrupt to digital pin 0, which doesn't seem to be connected to anything based on the source code you show. Also in your interrupt service routine, you read the button into the variable buttonState, but you don't access that variable anywhere else in the code.

tddguru
  • 392
  • 1
  • 4
  • attachInterrupt and Pin-Number are a bit complicated Pin 2 and attachInterrupt(0, func, RISING) go together on an Arduino UNO e.g. – datafiddler Nov 08 '16 at 13:14