Can't get timing/trigger quite right

Hi all, I've been working on this all day. My brain is fried. I can't seem to get the logic right. If anyone can advise, I would appreciate it SOOOO much.

Project:
Input: beam break sensor
Output: servo

Expected result:

  1. beam is broken and stays broken for more than 5 seconds, servo rotates
  2. beam is broken for less than 5 seconds, servo doesn't rotate

Actual result:

  1. If i start with breaking beam for less than 5 seconds, works as expected
  2. If I follow that with breaking the beam for longer than 5 s, works as expected.
  3. If I follow THAT by breaking for less than 5, it still moves the servo
/* 
  Reward with candy when piano has been pracited enough
*/
#include <Servo.h>

#define SENSORPIN 4
int servoPin = 7;
unsigned long previousMillis = 0;
const long interval = 5000; //the value is a number of milliseconds, ie 1 second
Servo myservo;
int angle = 0;   // servo position in degrees

// variables will change:
int sensorState = 0, lastState=0;         // variable for reading the pushbutton status

void setup() {
  pinMode(servoPin, OUTPUT); // initialize the servo as an output
  pinMode(SENSORPIN, INPUT); // initialize the sensor pin as an input
  digitalWrite(SENSORPIN, HIGH); // turn on the pullup
  
  Serial.begin(9600);
  myservo.attach(servoPin);
}

void loop(){
  sensorState = digitalRead(SENSORPIN);  // read the state of the pushbutton value
  unsigned long currentMillis = millis(); //amount of time passed since program started
  myservo.write(0); 
  if (!sensorState && lastState) { //beam broken, start counting how long the beam is broken
    Serial.println("Practice has started"); 
    previousMillis;
  }

  if (sensorState && !lastState && (currentMillis - previousMillis >= 5000)) { //beam UNbroken and we've practiced enough
    //previousMillis;
    Serial.println("Good job!");
    myservo.write(180);
    delay(1000);
    myservo.write(0);
    delay(1000);
    myservo.write(180);
    delay(1000);
    myservo.write(0); 
    previousMillis = currentMillis;
    } 
 
  lastState = sensorState;
}

Displaying previousMillis and currentMillis might show the answer. Does the millis() become too big for the unsigned long(s) to contain?

Maybe...
previousMillis = currentMillis;

Also... your current servo logic only triggers when the beam becomes "unbroken" after 5 seconds - is that what is should do? or should it trigger after 5 seconds of being broken regardless?

Good question. Either method would work. Either I practice for 30 minutes or more. and I'm alerted that I reached the time I wanted to OR I practice and then find out as a surprise if I reached time or not. :slight_smile:

I've tried previousMillis = currentMillis; everywhere so I'm wondering if it's an order of operations thing. I should probably write down the combinations I've tried because I feel like I've tried them all. :smile:

This needs to happen from the time the beam is first broken. In here...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.