counting inputs and controlling outputs

I am trying to turn on a solenoid for 20 seconds (the solenoid should turn off after the 20s interval) when a button is pushed. Then when the button is pushed again the solenoid needs to remain off. The cycle should then repeat itself. I am not a programmer of any sort so this is a very frustrating project for me, below is the code I have been trying to use, but it is not working anything like I want it to most likely because it is severely wrong. I have even combined some of the example codes in the Arduino Library with no luck.

Any help would be appreciated!!!

const int Sol1= 13; //solenoid output pin
const int button=7;          //button input pin

int buttonstate=0; 
int lastbuttonstate = 0;

int solstate=LOW; //solenoid state
unsigned long previousmillis = 0;
const long interval=20000;

void setup() {
  pinMode(Sol1,OUTPUT);
  pinMode(button,INPUT);
  Serial.begin(9600);
}

void loop() {  
buttonstate=digitalRead(button);
if (buttonstate!=lastbuttonstate)
  {  
  if (buttonstate == HIGH)
  {
for (int buttonpushcounter = 1;buttonpushcounter<=2;buttonpushcounter++)
{
  Serial.print("number of button pushes:  ");
  Serial.println(buttonpushcounter);
  
   unsigned long currentmillis = millis();
    if(currentmillis - previousmillis >= interval) {
    previousmillis = currentmillis;  
    solstate=HIGH;
    }

}
}
}
digitalWrite(Sol1, solstate);
lastbuttonstate=buttonstate;

Change this
pinMode(button,INPUT);
to this
pinMode(button,INPUT_PULLUP);
with button wired to connect the pin to Gnd when pressed.
Than change this
if (buttonstate == HIGH)
to look for a LOW:
if (buttonstate == LOW)
to go along with the low on button press.

What do you have for a solenoid driver?

Do you mean that you only want the solenoid to move the very first time the button is pressed, and never afterwards?

If so you just need a variable (let's call it solenoidTriggered) which is set to false in setup() and is set to true when the solenoid is first activated. Something like this

if (buttonState == LOW && solenoidTriggered == false) { // assumes LOW when pressed
    solenoidTriggered = true;
    // code to make solenoid work
}

...R

Robin2:
Do you mean that you only want the solenoid to move the very first time the button is pressed, and never afterwards?

If so you just need a variable (let's call it solenoidTriggered) which is set to false in setup() and is set to true when the solenoid is first activated. Something like this

if (buttonState == LOW && solenoidTriggered == false) { // assumes LOW when pressed

solenoidTriggered = true;
    // code to make solenoid work
}



...R

No I need the solenoid to turn on for 20s when the button is pushed (then off after the 20s). When pressed again it needs to remain off. When pressed a 3rd time it needs to turn on again for 20s etc...
I have had better luck with the code below, this allows me to turn it on then off when the button is pushed, but i cannot get it to remain on for the 20s then turn itself off when the button is initially pushed.

const int Sol1= 13;
const int button=7;

int buttonpushcounter = 0;
int buttonstate=0;
int lastbuttonstate = 0;

int solstate;
unsigned long previousmillis = 0;
const long interval=2000;

void setup() {
  pinMode(Sol1,OUTPUT);
  pinMode(button,INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {  
 buttonstate = digitalRead(button);
if (buttonstate!=lastbuttonstate)
  {  
  if (buttonstate == HIGH)
  {
  buttonpushcounter++;
  Serial.print("number of button pushes:  ");
  Serial.println(buttonpushcounter);
  }
  delay(50);
  }
  lastbuttonstate=buttonstate;

  if (buttonpushcounter%2==1)
  {
    solstate=HIGH;
    unsigned long currentmillis = millis();
      if(currentmillis - previousmillis >= interval) 
      {
        previousmillis = currentmillis; 
        solstate=LOW;
      }
   }  
    else
    {
    solstate=LOW;
    }
    digitalWrite(Sol1, solstate);

I think this piece of timing code

if (buttonpushcounter%2==1)
  {
    solstate=HIGH;
    unsigned long currentmillis = millis();
      if(currentmillis - previousmillis >= interval)
      {
        previousmillis = currentmillis;
        solstate=LOW;
      }
   }

should be triggered when the solenoid is turned on, rather than by a button state or button count.

If you only want to act on every second button press then your decision to turn the solenoid on (and start the timer) should take account of button count.

...R

Hi,
What is the application that needs this sort of operation?

It may help if we know the full picture.

Thanks... Tom..... :slight_smile:

I am making a table that lifts trays and shakes them on an assembly line. So the idea is when a tray moves over the shaker it will hit a button, which activates the solenoid powering the pneumatic cylinders. These cylinders then lift the tray and shakes them for 20s. after the 20s is up the solenoid will be turned off lowering the table, upon being lowered the tray will then hit the button again (at this point I want the solenoid to remain off). The tray will then move on its way and another one will take its place repeating the cycle.

The solenoid is 24v I am using a TIP120 transistor so the 5v signal from the arduino activates the solenoid. I also used a voltage divider circuit to lower the 24v to 4v to be used as the input upon the button being pressed.

I hope this helps I am still not having any luck with trying to figure out the code to make the solenoid do what I want.

I figured that since the solenoid was not turning off at the appropriate time, I tried adding this bit to the code to see what the "currentmillis" and "previousmillis" were doing. I found that both variables are never exceeding the "interval" range specified before the "if" statement because the "previousmillis" variable is counting as if it where assigned the millis() command, which means the criteria for that "if" statement is not being met, hence the solenoid is not turning off.

Why is the "previousmillis" even counting when it should be a variable that just holds a value?

 if (buttonpushcounter%2==1)
  {
    solstate=HIGH;
    unsigned long currentmillis = millis();
    Serial.print("current millis before:  ");
    Serial.println(currentmillis);
    Serial.print("previous millis before:  ");
    Serial.println(previousmillis);
   if(currentmillis - previousmillis >= interval) 
   {
   solstate=LOW;
   }
   previousmillis = currentmillis; 
   }

I think you have the line
previousmillis = currentmillis;
in the wrong place. I think it should go immediately after
solstate=LOW;
so that iit only updates when the time has expired

I also think that this would be more obvious if you indent your code more carefully.

...R