New to arduino, need help with this code related to ir sensor and motor

I am using an IR sensor, arduino nano and motor, if IR sensor input is above 500(pn the analog 1023 system) for 0.5 second then the motor should turn on for 1 second then turn off. There should be a cooldown of 3 seconds. Within those 3 seconds the motor should not turn on even if the input is above 500 for more 0.5 seconds. I dont know how to generate requirement for input being above 500 for more than 1 second and I am not confident about rest of the code.

const int IR_PIN = A1;
const int MOTOR_PIN = 10;
const int MINI = 500; //minimum input received by sensor to send output in 1023 system 

void setup() {
  Serial.begin(9600);
  pinMode(MOTOR_PIN, OUTPUT);
  pinMode(IR_PIN, INPUT);
  
}

void loop() {
  // making the ir input a variable
  int input = analogRead(IR_PIN);
  
  // if sensor value mini than "MINI" for 1 second Motor turns on, what code is required to complete the function
  if (input > MINI)
    
    digitalWrite(MOTOR_PIN, HIGH);
    delay(01s); //motor should be turned on for 1 second
    digitalWrite(MOTOR_PIN, LOW); //motor should be turned off after 1 second
    delay(3s); //3 seconds cooldown before the system can be activated again
    
  //the motor should be off when input value is less than mini
  else if (input < MINI)
    digitalWrite(LED_PIN, LOW);

If you have any suggestions or additions pls help

the code structure you describe would work well with a state machine approach

what is state machine approach?

that's a great google search question :slight_smile:

if you read French you can have a look at my (tutorial) (Google translate would probably work as well to read that)

your requirements could look something like this

I am not understanding how can I integrate the input>500 for 500 milliseconds requirement in my code

not so trivial an exercise

consider

#undef MyHW
#ifdef MyHW
const int IR_PIN    = A0;
#else
const int IR_PIN = A1;
#endif

const int MOTOR_PIN = 10;
const int Thresh = 500;

enum { Off = HIGH, On = LOW };

enum { OneSec = 1000, ThreeSec = 3000 };
unsigned long period;
unsigned long msecLst;
unsigned long msec;

bool tmrAct;
int  irLst;

char s [50];

// -----------------------------------------------------------------------------
enum { ST_IDLE, ST_PEND, ST_ACT, ST_COOLDOWN };
const char *stStr [] = {
    "ST_IDLE",
    "ST_PEND",
    "ST_ACT",
    "ST_COOLDOWN",
};

enum { STIM_NONE, STIM_TMR, STIM_IR_ACT, STIM_IR_NOT };
const char *stimStr [] = {
    "STIM_NONE",
    "STIM_TMR",
    "STIM_IR_ACT",
    "STIM_IR_NOT",
};

int state = ST_IDLE;

void
stMach (
    int stim )
{
    sprintf (s, " state %d %s, stim %d %s",
            state, stStr [state], stim, stimStr [stim]);
    Serial.println (s);
    
    switch (state) {
    case ST_IDLE :
        if (STIM_IR_ACT == stim)  {
            msecLst = msec;
            tmrAct  = true;
            period  = OneSec;
            state   = ST_PEND;
        }
        break;

    case ST_PEND :
        if (STIM_IR_NOT == stim)  {
            tmrAct  = false;
            state   = ST_IDLE;
        }
        else if (STIM_TMR == stim)  {
            msecLst = msec;
            period  = OneSec;
            tmrAct  = true;
            state   = ST_ACT;

            digitalWrite (MOTOR_PIN, On);
        }
        break;

    case ST_ACT :
        if (STIM_TMR == stim)  {
            digitalWrite (MOTOR_PIN, Off);

            msecLst = msec;
            period  = ThreeSec;
            tmrAct  = true;
            state   = ST_COOLDOWN;
        }
        break;

    case ST_COOLDOWN :
        if (STIM_TMR == stim)
            state   = ST_IDLE;
        break;
    }
}

// -----------------------------------------------------------------------------
void loop ()
{
    msec = millis ();

    if (tmrAct &&  (msec - msecLst) > period)  {
        tmrAct = false;
        stMach (STIM_TMR);
    }

    int ir = analogRead (IR_PIN);
    if (5 < abs(irLst - ir)) {
        irLst = ir;

        if (Thresh < ir)
            stMach (STIM_IR_ACT);
        else
            stMach (STIM_IR_NOT);

        Serial.println (ir);
    }
}

// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);

    pinMode (MOTOR_PIN, OUTPUT);
    digitalWrite (MOTOR_PIN, Off);

    pinMode (IR_PIN, INPUT);
    irLst = analogRead (IR_PIN);
}

thats the most confusing thing I have seen all day

it's still early. think about it

Did you read about state machines yet ?

For extra information and examples on how to deal with time, look at Using millis() for timing. A beginners guide and Several things at the same time


The state machine diagram I shared above can really be implement by defining a state for each circle - so you have 4 states

enum {READY, IR_ON, MOTOR_ON, COOL_DOWN} currentState = READY;

