Code not working, why?

I am new to Arduino and have written a code using New_Ping library for Mega 2560 but it is not working. The circuit is simple. I read the distance of 0 to 100 cm using SR04 Ultrasoonic (US) sensor and convert it to led count (10 leds) and light up the bargraph leds but it is not working.

I am posting the code here. Please help me.

#include <NewPing.h>

#define TRIGGER_PIN  4  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     5  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 100 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int ledPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
unsigned int ledCount = 10;  // Number of LEDs
double distanceIncm = 0;
unsigned int ledCnt = 0;

void setup() {
  Serial.begin(9600); // Open serial monitor at 9600 baud to see ping results.
  delay(200);
}

void loop() {
  delay(2000);                      // Wait 2000ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  distanceIncm = uS / US_ROUNDTRIP_CM;
  Serial.println(distanceIncm); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  
  ledCnt = (int)(distanceIncm / 10.0);
  Serial.println(ledCnt);
  
  for (int thisLed = 0; thisLed < ledCnt; thisLed++) {
            digitalWrite(ledPins[thisLed], HIGH);  // Turn on LED    
    }
    for (int thisLed = 9; thisLed > (ledCnt - 1); thisLed--) {
            digitalWrite(ledPins[thisLed], LOW);  // Turn on LED    
    }

}

it is not working.

What does it do or not do ?

  for (int thisLed = 0; thisLed < ledCnt; thisLed++) {
    digitalWrite(ledPins[thisLed], HIGH);  // Turn on LED
  }
  for (int thisLed = 9; thisLed > (ledCnt - 1); thisLed--) {
    digitalWrite(ledPins[thisLed], LOW);  // Turn on LED
  }

Which of the digitalWrite() commands turns the LED on and which turns it off ? If the second one turns them off then you will have no time to see them on. Shouldn’t you turn off all of the LEDs before turning some of them on ?

    digitalWrite(ledPins[thisLed], LOW);  // Turn on LEDThe first time through the for loop you will be reading the 10th element of the 9 element ledPins array.

  ledCnt = (int)(distanceIncm / 10.0);

Forcing float math and then casting the result to an int is silly.

The 1st loop turns on the leds and 2nd loop turns off.

If distance is 20 cm then 20/10 = 2 and ledCnt = 2, so, 0th and 1st leds turn ON and others are turned OFF. What is wrong in the code. Why it doesn't work? I have 330E resistors in series with leds.

What is wrong in the code. Why it doesn't work?

You still not have explained (well enough) what is not working. On the second pass, what is ledCnt? Which LED pins are (supposed to be) turned on? What do the Serial.print() statements you add to the for loops tell you?

The 1st loop turns on the leds and 2nd loop turns off.

Leaving aside any other problems for the moment, how long will the LEDs stay on so that you can see them ?

It will stay ON as long as the distance remains same. If distance value is 20 then 20/10 = 2 and so 2 leds light up and others Off and it remains there until the distance changes. Here is the new code but still it is not working.

I need float value because if distance is 9 cm then int result will be 9/10 = 0 and I need to turn off motor when distance is 5 cm. So float value is used to turn ON or OFF pump and int value is used for led loops.

#include <NewPing.h>

#define TRIGGER_PIN  4  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     5  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int ledPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
unsigned int ledCount = 10;  // Number of LEDs
double distanceIncm = 0;
unsigned int ledCnt = 0;

void setup() {
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
            pinMode(ledPins[thisLed], OUTPUT);  // Turn on LED    
    }
  Serial.begin(9600); // Open serial monitor at 115200 baud to see ping results.
  delay(200);
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  //Serial.print("Ping: ");
  distanceIncm = uS / US_ROUNDTRIP_CM;
  Serial.println(distanceIncm); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  //Serial.println("cm");
  
  ledCnt = (unsigned int)(distanceIncm / 10.0);
  Serial.println(ledCnt);
  
  int thisLed = 0;
  
  while (thisLed < ledCnt) {
            digitalWrite(ledPins[thisLed], HIGH);  // Turn on LED    
            thisLed++;
  }
  
  thisLed = 9;
  
    while (thisLed >= ledCnt) {
            digitalWrite(ledPins[thisLed], LOW);  // Turn on LED
            thisLed--;    
    }  
}

How long do you expect the LEDs to be illuminated?
Do you think your eye can distinguish an interval that short?

No, you don’t need floating point.

Hi jayanthd

If you change this line of code, as a test ...

// ledCnt = (unsigned int)(distanceIncm / 10.0);
ledCnt = 5;

... then you are expecting LEDs 0 to 4 to be turned on, and LEDs 9 down to 5 to be turned off, each time round loop(). Is that right?

What happens if you make this change? I'm still not clear which LEDs if any are coming on.

Have you tried a very simple test program to turn each LED on the "brute force" way?

digitalWrite(ledPins[0], HIGH);
digitalWrite(ledPins[1], LOW);
etc

Regards

Ray

It worked now but can this code be improved ?

I don’t know whether I can use float in loops or not. The problem is if distanceIncm is 5 then 5/10 will result in 0 if int is used for ledCnt. So, I will not be able to turn of pump. The pump will turn OFF when distance goes below 10 cm. I only want the pump to turn OFF when distance is 5 cm and turn ON when distance is 100 cm. When value >= 10 cm and <= 100 cm then in steps of 10 I turn ON leds.

