Stuck in basics (newbee)

Hi

I´m going to start and apologize. I´m a totally beginner on this. My projekt is to do a automatic doggie door but I am stuck.

My first attempt looked like this:

const int buttonPin = 2;    // Button
const int forward = 7;      // Forward
const int backward = 6;     // Backword

int buttonState = 0;         

void setup() {
  pinMode(forward, OUTPUT);
  pinMode(backward, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn on:
    digitalWrite(forward, LOW);
    digitalWrite(backward, HIGH);
    delay(5000);

     digitalWrite(forward, HIGH);
     digitalWrite(backward, HIGH);
     delay(5000);

     digitalWrite(forward, HIGH);
     digitalWrite(backward, LOW);
     delay(5500);

  } else {
    // When OFF:
    digitalWrite(forward, HIGH);
    digitalWrite(backward, HIGH);
  }
}

It works but... I don´t want it to crush my dogs :) So I worked out a genues plan (so I thought) that I wanted it to open if the button whas pressed again. But that is not possible with delay. Then I turned to millis and now I´m stuck.

This is what I got:

class Flasher
{

  int ledPin;      
  long OnTime;     
  long OffTime;    

  int ledState;                 
  unsigned long previousMillis;   

  public:
  Flasher(int pin, long on, long off)
  {
  ledPin = pin;
  pinMode(ledPin, OUTPUT);     
    
  OnTime = on;
  OffTime = off;
  
  ledState = LOW; 
  previousMillis = 0;
  }

  void Update()
  {
    
    unsigned long currentMillis = millis();
     
    if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
    {
      ledState = LOW;  
      previousMillis = currentMillis;  
      digitalWrite(ledPin, ledState);  
    }
    else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
    {
      ledState = HIGH;  // turn it on
      previousMillis = currentMillis;   
      digitalWrite(ledPin, ledState);   
    }
  }
};

Flasher led1(12, 100, 400);
Flasher led2(13, 350, 350);
Flasher led3(8, 500, 100);

void setup()
{
}

void loop()

{
  if(digitalRead(2) == HIGH)
  {
  led1.Update();
  led2.Update();
  }

  else if(digitalRead(2) == LOW)
  {
  led3.Update();
  }
  
  
}

What I want it to do is: When button is pressed. It should open, stop, close, stop. If button is pressed again no matter where in the sequense it is, beginn from start and open again.

Youtube video

Best Regards Jerry

What door? Your code seems to be flashing three separate LEDs. I can see nothing to do with moving any door.

Perhaps some explanation of how the door is connected to the Arduino and actually moved would help.

Steve

slipstick: What door? Your code seems to be flashing three separate LEDs. I can see nothing to do with moving any door.

Perhaps some explanation of how the door is connected to the Arduino and actually moved would help.

Steve

Hi

Exactly, I was playing with LED´s instead of accuators just to lern how to get it to work.

Obvioustly I didn´t :)

But the basics is the same. If I can get the LED´s to work, then I can get the accuator to work.

|500x244

This is how it is setup for the moment. The relaybord is not in use for the moment.

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

...R

JerrySWE: This is what I got:

...and what does it do, or not do?

aarg: ...and what does it do, or not do?

Of course, I will try to explain.

The first program worked fine with accuators, but used delay.

What I am trying to do now is to use millis instead. "What I got" is my attempt to use millis with LED´s. It work´s fine and update LED on pin 12 and 13 when the button is pressed and run LED on pin 8 constantly in the orders of the preset millis.

My problem now is that when I press the button it is updateing LED 12 and 13 as it should. But as soon as I let go of the button it stops. I want it to play the whole sequence with just one touch on the button, not stop just because I release pressure of the button. And if the button is pressed again dureing the sequence I want it to stop and start over from the beginning again.

Study the state change example in the IDE examples.

I want it to play the whole sequence with just one touch on the button, not stop just because I release pressure of the button

It sounds like you need to detect when the button [u]becomes[/u] pressed rather than when it [u]is[/u] pressed. Have a look at the StateChangeDetection example in the IDE

I see a state machine in your future. When you've got a handle on detecting changes, check out the switch/case pair.

UKHeliBob: It sounds like you need to detect when the button [u]becomes[/u] pressed rather than when it [u]is[/u] pressed. Have a look at the StateChangeDetection example in the IDE

Thanks

I have read about StateChangeDetection but I do not really understand how I will make it work. Do you have any examples of how i get it in my cod?

Best regards Jerry

Hi, Can I suggest you make some variable names more descriptive.

const int forward = 7;      // Forward
const int backward = 6;     // Backword

To;

const int DoorforwardPin = 7;      // Forward
const int DoorbackwardPin = 6;     // Backword

It helps .. Tom... :)

What I want it to do is: When button is pressed. It should open, stop, close, stop. If button is pressed again no matter where in the sequense it is, beginn from start and open again.

enum State {
  IDLE, OPENING, PAUSING, CLOSING
} state= IDLE;

uint32_t start_time;


loop() {
  if(the button is pressed) {
    if(state == CLOSING) {
      turn off the closing actuator
    }
    state = OPENING;
    start_time = millis();
  }  
  else {
    switch(state) {
    case IDLE:
      // do nothing
      break;

    case OPENING:
      if(millis()-start_time >= opening time) {
        turn off the opening actuator;
        start_time = millis();
        state = PAUSING;
      }
      // else do nothing
      break;

    case PAUSING:
      if(millis()-start_time >= pause time) {
        turn on the closing actuator;
        start_time = millis();
        state = CLOSING;
      }
      // else do nothing
      break;

    case CLOSING:
      if(millis()-start_time >= close time) {
        turn off the closing actuator;
        state = IDLE;
      }
      // else do nothing
      break;
    }
  }

}

