Help with timers

Hey everyone, I need some help if you could with my project. What I have here is an arcade machine that I have built that runs off a raspberry pi. To power that on and off I have my Uno, that runs off an HC-SR04 disctance sensor.

The idea is that when the UNO detects a player has approached the console say <50cm, the UNO pauses for a few seconds to confirm the person is actually standing there and not just passing by, then truns the PI on and boots the arcade up.

When the player walks away, the UNO reads that the player is not there anymore say >50cm and then pauses for 15 seconds in case the player has gone to grab their drink etc, then powers the system down.

In each case during that pause time the uno should be taking readings from the sensor and ensuring that that threshold of 50cm is consistently either higher or lower in that time so as not to power off or on unexpectedly.

what i am finding is that the UNO is constantly reading the distance, and rapiddly flicking the relay on or off ignoring the timers, i also finding that the sensor may read say:
5,5,5,6,6,4,5,5,2357,5,4,5,5...etc
Since its not paying attention to the timer it flicks the relay off thus turning everything off for that brief millisecond where it threw a bizzare distance read.

how can i slow the distance reads, to eliminate those faulty distance reads, and can you see where the timers are not working correctly?

I am sure this code can be cleaner, I am not very well versed in code. What I have here is lots of snippets that I have been pinching from one tutorial or another. I have been working on this for months with variations to this here and there and no luck getting the result i am after. I suspect that the solution will be a fairly simple syntax or formatting issue, but i don't really know.

note: in the code i have attached i have stripped out the leds fade up when powerd on and fade down when powering off, to make this easier for you guys to look through. so you might spot the references to those in there that are not actioned

what do you think??

//  Arcade By Dave Lobato
//  davidlobato.dl@gmail.com
//  last updated: 25/07/2021 by: Dave Lobato

#include "Arduino.h"
#include <FastLED.h>
#include <Pushbutton.h>

#define BUTTON_PIN      4
#define RELAY_PIN       13
#define MARQUEE_PIN     7
#define BACKLIGHT_PIN   6
#define COLOR_ORDER     GRB
#define CHIPSET         WS2812B
#define NUM_LEDS_MARQ   104      //Change to match number of LEDs in Marquee.  
#define NUM_LEDS_BACK   150       //Change to match number of LEDs on backlighting

Pushbutton pbutton1(BUTTON_PIN);

CRGB Mleds[NUM_LEDS_MARQ];
CRGB Bleds[NUM_LEDS_BACK];

int count = 0;// used for the switch case top cycle led patterns
const int trigPin = 9;// set up for ultrasonic proxy sensor
const int echoPin = 10;
long duration;
int Distance;
bool Player = false;

const unsigned long pStart = 2000;//---interval from player detections to power up system---
const unsigned long pLeave = 15000;//---interval from player leaving to power off---
unsigned long PlayerMillis = 0; // set up for player detection imers
unsigned long PrevPlayerMillis = 0;
unsigned long NoPlayerMillis = 0; // set up for no player detected timers
unsigned long PrevNoPlayerMillis = 0;
const long interval = 50;

int Brightness = 10; // ------ sets amount to fade the leds by-----

void setup() {

  pinMode(trigPin, OUTPUT);   //---------sets up the proxy sensor-----
  pinMode(echoPin, INPUT);
  pinMode(RELAY_PIN, OUTPUT);   //---------sets up the mains relay for the rasberry pi--------
  digitalWrite(RELAY_PIN, LOW);
  pinMode(MARQUEE_PIN, OUTPUT);   //---------sets up the marquee lights and the backlighting-------
  pinMode(BACKLIGHT_PIN, OUTPUT);
  FastLED.addLeds<CHIPSET, BACKLIGHT_PIN, COLOR_ORDER>(Bleds, NUM_LEDS_BACK).setCorrection( TypicalLEDStrip );
  FastLED.addLeds<CHIPSET, MARQUEE_PIN, COLOR_ORDER>(Mleds, NUM_LEDS_MARQ).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( 150 ); // --------Sets master brightness to begin illuminating-------------

  for (int j = 0; j < NUM_LEDS_MARQ; j++) {   //---------turn off all LEDS to begin...
    Mleds[j] = CRGB::Black;
  }
  for (int j = 0; j < NUM_LEDS_BACK; j++) {
    Bleds[j] = CRGB::Black;
  }
  FastLED.show();
  Serial.begin(9600);
}