Freq is not a problem. Let me explain. If distance is 12 cm then 12/10 = 1.2 casted gives 1. So, for value > 10 and < 20 I get 1 as distance in int. So, the loops keep 1st LED turned ON and remaining OFF. The turning OFF loop doesn’t turn OFF all leds. The loop turns OFF only the unnecessary leds to the present condition.

#include <NewPing.h>

#define TRIGGER_PIN  4  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     5  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int ledPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
unsigned int ledCount = 10;  // Number of LEDs
double distanceIncm = 0;
signed int ledCnt = 0;

void setup() {
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
            pinMode(ledPins[thisLed], OUTPUT);  // Turn on LED    
    }
  Serial.begin(9600); // Open serial monitor at 115200 baud to see ping results.
  delay(200);
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  //Serial.print("Ping: ");
  distanceIncm = uS / US_ROUNDTRIP_CM;
  Serial.println(distanceIncm); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  //Serial.println("cm");
  
  ledCnt = (unsigned int)(distanceIncm / 10.0);
  Serial.println(ledCnt);
  
  signed int thisLed = 0;
  
  while (thisLed < ledCnt) {
            digitalWrite(ledPins[thisLed], HIGH);  // Turn on LED    
            thisLed++;
  }
  
  thisLed = 9;
  
  while (thisLed >= ledCnt) {
            digitalWrite(ledPins[thisLed], LOW);  // Turn on LED
            thisLed--;    
    }  
}

The problem is if distanceIncm is 5 then 5/10 will result in 0 if int is used for ledCnt

Simple arithmetic will solve your perceived problem

Check my previous post. I only want to display distance in steps of 10 cm because I have 10 leds and 100 cm to measure. So, 10 cm will turn ON 1 led and 100 cm = 100/10 = 10 will turn ON 10 leds. I don’t want to turn ON leds for 5 cm or 15 cm. When distance is 10 cm to < 20 cm then 1 led will be ON

if distance = 20 cm to < 30 cm then 2 leds turn ON.

5 cm is only used for turning OFF pump not leds. int value is used for leds and float value is used for pump ON / OFF. When distance is 100 cm or more then pump turns ON and when distance reaches 5 cm pump turns OFF.

... then you are expecting LEDs 0 to 4 to be turned on, and LEDs 9 down to 5 to be turned off, each time round loop(). Is that right?

That's wrong. I have explained in my previous post. It is a fluid level controller. Level is displayed in steps of 10 cm upto 100 cm. It is a 4 X 4 X 4 tank.

5 cm is only used for turning OFF pump not leds

Then, clearly (to everyone but you) the number of LEDs lit has NOTHING to do with the pump state. Why do YOU keep insisting that there IS a relationship?

See, float value gets actual distance like 5 cm, 12 cm, etc... there is no relationship. int value is used for leds and float for pump ON/OFF. When did I say that there is a relationship. It is only that same value (float) is used for pump and leds but for leds after casting. So, I can't eliminate float. If I do then pump ON/OFF will not work.

It is only that same value (float) is used for pump and leds but for leds after casting. So, I can't eliminate float. If I do then pump ON/OFF will not work.

No one is asking you to. But, think about this:

  distanceIncm = uS / US_ROUNDTRIP_CM;

Both values on the right are integer values, so integer arithmetic is preformed, resulting in an integer value. Storing that in a float will not magically recover the truncated data.

  ledCnt = (unsigned int)(distanceIncm / 10.0);

Dividing an integer value(stored in a float) by 10.0 will not recover that lost data, either. Explicitly truncating the data, as opposed to implicitly truncating the data, is not necessary.

The value stored in ledCnt is an int. That has NOTHING to do with turning the pump on or off.

There isn't even anything in your code that turns a pump on or off, so this whole discussion is pointless.

Both values on the right are integer values,

I didn't know that. I thought they were float. I will use unsigned integer instead of float.

How can I implement these codes if I want to use 2 Ultrasonic sensors in the project. I will measure distance of fluid in 2 tanks using 2 sensors but one at a time. I don't need interrupts.

unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
     //Serial.print("Ping: ");
     distanceIncm = uS / US_ROUNDTRIP_CM;

Can I do like this ?

#define TRIGGER_PIN1  4  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN1     5  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE1 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor //distance is rated at 400-500cm.


#define TRIGGER_PIN2  4  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN2     5  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE2 350 // Maximum distance we want to ping for (in centimeters). Maximum sensor //distance is rated at 400-500cm.


NewPing sonar1(TRIGGER_PIN1, ECHO_PIN1, MAX_DISTANCE1); // NewPing set
NewPing sonar2(TRIGGER_PIN2, ECHO_PIN2, MAX_DISTANCE2); // NewPing set


unsigned int uS = sonar1.ping(); // Send ping, get ping time in microseconds (uS).
     //Serial.print("Ping: ");
     distanceIncm = uS / US_ROUNDTRIP_CM;

//other code here

unsigned int uS = sonar2.ping(); // Send ping, get ping time in microseconds (uS).
     //Serial.print("Ping: ");
     distanceIncm = uS / US_ROUNDTRIP_CM;

//other code here

Can I do like this ?

If you want to, but wouldn’t it be better to get your current program working first ?

Can I do like this ?

No. How do you think you are going to attach two sensors to the same set of pins?