Graag feedback op een oplossing die ik gemaakt hebt voor een YT cursus

HOi,

In de tussentijd heb ik een lesje gemaakt van de McWorther arduino cursus waar ik een temperatuur en luchtvochtigheid moet meten en laten zien op een lcd scherm.

Wat vinden jullie van de layout en de code

Wokwi : https://wokwi.com/projects/447268238706550785

Code :

#include "DHT.h"
#include "LiquidCrystal.h"

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal LCD(12, 8, A5, A4, A3, A2);

float temp;
float humidity;

unsigned long lastRead = 0;
const unsigned long interval = 2000; // 2 seconds

void readSensor() {
  temp = dht.readTemperature();
  humidity = dht.readHumidity();

  if (isnan(temp) || isnan(humidity)) {
    LCD.clear();
    LCD.setCursor(0, 0);
    LCD.print("Sensor Error!");
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
}

void displayData(String text, float measurement, String symbol, int pos) {
  LCD.setCursor(0,pos); 
  LCD.print(text); 
  LCD.setCursor(8,pos); 
  LCD.print(":"); 
  LCD.setCursor(10,pos); 
  LCD.print(measurement); 
  LCD.setCursor(14,pos); 
  LCD.print(symbol);
}



void setup() {
  Serial.begin(9600);
  dht.begin();
  LCD.begin(16, 2);

  LCD.print("DHT22 Monitor");
  delay(1000);
  LCD.clear();
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - lastRead >= interval) {
    lastRead = currentMillis;
    
    readSensor();        
    displayData("Temp", temp, "C", 0); 
    displayData("Humitidy", humidity, "%",1 ) ;    
  }
}

Wanneer de temperatuur negatief wordt, of de luchtvochtigheid 100,00% is, herstelt het display zich niet.

Dank je

Ik moet even goed nadenken hoe dit op te lossen.

Ik kan de lcd helemaal leeg maken maar dat geeft een flikkerend beeld en dat is ook niet mooi

Begin met afdrukken waar 100,0 het % niet dekt of -99,9 de C niet dekt... lcd.print(11,0);

100.0.. Geen ruimte 
x99.9.. Voorvoegsel één spatie 
xx9.9.. Voorvoegsel twee spaties 
x-0.1.. Voorvoegsel één spatie 
-10.0.. Geen ruimte 
-99.9.. Geen ruimte

Dank je

Ben nog niet helemaal blij
IK ga morgen even verder kijken hoe ik dit op kan lossen.

Code gebruiken... iemand zoals ...

if ((value < 100) && (value > 9))
  lcd.print(" ");
if ((value < 10) && (value > 0))
  lcd.print(" ");
.
.
.

Dat kun je ook ondervangen.
Schrijf alleen iets naar je LCD als er ook iets verandert.
Bewerkingen op je LCD nemen relatief veel tijd in beslag en zijn daarmee duur.
Ik noem dat bewerkingen, omdat het wissen van je scherm, niets anders is als het schrijven van spaties.
In de LCD van het plaatje hierboven zou je bij het leegmaken van je LCD eerst 32 spaties sturen, en daarna 32 andere tekens.
En dat kost dus veel dure microcontroller-tijd.
Wanneer je eerst bekijkt of er wel iets veranderd moet worden, kun je veel tijd besparen wanneer er helemaal niets veranderd is (want dat bekijken kost juist heel weinig tijd).
Ik weet dat dat lastig voor je is, maar in dit antwoord zit ook een hint naar waar xfpd het over heeft, alleen staat het er niet direct in woorden in en moet je het tussen de regels door er uit zien te halen.

oke

Even verder spelen dan.
IK ben ook nog niet helemaal tevreden dat als de luchtvochtigheid 100% is, de % wegvalt.

Dat wordt dus of "huminity" afkorten of gaan voor een soort scrolling effect waar je eerst de temperatuur ziet en na bijvoorbeeld 4 seconden de luchtvochtigheid

Dit lijkt beter

#include "DHT.h"
#include "LiquidCrystal.h"

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal LCD(12, 8, A5, A4, A3, A2);

float temp;
float humidity;

float oldTemp = 0; 
float oldHumidity = 0 ; 

unsigned long lastRead = 0;
const unsigned long interval = 2000; // 2 seconds

void setup() {
  Serial.begin(9600);
  dht.begin();
  LCD.begin(16, 2);

  LCD.print("DHT22 Monitor");
  delay(1000);
  LCD.clear();
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - lastRead >= interval) {
    lastRead = currentMillis;
    
    readSensor();        
    displayData("Temp", temp, "C", 0); 
    displayData("Humitidy", humidity, "%",1 ) ;    
  }
}

void readSensor() {
  temp = dht.readTemperature();
  humidity = dht.readHumidity();

  if (isnan(temp) || isnan(humidity)) {
    LCD.clear();
    LCD.setCursor(0, 0);
    LCD.print("Sensor Error!");
    Serial.println("Failed to read from DHT sensor!");
  }

  if (oldTemp != temp || oldHumidity != humidity) {
    LCD.clear(); 
    oldTemp = temp; 
    oldHumidity = humidity;  
  }
}

