Counter or timer info needed to complete Project

I am looking for some direction or advise so I can learn which way to proceed to finish this coding.
Which way would be best to be able to turn off the RED LED,
After the object has come to rest, (distance <=30)
With a short time period ON to display the red as final position?
I haven't done much with timing or counter yet. FYI
Thanks for any help.

/*LCD circuit:
 * LCD RS pin to digital pin 13
 * LCD Enable pin to digital pin 12
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)*/

#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 13, 5, 4, 3, 2); //Interface pins of the LCD 
const int trig_pin=8;//ultrasonic
const int echo_pin=9;//ultrasonic
long distance,duration;
int redPin = 11;
int greenPin = 10;



void setup() {
  
lcd.begin(16,2);
lcd.setCursor(0,0); //set the cursor to column 0 and line 0
pinMode(8,OUTPUT);
pinMode(9,INPUT);
pinMode(redPin,OUTPUT);//RGB LED red 
pinMode(greenPin,OUTPUT);//RGB LED green
}

void loop() {

digitalWrite(8,HIGH);
delayMicroseconds(20);
digitalWrite(8,LOW);
delayMicroseconds(20);
duration = pulseIn(echo_pin, HIGH); //To receive the reflected signal.
distance= duration*0.034/2;
lcd.setCursor(0,0);
lcd.print("Distance is ");
lcd.setCursor(0,1); //set the cursor to column 1 and line 1
lcd.print(distance);
lcd.print("cm ");
delay(100);

if(distance <=125){
  analogWrite(greenPin,100);//green LED ON 
  analogWrite(redPin,0);
}
if (distance <=60){
 analogWrite(redPin,250);// yellow LED ON
analogWrite(greenPin,90);
}
if (distance <=30){
analogWrite(redPin,255);//red LED ON
analogWrite(greenPin,0);
}
if (distance >=175){
  analogWrite(greenPin,0);//both LED OFF
  analogWrite(redPin,0); 
}
}
/code]

How do you determine that the gadget is at rest? Is that what you’re asking?

Perhaps you should work on that before worrying about the red led. Regardless, the logic of the cascading IF statements isn’t going to work, you need each IF to test for a range like this:

if (distance > 125 ){
  analogWrite(greenPin,0);//both LED OFF
  analogWrite(redPin,0); 
}
else if ( distance <=125 && distance > 60 ){
  analogWrite(greenPin,100);
  analogWrite(redPin,0);
}
else if ( distance <=60 && distance > 30 ){
 analogWrite(redPin,250);
 analogWrite(greenPin,90);
}
else if (distance <=30){
  analogWrite(redPin,255);
  analogWrite(greenPin,0);
}

Explicit range selection is not required if the comparisons are arranged properly:

if (distance > 125 ){
 analogWrite(greenPin,0);//both LED OFF
 analogWrite(redPin,0);
}
else if (distance > 60 ){
 analogWrite(greenPin,100);
 analogWrite(redPin,0);
}
else if (distance > 30 ){
analogWrite(redPin,250);
analogWrite(greenPin,90);
}
else { //<=30
 analogWrite(redPin,255);
 analogWrite(greenPin,0);
}

It's not that I am trying to determine position with the different range setting, they are to show approx. position.
The final position will always be the same.
The different colours of the Led are visual indicators of the progress of travel.
I am looking for a way to turn off the red LED, let's say for an example, 30 seconds when the final position is obtained.

Use a state machine. Initial (armed) state and reached final position becomes Delay state with the LED off, and after 30 seconds the Final state. Add provisions to return to Initial state.

Since this is all pretty new to me could I ask , would you elaborate on that procedure please.
Perhaps direct me to where I might read up on what you are describing.
I have tried as many things that I have read about , primarily trying to use the distance data or trying to figure out if it was possible to use the info from analog read. Without any success.

Thanks