void loop() {
  LedCycle(); // activates switch case cycle function for the led patterns
  
  digitalWrite(trigPin, LOW); // ultrasonic proximity sensor process
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  Distance = (duration * .0343) / 2;  // sets distance to cm's
  Serial.println(Distance); // prints distance to monitor

  if (Distance <= 50) {        // player is close to console--
    PlayerMillis = millis();  // starts player present timer--
    Player = true;            // declares player present--
    Serial.println("Player Found");
    if (PlayerMillis - PrevPlayerMillis > pStart) { // check the time a player has been present for
      digitalWrite(RELAY_PIN, HIGH);    // power on the system
      Serial.println("System Activated");
    }
    PrevPlayerMillis += PlayerMillis; // save the time the player was last detected
  }
  if (Distance > 50) {          // no player detected near to console
    NoPlayerMillis = millis(); // starts no player present timer
    Player = false;             // declares player not present
    Serial.println("No Player Found");
    if (NoPlayerMillis - PrevNoPlayerMillis > pLeave) { // check how long the player has been missing
      digitalWrite(RELAY_PIN, LOW); // if long enough power, off the system
      Serial.println("System DeActivated");
    }
    PrevNoPlayerMillis += NoPlayerMillis; // save the last time no player was detected
  }
} // -----------------------------------------END LOOP-----------------------------------------------------//

void LedCycle() {// switch case funcion uses a momentary button to cycle through led patterns, this works well
  if (pbutton1.isPressed()) {   //-----press button to cycle LED patterns-----
    count = count + 1;
    delay(400);
    switch (count) {
      case 0:
        movingDots();
        break;
      case 1:
        rainbowBeat();
        break;
      case 2:
        redWhiteBlue();
        break;
      case 3:
        DarkBlue();
        break;
      case 4:
        DarkRed();
        break;
      case 5:
        Indigo();
        break;
      case 6:
        count = 0;
        break;
    }
    FastLED.show();

  }
} 
//-------- the following are all the led patterns for the back lighting
void movingDots() {

  uint16_t posBeat  = beatsin16(30, 0, NUM_LEDS_BACK - 1, 0, 0);
  uint16_t posBeat2 = beatsin16(60, 0, NUM_LEDS_BACK - 1, 0, 0);

  uint16_t posBeat3 = beatsin16(30, 0, NUM_LEDS_BACK - 1, 0, 32767);
  uint16_t posBeat4 = beatsin16(60, 0, NUM_LEDS_BACK - 1, 0, 32767);

  // Wave for LED color
  uint8_t colBeat  = beatsin8(45, 0, 255, 0, 0);

  Bleds[(posBeat + posBeat2) / 2]  = CHSV(colBeat, 255, 255);
  Bleds[(posBeat3 + posBeat4) / 2]  = CHSV(colBeat, 255, 255);

  fadeToBlackBy(Bleds, NUM_LEDS_BACK, 10);
}
void rainbowBeat() {

  uint16_t beatA = beatsin16(30, 0, 255);
  uint16_t beatB = beatsin16(20, 0, 255);
  fill_rainbow(Bleds, NUM_LEDS_BACK, (beatA + beatB) / 2, 8);
}
void redWhiteBlue() {

  uint16_t sinBeat   = beatsin16(30, 0, NUM_LEDS_BACK - 1, 0, 0);
  uint16_t sinBeat2  = beatsin16(30, 0, NUM_LEDS_BACK - 1, 0, 21845);
  uint16_t sinBeat3  = beatsin16(30, 0, NUM_LEDS_BACK - 1, 0, 43690);

  Bleds[sinBeat]   = CRGB::Blue;
  Bleds[sinBeat2]  = CRGB::Red;
  Bleds[sinBeat3]  = CRGB::White;

  fadeToBlackBy(Bleds, NUM_LEDS_BACK, 10);
}
void DarkBlue() {
  for (int j = 0; j < NUM_LEDS_BACK; j++) {
    Bleds[j] = CRGB::DarkBlue;
  }
  FastLED.show();
}
void DarkRed() {
  for (int j = 0; j < NUM_LEDS_BACK; j++) {
    Bleds[j] = CRGB::DarkRed;
  }
  FastLED.show();
}
void Indigo() {
  for (int j = 0; j < NUM_LEDS_BACK; j++) {
    Bleds[j] = CRGB::Indigo;
  }
  FastLED.show();
}

