How to take a single reading from a sensor and display it using a button

Hi,

I am new to arduino.

I am trying to display a single reading from an ardiuno sensor (in this example the ultrasonic HC-SR04 sensor) and display it on the LCD after I press the button.

Equipment - Arduino Uno, 2x16 LCD screen (parallel), potentiometer, a single button and the HC-SR04 ultrasonic sensor.
The two readings that are being output are distance (top line) and speed (second line).

The code is included below.

The problems I keep running into are that when I press the button, I consistently get a "0.00 cm" on top line and "0.00 cm/s" on the bottom line.

  • The double variables are still there from some troubleshooting I have tried
  • The code works if I remove all the code associated with the button.

#include <NewPing.h>
#include <LiquidCrystal.h>

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

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int buttonPin = 6; // the pin that the pushbutton is attached to,

// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
double buttonState = 0; // current state of the button
double lastButtonState = 0; // previous state of the button
double uScm1 = 0;
double time1 = 0;
double speed1 = 0;

void setup() {
// initialize serial communication:
Serial.begin(115200);
// initialize the button pin as a input:
lcd.begin(16, 2);
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, LOW);
pinMode(LCD_LIGHT_PIN, OUTPUT);
digitalWrite(LCD_LIGHT_PIN, HIGH);
}

void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);
if (buttonState == LOW) {
double uS1 = sonar.ping_median(); // Send ping, get ping time in microseconds (uS).
double uScm1 = sonar.convert_cm(uS1);
lcd.setCursor(0, 0);
lcd.print(uScm1);
lcd.print(" cm ");
double time1 = millis();
delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
double uS2 = sonar.ping_median(); // Send ping, get ping time in microseconds (uS).
double uScm2 = sonar.convert_cm(uS2);
double time2 = millis();
double speed1 = abs((uScm2 - uScm1)) / ((time2 - time1) / 1000);
lcd.setCursor(0, 1);
lcd.print(speed1);
lcd.print(" cm/s ");
}
else {
lcd.setCursor(0, 0);
lcd.print(uScm1);
lcd.print(" cm ");
lcd.setCursor(0, 1);
lcd.print(speed1);
lcd.print(" cm/s ");
}
}

How is your button wired? Using external pullup?

I am pretty sure that my button is wired by a pulldown system.
The resister is on the ground side of the circuit

I put the resistor(10 ohm) on the 5v side of the circuit and it no longer worked.

You could use the built-in led on pin 13 to see if the logic of the code is taking you into the "if" when the button is pressed.

Post your circuit.... you need to be more sure than:

I am pretty sure that my button is wired by a pulldown system.

Pullups are much easier since you can use the internal ones.

This is my circuit.
Blue is ground

Ok, I have tried using pin 13 to see if the led turned on when I pressed the button.

It turned on as when I pressed the button. The output was again "0.00 cm" on top line, and "0.00 cm/s" on bottom line (while the led turned on)

wire the button like the attached schematic. You don't need the cap for now. Your picture is so big that it is hard to trace anything for all the scrolling around.

  if (buttonState == LOW) {

This code is written for a button wired like the schematic groundfungas posted (with a pullup resistor)

I think the if statement is true only when the button is held, not when it changes. The OP has the variables from the state change detection but not the code that would detect the transition.

  if (buttonState == LOW)

This code is for a Normally HIGH button that is ACTIVE LOW. It only requires one press and release. The fact that the OP has no
debounce code is a separate issue. The button has hardware debounce so the code should work if the button is pressed and released since all that is required is that it enter the IF statement code (meet the conditional, which it does) . Once inside that statement if the state goies High while executing any of the code inside that statement it will not be detected since there is
no code to read the button inside that if statement. I don't see why you say it is only true if Held down. Why ?

raschemmel, I see what you are saying. You are right. Once the button is detected as LOW it should take and display the range. The next time through the loop, if the button is not held down, the else will execute and display 0.0. True?

We really shouldn't even be having this discussion since the OP is so inexperienced he has completely omitted the delays after the lcd prints so everything gets overwritten in a millisecond. Before you can take your finger off the button it has already been overwritten by the else code. (I don't count the 50 mS ping delay because that is not at least 1000 mS)
When the OP decides to add those delays then we can revisit this subject.

Ok,
I've gone through the comments and the diagram, thanks for this.

I've added an internal pullup resistor, and the lcd delay. I have also switched to the more usual "if (buttonState == HIGH)" setup, and changed it accordingly in the "setup" section.

When I press the button the lcd screen still displays "0.00 cm" on the top line and "0.00 cm/s" on the lower line.

void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
double uS1 = sonar.ping_median(); // Send ping, get ping time in microseconds (uS).
double uScm1 = sonar.convert_cm(uS1);
lcd.setCursor(0, 0);
lcd.print(uScm1);
lcd.print(" cm ");
double time1 = millis();
delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
double uS2 = sonar.ping_median(); // Send ping, get ping time in microseconds (uS).
double uScm2 = sonar.convert_cm(uS2);
double time2 = millis();
double speed1 = abs((uScm2 - uScm1)) / ((time2 - time1) / 1000);
lcd.setCursor(0, 1);
lcd.print(speed1);
lcd.print(" cm/s ");
delay(250);
digitalWrite(ledPin, LOW);
}
else {
lcd.setCursor(0, 0);
lcd.print(uScm1);
lcd.print(" cm ");
lcd.setCursor(0, 1);
lcd.print(speed1);
lcd.print(" cm/s ");
digitalWrite(ledPin, HIGH);

}
}