marți, 25 august 2015

Afisaj matriceal din 8x8 leduri controlat de MAX7219 (2)

   In articolul precedent am prezentat modululele de afisare din 8x8 leduri controlate de MAX7219, folosind librariile Ledcontrol si apoi MaxMatrix
   Am realizat o varianta de ceas cu date meteo cu 4 module de afisare, la care se regleaza automat nivelul intensitatii luminoase a afisajului in functie de mediu si am folosit urmatoarele:
- modul cu DS3231 pentru partea de ceas si data (functioneaza fara modificari si DS1307)
- senzor DHT22 pentru temperatura si umiditate
- fotorezistenta montata intr-un divizor rezisitiv
   Montajul arata asa:
iar schema folosita a fost:
   In timpul experimentelor, am tot alimentat montajul ba din mufa usb, ba direct pe pinul +5V si GND si am observat ca uneori apar probleme la partea de ceas, aparand date eronate, asa ca am cautat solutii hard si soft si m-am oprit la una soft, de "curatire" a magistralei i2c, dupa cum am gasit in articolul Reliable Startup for I2C Battery Backed RTC Why the Arduino Wire library is not enough:
/**
 * I2C_ClearBus
 * (http://www.forward.com.au/pfod/ArduinoProgramming/I2C_ClearBus/index.html)
 * (c)2014 Forward Computing and Control Pty. Ltd.
 * NSW Australia, www.forward.com.au
 * This code may be freely used for both private and commerical use
 */

#include <Wire.h>

/**
 * This routine turns off the I2C bus and clears it
 * on return SCA and SCL pins are tri-state inputs.
 * You need to call Wire.begin() after this to re-enable I2C
 * This routine does NOT use the Wire library at all.
 *
 * returns 0 if bus cleared
 *         1 if SCL held low.
 *         2 if SDA held low by slave clock stretch for > 2sec
 *         3 if SDA held low after 20 clocks.
 */
int I2C_ClearBus() {
  TWCR &= ~(_BV(TWEN)); //Disable the Atmel 2-Wire interface so we can control the SDA and SCL pins directly

  pinMode(SDA, INPUT_PULLUP); // Make SDA (data) and SCL (clock) pins Inputs with pullup.
  pinMode(SCL, INPUT_PULLUP);

  delay(2500);  // Wait 2.5 secs. This is strictly only necessary on the first power
  // up of the DS3231 module to allow it to initialize properly,
  // but is also assists in reliable programming of FioV3 boards as it gives the
  // IDE a chance to start uploaded the program
  // before existing sketch confuses the IDE by sending Serial data.

  boolean SCL_LOW = (digitalRead(SCL) == LOW); // Check is SCL is Low.
  if (SCL_LOW) { //If it is held low Arduno cannot become the I2C master. 
    return 1; //I2C bus error. Could not clear SCL clock line held low
  }

  boolean SDA_LOW = (digitalRead(SDA) == LOW);  // vi. Check SDA input.
  int clockCount = 20; // > 2x9 clock

  while (SDA_LOW && (clockCount > 0)) { //  vii. If SDA is Low,
    clockCount--;
  // Note: I2C bus is open collector so do NOT drive SCL or SDA high.
    pinMode(SCL, INPUT); // release SCL pullup so that when made output it will be LOW
    pinMode(SCL, OUTPUT); // then clock SCL Low
    delayMicroseconds(10); //  for >5uS
    pinMode(SCL, INPUT); // release SCL LOW
    pinMode(SCL, INPUT_PULLUP); // turn on pullup resistors again
    // do not force high as slave may be holding it low for clock stretching.
    delayMicroseconds(10); //  for >5uS
    // The >5uS is so that even the slowest I2C devices are handled.
    SCL_LOW = (digitalRead(SCL) == LOW); // Check if SCL is Low.
    int counter = 20;
    while (SCL_LOW && (counter > 0)) {  //  loop waiting for SCL to become High only wait 2sec.
      counter--;
      delay(100);
      SCL_LOW = (digitalRead(SCL) == LOW);
    }
    if (SCL_LOW) { // still low after 2 sec error
      return 2; // I2C bus error. Could not clear. SCL clock line held low by slave clock stretch for >2sec
    }
    SDA_LOW = (digitalRead(SDA) == LOW); //   and check SDA input again and loop
  }
  if (SDA_LOW) { // still low
    return 3; // I2C bus error. Could not clear. SDA data line held low
  }

  // else pull SDA line low for Start or Repeated Start
  pinMode(SDA, INPUT); // remove pullup.
  pinMode(SDA, OUTPUT);  // and then make it LOW i.e. send an I2C Start or Repeated start control.
  // When there is only one I2C master a Start or Repeat Start has the same function as a Stop and clears the bus.
  /// A Repeat Start is a Start occurring after a Start with no intervening Stop.
  delayMicroseconds(10); // wait >5uS
  pinMode(SDA, INPUT); // remove output low
  pinMode(SDA, INPUT_PULLUP); // and make SDA high i.e. send I2C STOP control.
  delayMicroseconds(10); // x. wait >5uS
  pinMode(SDA, INPUT); // and reset pins as tri-state inputs which is the default state on reset
  pinMode(SCL, INPUT);
  return 0; // all ok
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  int rtn = I2C_ClearBus(); // clear the I2C bus first before calling Wire.begin()
  if (rtn != 0) {
    Serial.println(F("I2C bus error. Could not clear"));
    if (rtn == 1) {
      Serial.println(F("SCL clock line held low"));
    } else if (rtn == 2) {
      Serial.println(F("SCL clock line held low by slave clock stretch"));
    } else if (rtn == 3) {
      Serial.println(F("SDA data line held low"));
    }
  } else { // bus clear
    // re-enable Wire
    // now can start Wire Arduino master
    Wire.begin();
  }
  Serial.println("setup finished");
}

