hello evrybody , i am using an i2c lcd in my project to show temperature and humidity
but it shows me only the first line , the second is not clear even i changed the contrast , could somone give me a hand
Same photo twice?
The problem is in the code you didn't post.
well , you can see the code please ?
DHT_Unified_Sensor.ino (6.19 KB)
Achref-Abbassi:
well , you can see the code please ?
Except that you did not show it in the body of your post, but attached it instead as a ".ino" file which is very inconvenient.
Could you go and read the instructions for posting (point number 7) and post it accordingly?
Paul__B:
Except that you did not show it in the body of your post, but attached it instead as a ".ino" file which is very inconvenient.
To each his own, I guess.
I know many seem to want the code inline, but I actually prefer code in attachments, as I have my browser configured appropriately to bring up the file in my preferred code editor.
For me, inline is inconvenient.
--- bill
hello , sorry i didn't know how to post the code like this , thank you Paul___B
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#define DHTPIN 4 // Define the temp sensor data pin
#define DHTTYPE DHT22 // define the temp/hum sensor type
#define RELAY_1 8 // define the relay 1 to 4 control pins
#define RELAY_2 9
#define RELAY_3 10
#define RELAY_4 11
DHT dht(DHTPIN, DHTTYPE); //initialize the temp sensor
LiquidCrystal_I2C lcd(0x27,16,2); //set up what port the LCD will use
int istate = 0;
const int buttonPin1 = 5; // the pin that the Up pushbutton is attached to
const int buttonPin2 = 6; // the pin that the Down pushbutton is attached to
int buttonState1 = 0;
int buttonState2 = 0;
float val = 0 ; //val to increment/decrement (buttons/ threshold)
int is, im, ih, id, ida, iha, ima; // variables for time
float time, s1, m1, h1, d1; // Set up variables to calculate time
int ic, ip, ik;
byte thermo[8] = {B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110}; //thermometer icon
byte drop[8] = {B00100, B00100, B01010, B01010, B10001, B10001, B10001, B01110}; //drop icon
byte arrow[8] = { B00100, B01010, B10101, B00100, B10101, B01010, B00100,}; // smile icon
byte tim[8] = {B00000, B01110, B10101, B10101, B10011, B10001, B01110,}; // clock
int END = 0;
boolean rotate = 0;
unsigned long previousMillis = 0;
const long interval = 3600000UL; //timer for roll eggs 1HOUR
void setup()
{
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
dht.begin(); //start the temp sensor
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
pinMode(RELAY_3, OUTPUT);
pinMode(RELAY_4, OUTPUT);
digitalWrite(RELAY_3,HIGH);
digitalWrite(RELAY_4,LOW);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Incubator 1.0");
lcd.setCursor(0, 1);
lcd.print("A initier!");
delay(2000);
lcd.createChar(0, thermo);
lcd.createChar(1, drop);
lcd.createChar(2, arrow);
lcd.createChar(3, tim);
dht.begin();
}
//loop to read the sensor and display
void loop() {
int buttonState1 = digitalRead(buttonPin1);
int buttonState2 = digitalRead(buttonPin2);
delay(10);
if (buttonState1 == HIGH)
{
val-=0.1;
}
else if (buttonState2 == HIGH)
{
val+=0.1;
}
float h = dht.readHumidity(); // Read the humidity
float t = dht.readTemperature(); // Read temperature in celsius
float f = dht.readTemperature(true); // get the temperature in Fahreheit
//Temperature controller
if (t >= (37.7 + val))
{ // Set the temperature for the relay to come on (ideal 37.7ºC)
digitalWrite(RELAY_1,LOW); // TO HOT: Turns Relay OFF
digitalWrite(RELAY_2,LOW);
}
if (t <= (37.5 + val))
{ // Set the temperature for the relay to come on (ideal 37.7ºC)
digitalWrite(RELAY_1,HIGH); // TO HOT: Turns Relay ON
digitalWrite(RELAY_2,HIGH);
}
// uncomment to compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
time = millis(); // Get time in milliseconds since tunit turn on
s1 = time / 1000; // Convert time to seconds, minutes, hours, days
m1 = s1 / 60;
h1 = m1 / 60;
d1 = h1 / 24;
id = int(d1); //d // Strip out remainder to leave Days:Hours:Minutes:Seconds
ih = int((d1 - int(d1)) * 24); //h
im = int((h1 - int(h1)) * 60); //m
is = int((m1 - int(m1)) * 60); //s
// Calculate approximate TIME till hatch (assume 21 days to hatch) - not used yet
ida = 21 - id;
iha = 24 - ih;
ima = 60 - im;
if (isnan(h) || isnan(t) || isnan(f)) {
// if sensor can't be read
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sensor Failure");
lcd.print("Sensor Failure" );
digitalWrite(RELAY_1,HIGH); // ERRO: Turns 1 Relay OFF to not kill all the eggs
digitalWrite(RELAY_2,LOW);
delay(5000);
return;
}
else { // for LCD 16x2
//sensor was read succesfully so print values to LCD 16x2
lcd.clear(); // Clear the LCD
//Print temperature and humidity in first two lines
lcd.setCursor(0, 0);
lcd.print("Temperature:");
lcd.write(byte(0)); // Write the Thermometer icon
lcd.print(t , 1);
lcd.print((char)223);
lcd.print("C ");
lcd.setCursor(0,1);
lcd.write(byte(1)); // Write the drop icon
lcd.print("Humidade:");
lcd.print(h, 0);
lcd.print("%");
lcd.print(" ");
lcd.print(ic);
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.write(byte(3));
lcd.print(" ");
// Print timein format Time: xxd:xxh:xxm:xxs
lcd.print(id);
lcd.print("d ");
lcd.print(ih);
lcd.print(":");
lcd.print(im);
lcd.print(" ");
lcd.print(is); lcd.print(" ");
lcd.print(val,1);
if (21 - id <= 3){
// Print days left till hatch
lcd.print("!");
END = 1; //stop move eggs
}
}
// this section is to roll eggs
if (END==0){
if (ih%2==0){
if ( ih%4==0 && rotate ==1){
digitalWrite(RELAY_3,HIGH);
digitalWrite(RELAY_4,LOW);
rotate = 0 ;
}if ( ih%4 != 0 && rotate == 0){
digitalWrite(RELAY_3,HIGH);
digitalWrite(RELAY_4,LOW);
rotate = 1 ;
}
}
}
}
I can't really see the display in the photos you posted earlier to understand what you mean by:
"... it shows me only the first line , the second is not clear even i changed the contrast ..."
I don't see anything obvious in the code other than you are constantly clearing the screen before updating it.
That will cause flicker effects and the 2nd line will experience more of the effect since the characters on the 2nd line will be on the display for a shorter amount of time before the next clear.
You really want to avoid using clear(), it is a relatively slow operation, and cause flicker effects.
There are many techniques to do this, but it usually involves just updating the display when something changes or after a period of time.
And even then, it is still better to avoid using clear() so that what is on the display is never erased.
i.e. the display is simply updated/over-written with the new characters.
What creates the flicker effects is the period of time where there is nothing on the display to the point in time where it is updated with the new characters.
Other than that, maybe you could provide some additional description of what is on the display vs what you expected to be on the display and post some clearer photos of the display so we can see it too.
--- bill
If your display output is always in fixed locations, and the messages/numbers are fixed field widths,
then you may be able to get away with simply not doing the clear().
This will eliminate the flicker, but if the messages/numbers are rapidly changing, those characters/digits may be a bit hard to read since they are changing so rapidly.
--- bill
bperrybap:
I know many seem to want the code inline, but I actually prefer code in attachments, as I have my browser configured appropriately to bring up the file in my preferred code editor.
For me, inline is inconvenient.
Fine for you indeed, but near-impossible for anyone using a tablet. Mike frequently complains about that.
And a significant problem is that by default with the Arduino IDE, opening a .ino necessarily loads the IDE which as you know, is a slow business, brings up all your current working projects and (with default settings at least, which has been discussed before) the IDE then wants to save it amongst your own projects which is hardly necessary when you only want to examine it and recommend minor corrections.
If posted inline, it can be quoted and easily re-posted.
There may be some Windoze accessory to implement the Linux middle-click auxiliary clipboard. That would be nice.
Started writing this yesterday, then got busy. Thank goodness for automatic drafts!
The normal path through that code prints 2 lines to the LCD, delays 10 milliseconds then clears the LCD.
Simple fix: increase the delay.
Correct fix: don't clear. Remember what you last wrote to the LCD and only overwrite the digits necessary. If you last wrote "10.0" degrees and it is now 9.9, write an extra space to overwrite the additional digit.
MorganS:
The normal path through that code prints 2 lines to the LCD, delays 10 milliseconds then clears the LCD.Simple fix: increase the delay.
Correct fix: don't clear. Remember what you last wrote to the LCD and only overwrite the digits necessary. If you last wrote "10.0" degrees and it is now 9.9, write an extra space to overwrite the additional digit.
As you increase the delay, at some point, the button response will start to suffer.
Personally, I wouldn't try to solve a flickering issue that way as there will still be some amount of flickering due to clearing the display before updating. This is particularly true with a slower interface like when using an i2c backpack and the LiquidCrystal_I2C library being used.
If you use the hd44780 library with the hd44780_I2Cexp i/o class library, the display could be updated twice as fast so the flickering would be reduced, but still not eliminated.
You don't have to remember what you wrote, if the fields are always fixed width.
While not optimal, constantly updating the display with the same characters including numbers will not cause flicker.
An optimization, would be to only update the display when something (like the number(s)) change.
using xxprintf() would make it easy to print the lines with fixed width fields.
However..... If the Arduino being used is using an AVR, like an Uno or Mega etc..., then floating point in sprintf() is not supported by default and is quite a pain to enable.
but If using a 3rd party Arduino board with something like an ESPxxxx core, or a Teensy product (including AVR cores), those include xxprintf support in the Print class so you could simply use lcd.printf() with the appropriate formatting string to create the formatted line on the display.
--- bill
Whenever we see someone refer to a "flickering" LCD display, we pretty much know that they are using lcd.clear in the loop() - and that is almost always a bad idea.
Even if you want to change the display to a different menu item or such, it is most efficient to home the cursor and overwrite both lines.
Numerical display sections do need to figure out (in advance) how many digits will be printed and add leading blanks to pad them to a fixed size, so that the decimal does not jump between 9.9 and 10.0 and such.
Paul__B:
Even if you want to change the display to a different menu item or such, it is most efficient to home the cursor and overwrite both lines.
Not sure about efficiency, but it is definitely faster to write all 32 characters on the 16x2 display than to use the "Clear Display" command, which is what clear() does.
The home() function is also very slow much slower than setCursor(0,0) as home() uses the "Return Home" command which does lots of internal initialization inside the display.. i.e. home() is very different from setCursor(0,0)
setCursor() takes the same amount of time as writing a single character to the display.
thaks for you all for your interaction ,
i understand that i ought to remove clear() , but the lcd must show me when i will set time to let the code count correctly the date of hatching , and as you will see in the picture in the attachement it show me only the temperature in the first line , in the second one humidity which not clear (look at the picture please)
It is not clear what you want to happen. Explain to us how you want all (three?) things to appear.
Post your current code.
the code must allow me to set the date with tow buttons first , and show the temperature and humidity measured by a DHT22 sensor , that's all , other parts of code is to command the relays for a bulb that's all .
the code is true on IDE but it don't give what i want on LCD . it makes me crazy
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#define DHTPIN 4 // Define the temp sensor data pin
#define DHTTYPE DHT22 // define the temp/hum sensor type
#define RELAY_1 8 // define the relay 1 to 4 control pins
#define RELAY_2 9
#define RELAY_3 10
#define RELAY_4 11
DHT dht(DHTPIN, DHTTYPE); //initialize the temp sensor
LiquidCrystal_I2C lcd(0x27,16,2); //set up what port the LCD will use
int istate = 0;
const int buttonPin1 = 5; // the pin that the Up pushbutton is attached to
const int buttonPin2 = 6; // the pin that the Down pushbutton is attached to
int buttonState1 = 0;
int buttonState2 = 0;
float val = 0 ; //val to increment/decrement (buttons/ threshold)
int is, im, ih, id, ida, iha, ima; // variables for time
float time, s1, m1, h1, d1; // Set up variables to calculate time
int ic, ip, ik;
byte thermo[8] = {B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110}; //thermometer icon
byte drop[8] = {B00100, B00100, B01010, B01010, B10001, B10001, B10001, B01110}; //drop icon
byte arrow[8] = { B00100, B01010, B10101, B00100, B10101, B01010, B00100,}; // smile icon
byte tim[8] = {B00000, B01110, B10101, B10101, B10011, B10001, B01110,}; // clock
int END = 0;
boolean rotate = 0;
unsigned long previousMillis = 0;
const long interval = 3600000UL; //timer for roll eggs 1HOUR
void setup()
{
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
dht.begin(); //start the temp sensor
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
pinMode(RELAY_3, OUTPUT);
pinMode(RELAY_4, OUTPUT);
digitalWrite(RELAY_3,HIGH);
digitalWrite(RELAY_4,LOW);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Incubator 1.0");
lcd.setCursor(0, 1);
lcd.print("A initier!");
delay(2000);
lcd.createChar(0, thermo);
lcd.createChar(1, drop);
lcd.createChar(2, arrow);
lcd.createChar(3, tim);
dht.begin();
}
//loop to read the sensor and display
void loop() {
int buttonState1 = digitalRead(buttonPin1);
int buttonState2 = digitalRead(buttonPin2);
delay(10);
if (buttonState1 == HIGH)
{
val-=0.1;
}
else if (buttonState2 == HIGH)
{
val+=0.1;
}
float h = dht.readHumidity(); // Read the humidity
float t = dht.readTemperature(); // Read temperature in celsius
float f = dht.readTemperature(true); // get the temperature in Fahreheit
//Temperature controller
if (t >= (37.7 + val))
{ // Set the temperature for the relay to come on (ideal 37.7ºC)
digitalWrite(RELAY_1,LOW); // TO HOT: Turns Relay OFF
digitalWrite(RELAY_2,LOW);
}
if (t <= (37.5 + val))
{ // Set the temperature for the relay to come on (ideal 37.7ºC)
digitalWrite(RELAY_1,HIGH); // TO HOT: Turns Relay ON
digitalWrite(RELAY_2,HIGH);
}
// uncomment to compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
time = millis(); // Get time in milliseconds since tunit turn on
s1 = time / 1000; // Convert time to seconds, minutes, hours, days
m1 = s1 / 60;
h1 = m1 / 60;
d1 = h1 / 24;
id = int(d1); //d // Strip out remainder to leave Days:Hours:Minutes:Seconds
ih = int((d1 - int(d1)) * 24); //h
im = int((h1 - int(h1)) * 60); //m
is = int((m1 - int(m1)) * 60); //s
// Calculate approximate TIME till hatch (assume 21 days to hatch) - not used yet
ida = 21 - id;
iha = 24 - ih;
ima = 60 - im;
if (isnan(h) || isnan(t) || isnan(f)) {
// if sensor can't be read
lcd.setCursor(0, 0);
lcd.print("Sensor Failure");
lcd.print("Sensor Failure" );
digitalWrite(RELAY_1,HIGH); // ERRO: Turns 1 Relay OFF to not kill all the eggs
digitalWrite(RELAY_2,LOW);
delay(5000);
return;
}
else { // for LCD 16x2
//sensor was read succesfully so print values to LCD 16x2
// Clear the LCD
//Print temperature and humidity in first two lines
lcd.setCursor(0, 0);
lcd.print("Temperature:");
lcd.write(byte(0)); // Write the Thermometer icon
lcd.print(t , 1);
lcd.print((char)223);
lcd.print("C ");
lcd.setCursor(0,1);
lcd.write(byte(1)); // Write the drop icon
lcd.print("Humidade:");
lcd.print(h, 0);
lcd.print("%");
lcd.print(" ");
lcd.print(ic);
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.write(byte(3));
lcd.print(" ");
// Print timein format Time: xxd:xxh:xxm:xxs
lcd.print(id);
lcd.print("d ");
lcd.print(ih);
lcd.print(":");
lcd.print(im);
lcd.print(" ");
lcd.print(is); lcd.print(" ");
lcd.print(val,1);
if (21 - id <= 3){
// Print days left till hatch
lcd.print("!");
END = 1; //stop move eggs
}
}
// this section is to roll eggs
if (END==0){
if (ih%2==0){
if ( ih%4==0 && rotate ==1){
digitalWrite(RELAY_3,HIGH);
digitalWrite(RELAY_4,LOW);
rotate = 0 ;
}if ( ih%4 != 0 && rotate == 0){
digitalWrite(RELAY_3,HIGH);
digitalWrite(RELAY_4,LOW);
rotate = 1 ;
}
}
}
}
Achref-Abbassi:
the code must allow me to set the date with tow buttons first , and show the temperature and humidity measured by a DHT22 sensor , that's all , other parts of code is to command the relays for a bulb that's all .
the code is true on IDE but it don't give what i want on LCD . it makes me crazy
That isn't what your code is doing.
I see no date support in this code.
The code does calculate elapsed total days, hours, minutes, seconds and then the fraction portion of hours, minutes, seconds elapsed, since the arduino was reset but has no knowledge of the actual date or time.
It also supports setting a value to control temperature with two buttons, but nothing related to setting a date or an elapsed time.
Using millis() time tracking can be an issue since if there is ever a power loss, time starts over again.
Also, the millis() counter will roll over after a period of time. If the counter is 32 bits - which is common - then it rolls over after around 49 days. That may or may not be acceptable for your use.
The issue for your LCD display is/was more than just using clear()
You are trying to print more than fits on a 16x2 display, including writing line 1 twice.
Was this code originally intended for a 20x4 display?
Look at the code:
The comment says :
//Print temperature and humidity in first two lines
The code is actually printing 3 lines (overwriting line 1) with more characters than 16 characters on each line and the display is only 16x2.
(I broke it up into 3 sections to describe it)
This code prints on line 0 starting at column 0
lcd.setCursor(0, 0);
lcd.print("Temperature:");
lcd.write(byte(0)); // Write the Thermometer icon
lcd.print(t , 1);
lcd.print((char)223);
lcd.print("C ");
Characters on line 0:
"Temperature:" 12 characters
byte(0) 1 character (garbage since custom char 0 was never setup)
(t,1) 4 characters ##.#
(char)223 1 character
"C " 2 characters
Total of 20 characters on a 16 line display.
Ths code prints on line 1 starting at column 0
lcd.setCursor(0,1);
lcd.write(byte(1)); // Write the drop icon
lcd.print("Humidade:");
lcd.print(h, 0);
lcd.print("%");
lcd.print(" ");
lcd.print(ic);
Characters on line 1
byte(1) 1 character (garbage since custom char 1 was never setup)
"Humidade:" 9 characters
(h,1) 2 characters ##
"%" 1 character
" " 1 character
"C " 2 characters
(ic) 1 character 0 (will not print a custom char, is zero since never initialized/used)
Total of 17 characters on a 16 line display.
This code also prints on line 1 starting on column 0 immediately overwriting the previous characters written to line 1
The characters printed will vary in length and position depending on the values of the variables.
It is not printing fixed width fields for the numbers.
Overwriting the line along with printing characters whos locations move around depending on the values of the numbers is the main issue causing visual issues on the display.
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.write(byte(3));
lcd.print(" ");
// Print timein format Time: xxd:xxh:xxm:xxs
lcd.print(id);
lcd.print("d ");
lcd.print(ih);
lcd.print(":");
lcd.print(im);
lcd.print(" ");
lcd.print(is); lcd.print(" ");
lcd.print(val,1);
characters on line 1
" " 1 character
byte(3) 1 character (garbage since custom char 3 was never setup)
" " 1 character
(id) 1-2 characters depending on value of number
"d" 1 character
(ih) 1-2 characters depending on value of number
":" 1 character
(im) 1-2 characters depending on value of number
" " 1 character (note: other seperators are ":" not <space>
(is) 1-2 characters depending on value of number
" " 1 character
(val,1) 4+ characters ##.# but could be more depending on value
Total of 15-19+ characters on a 16 line display.
[tt]
[hr]
You have some work to fix these issues.
--- bill
tank you very much Bill , i found solution thank to your help , you can see the picture in the attachement .
about time (clock) i think to use an RTC and the EEPROM but may be it's too hard since am a begginer in arduino , if you don't mind could you explain me how can i use it please ?
thank you again
Simply using an RTC is not too difficult, as there are libraries to do that.
When using actual time/date things can start to get complicated depending on how you want to handle daylight savings time adjustments.
For time tracking, I like to use the unix way of time tracking which simplifies things down to seconds since a fixed point in time.
Libraries like Time/Timelib and many of the RTC libraries also support tracking time this way..
Local timezone conversion and DST adjustments is a bit messy as the most common/popular library Time/TimeLib does not support timezones or DST changes.
One thing that could work for your application If you have network access, would be to simply get the timestamp from a time server.
You wouldn't need an RTC, and the code would work just like what you have today, in that you get a number that you calculate an offset from. The only difference would be the number is usually seconds instead of milliseconds.
This method would avoid any date/time settings, local timezones and the DST issue.
All you would then need to do is store a calculated ending "time" timestamp value in EEPROM whenever you started the cycle or set it.
When the board starts up, read the EEPROM and if the "time" saved is in the future, use it to continue.
This would allow recovering from a power failure.
Not sure which Arduino you have, but some like the ESP8266/ESP32 boards have built in WiFi.
The ESP parts are very cool because they have so much horsepower and resources.
They make it easy to things like create web pages so you can access the device remotely.
These are the libraries I'd recommend looking at for various time tracking capabilities
Time/Timelib - Most popular date/time tracking library
Uses unix epoch time tracking. Does not support DST changes
Has examples for how to use with an RTC or with a network connection instead of RTC.
Available in IDE library manager (search for TimeAlarms)
TimeAlarms - addon for Time/Timelib to add events/alarms
Available in IDE library manager
DST3232RTC - very good RTC library for DS3231/DS3231 modules
Works with Time/Timelib library
TimeZone - adds DST support to Time/TimeLib library
It allows setting DST rules to do local time and DST conversions.
While it isn't handling the unix properly to do this, it does work well.
Note: there is no way to handle unix time_t values properly when using the Time/TimeLib library since it is unaware of timezones.
Available in the IDE library manager.
EzTime - has date/time, DST, and network time support and a nice NTP client.
Has very good timezone and DST support including being able to set DST rules for any locale.
note: there are some issues/bugs in it - some people still use, but it is not usable for my projects
Available in IDE library manager
--- bill
grate !
thank you very much