and testing for each state all the arrows conditions leaving that state.

It's a simple translation of the diagram and the code would look like this

(typed here, fully untested)

const byte irPin = A1;
const byte motorPin = 10;
const int irTheshold = 500;
const unsigned long irDelay = 500; // ms
const unsigned long motorDelay = 1000; // ms
const unsigned long coolDownDelay = 3000; // ms

enum {READY, IR_ON, MOTOR_ON, COOL_DOWN} currentState = READY;

void motorOn() {
  digitalWrite(motorPin, HIGH);
}

void motorOff() {
  digitalWrite(motorPin, LOW);
}

void stateMachine() {
  // Some code was there before the double posting
}

void setup() {
  Serial.begin(115200); Serial.println();
  pinMode(motorPin, OUTPUT);
  pinMode(irPin, INPUT);I
}

void loop() {
  stateMachine();
}

Thanks, I kind of get it

here's a cruder approach

#undef MyHW
#ifdef MyHW
const int IR_PIN = A0;
#else
const int IR_PIN = A1;
#endif

const int MOTOR_PIN = 10;
const int Thresh    = 500;

enum { Off = HIGH, On = LOW };

unsigned long period;
unsigned long msecLst;
unsigned long msec;

bool tmrAct;
int  irLst;

char s [50];

// -----------------------------------------------------------------------------
void loop ()
{
    msec = millis ();

    if (tmrAct &&  (msec - msecLst) > period)  {
        Serial.println ("timer");

        tmrAct = false;

        digitalWrite (MOTOR_PIN, On);
        delay (1000);
        digitalWrite (MOTOR_PIN, Off);
        delay (3000);                   // cool down
        Serial.println (" timer done");
    }

    int ir = analogRead (IR_PIN);
    if (5 < abs(irLst - ir)) {
        irLst = ir;

        if (Thresh < ir)  {
            tmrAct = true;
            msecLst = msec;
            period  = 500;
        }
        else
            tmrAct = false;
            
        Serial.println (ir);
    }
}

// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);

    pinMode (MOTOR_PIN, OUTPUT);
    digitalWrite (MOTOR_PIN, Off);

    pinMode (IR_PIN, INPUT);
    irLst = analogRead (IR_PIN);
}

@prik0307
Why do you start second thread about the same problem? Cross-posting is against the Arduino forum rules. The reason is that duplicate posts can waste the time of the people trying to help.

I am making a touchless sanitiser dispenser using arduino nano, I am very new to arduino coding. I am using ir sensor, nano and water motor. If my ir sensor get threshold of higher than 500(in analog 1023 system) for 500 miliseconds than the motor turns on for 500 miliseconds and turns off. There will be a 3 second or 3000 milisecond cooldown between each pump. This is the code I have written here and there is an error in the else if command on line 28. Can somebody help

const int IR_PIN = A1;
const int MOTOR_PIN = 10;
const int MINI = 500; //minimum input received by sensor to send output in 1023 system 

void setup()
 {
   Serial.begin(9600);
   pinMode(MOTOR_PIN, OUTPUT);
   pinMode(IR_PIN, INPUT);
 }

void loop() 
{
 int input = analogRead(IR_PIN); // making the ir input a variable
  
  // if sensor value mini than "MINI" for 1 second Motor turns on
  if (input > MINI);
 {
   delay(500);
   if (input > MINI);
    { 
     digitalWrite(MOTOR_PIN, HIGH);
     delay(500); //motor should be turned on for 0.5 seconds
     digitalWrite(MOTOR_PIN, LOW); //motor should be turned off
     delay(2000); // 2 seconds cooldown before the system can be activated again
    }
    
  else if(input > MINI);  //the motor should be off when input value is less than mini
    {
      delay(500);
      if (input < MINI);
       {
       digitalWrite(MOTOR_PIN, LOW);
       }
      
    }
}
}
    if (input > MINI);

Your problem is caused by the semicolon on this and other lines where you use an if

The semicolon is the only code executed when the if returns true. Delete it, and others like it

Your suggestion worked, ty so much
Just wanted to ask, will my code work for my sanitizer dispenser because I lack the ability to test it currently and I don't trust my code

Sounds good. Do you understand why the semicolons caused problems ?

I did not look to see whether it worked as required

You can test it by adding Serial.print()s at relevant points where so that you can see what is going on

I debugged it and it worked after removing semi-colons from the if and else if commands. what is serial.print()s ?

At appropriate points in the code print messages

void loop()
{
  int input = analogRead(IR_PIN); // making the ir input a variable
  Serial.print("input = ");
  Serial.println(input);
  // if sensor value mini than "MINI" for 1 second Motor turns on
  if (input > MINI)
  {
    Serial.println("input > MINI - waiting 500mS");
    delay(500);

and so on

nice, ty

The trick is to print what is important and to print a text label so that you know what is being printed

Once you know that some parts work, such as reading the input, then you don't have to print that value any more

Incidentally, what sort of IR sensor are you using and are you sure that it has an analogue output ? Please post a link to the sensor