void loop() {
  // put your main code here, to run repeatedly:
  // do Wire RTC stuff here.
}
   Sketch-ul meu, adaptat acestei solutii este maxmatrix_DS3231_clear_DHT22_4digit_ver6m0.ino !!!
   Ulterior, m-am gandit ca in locul senzorului DHT22 sa folosesc un sensor DHT11 pentru date de umiditate, avand in vedere ca precizia este suficienta, iar pentru temperatura sa folosesc un senzor DS18B20.
   Pentru a folosi doar un DHT11 in locul lui DHT22, se fac modificari minore in sketch:
in
   Daca se doreste si o temperatura cu precizie buna, se poate folosi partea de citirea unui senzor DS18B20 cum e prezentata in materialul de la http://arduinoprojects.ru/ (in care pinul de date este la D8) si astfel sketch-ul devine maxmatrix_ds18b20_dht_4module_ver7m0.ino.
   Schema se modifica foarte putin, dupa cum se observa:
iar montajul arata asa:
 
 
   Am facut si un filmulet numit statie meteo si ceas cu data pe afisaj led de 32x8 leduri (4) in care prezint modificarile si cum apar informatiile pe afisajul compus din cele 4 module:
   Am adaugat si partea de a putea alege rezolutia de la 9 la 12 biti, dupa cum se vede in sketch-ul maxmatrix_ds18b20_dht_4module_ver7m1.ino.