Looks like I just committed a cardinal sin of this forum.
Asking for guidance , before doing some research on the question asked. My Bad.
I will do my reading and follow up with questions later.

Compiles, not tested:

/*LCD circuit:
 * LCD RS pin to digital pin 13
 * LCD Enable pin to digital pin 12
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)*/

#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 13, 5, 4, 3, 2); //Interface pins of the LCD 

const int trig_pin=8;//ultrasonic
const int echo_pin=9;//ultrasonic
float
    distance;
unsigned long
    echo_time;

int redPin = 11;
int greenPin = 10;



void setup() 
{  
    lcd.begin(16,2);
    lcd.setCursor(0,0); //set the cursor to column 0 and line 0
    lcd.print("Distance is ");
    
    pinMode( trig_pin,OUTPUT );
    pinMode( echo_pin,INPUT );
    pinMode( redPin,OUTPUT );//RGB LED red 
    pinMode( greenPin,OUTPUT );//RGB LED green    
    
}//setup
 
void loop() 
{
    UpdateDistance();
    UpdateLCD();
    LEDStateMachine();

}//loop

void UpdateLCD( void )
{
    static unsigned long
        timeLCD = 0;
    unsigned long
        timeNow;

    timeNow = millis();
    if( timeNow - timeLCD < 300 )
        return;
    timeLCD = timeNow;

    lcd.setCursor(0,1); //set the cursor to column 1 and line 1
    lcd.print(distance);
    lcd.print("cm ");
    
}//UpdateLCD

void UpdateDistance( void )
{
    static unsigned long
        timeUltrasound = 0;
    unsigned long
        timeNow;

    timeNow = millis();
    if( timeNow - timeUltrasound < 100 )
        return;
    timeUltrasound = timeNow;

    digitalWrite(trig_pin,HIGH);
    delayMicroseconds(20);
    digitalWrite(trig_pin,LOW);
    delayMicroseconds(20);
    echo_time = pulseIn(echo_pin, HIGH); //To receive the reflected signal.
    distance= (float)echo_time*0.034/2.0;
    
}//UpdateDistance

// LED state machine states
#define ST_INIT             0
#define ST_INDETERMINATE    1
#define ST_DIST_FAR         2
#define ST_DIST_GREEN       3
#define ST_DIST_YELLOW      4
#define ST_DIST_RED         5
#define ST_RED_TIMER        6
#define ST_STOPPED          7
//
void LEDStateMachine( void )
{
    byte
        temp;
    static float
        fStopDist = 0.0;
    static byte
        stateLEDs = ST_INIT;
    static unsigned long
        timeRedLED = 0;
    
    switch( stateLEDs )
    {
        case    ST_INIT:
            //initialize the state
            stateLEDs = DistanceToState();
            
        break;
        
        case    ST_INDETERMINATE:
        case    ST_DIST_FAR:
            //far distance or indeterminate (0.0, somewhere between 125 and 175...)
            analogWrite( greenPin,0 );//both LED OFF
            analogWrite( redPin,0 ); 
            stateLEDs = DistanceToState();
            
        break;

        case    ST_DIST_GREEN:
            analogWrite( greenPin,100 );//green LED ON 
            analogWrite( redPin,0 );
            stateLEDs = DistanceToState();
            
        break;

        case    ST_DIST_YELLOW:
            analogWrite( redPin,250 );// yellow LED ON
            analogWrite( greenPin,90 );
            stateLEDs = DistanceToState();
            
        break;

        case    ST_DIST_RED:
            //when we enter the "red zone":
            // - grab the current distance
            // - set the LED red
            // - grab the current millis count
            // - move to the red timer state
            fStopDist = distance;
            analogWrite( redPin,255 );//red LED ON
            analogWrite( greenPin,0 );
            timeRedLED = millis();
            stateLEDs = ST_RED_TIMER;
            
        break;

        case    ST_RED_TIMER:
            //check to see if we're still in the "red zone"
            if( distance == 0 || distance > 30 )
                //if not, reset stateLEDs
                stateLEDs = DistanceToState();
            else
            {
                //has the distance changed more than 2cm from when we hit red?
                if( abs( distance - fStopDist ) > 2.0 )
                {
                    //yes...reset the "initial" distance and red timer
                    fStopDist = distance;
                    timeRedLED = millis();
                    
                }//if

                //check if 30-sec has passed
                if( (millis() - timeRedLED) > 30000 )
                {
                    //if so, turn off the LED, then enter the "STOPPED" state
                    analogWrite( redPin,0 );//red LED OFF
                    analogWrite( greenPin,0 );
                    
                    stateLEDs = ST_STOPPED;
                                        
                }//if
                    
            }//else
            
        break;

        case    ST_STOPPED:
            //just wait for the distance to indicate we've moved out of the "red zone"
            //then go to that state
            temp = DistanceToState();
            if( temp > 30 )
                stateLEDs = temp;
            
        break;
        
    }//switch
    
}//LEDStateMachine