void displayData(String text, float measurement, String symbol, int pos) {
  LCD.setCursor(0,pos); 
  LCD.print(text); 
  LCD.setCursor(8,pos); 
  LCD.print(":"); 
  LCD.setCursor(10,pos); 
  LCD.print(measurement); 
  LCD.setCursor(14,pos); 
  LCD.print(symbol);
  LCD.setCursor(15,pos); 
  LCD.print(" "); 
}

Alleen hou ik er niet van dat ReadSensor nu ook de lcd bestuurd.
En het probleem blijft dat bij luchtvochtigheid van 100% er dit in de lcd staat
humidity 100.% in plaats van humidity 100.00%

Dus nog even doorpuzzelen

iemand een slimme oplossing.

De makkelijkste zou zijn om de luchtvochtheid alleen in gehele getallen te doen.

Mooiste zou zijn om eerst de een te zien en dan een soort scrollende beweging en dan de andere.

Je vroeg om commentaar, dus hier komt nog wat:
Ik zie nu 2 zpelvauten voorbij komen:
1 keer "Humitidy" in het plaatje van je LCD, en 1 keer "huminity" in de post een stukje naar boven.
Het Engelse woord voor luchtvochtigheid, is Humidity.
Je kunt dat afkorten naar Hum, dan de beide : eventueel (hoeft niet maar ik zou dat wel doen) nog 1 positie naar links zetten waardoor er altijd een spatie staat tussen de : en de veranderende waarde.
Verder kun je dan je procent en je Celsius teken vastzetten op de laatste positie van de betreffende regel.
Het juist positioneren van veranderende waardes is al vaker hier op het forum besproken en daarbij ook uitgewerkt, kan best wat codeerwerk zijn maar is geen rocket science.

Ik ben het met je eens dat dit misschien wel duidelijker en mooier kan.
Wel lijkt het me een goed idee om het eerst werkend te krijgen, en het daarna mooier te maken, maar dat is wel aan jou.

Ik zie een functie die heet displayData.
In die functie print je alle inhoud naar je scherm, maar dan per lijn.
Dat betekent dat je heel veel met variabelen zit te pingpongen tussen fucnties.
En het betekent ook dat je iets anders doet dan eerder is geadviseerd.

In je laatste post zie ik ook iets voorbij komen over scrollen, maar dat kijkt mij niet nodig voor de beperkte hoeveelheid gegevens die je hier wil weergeven.

Ik stel een iets andere werkwijze voor (omdat ik dat al vaker heb gebruikt en daar zelf
tevreden over ben).
Maak 3 zones in je scherm.
De eerste zone is het format.
Daar schrijf je eenmalig de vaste inhoud naar je scherm, dus de inhoud die nooit hoeft te veranderen.
Daar kun je ook een eigen functie van maken, en je kunt ook overwegen of je dat voor deze sketch binnen of buiten loop() wil doen (vanwege dat eenmalige).
Dan heb je de 2e zone waar je de graden weergeeft, en de 3e zone waar je de luchtvochtigheid weergeeft.
Alleen dat stukje zou ik in een functie zetten die heet displayData en dan zijn er dus 2 functies die je display kunnen aansturen.

Als je dit terugleest, zie je dan overeenkomsten met wat er eerder geadviseerd is ?

Ik zie dat je ook een foutmelding wil kunnen weergeven op je LCD, omdat dat nou eenmaal je communicatie middel naar de gebruiker is.
Ik vind het zelf helemaal niet zo'n probleem dat je in dat uitzonderlijke geval je LCD apart aanstuurt.
Tenzij je meerdere foutmeldingen kunt hebben en een procedure wil volgen waarin deze worden weergegeven (bijvoorbeeld in volgorde van belangrijkheid van deze meldingen, zoals dringendst eerst).
Dat zou dus een 3e LCD aansturende functie zijn.

Wanneer deze melding tijdelijk kan zijn, dan moet je daarna wel weer dat format van je display aanroepen na het verlopen van de melding.

Ik zie ook dat je heel grof kijkt of er data veranderd is, en je in dat geval je hele scherm wist.
Dat is ook niet wat er eerder geadviseerd is en zal daarom ook een minder stabiel beeld geven.

Ik hoop dat dit bericht te volgen is en dat je er weer een stapje mee kunt zetten.

oke

Je bedoeld als dit :

                   temperatuur             luchtvochtigheid
                     19.0                                 80

Zie alleen niet hoe je de eerste zone bedoeld.

of bedoel je meer als dit

temperatuur                       19.0 C 
luchtvochtigheid                                               80%

En is de lcd nu wel of niet goed aangesloten ?

Chips,

Dit werkt niet

#include "DHT.h"
#include "LiquidCrystal.h"

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal LCD(12, 8, A5, A4, A3, A2);