Hello,
you can derive a timer function by using the BLINK WITH OUT IDE example simply.

1. You may start from yourself with the following control structures:

void loop()
{
    while player is not here
    {
        acquire sensor value and display
    }
    if player is at a distance less than 50 cm
    {
         Power On to PI
         wait for 5-sec during which acquire sensor signals and display them
         exit
    } 
   else  if player is at a distance greater than 50 cm
            {
                Power Down PI
                wait for 15-sec during which acquire sensor signals and display them
                exit
            }
}

2. Write programming codes for the control structures of Step-1.
(1) How do we know that a palyer is here?
Ans: When the player is here, DPin-2 (for example) assumes HIGH state.

do
{
    acquireSensors();    //routine to acquire sensor signals and display
}
while (digitalRead(2) != HIGH);   //be in the loop until the player is present

(2) Measure distance of the player and save in x. Keep checking for 5-sec that x is less than 50 cm; also keep acuiring sensor vlaues within this 5-sec period.

unsigned long prMillis = millis();
while(millis() - prMillis < 5000)
{
     acquireSensors();       //acquire sensor signals and display    
     x = measureDistance();   //measure distance of the player
     if(x  > 50)
     {
         flag = true;    //indicates that the player has gone beyond 50 cm
         break;
     }
}
if(flag != true)    //player stayed for 5-sec at a distance less than 50 cm 
{
         //Power ON PI
}

Try to follow the logic of the rough codes of Step-2 and modify them as needed to meet your requirements.

Hey hey, thanks for this i'll do my best to follow this through and i'll post up what I come up with and how it goes.

#define RELAY_PIN       13

// set up for ultrasonic proxy sensor
const int trigPin = 9; 
const int echoPin = 10;

bool SystemOn = false;

// interval from player arrival to power up
const unsigned long pStart = 2000;
// interval from player departure to power down
const unsigned long pLeave = 15000;

unsigned long PlayerMillis = 0;

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

   //---------sets up the proxy sensor-----
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

   // mains relay for the rasberry pi
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // Off
  SystemOn = false;
}

void loop()
{
   // Measure distance (ultrasonic)
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  unsigned long duration = pulseIn(echoPin, HIGH);
  int Distance = (duration * .0343) / 2;  // sets distance to cm's
  Serial.println(Distance); // prints distance to monitor
  bool playerIsPresent = (Distance != 0 && Distance < 50);

  static bool playerWasPresent = false;

  if (playerIsPresent != playerWasPresent)
  {
    // Player presence has changed
    playerWasPresent = playerIsPresent;

    if (playerIsPresent)
      Serial.println("Player Arrived");
    else
      Serial.println("Player Departed");

    // Record the last time the player arrived or departed
    PlayerMillis = millis();
  }

  if (SystemOn)
  {
    // The system is on.  Check to see it it is time to turn off
    if (!playerIsPresent && millis() - PlayerMillis > pLeave)
    {
      // Time to turn off the system
      digitalWrite(RELAY_PIN, LOW); // power off the system
      Serial.println("System DeActivated");
      SystemOn = false;
    }
  }
  else
  {
    // The system is off.  Check to see if it is time to turn on
    if (playerIsPresent && millis() - PlayerMillis > pStart)
    {
      // Time to turn on the system
      digitalWrite(RELAY_PIN, HIGH);    // power on the system
      Serial.println("System Activated");
      SystemOn = true;
    }
  }

} // -----------------------------------------END LOOP-----------------------------------------------------//
1 Like

How to write Timers and Delays in Arduino includes an example of Delay execution until condition has been true for X secs
which may be closer to what you need.
also see Multi-tasking in Arduino for how to structure your code when using millis() timers.
multitaskingDiagramSmall

Please, follow SSS (Small Start Strategy) Methodology to create your sketch. In SSS Methodology, a basic (simple and elementary) unit of "hardware and associated software" is tested and then another basic unit is added/tested and then the next basic unit is added/tested until the project comes to the end.

this worked beautifully, thankyou very much! i just need to incorporate the lighting effects and its done! thakns again! :slight_smile:

thanks for the advice everyone i will do my best to use that info as well.

good hustle!!