Right now I have a machine that is not staying down/engaged for the set time 20-30secs.
This machine cycles 1000x per day and is hard to tell when it fails.
My thought process was if the sensor detects something, delay 3 secs and test again.
If there is nothing there send a signal to the led, else do nothing.
The sensor works as intended and flashes when an object does not stay for long enough.
The issue is that if the object is detected for more than 3 secs the light stays on until the object is removed. I have attached the code below. Any suggestion or help would be greatly appreciated.
int SensorPin = 2;
int OutputPin = 13;
void setup() {
Serial.begin(115200);
pinMode(OutputPin, OUTPUT);
pinMode(SensorPin, INPUT);
}
void loop() {
int val = digitalRead(SensorPin);
Serial.print("SensorPin Value: ");
Serial.println(val);
delay(10);// wait for 0.01s
if(val==LOW){
delay(3000);
if(val<=HIGH){
digitalWrite(OutputPin, HIGH);
}
}
else
{
digitalWrite(OutputPin, LOW);
}
}
Updated description:
We have a coating machine uses an arm to dip parts into a bath and holds them there for 30 secs as a voltage is applied to the bath. The control of this arm is PLC ladder logic and does not have a check for short cycling(not staying down for the set time). Using the IR detector I want to identify when the arm comes down that it stays there. If it does not stay down for 3 secs to send signal to the led light and exit the loop.
The failure happens instantaneously, the arm travels down and instantly travels back up.
So If the IR detects the arm(IR=LOW), delay 3 secs and check again if arm has moved(IR=HIGH) send signal to LED. If after 3 secs the arm is still there(IR=LOW) do nothing.
Ideally I would like it to end loop after failure is found and reset the Arduino to continue detecting.
This is meant to be a detection device to signal the operator there is an error. That way we can review the video footage of the PLC, hopefully finding the faulty component or narrowing it down.
Thank you for your patience this is my first time posting.
So after many try's the delay function was stopping my code.
Trying this in switch case form but still not working. As soon as an object is detected the program exits with the light on. Any suggestions.
Hopefully this code is easier to read.
#define IR_SENSOR_PIN 2 // The Infrared sensor is connected to digital pin 2
#define LED_PIN 13 // The LED is connected to digital pin 13
enum State {
OBJECT_NOT_DETECTED,
OBJECT_DETECTED_LESS_THAN_5_SEC,
OBJECT_DETECTED_MORE_THAN_5_SEC
};
State currentState = OBJECT_NOT_DETECTED;
unsigned long objectDetectedTimestamp = 1;
void setup() {
Serial.begin(9600);
pinMode(IR_SENSOR_PIN, INPUT); // Infrared sensor is used as input
pinMode(LED_PIN, OUTPUT); // LED is used as output
digitalWrite(LED_PIN, LOW); // Initial state of LED is off
}
void loop() {
int sensorValue = digitalRead(IR_SENSOR_PIN); // Read the value from the sensor
Serial.print("sensorPin Value: ");
Serial.println(sensorValue);
switch (currentState) {
case OBJECT_NOT_DETECTED:
if (sensorValue == LOW) {
objectDetectedTimestamp = millis();
currentState = OBJECT_DETECTED_LESS_THAN_5_SEC;
}
break;
case OBJECT_DETECTED_LESS_THAN_5_SEC:
if (sensorValue == HIGH) {
currentState = OBJECT_NOT_DETECTED;
} else if ((millis() - objectDetectedTimestamp) > 5000) {
currentState = OBJECT_DETECTED_MORE_THAN_5_SEC;
}
break;
case OBJECT_DETECTED_MORE_THAN_5_SEC:
digitalWrite(LED_PIN, LOW);
break;
}
// Turn on the LED and exit program if an object is detected for less than 5 seconds
if (currentState == OBJECT_DETECTED_LESS_THAN_5_SEC && (millis() - objectDetectedTimestamp) < 5000) {
digitalWrite(LED_PIN, HIGH);
while (true); // Infinite loop to stop the program
}
}
if (currentState == OBJECT_DETECTED_LESS_THAN_5_SEC && (millis() - objectDetectedTimestamp) < 5000) {
digitalWrite(LED_PIN, HIGH);
while (true); // Infinite loop to stop the program
}
The moment the switch is LOW this will evaluate and you are in your infinite loop.
Suggest you not use switch/case.
Suggest you place { and } braces on separate lines.
Infinite loops like you are using are a very bad idea.
Okay thank you!
I will remove the infinite loop.
Good to know I tried this with if/else but similar results(but had a infinite loop at the end so I will try without later today).
Thinking the issue is that millis - objectDetectedTimestamp will always be under 5 secs, satisfying both arguments even thou it has not waited long enough, not sure how to get around that.
#define IR_SENSOR_PIN 2 // The Infrared sensor is connected to digital pin 2
#define LED_PIN 13 // The LED is connected to digital pin 13
unsigned long objectDetectedTimestamp;
bool objectDetected = false;
void setup() {
pinMode(IR_SENSOR_PIN, INPUT); // Infrared sensor is used as input
pinMode(LED_PIN, OUTPUT); // LED is used as output
digitalWrite(LED_PIN, LOW); // Initial state of LED is off
}
void loop() {
int sensorValue = digitalRead(IR_SENSOR_PIN); // Read the value from the sensor
if (sensorValue == LOW) { // If an object is detected
if (!objectDetected) { // If this is the first detection
objectDetectedTimestamp = millis(); // Record the detection time
objectDetected = true;
}
else if ((millis() - objectDetectedTimestamp) > 5000) { // If the object is detected for more than 5 seconds
digitalWrite(LED_PIN, LOW); // Turn off the LED
}
}
else
{
objectDetected = false; // No object is detected, reset the flag
}
// If an object is detected for less than 5 seconds
if (objectDetected && (millis() - objectDetectedTimestamp) < 5000) {
digitalWrite(LED_PIN, HIGH); // Turn on the LED
}
}
Okay I removed the infinite loops from both versions and they work great(switch case is clunky)
Thank you for that insight!
So how would you "break" the cycle?
Current state will work for my testing, but would like the light to stay on if under 5 secs until either hitting a button or restarting the loop by hitting the reset button.
See if you can work your way through this example.
It should be quite close to what has been discussed.
#define PUSHED LOW
#define RELEASED HIGH
#define LEDon HIGH
#define LEDoff LOW
#define OBJECTdetected LOW
#define OBJECTgone HIGH
#define ENABLED true
#define DISABLED false
#define IR_SENSOR_PIN 2
#define resetSwitch 3
#define heartbeatLED 12
#define LED_PIN 13
bool detectedFlag = DISABLED;
byte lastResetSwitch = RELEASED;
byte lastIRstate = OBJECTgone;
//timing stuff
unsigned long heartbeatTime;
unsigned long checkSwitchesTime;
unsigned long objectDetectedTime;
// s e t u p ( )
//********************************************^************************************************
void setup()
{
pinMode(IR_SENSOR_PIN, INPUT_PULLUP);
pinMode(resetSwitch, INPUT_PULLUP);
pinMode(heartbeatLED, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LEDoff);
} //END of setup()
// l o o p ( )
//********************************************^************************************************
void loop()
{
//************************************************ T I M E R heartbeatLED
//is it time to toggle heartbeat LED ?
if (millis() - heartbeatTime >= 500ul)
{
//restart this TIMER
heartbeatTime = millis();
//toggle the LED
digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
}
//************************************************ T I M E R checkSwitchesTime
//is it time to read the switches and sensors ?
if (millis() - checkSwitchesTime >= 20ul)
{
//restart this TIMER
checkSwitchesTime = millis();
checkSwitches();
}
//************************************************ T I M E R object timing
//if the TIMER is enabled, has the TIMER expired ?
if (detectedFlag == ENABLED && millis() - objectDetectedTime >= 5000ul)
{
//disable this TIMER
detectedFlag = DISABLED;
digitalWrite(LED_PIN, LEDoff);
}
//************************************************
//other non blocking code goes here
//************************************************
} //END of loop()
// c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
byte state;
//******************************************* resetSwitch
state = digitalRead(resetSwitch);
//has there been a change reset switch state ?
if (lastResetSwitch != state)
{
//update to this new state
lastResetSwitch = state;
//is the reset switch pushed ?
if (state == PUSHED)
{
//disable object TIMER
detectedFlag = DISABLED;
digitalWrite(LED_PIN, LEDoff);
}
} //END of this switch
//******************************************* IR_SENSOR
state = digitalRead(IR_SENSOR_PIN);
//has there been a change in the sensor state ?
if (lastIRstate != state)
{
//update to this new state
lastIRstate = state;
//do we see an object ?
if (state == OBJECTdetected)
{
digitalWrite(LED_PIN, LEDon);
//enable TIMER
detectedFlag = ENABLED;
//start the detection TIMER
objectDetectedTime = millis();
}
//object has disappeared
else
{
//disable TIMER
detectedFlag = DISABLED;
digitalWrite(LED_PIN, LEDoff);
}
} //END of this sensor
} //END of checkSwitches()
//********************************************^************************************************
since the above is outside the condition testing the state of the IR sensor, it will be true as soon as objectDetected is set true. the 5 sec period is almost certainly < 5 sec.
look this over
#define IR_SENSOR_PIN 2
#define LED_PIN 13 // The LED is connected to digital pin 13
unsigned long objectDetectedTimestamp;
bool objectDetected = false;
enum { Idle, Pending, Detected };
int state;
// -----------------------------------------------------------------------------
void loop ()
{
unsigned long msec = millis ();
int sensorValue = digitalRead (IR_SENSOR_PIN);
delay (50); // debounce switch
if (sensorValue == LOW) {
switch (state) {
case Idle:
Serial.println ("triggered");
objectDetectedTimestamp = msec;
state = Pending;
break;
case Pending:
if ((msec - objectDetectedTimestamp) > 5000) {
digitalWrite (LED_PIN, HIGH); // Turn on the LED
Serial.println ("detected");
state = Detected;
}
break;
case Detected:
break;
}
}
else if (Idle != state) {
state = Idle;
Serial.println ("released");
digitalWrite (LED_PIN, LOW); // turn off LED
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
pinMode (IR_SENSOR_PIN, INPUT_PULLUP); // Infrared sensor is used as input
pinMode (LED_PIN, OUTPUT); // LED is used as output
digitalWrite (LED_PIN, LOW); // Initial state of LED is off
}