Run through sequence once on each button state.

Hi, I am very much a novice at this and was wandering if I could get some advice here.

I am trying to get a code on my arduino that will read the state on a digital pin and run through a different sequence of simple digitalWrite events depending on if the state is high or low. The part I am having a hard time with is I need it to only go through the sequence once every time the pin changes it's state. The current code I have here continuously loops the code during each state.

I tried using millis() to make it only run until it hit the end of the interval, but then after that it wouldn't run again. I tried for a considerable amount of time to use an interrupt as well, but I just couldn't get it to work.

Here is my current basic code:

int tractorState = 1;
int statePin = 7;

int highPin = 13;

int starterPin = 6;

int ptoForward = 4;
int ptoReverse = 3;

int throttleForward = 8;
int throttleReverse = 5;

void setup() {
Serial.begin(9600);
pinMode(ptoForward,OUTPUT);
pinMode(ptoReverse,OUTPUT);
pinMode(throttleForward,OUTPUT);
pinMode(throttleReverse,OUTPUT);
pinMode(starterPin,OUTPUT);
pinMode(highPin,OUTPUT);
pinMode(tractorState,INPUT);
}

void loop() {

tractorState = digitalRead(statePin);
digitalWrite(highPin,HIGH);

if (tractorState == 1 )

{
starttractor();
startpto();
increasethrottle();
}
else if(tractorState == 0)
{
stoptractor();
stoppto();
decreasethrottle();
}

}
void starttractor(){
digitalWrite(starterPin,HIGH);
}

void startpto(){
digitalWrite(ptoForward, HIGH);
delay(10000);
digitalWrite(ptoForward, LOW);
}

void increasethrottle(){
digitalWrite(throttleForward,HIGH);
delay(10000);
digitalWrite(throttleForward,LOW);
}

void stoptractor(){
digitalWrite(starterPin,LOW);
}

void stoppto(){
digitalWrite(ptoReverse, HIGH);
delay(10000);
digitalWrite(ptoReverse, LOW);
}

void decreasethrottle(){
digitalWrite(throttleReverse,HIGH);
delay(10000);
digitalWrite(throttleReverse,LOW);
}

Any feedback would be great. Thanks.

Hi,

The problem is that Arduino is much faster than you are.

A simple way to fire only once is to use the Click paradigm. Don't do anything before I release the switch.

That would translate to :

if (digitalRead(statePin) {
  while digitalRead(statePin) {;} //Wait for the button to be released
}

You could also take a look at this and this.

Jacques

using flags rather than code would be a better way to handle the function calls

int tractorState = 1;
int statePin = 7;

int highPin = 13;

int starterPin = 7;

int ptoForward = 4;
int ptoReverse = 3;

int throttleForward = 8;
int throttleReverse = 5;

void setup() {
  Serial.begin(9600);
  pinMode(ptoForward, OUTPUT);
  pinMode(ptoReverse, OUTPUT);
  pinMode(throttleForward, OUTPUT);
  pinMode(throttleReverse, OUTPUT);
  pinMode(starterPin, OUTPUT);
  pinMode(highPin, OUTPUT);
  pinMode(tractorState, INPUT);
}

void loop() {
  static byte startonetime;
  static byte stoponetime;

  tractorState = digitalRead(statePin);
  digitalWrite(highPin, HIGH);

  if (tractorState == 1 )

  {
    startonetime = 1;//set a flag
  }
  else if (tractorState == 0)
  {
    stoponetime = 1;//set a flag
  }

  if (startonetime == 1) {//as this code is before stop it will run this cycle
    starttractor();
    startpto();
    increasethrottle();
    startonetime = 0;// this will stop it running the cycle again
  }

  if (stoponetime == 1) {//this code will run after the start cycle if both flags are true
    stoptractor();
    stoppto();
    decreasethrottle();
    stoponetime = 0;
  }

  //this is bad coding but as you are using delays it should work
  // plus it shows you how to use flags to control code
}
void starttractor() {
  digitalWrite(starterPin, HIGH);
}

void startpto() {
  digitalWrite(ptoForward, HIGH);
  delay(10000);
  digitalWrite(ptoForward, LOW);
}

void increasethrottle() {
  digitalWrite(throttleForward, HIGH);
  delay(10000);
  digitalWrite(throttleForward, LOW);
}

void stoptractor() {
  digitalWrite(starterPin, LOW);
}

void stoppto() {
  digitalWrite(ptoReverse, HIGH);
  delay(10000);
  digitalWrite(ptoReverse, LOW);
}

void decreasethrottle() {
  digitalWrite(throttleReverse, HIGH);
  delay(10000);
  digitalWrite(throttleReverse, LOW);
}