PaulMurrayCbr: ``` enum State {   IDLE, OPENING, PAUSING, CLOSING } state= IDLE;

uint32_t start_time;

loop() {   if(the button is pressed) {     if(state == CLOSING) {       turn off the closing actuator     }     state = OPENING;     start_time = millis();   }    else {     switch(state) {     case IDLE:       // do nothing       break;

    case OPENING:       if(millis()-start_time >= opening time) {         turn off the opening actuator;         start_time = millis();         state = PAUSING;       }       // else do nothing       break;

    case PAUSING:       if(millis()-start_time >= pause time) {         turn on the closing actuator;         start_time = millis();         state = CLOSING;       }       // else do nothing       break;

    case CLOSING:       if(millis()-start_time >= close time) {         turn off the closing actuator;         state = IDLE;       }       // else do nothing       break;     }   }

}

It looks exactly like what I want.

But I do not really understand how I'll make it work.

JerrySWE: It looks exactly like what I want.

But I do not really understand how I'll make it work.

It takes time and study. You'll get it.

aarg: It takes time and study. You'll get it.

What I do not understand is how uint32_t and enum work the rest I have begun to understand, I think.

I have read lots of articles about state machines and made a hilarous try, like this.

enum State {IDLE, OPENING, PAUSING, CLOSING
} state= IDLE;  //?

uint32_t start_time; //?

const int buttonPin = 2;    // Button
const int forward = 7;      // Forward
const int backward = 6;     // Backword

int buttonState = 0;
int forwardState = HIGH:
int backwordState = HIGH:

long forwardInterval = 3000; //On time forward
long backwordInterval = 3000; //On time backword
unsigned long currentMillis = 0; //?


void setup()
{
    pinMode(forward, OUTPUT); //Sets pin 7 to output
    pinMode(backword, OUTPUT); //Sets pin 6 to output 
    pinMode(buttonPin, INPUT); //Sets buttonPin to input
    
    currentMillis = millis();
}

void loop () {
  if(buttonPin = HIGH) {
    if(state == CLOSING) {
      turn off the closing actuator
    }
    state = OPENING;
    start_time = millis();
  }  
  else {
    switch(state) {
    case IDLE:
      // do nothing
      break;

    case OPENING:
      if(millis()-start_time >= opening time) {
        turn off the opening actuator;
        start_time = millis();
        state = PAUSING;
      }
      // else do nothing
      break;

    case PAUSING:
      if(millis()-start_time >= pause time) {
        turn on the closing actuator;
        start_time = millis();
        state = CLOSING;
      }
      // else do nothing
      break;

    case CLOSING:
      if(millis()-start_time >= close time) {
        turn off the closing actuator;
        state = IDLE;
      }
      // else do nothing
      break;
    }
  }

}

I'm unsure if I need void OPENING, void CLOSING etc or if I do not need them due to Enum?

JerrySWE:
What I do not understand is how uint32_t and enum work

Did you Google them?

OPENING and CLOSING are the names of specific states within the state machine. They are NOT functions, they are states of type enum (an enumerated ‘variable’ type). No ‘void’ needed.

aarg:
Did you Google them?

Yes I have.

What I understand is enum = #define but I’m not quite sure what the differences are.

uint32_t start_time; I do not find anything about. At least nothing that makes me understand.

Power_Broker:
OPENING and CLOSING are the names of specific states within the state machine. They are NOT functions, they are states of type enum (an enumerated ‘variable’ type). No ‘void’ needed.

Thank you, that was exactly what I wanted to know

Okay. I think I'm starting to get hold of it.

I'm not receiving an error message, but the program does not work as it should. What happens is that both relays become active, then nothing more.

enum State {IDLE, OPENING, PAUSING, CLOSING
} state = IDLE;

uint32_t start_time;

const uint32_t OPENING_ms = 3L * 1000L;
const uint32_t PAUSING_ms = 2L * 1000L;
const uint32_t CLOSING_ms = 3L * 1000L;

const int buttonPin = 2;    // Button
const int forwardPin = 7;      // Forward
const int backwardPin = 6;     // Backword

int buttonState = 0;


void setup(){
    Serial.begin(9600);
    
    pinMode(forwardPin, OUTPUT); //Sets pin 7 to output
    pinMode(backwardPin, OUTPUT); //Sets pin 6 to output 
    
    pinMode(buttonPin, INPUT_PULLUP); //Sets buttonPin to input

    state = IDLE;
    start_time = millis();
}

//boolean ButtonWasOn() {
  //search for buttom press
//  return digitalRead(buttonPin) == LOW;
//}

void loop () {

  buttonState = digitalRead(buttonPin);
  
   if(buttonState == HIGH) {
    if(state == CLOSING) {
      //turn off the closing actuator
    }
    state = OPENING;
    start_time = millis();
  }  
  else {
    switch(state) {
    case IDLE:
      // do nothing
      break;

    case OPENING:
      if(millis()-start_time >= OPENING_ms) {
        //turn off the opening actuator
        start_time = millis();
        state = PAUSING;
      }
      // else do nothing
      break;

    case PAUSING:
      if(millis()-start_time >= PAUSING_ms) {
        //turn on the closing actuator
        start_time = millis();
        state = CLOSING;
      }
      // else do nothing
      break;

    case CLOSING:
      if(millis()-start_time >= CLOSING_ms) {
        //turn off the closing actuator
        state = IDLE;
      }
      // else do nothing
      break;
    }
  }

}