float temp;
float humidity;

float oldTemp = 0; 
float oldHumidity = 0 ; 

unsigned long lastRead = 0;
const unsigned long interval = 2000; // 2 seconds

void setup() {
  Serial.begin(9600);
  dht.begin();
  LCD.begin(16, 2);

  LCD.print("DHT22 Monitor");
  delay(1000);
  LCD.clear();

  LCD.setCursor(0,0); 
  LCD.print("Temp"); 
  LCD.setCursor(8,0); 
  LCD.print(":"); 
  LCD.setCursor(11,0); 
  LCD.print(temp);
  LCD.print("C");
  
  LCD.setCursor(0,1) ;
  LCD.print("Humidity: "); 
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - lastRead >= interval) {
    lastRead = currentMillis;
    
    readSensor(); 
    displayData();        
   
  }
}

void readSensor() {
  temp = dht.readTemperature();
  humidity = dht.readHumidity();

  if (isnan(temp) || isnan(humidity)) {
    LCD.clear();
    LCD.setCursor(0, 0);
    LCD.print("Sensor Error!");
    Serial.println("Failed to read from DHT sensor!");
  }

}

void displayData() {

  if (oldTemp != temp) {
    LCD.setCursor(10,0); 
    LCD.print("    "); 
    LCD.setCursor(10,0); 
    LCD.print(temp);
    oldTemp = temp; 
  }
  
}

@MAS3 kun je eens een tekening maken of wat jij bedoeld.

Blauw is zone 1.
Oranje is zone 2.
Rood is zone 3.

Dit is heel eenvoudig te maken en volgens mij ook veel simpeler te managen dan wat je tot nog toe hebt geprobeerd.
Als je dit onder de knie hebt, kun je soortgelijke dingen voor andere sketches gebruiken (met veel meer zones bijvoorbeeld).
Neem het begrip zone niet al te nauw, dat hoef je zo niet uit te werken in een sketch waarin je zones definieert ofzo.
Wat ikzones noem is om het in het hoofd voor te kunnen stellen waar welke informatie getoond wordt.

oke

Dan ben ik dus op de goede weg.

Zie alleen niet hoe ik de code veel simpler kan maken

En waar ik tegenaan loop is als voorbeeld dit :

hier neemt de temperatuur zoveel ruimte in dat de C wegvalt omdat de regel groter wordt als 16 characters.

Zo misschien is dit wel een idee dan :

temp :                     humidity: 
-40.00C                     100%

of misschien een 20 x 4 lcd pakken.
Heb ik wel 2 lege regels maar dat is denk ik minder frusterend dan dat nu dingen wegvallen

Deze opdracht maakt me gek

Heb de iets grotere lcd gepakt en de code wat aangepast.
En wat ik ook doe als ik van een negatief groot getal naar iets anders ga,blijft de laatste nul staan.

Je conclusie uit je eerste antwoord is niet helemaal juist.
En het probleem is dan ook niet helemaal wat je denkt.
Want er staat een spatie na de :
Die spatie kan ook gebruikt worden voor de min of voor de honderdtallen.
Maar je moet je ook afvragen hoeveel tekens je wil weergeven, en dat dan reserveren.
Je kunt gewoon controleren of je een negatief getal bij de temperatuur moet gaan weergeven, en in dat geval de betreffende ruimte reserveren.
Bij de luchtvochtigheid kom je zelden een negatief getal tegen.
Wanneer je een negatief getal hebt, kun je daarna ook controleren of dat nog steeds het geval is, en wanneer niet daar de passende maatregel op nemen.
Hetzelfde geldt voor de honderdtallen, heb je die, moet je de ruimte ervoor reserveren.
Heb je die niet dan hoeft dat ook niet, en heb je die niet meer, is er weer een daarbij passende maatregel.

Wat je nu dus eerst moet gaan doen, zonder dat je meteen code gaat schijven, is een overzicht maken van welke waardes je allemaal kunt verwachten, en hoeveel ruimte dat gaat innemen.
Daar kun je dan dus de ruimte alvast voor reserveren bij het bepalen van de groottes van de zones.
Zijn er waardes die je wel zou kunnen meten maar niet weer wil geven omdat ze buiten je (praktische) meetbereik komt, kun je daar ook nog wat mee doen op je LCD door niet die waarde maar een bijpassende mededeling te printen.

oke

met de temp kan ik de volgende groottes tegenkomen

getal                            grootte 

-40.0                              5 
- 4.0                              4
0.0                                3
4.0                                3
10.0                              4 

Dus voor elk getal verschillende spaties nemen ??

maar dan kan ik ook een string maken en dan de lengte nemen.

dan wordt het zoiets als spaties = len( input as string)

Ben ik nu op de goede weg ?

of zoiets doen als dtostrf(temp, 5, 1, tbuf);
Dan weet ik altijd zeker dat alles 5 characters lang is.
dan kan ik altijd 5 spaties gebruiken