//convert a distance to a value usable in the state machine
byte DistanceToState( void )
{
    if( distance >= 175.0 )
        return ST_DIST_FAR;
    else if( distance <= 125.0 && distance > 60.0 )
        return ST_DIST_GREEN;
    else if( distance <= 60.0 && distance > 30.0 )
        return ST_DIST_YELLOW;
    else if( distance <= 30.0 && distance > 0.0 )
        return ST_DIST_RED;
    else
        return ST_INDETERMINATE;
    
}//DistanceToState

Most references on state machines are awful. Way too technical and tied up in diagram symbols.

This is the best one I know of... State Machine

First of all I would like to Thank Morgan S, it looks like a good web site for understandable information at my level.
Blackfin That's more than I ever though of getting from this forum Thanks.

I compiled and uploaded your code to my UNO, Here is what I see it doing.
As the different zones are entered, the appreciate LED colour lights.
If it runs time (30seconds) in the red zone the red LED extinguishes alright , then subsequent movement into any zone shows the distance measurement with none of the colours lighting in the LED.
Another observation is, if movement is detected any where in the scan zone initially and does remain until timeout, the red led stays lit and randomly blinks . Also any movement through the scan zone will lit the appreciate LED colour.

Any thoughts on these would be appreciated.

Thanks

Describe what behaviour you would like to get instead. Describe it using state names, e.g. from state X the automaton should move to state Y instead of state Z.

krobert35:
I compiled and uploaded your code to my UNO, Here is what I see it doing.
As the different zones are entered, the appreciate LED colour lights.
If it runs time (30seconds) in the red zone the red LED extinguishes alright , then subsequent movement into any zone shows the distance measurement with none of the colours lighting in the LED.

Had a look at the "stopped" state and noticed an error. Copy and paste this piece of code over the existing ST_STOPPED state code:

        case    ST_STOPPED:
            //just wait for the distance to indicate we've moved out of the "red zone"
            //then go to that state
            if( distance  > 30 )
                stateLEDs = DistanceToState();
            
        break;

Another observation is, if movement is detected any where in the scan zone initially and does remain until timeout, the red led stays lit and randomly blinks . Also any movement through the scan zone will lit the appreciate LED colour.

Not sure what you're asking here, sorry. Your OP asked: "Which way would be best to be able to turn off the RED LED, After the object has come to rest, (distance <=30)"