10 comentarii:

  1. Buna ziua,
    Urmaresc articolele domnului Nicu Florica cu interes si am realizat multe dintre ele si sunt foarte incantat de ele.
    Am realizat, in ultimele zile, montajul "Afisaj matriceal din 8x8 leduri controlat de MAX7219 (3) publicat de domnul Nicu Florica marti, 3 noiembrie 2015, si am intampinat 2 probleme:
    - in sketch-ul respectiv la randul 27 compilatorul indica eroare pe care am rezolvat-o (inspirandu-ma din alt articol) modificand textul respectiv in PROGMEM const unsigned char CH [] = {
    - a doua problema pe care eu nu pot sa o rezolv este ca prin incarcarea sketch-ului nu afiseaza data si ora reala ci niste date anterioare.
    Daca montajul ar avea butoanede reglaj data si ora totul s-ar rezolva.
    Deci rugamintea mea ar fi daca ma puteti ajuta in rezolvarea acestei probleme.
    Multumesc foarte mult,
    Cezar Armasescu
    adresa de e-mail: cezar_armasescu@yahoo.com

    RăspundețiȘtergere
  2. depinde de compilator (versiune Arduino IDE) pt prima eroare.. xred ca in sketch a ramas activ sa incarce data si ora calculatorului.. trebui comentala linia unde RTC-ul incarxa ora de la PC... acum sunt pe telefon si nu vad sketch-ul... dar e undeva in SETUP...

    RăspundețiȘtergere
    Răspunsuri
    1. Cezar Armasescu 10 februarie 2016, 7:52
      Buna dimineata,
      Multumesc pentru raspuns.
      Eu sunt incepator in domeniul programarii. Am folosit un RTC cu DS3231, iar in sketch se vorbeste de DS1307, dar stiu ca sunt echivalente deci ar trebui sa mearga si cu acesta. Am sa incerc cu un alt RTC si sa incarc din nou sketch-ul si sa vad daca se rezolva problema. In momentul in care aveti timp si posibilitatea sa va ganditi la aceasta problema astept un sfat de la dumneavoastra.
      Cu stima,
      Cezar Armasescu

      Ștergere
    2. dati-mi pe mail versiunea incarcata sa fac modificarea.. dar cred ca aici e problema:
      RTC.begin();
      if (! RTC.isrunning()) {
      //Serial.println("RTC is NOT running!");
      // following line sets the RTC to the date & time this sketch was compiled
      RTC.adjust(DateTime(__DATE__, __TIME__));
      }
      trebuie schimbate cu
      RTC.begin();
      // if (! RTC.isrunning()) {
      //Serial.println("RTC is NOT running!");
      // following line sets the RTC to the date & time this sketch was compiled
      // RTC.adjust(DateTime(__DATE__, __TIME__));
      //}
      ....

      Ștergere
  3. Nu stiu adresa dvs de mail.
    Ultima data am incarcat sketch-ul: maxmatrix_ds18b20_dth_4module_ver7m0.ino
    Multumesc pentru timpul acoedat.
    Cezar Armasescu
    adresa de e-mail:cezar_armasescu@yahoo.com

    RăspundețiȘtergere
  4. Am incarcat sketch-ul cu modificarile transmise de dumneavoastra, dar problema nu s-a rezolvat, afiseaza data 01.01.2000, iar ceasul 00:00.
    Lasand montajul sa functioneze RTC-ul incepe sa numere minute.
    Poate mai trebuie ceva modificat/completat in sketch.
    Multumesc.
    Cezar Armasescu

    RăspundețiȘtergere
    Răspunsuri
    1. nu cumva bateria e moarta? si trebuie lasat sketch-ul ca inainte?

      Ștergere
  5. Modulul RTC si bateria sunt noi. Am sa schimb bateria totusi si am sa schimb si RTC cu altul. Am sa va comunic ce rezultate obtin.
    Multumesc.
    Cezar Armasescu

    RăspundețiȘtergere
  6. Am inlocuit RTC DS3231 cu un RTC DS1307 nou, am incarcat skerch-ul ver 7m0.ino, fara modificari si este in regula, s-au incarcat data si ora corecte. Nu-mi explic dece cu DS3231 nu functioneaza corect. De fapt pe modulul DS3231 exista niste ploturi denumite A0, A1, A2, care se pot shunta si probabil se aleg niste moduri de functionare, insa in documentatia gasita pe internet nu spune nimic despre aceasta operatie.
    Va multumesc pentru colaborare si imi cer scuze de deranj.
    Cezar Armasescu

    RăspundețiȘtergere