HC-sr04 stops working

Hey all,

I am just getting back into dabbling with my hc-sr04...so i decide to use it and some neopixels to make a stop meter for my mom sho she doesn't wreck her car pulling into the garage. my issue is simple...if i get too close or too far with from the sensor, it stops working...if you reset the arduino it works fine or if you just pull the sensor and put it back in it will reset and work fine until you are too close or too far away again. here is the code, let me know if i am doing anything wrong...but it works as planned ortherwise:

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#include <NewPing.h>
#define TRIGGER_PIN  52
#define ECHO_PIN     53
#define MAX_DISTANCE 120
#define PIN 6
#define LEDNUM 8

int codeFact = (MAX_DISTANCE / (LEDNUM * 3));
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDNUM, PIN, NEO_RGB + NEO_KHZ800);
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
  strip.begin();
    strip.show(); 
    for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
      strip.setPixelColor(i, strip.Color(0, 255, 0));
      strip.show();
      delay(50);
    }
    for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
      strip.setPixelColor(i, strip.Color(255, 255, 0));
      strip.show();
      delay(50);
    }
    for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
      strip.setPixelColor(i, strip.Color(255, 0, 0));
      strip.show();
      delay(50);
    }
    for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
      strip.setPixelColor(i, strip.Color(0, 0, 0));
      strip.show();
      delay(50);
    }

Serial.begin(115200);
}

void loop() 
{
 delay(200);
  int uS = sonar.ping();
  int dis = uS / US_ROUNDTRIP_CM;
 
  if (dis == 0)
  {
     for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
      strip.setPixelColor(i, strip.Color(0, 0, 0));
      strip.show();
    }
  }
  else
  {
    uint32_t sCol;
    uint32_t eCol;
    int code = ((MAX_DISTANCE - dis) / codeFact);
    int sPhase = code / LEDNUM;
    switch (sPhase)
    {
      case 0:
        sCol = strip.Color(0, 0, 0);
        eCol = strip.Color(0, 255, 0);
        break;
      case 1:
        sCol = strip.Color(0, 255, 0);
        eCol = strip.Color(255, 255, 0);
        break;
      case 2:
        sCol = strip.Color(255, 255, 0);
        eCol = strip.Color(255, 0, 0);
        break;
    }
    for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
      if(code % LEDNUM <= i)
      {
        strip.setPixelColor(i, sCol);
      }
      else
      {
        strip.setPixelColor(i, eCol);
      }
    }
    strip.show();
  }
}

What happens when dis is greater than MAX_DISTANCE? Code is negative? Everything blows up!

what is codeFact (6)?
Why LEDNUM?

How can sPhase be 0,1,2? if code is negative?

max_distance uS US_roundTrip_cm dis code sPhase
120 0 146 0 20 2
120 500 146 3 19 2
120 1000 146 6 19 2
120 3000 146 20 16 2
120 5000 146 34 14 1
120 7000 146 47 12 1
120 9000 146 61 9 1
120 10000 146 68 8 1
120 13000 146 89 5 0
120 16000 146 109 1 0
120 19000 146 130 -1 0
120 22000 146 150 -5 0
120 25000 146 171 -8 -1
120 30000 146 205 -14 -1
120 35000 146 239 -19 -2
120 40000 146 273 -25 -3
120 45000 146 308 -31 -3
120 50000 146 342 -37 -4

sPhase is on 0..2 for a few values you need a different equation or a better definition of the problem.

What are the ranges for each color?

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

according to how new ping is supposed to work, if the ping is greater than the MAX_DISTANCE then it will return 0...in that case, it already takes into consideration that case on the if statement.

so dis should only be between 0 and 120...this will ensure that code is never negative.

codeFact is the increment in cm between the lights moving to the next step...this will be dynamic so if i decide to use a larger distance or more leds, that it will auto adapt.

I added LEDNUM later on to keep with the convention of having all my changeable variables at the top of the code...I'm just weird like that.

the ranges for each color will very depending on the MAX_DISTANCE and LEDNUM...so that is why I make codeFact...ex:// if i have 5 leds...there will be LEDNUM * 3 different light stages (sPhase) that will be shown...the codeFact is the range of a particular stage...in the previous example, assume I have the MAX_DISTANCE as 150...then the first led will turn on when distance is between 150 - 141

the section of the loop that displays the colors for the distance works fine...my issue is when the distance is 0 OR is greater than MAX_DISTANCE, the sensor stops click and sending data on the ping...when one of these occur, then the sensor fails until the arduino is reset (by reset button or pulling the power) OR but removing the power from the sensor and restoring it

I even commented everything except the following and added Serial

 delay(200);
  int uS = sonar.ping();
  int dis = uS / US_ROUNDTRIP_CM;
  Serial.println(dis);

If i bring the delay all the way up to 2000 ms, it will recover from the object too far...but not the object too close