Triggering a pinball solenoid

Hi,

I'm trying to get my pinball solenoids to trigger from the Arduino UNO.
Currently I'm trying with just a push button & LED for testing.
When the button is pushed it should turn the LED on. If the button is still on for longer than 400ms then it should flash - 120ms off / 10ms on.
I've increased the final timings by x10 to see the LED flashing how I want it first.
Currently the code below acts as an elaborate toggle switch.

class Flasher
{
  int ledPin;
  long OnTime40ms;
  long OffTime;
  long FlashTime;
  int ledState;
  unsigned long previousMillis;
  boolean initial40ms;

  public:
  Flasher(int pin, long on, long off, long flash)
  {
  ledPin = pin;
  byte Count = 0;
  pinMode(ledPin, OUTPUT);

  OnTime40ms = on;
  OffTime = off;
  FlashTime = flash;

  //ledState = HIGH;
  previousMillis = 0;
  }

  void Update(unsigned long currentMillis)
  {
    if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime40ms) && (initial40ms = false))
    {
      ledState = LOW;
      previousMillis = currentMillis;
      digitalWrite(ledPin, ledState);
      initial40ms = true;
    }
    else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
    {
      ledState = HIGH;
      previousMillis = currentMillis;
      digitalWrite(ledPin, ledState);
    }
    else if ((ledState == HIGH) && (currentMillis - previousMillis >= FlashTime) && (initial40ms = true))
      ledState = LOW;
      previousMillis = currentMillis;
      digitalWrite(ledPin, ledState);
  }
};

const byte LeftButton = 2;
Flasher led(13, 400, 120, 10);

void setup() 
{
  pinMode(LeftButton, INPUT_PULLUP);
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);
}
SIGNAL(TIMER0_COMPA_vect) 
{
  unsigned long currentMillis = millis();
  if(digitalRead(LeftButton) == LOW)
  {
     led.Update(currentMillis);
  }
} 
void loop()
{
}

Hi,
Welcome to the forum.

How do you expect it to work if you have no code in the void loop() and your setup just sets input and timer parameter?

Can you tell us your electronics, programming, Arduino, hardware experience?

Unless this is a special way of C++ programming.

Thanks… Tom… :slight_smile:

Yes. But what is wrong with it ?
For troubleshooting, you could start by incrementing a global (volatile) counter the interrupt service routine to see if is being called as expected by the timer. Print the counter every second or so in the loop().

Hi Tom,

The button triggers a timer interrupt in the setup. Enabling it to process instantaneously. Freeing up the loop(). Yes its a special way of C++ programming.
I’m an Electronics Technician by trade but I haven’t played much with microcontrollers since college.
I’ve updated the code. Now it processes the first if() statement instantaneously (needs to be for 1 second). Then it toggles between the other 2 if() statements if the button is still held down (which is good).

class Flasher
{
  int ledPin;
  int OnTime40ms;
  long OffTime;
  long InitTime;
  byte Counter;
  long Counter40ms;
  boolean button;
  boolean buttonState;

  int ledState;
  unsigned long previousMillis;

  public:
  Flasher(int pin, long on, long off, long init, boolean Count)
  {
  ledPin = pin;
  pinMode(ledPin, OUTPUT);

  OnTime40ms = on;
  OffTime = off;
  InitTime = init;
  Counter = Count;

  ledState = HIGH;
  previousMillis = 0;
  }

  void Update(unsigned long currentMillis)
  {
    if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime40ms) && (Counter <= 0))
    {
      ledState = LOW;
      previousMillis = currentMillis;
      digitalWrite(ledPin, ledState);
      buttonState = digitalRead(button);
      Counter++;
      Serial.println(buttonState);
      Serial.println("40ms");
    }
    else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
    {
      ledState = HIGH;
      previousMillis = currentMillis;
      digitalWrite(ledPin, ledState);
      Serial.println("12ms");
    }
    else if ((ledState == HIGH) && (currentMillis - previousMillis >= InitTime) && (Counter > 0))
    {
      ledState = LOW;
      previousMillis = currentMillis;
      digitalWrite(ledPin, ledState);
      Serial.println("1ms");
    }
  }  
};

const byte LeftButton = 2;
Flasher led(13, 1000, 500, 100, 0);

void setup()
{
  Serial.begin(9600);
  pinMode(LeftButton, INPUT_PULLUP);
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);
}
SIGNAL(TIMER0_COMPA_vect)
{
  unsigned long currentTime = millis();
  if(digitalRead(LeftButton) == LOW)
  {
    led.Update(currentTime);
  }
}
void loop()
{
}

This will not happen with a byte Counter: ( Counter <= 0 )
but it looks like you are making progress.

Your choice of timer0 is also not ideal on a Uno (ATmega328P) because this is also used for millis() which you are also currently using. Maybe chose another timer.