To check for coming to a rest I look for the distance value to remain within +/- 2cm of the value it was when the "red zone" state was entered. If the distance value changes while timing the red LED shut-off:

  • if the distance goes to 0.0 (indicating nothing in range of the ultrasound or something too close to the ultrasound the red state is exited and the INDETERMINATE or FAR states entered respectively (which happen to do the same thing; turn off the LEDs.)

  • If the distance measurement remains less than or equal to 30 and greater than 0 but changes by more than +/-2cm the timer is reset; the state remains "red" but the timing period is extended until distance changes are seen to fall within that window. Here I'm looking for the thing to be "at rest" as you say.

Once the red LED is off, the intent was to sit in the "stop" state, monitoring the distance and when it showed a value that was outside the red zone, to execute that state. It was late and I made an error, misusing the return value from my DistanceToState() function to compare against a distance (that's the fix above.)

I don't go to the extent in the STOPPED state to look for small movements; only if it exits the red zone.

Assuming the fix restores otherwise normal LED operation when the red zone is exited, can you clarify what behavior you want?

The red zone eg. stopped state, come to rest. Will be a distance to be determined later.
Then final position won't always be the same position varying by a few cm each time.
So <= 30 will define it adequately.

I have uploaded your patched code and the random LED no longer exist. The code works as intended
for indicating the positions, repeatedly, until the object remains in the red zone for longer than the 30 seconds . After the red LED isn't lit , movement is indicated by the distance measurement but the LED doesn't lit again.

It is restored again with a power down of the UNO.

krobert35:
The red zone eg. stopped state, come to rest. Will be a distance to be determined later.
Then final position won't always be the same position varying by a few cm each time.
So <= 30 will define it adequately.

I have uploaded your patched code and the random LED no longer exist. The code works as intended
for indicating the positions, repeatedly, until the object remains in the red zone for longer than the 30 seconds . After the red LED isn't lit , movement is indicated by the distance measurement but the LED doesn't lit again.

It is restored again with a power down of the UNO.

This is interesting. I can't see an immediate reason for this (the lights staying off.) I added some serial debug messages to the state machine if you're willing to load the code up and report back what it's saying:

/*LCD circuit:
 * LCD RS pin to digital pin 13
 * LCD Enable pin to digital pin 12
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)*/

#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 13, 5, 4, 3, 2); //Interface pins of the LCD 

const int trig_pin=8;//ultrasonic
const int echo_pin=9;//ultrasonic
float
    distance;
unsigned long
    echo_time;

int redPin = 11;
int greenPin = 10;



void setup() 
{  
    Serial.begin( 9600 );
    
    lcd.begin(16,2);
    lcd.setCursor(0,0); //set the cursor to column 0 and line 0
    lcd.print("Distance is ");
    
    pinMode( trig_pin,OUTPUT );
    pinMode( echo_pin,INPUT );
    pinMode( redPin,OUTPUT );//RGB LED red 
    pinMode( greenPin,OUTPUT );//RGB LED green    
    
}//setup
 
void loop() 
{
    UpdateDistance();
    UpdateLCD();
    LEDStateMachine();

}//loop

void UpdateLCD( void )
{
    static unsigned long
        timeLCD = 0;
    unsigned long
        timeNow;

    timeNow = millis();
    if( timeNow - timeLCD < 300 )
        return;
    timeLCD = timeNow;

    lcd.setCursor(0,1); //set the cursor to column 1 and line 1
    lcd.print(distance);
    lcd.print("cm ");
    
}//UpdateLCD

void UpdateDistance( void )
{
    static unsigned long
        timeUltrasound = 0;
    unsigned long
        timeNow;

    timeNow = millis();
    if( timeNow - timeUltrasound < 100 )
        return;
    timeUltrasound = timeNow;

    digitalWrite(trig_pin,HIGH);
    delayMicroseconds(20);
    digitalWrite(trig_pin,LOW);
    delayMicroseconds(20);
    echo_time = pulseIn(echo_pin, HIGH); //To receive the reflected signal.
    distance= (float)echo_time*0.034/2.0;
    
}//UpdateDistance

// LED state machine states
#define ST_INIT             0
#define ST_INDETERMINATE    1
#define ST_DIST_FAR         2
#define ST_DIST_GREEN       3
#define ST_DIST_YELLOW      4
#define ST_DIST_RED         5
#define ST_RED_TIMER        6
#define ST_STOPPED          7
//
void LEDStateMachine( void )
{
    float
        temp;
    static float
        fStopDist = 0.0;
    static byte
        stateLEDs = ST_INIT;
    static unsigned long
        timeRedLED = 0;
    
    switch( stateLEDs )
    {
        case    ST_INIT:
            //initialize the state
            stateLEDs = DistanceToState();
            
        break;
        
        case    ST_INDETERMINATE:
        case    ST_DIST_FAR:
            if( stateLEDs == ST_INDETERMINATE )
                Serial.println( "State ST_INDETERMINATE" );
            else
                Serial.println( "State ST_DIST_FAR" );
            
            
            //far distance or indeterminate (0.0, somewhere between 125 and 175...)
            analogWrite( greenPin,0 );//both LED OFF
            analogWrite( redPin,0 ); 
            stateLEDs = DistanceToState();
            
        break;

        case    ST_DIST_GREEN:
            Serial.println( "State ST_DIST_GREEN" );
            analogWrite( greenPin,100 );//green LED ON 
            analogWrite( redPin,0 );
            stateLEDs = DistanceToState();
            
        break;

        case    ST_DIST_YELLOW:
            Serial.println( "State ST_DIST_YELLOW" );
            analogWrite( redPin,250 );// yellow LED ON
            analogWrite( greenPin,90 );
            stateLEDs = DistanceToState();
            
        break;

        case    ST_DIST_RED:
            Serial.println( "State ST_DIST_RED" );
            //when we enter the "red zone":
            // - grab the current distance
            // - set the LED red
            // - grab the current millis count
            // - move to the red timer state
            fStopDist = distance;
            analogWrite( redPin,255 );//red LED ON
            analogWrite( greenPin,0 );
            timeRedLED = millis();
            stateLEDs = ST_RED_TIMER;
            
        break;

        case    ST_RED_TIMER:
            Serial.println( "State ST_RED_TIMER" );
            //check to see if we're still in the "red zone"
            if( distance == 0.0 || distance > 30.0 )
                //if not, reset stateLEDs
                stateLEDs = DistanceToState();
            else
            {
                //has the distance changed more than 2cm from when we hit red?
                if( abs( distance - fStopDist ) > 2.0 )
                {
                    //yes...reset the "initial" distance and red timer
                    fStopDist = distance;
                    timeRedLED = millis();
                    
                }//if

                //check if 30-sec has passed
                if( (millis() - timeRedLED) > 30000 )
                {
                    //if so, turn off the LED, then enter the "STOPPED" state
                    analogWrite( redPin,0 );//red LED OFF
                    analogWrite( greenPin,0 );
                    
                    stateLEDs = ST_STOPPED;
                                        
                }//if
                    
            }//else
            
        break;

        case    ST_STOPPED:
            //just wait for the distance to indicate we've moved out of the "red zone"
            //then go to that state
            Serial.println( "State ST_STOPPED" );
            Serial.print( "Distance :" ); Serial.println( distance, 2 );
            if( distance  > 30.0 )
                stateLEDs = DistanceToState();
                
            Serial.print( "stateLEDs :" ); Serial.println( stateLEDs );
            
        break;
        
    }//switch
    
}//LEDStateMachine

//convert a distance to a value usable in the state machine
byte DistanceToState( void )
{
    if( distance >= 175.0 )
        return ST_DIST_FAR;
    else if( distance <= 125.0 && distance > 60.0 )
        return ST_DIST_GREEN;
    else if( distance <= 60.0 && distance > 30.0 )
        return ST_DIST_YELLOW;
    else if( distance <= 30.0 && distance > 0.0 )
        return ST_DIST_RED;
    else
        return ST_INDETERMINATE;
    
}//DistanceToState

Well it WORKS
I have tried repeatedly and it performs correctly.

Many Thanks for your Effort.

This will certainly give me a good example to learn from since I know the function intended.

Thanks again
K.