Hello, I’ve used a Nano to build a 7-segment display that shows the temperature from a sensor, and I’m looking for a little help. I’ve got it mostly working, the temperature is read and displayed correctly, but the display is flickering. I’ve been able to use the display on its own to show numbers without flicker, so I’m suspecting its one of the temperature functions (read, value lookup, etc) taking long enough to cause the display to lag? I tried adding a delay timer to reduce the number of temperature reads, which sort of works, now it flickers about once/sec and is steady otherwise.
Any thoughts/suggestions? Is the Nano not powerful enough to do what I’m trying to do?
#include "SevSeg.h"
#include <DallasTemperature.h>
#include <OneWire.h>
int temp_sensor = 5; // Temp sensor on pin 5
float temperature = 0; // initialize temperature variable
int timer = 10000; // Timer to delay temp check by ~1sec
SevSeg sevseg; //Instantiate a seven segment controller object
OneWire oneWirePin(temp_sensor);
DallasTemperature sensors(&oneWirePin);
void setup(void){
sensors.begin();
byte numDigits = 2; // Number of digits in 7-seg display
byte digitPins[] = {2, 3}; // digit pins from left to right
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12}; // segments in order: a,b,c,d,e,f,g
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = false; // Default 'false' is Recommended
bool leadingZeros = true; // 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
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90);
}
void loop(){
sensors.requestTemperatures(); // read sensor
temperature = sensors.getTempFByIndex(0); // convert sensor data to degrees F
while (timer > 0) { // delay temp check for 1 sec
timer -= 1;
sevseg.setNumber(temperature, 1); // set number to be drawn on display
sevseg.refreshDisplay(); // Must run repeatedly
}
timer = 10000; // reset countdown
}
#include "SevSeg.h"
#include <DallasTemperature.h>
#include <OneWire.h>
int temp_sensor = 5; // Temp sensor on pin 5
float temperature = 0; // initialize temperature variable
int timer = 10000; // Timer to delay temp check by ~1sec
SevSeg sevseg; //Instantiate a seven segment controller object
OneWire oneWirePin(temp_sensor);
DallasTemperature sensors(&oneWirePin);
void setup(void) {
sensors.begin();
byte numDigits = 2; // Number of digits in 7-seg display
byte digitPins[] = { 2, 3 }; // digit pins from left to right
byte segmentPins[] = { 6, 7, 8, 9, 10, 11, 12 }; // segments in order: a,b,c,d,e,f,g
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = false; // Default 'false' is Recommended
bool leadingZeros = true; // 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
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90);
}
unsigned long lastUpdate = 0;
void loop() {
unsigned long now = millis();
if( now - lastUpdate >= 1000 ) {
sensors.requestTemperatures(); // read sensor
temperature = sensors.getTempFByIndex(0); // convert sensor data to degrees F
sevseg.setNumber(temperature, 1); // set number to be drawn on display
lastUpdate = now;
}
sevseg.refreshDisplay();
}
Yea a long delay is my backup plan, I’m just using this to display the temp of an aquarium, I just wanted to see if there was just something I was doing wrong first. Out of curiosity, would a different model Arduino have a faster processor?
So maybe a silly question, how would you compare the data in the sensor object without using the ‘getTempFByIndex’? Arduino is complaining about my ‘if’ statement:
“no match for 'operator!=' (operand types are 'DallasTemperature' and 'DallasTemperature')”
I guess you can’t compare the objects directly?
#include "SevSeg.h"
#include <DallasTemperature.h>
#include <OneWire.h>
int temp_sensor = 5; // Temp sensor on pin 5
float temperature = 0; // initialize temperature variable
int timer = 10000; // Timer to delay temp check by ~1sec
SevSeg sevseg; //Instantiate a seven segment controller object
OneWire oneWirePin(temp_sensor);
DallasTemperature sensor(&oneWirePin); // Sensor object
DallasTemperature oldsensor(&oneWirePin); // Sensor "old data" storage object
void setup(void) {
sensor.begin();
byte numDigits = 2; // Number of digits in 7-seg display
byte digitPins[] = { 2, 3 }; // digit pins from left to right
byte segmentPins[] = { 6, 7, 8, 9, 10, 11, 12 }; // segments in order: a,b,c,d,e,f,g
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = false; // Default 'false' is Recommended
bool leadingZeros = true; // 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
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90);
}
unsigned long lastUpdate = 0;
void loop() {
unsigned long now = millis();
if( now - lastUpdate >= 1000 ) { // read sensor once every 1sec (1000ms) to work around flicker when temp is updated
oldsensor = sensor; // backup sensor data
sensor.requestTemperatures(); // read sensor
if (oldsensor != sensor) { // if new data is different
temperature = sensor.getTempFByIndex(0); // convert sensor data to degrees F
sevseg.setNumber(temperature, 1); // set number to be drawn on display
}
lastUpdate = now;
}
sevseg.refreshDisplay(); // refresh 7seg display
}
You can reduce the blanked time by switching to async operation (look at sensors.setWaitForConversion(false); and everything that goes with that). Reduce, but not eliminate. There's still a little flicker left.
A better solution might be to ditch SevSeg and look for a library that does the digit multiplexing in an interrupt. But that has potential conflicts with the OneWire library disabling interrupts at critical junctures.
An even better solution is probably to do things in hardware with a TM1637 or MAX7219 module.
Or use a couple of discrete digits and a shift register for the segments (74HC595?).
Or switch to a different temperature sensor that is quicker to read. TMP36/7 on an analog pin? DHT20 on I2C?
Ok, snagged a pack of TMP36’s, let’s see if reading these on an analog pin is any faster. If it works, I guess I can just coat it in epoxy to waterproof it
I see you made two instances of DallasTemperature.
Use just one instance. Read the temperature. Compare oldTemp (which is "random" on the first compare) to newTemp. If different, save newTemp to oldTemp and update display.
float oldTemp, newTemp;
void setup() {
// setup stuff
}
void loop() {
// loop stuff
.
.
sensor.requestTemperatures(); // read sensor
newTemp = sensor.getTempFByIndex(0); // convert sensor data to degrees F
if (oldTemp != newTemp) { // if new data is different
oldTemp = newTemp; // store newTemp
sevseg.setNumber(newTemp, 1); // set number to be drawn on display
}
}
So it does run, but still flickering unfortunately. At this point I suspect Van is correct and the lag is coming from either reading the sensor data or the index lookup, so switching out the sensor (or adding hardware to control the display) is probably the only solution
Even going with the hardware address and async the display still flickers a little (I tried it). It just takes too long to read the one wire sensor for POV to still work.
#include "SevSeg.h"
#include <DallasTemperature.h>
#include <OneWire.h>
int temp_sensor = 5; // Temp sensor on pin 5
float temperature = 0; // initialize temperature variable
int timer = 10000; // Timer to delay temp check by ~1sec
SevSeg sevseg; //Instantiate a seven segment controller object
OneWire oneWirePin(temp_sensor);
DallasTemperature sensor(&oneWirePin); // Sensor object
// DallasTemperature oldsensor(&oneWirePin); // Sensor "old data" storage object
float oldTemp, newTemp;
void setup(void) {
sensor.begin();
byte numDigits = 2; // Number of digits in 7-seg display
byte digitPins[] = { 2, 3 }; // digit pins from left to right
byte segmentPins[] = { 6, 7, 8, 9, 10, 11, 12 }; // segments in order: a,b,c,d,e,f,g
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = false; // Default 'false' is Recommended
bool leadingZeros = true; // 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
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90);
}
unsigned long lastUpdate = 0;
void loop() {
unsigned long now = millis();
if( now - lastUpdate >= 1000 ) { // read sensor once every 1sec (1000ms) to work around flicker when temp is updated
sensor.requestTemperatures(); // read sensor
newTemp = sensor.getTempFByIndex(0); // convert sensor data to degrees F
if (oldTemp != newTemp) { // if new data is different
oldTemp = newTemp; // store newTemp
sevseg.setNumber(newTemp, 1); // set number to be drawn on display
}
lastUpdate = now;
}
sevseg.refreshDisplay(); // refresh 7seg display
}
While the code's off doing this, it can't be keeping the display refreshed. And with the default 9 bits it takes 94 ms to get the temperature. More than long enough to see.