Se afișează postările cu eticheta LCD2004. Afișați toate postările
Se afișează postările cu eticheta LCD2004. Afișați toate postările

vineri, 24 octombrie 2025

Ceas RTC cu caractere mari si date meteo pe afisaj LCD2004 (2)

   La rugamintea lui Gabi Loreti am inlocuit unul din senzorii DHT22 (AM2302) din proiectul anterior cu un senzor combinat AHT20 cu BMP280.

   El e pasionat, in general, doar de afisaje VFD sau OLED, dar i-a placut modul cum arata informatiile pe un afisaj alfanumeric LCD2004, asa ca am modificat programul proiectului anterior si acum acesta este big_font_weather_clock_v2a.ino.
    Gabi a facut mai multe poze pentru a face un articol, avand in vedere ca poate fi interesant si pentru altii:
   Noul mdulul contine 2 senzori ce sunt conectati pe i2c, iar la cautarea cu programul (care ar trebui sa fie arhicunoscut) i2c_scanner obtinem
si daca mai cautam pe internet gasim ca senzorul AHT20 este conectat la adresa 0x38, iar senzorul BMP280 la 0x77 (dar poate fi si 0x76).
   Schema de conectare este simpla
  Deoarece acest modul ce contine acesti senzori mi s-a parut interesant, am comandat si eu cativa, si am facut si eu teste:
inclusiv niste filmulte:



luni, 13 octombrie 2025

Termostat reglabil cu ceas RTC si afisaj LCD2004

    Dupa ce am fost multumit de modul de afisare, reglare si stabilitate la proietul anterior, de Ceas RTC cu caractere mari si termometru pe afisaj LCD2004 am trecut s la partea de proiect mult mai util, un termostat reglabil cu ceas RTC.

   Schema deriva din cea a ceasului, doar ca am pus 3 leduri, unul rosu pentru temperatura scazuta (sub pragul de temperatura), unul verde pentru temperatura normala (valoare peste pragul de temperatura) si unul galben pentru a simula comanda la centrala / calorifer electric. etc (care se aprinde cand temperatura este sub pragul de temperatura si se stinge la depasirea pragului de temperatura plus valoarea histerezisului)

   La o apasare scurta se comuta afisarea cu caractere mari a orei cu cea a temperaturii, apoi iar ora, etc.
   Cateva exemple:
- temperatura mai mica decat pragul reglat (led rosu aprins, led galben aprins, adica incalzitor pornit, pe afisaj apare si o steluta indicand pornirea sistemului de incalzire)
- temperaura peste pragul reglat, dar mai mica decat pragul de oprire (led verde pornit indicand faptul ca temperatura e mai mare decat valoarea reglata, led galben aprins insemnand ca sistemul de incalzire e pornit, iar pe afisaj este si steluta)
- temperatura este peste pragul de decuplare (led verde aprins, led galben stins indicand oprirea sistemului de  incalzire, iar pe ecran nu mai apare steluta)
   Daca apasam lung pe buton (mai mult de 3-4 secunde), se intra in meniul de reglaj, de data asta avem:
- reglaj temperatura
- reglaj histerezis
- reglaj an
- reglaj luna
- reglaj zi
- reglaj minute
- reglaj secunde
    Am facut si niste filmulete:
PS: Programul (sketch-ul) adaptat de mine si folosit este big_font_clock_thermometer_v5a.ino !

marți, 7 octombrie 2025

Ceas RTC cu caractere mari si date meteo pe afisaj LCD2004

    In urma unei cautari pentru un ceas cu date meteo si eventual termostat, am dat de cel prezentat in articolul  Big Characters Weather Clock (int/ext temp, hum, press) scris de un conational, Viorel Racoviteanu. Articolul este postat si pe blogul propriu in articolul cu acelasi nume.


   Schema nu este complicata
doar ca are 2 senzori BME280, care au fost de negasit, prin cutii, la momentul testului, ca si un encoder, dar aveam niste senzori DHT22 (AM23202), asa ca am modificat programul, care a  devenit big_font_weather_clock_v1a.ino si are, de asemenea, conexiunea dintre Arduino si afisajul LCD2004 cu o interfata i2c.


   Schema (pe care o s-o adaug mai tarziu) are conexiunile intre placa Arduino si componente astfel:
- cu afisajul prin interfata i2c: SDA la A4 si SCL la A5 (detalii despre asta in articolele Wire si Interface an I2C LCD with Arduino)
- primul senzor DHT22 la D5 (detalii la Arduino - DHT22)
- al doiea senzor DHT22 la D6
- encoder KY-040 cu CLK la D2, DT la D3, SW la D4 (detalii in articolul wokwi-ky-040 Rotary Encoder Reference).
  Am facut si 2 filmulete, fara a avea encoderul montat:
    Ulterior, am montat encoderul, dar nu mi-a placut modul de reglare, care depinde foarte mult cum apasam butonul fara retinere, asa ca am inlocuit modul de reglaj cu unul de il mai folosisem si e preluat din articolul Arduino Astronomical Clock (or Arduino Pond Pump Controller!) scris de A.G.Doswell (Doz' Blog), asa ca programul devine big_font_weather_clock_v2.ino.
    Am facut si de data asta 2 filmulete:

PS: In timpul testelor am constatat ca unul din senzorii DHT22 (AM2302) indica eronat umiditatea, desi testele au fost facute doar in casa, la temperatura si umiditate in limite uzuale (normale), deci inaintea montarii definitive trebuie facute teste de mai lunga durata, pentru a fi siguri ca senzorul va functiona si in conditi extreme (frig/cald, umiditate ridicata, etc)

sâmbătă, 28 iunie 2014

Receptor GPS conectat la un Arduino (3)

   Pana acum am folosit librariile TinyGPS si TinyGPS++ create de Mikal Hart, dar receptorul folosit de mine, nu transmite datele in format GPGCA si GPRMC, ci in format GPGCA si GPVTG si de aceea nu puteam primi informatia despre viteza...
   Am realizat asta abia dupa ce am recitit articolul  tronixstuff: Arduino and EM406A GPS si am retestat primul sketch, fara librarii, cand am obtinut pe ecranul de monitorizare seriala:
   Dupa ce am mai studiat articolul NMEA data, am gasit ca viteza in km/h este in campul $GPVGT, la pozitia a 7-a:
si am reusit sa o "scot" cu ajutorul librariei TinyGPS++, deoarece autorul lor, Mikal Hart, s-a gandit ca mai sunt si alte date si sisteme de codare date, asa ca a creat o comanda speciala de extragere a unei valori dintr-un camp anume, cum este:
TinyGPSCustom magneticVariation(gps, "GPRMC", 10)
care se combina cu cea de afisare:
if (magneticVariation.isUpdated())
{
  Serial.print("Magnetic variation is ");
  Serial.println(magneticVariation.value());
}
   Deoarece eu aveam nevoie de viteza, am folosit urmatoarea parte de extragere a vitezei
   // for speed in kilometers per hour
   TinyGPSCustom zdop(gps, "GPVTG", 7); // $GPVTG sentence, 7th element 
iar partea de afisare:
   // viteza extrasa custom
   lcd.setCursor(0,3); // put cursor at colon x and row y
   lcd.print("viteza: ");
   int viteza = atoi (zdop.value());
   // lcd.print(zdop.value());
   if (viteza>100.0) lcd.print(viteza);
   else
   if (viteza>10.0) {lcd.print(" "); lcd.print(viteza);}
   else 
   if (viteza<10.0) {lcd.print("  "); lcd.print(viteza);}
   lcd.print("km/h");

   Montajul de test, in timp ce masina se deplasa (in stanga este viteza obtinuta cum am aratat mai sus, iar in dreapta e ce ar afisa libraria, adica zero permanent):
 
   Ulterior, am mai modificat sketch-ul si am facut si 2 filmulete:
- receptor GPS si Arduino (3)
receptor GPS si Arduino (4)
   Sketch-ul folosit este:
// source: http://arduiniana.org/libraries/tinygpsplus/
// for see your position: http://www.gps-coordinates.net/
// for new article made by niq_rohttp://nicuflorica.blogspot.com/

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

#include <LiquidCrystal.h>
// folosesc libraria pentru afisaje LCD simple
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// indic modul de legare, vezi mai jos:
/*                                    -------------------
                                      |  LCD  | Arduino |
                                      -------------------
 LCD RS pin to digital pin 7          |  RS   |   D7    |
 LCD Enable pin to digital pin 6      |  E    |   D8    |
 LCD D4 pin to digital pin 5          |  D4   |   D9    |
 LCD D5 pin to digital pin 4          |  D5   |   D10   |
 LCD D6 pin to digital pin 3          |  D6   |   D11   |
 LCD D7 pin to digital pin 2          |  D7   |   D12   |
 LCD R/W pin to ground                |  R/W  |   GND   |
                                      -------------------
niq_ro adapted this sketch for see data on 2004 LCD
*/

// for speed in knots (noduri) 
//TinyGPSCustom sdop(gps, "GPVTG", 5); // $GPVTG sentence, 5th element
// for speed in kilometers per hour
TinyGPSCustom zdop(gps, "GPVTG", 7); // $GPVTG sentence, 7th element 

void setup()
{
  Serial.begin(115200);
  ss.begin(GPSBaud);

  Serial.println(F("FullExample.ino"));
  Serial.println(F("An extensive example of many interesting TinyGPS++ features"));
  Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
  Serial.println(F("Sats HDOP Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum"));
  Serial.println(F("          (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
  Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));


lcd.begin(20, 4); // set up the LCD's number of columns and rows: 

 lcd.clear(); // clear the screen
 lcd.setCursor(1, 0); // put cursor at colon x and row y
 lcd.print("GPS data - 6.2014"); // print a text
 lcd.setCursor(1, 1); // put cursor at colon x and row y
 lcd.print("ver 1.5 by niq_ro"); // print a text
 lcd.setCursor(1, 2); // put cursor at colon x and row y
 lcd.print("Craiova - Romania"); // print a text
 delay (2000);
 lcd.clear(); // clear the screen
}

void loop()
{
  // partea de ecran LCD 20x4
  afisareecran();
  
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);

  unsigned long distanceKmToLondon =
    (unsigned long)TinyGPSPlus::distanceBetween(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON) / 1000;
  printInt(distanceKmToLondon, gps.location.isValid(), 9);

  double courseToLondon =
    TinyGPSPlus::courseTo(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON);

  printFloat(courseToLondon, gps.location.isValid(), 7, 2);

  const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

  printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

  printInt(gps.charsProcessed(), true, 6);
  printInt(gps.sentencesWithFix(), true, 10);
  printInt(gps.failedChecksum(), true, 9);

  // speed in km/h
  Serial.print(" ");
  Serial.print(zdop.value());
  int vitesa1 = atoi (zdop.value());
  Serial.print("/");
  Serial.print(vitesa1);
  Serial.println();
  
  smartDelay(1000);

  if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
}

// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

static void printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
}

static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {

    char sz[32];
   sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
//    sprintf(sz, "%02d/%02d/%02d ", gps.date.month(), gps.date.day(), gps.date.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
//  sprintf(sz, "%02d:%02d:%02d ", gps.time.hour(), gps.time.minute(), gps.time.second());
    Serial.print(sz);

  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

static void printStr(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartDelay(0);
}

static void afisareecran()
{
// lcd.clear(); // clear the screen

// partea de ora
// ora de vara a Romaniei - 
// trebuie sa pun un comutator pentru selectie de iarna si de vara
 int ora = 3 + gps.time.hour();
 if (ora ==24) ora=0;
 if (ora ==25) ora=1;
 if (ora ==26) ora=2;
 lcd.setCursor(0,2); // put cursor at colon 2 and row 2
 if (ora<10) lcd.print(" "); 
 lcd.print(ora); 
 lcd.print(":");
 if (gps.time.minute()<10) lcd.print("0"); 
 lcd.print(gps.time.minute()); 
 lcd.print(":");
 if (gps.time.second()<10) lcd.print("0"); 
 lcd.print(gps.time.second()); 

// parte de coordonate GPS
 lcd.setCursor(0,0); // put cursor at colon 0 and row 0 = left/up
 lcd.print("LAT:");
 lcd.print(gps.location.lat(),6);
 lcd.write(0b11011111);
 lcd.setCursor(0,1); // put cursor at colon 0 and row 1 
 lcd.print("LON:");
 lcd.print(gps.location.lng(),6);
 lcd.write(0b11011111);

// numar sateliti receptionati
 lcd.setCursor(10,2); // put cursor at colon 15 and row 2
 lcd.print(gps.satellites.value());
 if (gps.satellites.value() == 1) lcd.print(" satelit ");
 else lcd.print(" sateliti");

// viteza
/*
lcd.setCursor(10,3); // put cursor at colon x and row y
double viteza = gps.speed.kmph(); 
// tests
// double viteza = 0.;
// double viteza = 5;
// double viteza = 14;
// double viteza = 104;
 if (viteza>100.0) lcd.print(viteza);
 else
 if (viteza>10.0) {lcd.print(" "); lcd.print(viteza);}
 else 
 if (viteza<10.0) {lcd.print("  "); lcd.print(viteza);}
// lcd.print(viteza);
// lcd.print(gps.speed.kmph());
 lcd.print("km/h");
*/

// altitudine
  lcd.setCursor(16,0); // put cursor at colon 16 and row 0
  lcd.print("ALT:");
  int cota = gps.altitude.meters();
  lcd.setCursor(15,1); // put cursor at colon 15 and row 1
// cota=5;
//cota=15;
//cota=497;
//cota=2056;
 if (cota>1000) lcd.print(cota);
 else
 if (cota>100) {lcd.print(" "); lcd.print(cota);}
 else
 if (cota>10) {lcd.print("  "); lcd.print(cota);}
 if (cota<10) {lcd.print("   "); lcd.print(cota);}
 lcd.print("m");
 
// viteza extrasa custom
 lcd.setCursor(0,3); // put cursor at colon x and row y
 lcd.print("viteza: ");
 int viteza = atoi (zdop.value());
// lcd.print(zdop.value());
 if (viteza>100.0) lcd.print(viteza);
 else
 if (viteza>10.0) {lcd.print(" "); lcd.print(viteza);}
 else 
 if (viteza<10.0) {lcd.print("  "); lcd.print(viteza);}
 lcd.print("km/h");
 }  
pentru schema de conectare din articolul anterior:

PS: intre timp am folosit caractere mari pentru viteza:
 
   Am facut si un filmulet numit receptor GPS si Arduino (5):

PS: Am reusit sa fac si niste teste in masina, doar ca am doar poze momentan:

14.7.2014
   In weak-end, am reusit sa mai fac teste pe masina:
inclusiv 3 filmulete: