Hi,
I've completed a range sensor project, and have noticed an odd behavior I can't fix. When the sensor is active and taking readings, the farther things are from it, the more volatile the 4-digit seven-segment display is. I mean, at close ranges, the display looks fine, solid on. As the distances measured get longer, the lcd starts to flicker until it starts to look like it is having a very slow refresh rate.
I'd appreciate any guidance- I'm new to the arduino hardware and programming. As of now, I'm assuming this is the best I can do with the parts I have.
How it works:
- Turn a potentiometer to adjust the range at which anything closer will trigger an alarm.
- See the distance selected on a 4-digit seven-segment display.
- press a button to arm the sensor and begin readings.
- when button is pressed, an LED turns on, and the sensor begins taking measurements.
- when an object in front of the sense moves to a range closer than that which was selected, a buzzer sounds.
Parts List:
- Arduino (Elegoo) Mega2560
- Ultrasonic Ranging Module HC-SR04
- 4-digit seven-segment display (5641-AS)
- 5 220 ohm resisters
- 1 red led
6 Potentiometer (see attached) - Small button
- Active Buzzer (see attached)
Code:
#include <SevSeg.h>
SevSeg sevseg; //Instantiate a seven segment object
#define btnpin 3 //button
#define ledpin 10 //led
#define buzzpin 9 //buzzer
#define pingPin 11 //range finder
#define echoPin 12 //range finder
#define potpin A0 //pin used to read the potentiometer
// Declare variables
int ledState = LOW; // Current led state
int lastButtonState; // The previous state of the button
int currentButtonState; // The current state of the button
bool systemActive = false; // Flag to track system activation
const int startDist = 10;
//DECLARE VARIBLES FOR THE MILLI TIMER
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long interval = 0; // interval at which to REFRESH THE 7-SEG DISPLAY (milliseconds)
const long interval2 = 0; // interval at which the measurement is taken
void setup() {
//SEVSEG SETUP VARIABLES
byte numDigits = 4;
byte digitPins[] = { 32, 29, 28, 26 };
byte segmentPins[] = { 31, 27, 24, 22, 34, 36, 25 };
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_CATHODE; // See README.md for options
bool updateWithDelays = false; // Default 'false' is Recommended
bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
bool disableDecPoint = true; // Use 'true' if your decimal point doesn't exist or isn't connected. Then, you only need to specify 7 segmentPins[]
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(1);
//END SEVSEG SETUP
pinMode(btnpin, INPUT_PULLUP);
pinMode(ledpin, OUTPUT);
pinMode(buzzpin, OUTPUT);
Serial.begin(9600);
// Initialization of currentButtonState and lastButtonState
currentButtonState = digitalRead(btnpin);
lastButtonState = currentButtonState;
}
void loop() {
// Update currentButtonState - MOVED FROM SETUP
currentButtonState = digitalRead(btnpin); //TAKES ACTUAL PIN READING (HIGH OR LOW) AND SAVES VALUE TO THE VARIABLE, 'CURRENTBUTTONSTATE'.
int potval = analogRead(potpin); //identifies a variable to hold the voltage value of the potentiometer
int potinch = map(potval, 0, 1023, 1, 72);
// Serial.print(potinch); //PRINTS THE NUMBER OF INCHES SET VIA THE POTENTIOMETER.
// Serial.println(" USER SET inches");
/* check to see if it's time to REFRESH THE 7-SEG; that is, if the difference
between the current time and last time you blinked the LED is bigger than
the interval at which you want to blink the LED.
*/
unsigned long currentMillis = millis();
//code for timing the writing to the display
if (currentMillis - previousMillis >= interval) { //ALLOWS A TIMER TO CONTROL FREQUENCY OF DISPLAY BEING UPDATED.
// save the last time you blinked the LED
previousMillis = currentMillis;
//PRINTS 'POTINCH' TO THE 7 SEG DISPLAY
sevseg.setNumber(potinch, 2); //prints the 'POTINCH' VARIABLE TO THE 7-SEGMENT DISPLAY
}
sevseg.refreshDisplay(); //REFRESHES THE DISPLAY
// Toggle system activation upon button press
if (lastButtonState == HIGH && currentButtonState == LOW) {
systemActive = !systemActive;
// Control RED LED based on system activation
if (systemActive) {
digitalWrite(ledpin, HIGH); // Turn on the LED when system is activated
} else {
digitalWrite(ledpin, LOW); // Turn off the LED when system is deactivated
digitalWrite(buzzpin, LOW); // Turn off the buzzer when system is deactivated
}
}
lastButtonState = currentButtonState; // Update the last button state
if (systemActive) {
unsigned long distanceMeasurementStartTime = millis();
long duration, inches, cm;
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(echoPin, INPUT); //THIS SETS UP THE PIN THAT SENDS TIMING DATA TO THE ARDUINO.
duration = pulseIn(echoPin, HIGH);
// convert the time into a distance -these call to the functions at the bottom of this sketch.
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
// Calculate time taken for distance measurement
unsigned long distanceMeasurementDuration = millis() - distanceMeasurementStartTime;
// Subtract time taken for distance measurement from interval
if (distanceMeasurementDuration < interval2) {
delay(interval2 - distanceMeasurementDuration);
}
// Code to activate buzzer based on distance
if (inches < potinch) { //compares measured distance against the desired triggering distance.
digitalWrite(buzzpin, HIGH); // Activate buzzer if distance is less than 10ft
} else {
digitalWrite(buzzpin, LOW); // Deactivate buzzer if distance is greater than 10ft
}
}
}
//FUNCTIONS BELOW
long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are 73.746
// microseconds per inch (i.e. sound travels at 1130 feet per second).
// This gives the distance travelled by the ping, outbound and return,
// so we divide by 2 to get the distance of the obstacle.
// See: https://www.parallax.com/package/ping-ultrasonic-distance-sensor-downloads/
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the object we
// take half of the distance travelled.
return microseconds / 29 / 2;
}
Lesson 5 Button.pdf (130.5 KB)
Lesson 6 Active buzzer.pdf (125.2 KB)