[TUTORIAL] Orologio/Cronometro con RTC e collegamento ad Internet (Parte 2 di 2)

Ciao a tutti...visto il super successo della prima edizione del blocco orologio, che sinceramente va alla perfezione, vorrei realizzare una nuova versione..
Ho acquistato un arduino yun e vorrei realizzare, quando arriva un impulso dall'esterno, sempre come faceva la versione precedente, riuscire ad inviare un email.
grazie mille in anticipo... :slight_smile:

"Qui comincia l'avventura del sig. Bonaventura ..."
... ok ... questa la capiscono solo quelli di una certa età ... :grin: :grin: :grin:

Pronti ad iniziare questo nuovo progetto ... anche se immagino essenzialmente vorrai trasportarci il vecchio e aggiungerci la parte per l'invio delle eMail tramite la parte Linux.

Ne abbiamo già discusso privatamente e direi che la strada più semplice da seguire, per inviare eMail al tuo account gMail e quella di utilizzare il servizio fornito da Temboo per l'invio di eMail da Arduino Yún :wink:

Direi che potresti cominciare, appunto, nel trasportare il vecchio programma sulla nuova scheda e verificare che tutto funzioni ... :wink:

Guglielmo

ho riprodotto il circuito come l'altro...
ho caricato lo sketch e non funziona.. mi vengono simboli strani..
ho caricato questo..

#include <LiquidCrystal.h>
#include <Wire.h>
//
const byte button  = 8;
const byte button1 = 9;
const byte start   = 6;
const byte stopp   = 7;
const byte led     =10;


//
int secs, mins, hrs, val, secc, minc, hrsc, secSt, minSt, hrsSt, intervallo, statoled, statoled1;
unsigned long currmillis, prevmillis, startmillis, durata, resetTime, momentoAvvenutoCambiamento, tempoled, loopled;
byte fStoContando, fsRTC, fRTCpresente;
//
LiquidCrystal lcd (12, 11, 5, 4, 3, 2);
//
// ------------------- decToBcd -------------------------

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// ------------------- bcdToDec -------------------------

byte bcdToDec(byte val) {
  return ( (val/16*10) + (val%16) );
}

void setup() {
  byte RTCstatus;
  prevmillis = 0;
  val        = 0;
  secs       = 0;
  mins       = 0;
  hrs        = 0;
  fStoContando = false;
  fsRTC        = false;
  momentoAvvenutoCambiamento = 0;
  fRTCpresente = false;
  intervallo  = 10;
  statoled     =0;
  statoled1    =5;


  //
  //inizializzio la libreria
  Wire.begin();
  //  
  //inizio la comunizaione con RTC
  Wire.beginTransmission(0x68);
  delay(50);
  if (Wire.endTransmission() == 0) {
    fRTCpresente=true;
  }
  //
  // Se il modulo è presente e se occorre inizializzo ...
  if (fRTCpresente) { 
    Wire.beginTransmission(0x68);      // Seleziona il  DS1307
    Wire.write(0x00);                  // ... seleziona il "Timekeeper Register" all'indirizzo 0x00"
    Wire.endTransmission();            //
    Wire.requestFrom(0x68, 1);         // ... richiede al RTC di ricevere 1 byte (a partire da 0x00)
    RTCstatus = (Wire.read() & 0x80);  // ... recupera il byte e ne fa AND con 0x80 per ottenere il CH (bit 7)
    if (RTCstatus != 0) {              // ... se il CH (bit 7) è a 1 allora bisogna inizializzare il RTC
      Wire.beginTransmission(0x68);    // Seleziona il DS1307
      Wire.write(0x00);                // ... seleziona il "Timekeeper Register" all'inirizzo 0x00"
      Wire.write(0x00);                // ... scrive 0x00 azzerandolo tutto (CH (bit 7) ed i secondi)
      Wire.endTransmission();
    }
    delay(50);
    //Leggo l'ora
    leggiRTC();
  }
  lcd.begin(16,4);
  lcd.print("ORA");
  lcd.setCursor(0,1);
  lcd.print("CRON");
  lcd.setCursor(-4,2);
  lcd.print("EXIT");
  lcd.setCursor(7,0);
  //
  pinMode(button,  INPUT_PULLUP);
  pinMode(button1, INPUT_PULLUP);
  pinMode(start,   INPUT_PULLUP);
  pinMode(stopp,    INPUT_PULLUP);
  pinMode( led, OUTPUT);
}

// funzioni generali
void loop(){
  aumenta();  
  orologio();
  cronometro();
  ledd();
}

//funzioni RTC
void salvaRTC() {
  if (fRTCpresente) {
    Wire.beginTransmission(0x68);
    Wire.write(0x00);
    Wire.write(decToBcd(secs));
    Wire.write(decToBcd(mins));
    Wire.write(decToBcd(hrs));
    Wire.endTransmission();
  }
}

void leggiRTC() {
  if (fRTCpresente) {
    Wire.beginTransmission(0x68);
    Wire.write(0x00);
    Wire.endTransmission();
    Wire.requestFrom(0x68, 3);
    secs  = bcdToDec(Wire.read() & 0x7f);  // seconds
    mins = bcdToDec(Wire.read());               // minutes
    hrs    = bcdToDec(Wire.read() & 0x3f);  // hours
  }
}

// funzioni orologio
void orologio() {
  currmillis = millis();
  if(currmillis-prevmillis > 999){
    prevmillis = currmillis;
    // Aggiorna l'orario
    secs++;
    if (secs > 59) {
      secs = 0;      
      mins++;
      if (mins > 59) {
        mins = 0;
        hrs++;
        // Qui legge RTC e aggiorna hrs, mins e secs
        //se la funzione fRTCpresente vera posso andare a leggiRTC
        leggiRTC();
        if (hrs > 24) { 
          hrs = 0;
        }      
      }
    }
    // Aggiorna il display
    lcd.setCursor(7,0);
    if (hrs < 10) lcd.print(" ");
    lcd.print(hrs);
    lcd.print(":");
    if (mins < 10) lcd.print("0");
    lcd.print(mins);
    lcd.print(":");
    if (secs < 10) lcd.print("0");
    lcd.print(secs);
  }
}

//funzioni aumenta ore/minuti
void aumenta() {
  // Controlla bottone minuti (button)
  val = digitalRead(button);
  if (val == LOW) {
    delay(75); // <<<<<<<<<<<<<<<< si può provare ad abbassarlo
    val = digitalRead(button);
    if (val == LOW) {
      // Pulsante premuto e rimbalzi finiti
      mins++;
      if (mins > 59) mins = 0;
      //
      lcd.setCursor(10,0);
      if (mins < 10) lcd.print("0");
      lcd.print(mins);
    }
  }
  // Controlla bottone ore (button1)
  val = digitalRead(button1);
  if (val == LOW) {
    delay(75); // <<<<<<<<<<<<<<<< si può provare ad abbassarlo
    val = digitalRead(button1);
    if (val == LOW) {
      // Pulsante premuto e rimbalzi finiti
      hrs++;
      if (hrs > 23) hrs = 0;
      //
      lcd.setCursor(7,0);
      if (hrs < 10) lcd.print(" ");
      lcd.print(hrs);
      // dato che ho cambiato le ore mi segno che devo aggiornare l'RTC
      fsRTC = true;
      momentoAvvenutoCambiamento = millis();
    }
  }
  // Controlla se devo aggiornare l'RTC
  if (fsRTC) {
    // controlo se è passato il tempo di 30 secondi dall'ultima modifica
    if (millis() - momentoAvvenutoCambiamento > 30000) {
      salvaRTC();
      fsRTC = false;
    }
  }
}

//funzione cronometro
void cronometro(){
  //
  // Controlo se già sto contando o no ...
  //
  if ( fStoContando) {
    //
    // Si, sto già contando, aggiorno solo il display ...
    //
    secc = (millis() - startmillis) / 1000;
    hrsc = secc / 3600;
    secc = secc - (hrsc * 3600);
    minc = secc / 60;
    secc = secc - (minc * 60);
    // Aggiorna durante il conteggio la seconda riga del display
    lcd.setCursor(7,1);
    if (hrsc < 10) lcd.print(" ");
    lcd.print(hrsc);
    lcd.print(":");
    if (minc < 10) lcd.print("0");
    lcd.print(minc);
    lcd.print(":");
    if (secc < 10) lcd.print("0");
    lcd.print(secc);
  }
  else {
    //
    // No, non sto contando quindi ... verifico la pressione del bottone Start ...
    //
    //resetTime
    //
    if (millis()-resetTime > 60000){
      lcd.setCursor(7,1);
      lcd.print("                ");
      lcd.setCursor(3,2);
      lcd.print("                 ");
      lcd.setCursor(-3,3);
      lcd.print("                 ");
    }
    //
    val = digitalRead(start);
    if (val == LOW) {
      delay(75); // <<<<<<<<<<<<<<<< si può provare ad abbassarlo
      val = digitalRead(start);
      if (val == LOW) {
        startmillis = millis();
        fStoContando = true; // ... si segna che ha iniziato a contare
        // Visualizza sul display l'ora a cui è partito ...
        secSt = secs;
        hrsSt = hrs;
        minSt = mins;
        //
        lcd.setCursor(3,2);
        if (hrsSt < 10) lcd.print(" ");
        lcd.print(hrsSt);
        lcd.print(":");
        if (minSt < 10) lcd.print("0");
        lcd.print(minSt);
        lcd.print(":");
        if (secSt < 10) lcd.print("0");
        lcd.print(secSt);
        lcd.setCursor(-3,3);
        lcd.print ("!!! suonato !!!");  



      }
    }
  }




  // Controlla se premuto Stop e calcola durata
  val = digitalRead(stopp);
  if (val == LOW) {
    delay(75); // <<<<<<<<<<<<<<<< si può provare ad abbassarlo
    val = digitalRead(stopp);
    if (val == LOW) {
      durata = millis() - startmillis;
      fStoContando = false; // ... si segna che ha terminato di contare
      resetTime=millis();
      // spegni led

      digitalWrite (led, LOW);



      //
    }
  }
}
void ledd(){
  if ( fStoContando) {
    tempoled= millis();
    if (tempoled >= (loopled +20)){
      analogWrite (led, statoled);
      statoled= statoled + statoled1;
      if ( statoled ==0 || statoled == 255){
        statoled1 = - statoled1;
      }
      loopled= tempoled;
    }
  }
}

... è l'ultima versione che sulla UNO funzionava correttamente immagino :roll_eyes:

Hai guardato bene le caratteristiche della Yún QUI ? Perché il processore della parte Arduino è diverso (UNO -> ATMega328P, Yún -> ATmega32u4) e non so se i piedini utilizzabili siano gli stessi ...
... fai una verifica tra il reference della Yún e i pin che stai utilizzando e, come al solito, se hai fatto collegamenti volanti con i Jumper ... controlla che il contatto sia affidabile :wink:

Guglielmo

si si ho preso pari pari lo sketch funzionante al 100% sulla uno e l'ho messo sul yun senza apportare nessuna modifica..
si i collegamenti sono volanti pero li ho controllati con il tester uno a uno e vanno bene..
ho fatto una verifica...
ho preso uno sketch vecchio, sempre del blocco orologio dove non c'era ancora l'RTC e funziona benissimo..
come può essere?? sembra che gli dia fastidio la comunicazione con l'RTC.. o una mia fantasia??

... a che pin hai collegato l'RTC ???

Guglielmo

RTC è stato collegato nei pin in alto a destra dove c' e scritto SDA e SCL..
ho trovato il problema... :grin: :grin:
ovviamente seguendo il tuo consiglio sono andato a vedere i pinout di tutte e due le schede...
guardando quella della yùn i pin 2 e 3 sono gli stessi di SDA e SCL ..
ho spostato in modo provvisorio i pin dello schermo su altri pin..e ora funziona...

geppopazzo:
ho trovato il problema... :grin: :grin:
ovviamente seguendo il tuo consiglio sono andato a vedere i pinout di tutte e due le schede...

C.V.D.

Guglielmo

:grin: Ottimo... :grin:..Questa volta ce la siamo cavata con poco... :grin:

Siccome i pin 2 e 3 sono dedicati per per SDA e SCL non li posso più utilizzare per il display vero??

No, però puoi collegare il display anche ai pin analogici. (ti si liberano i pin A4 e A5 bloccati invece sulla UNO)
Esempio:

LiquidCrystal lcd (12, 11, 5, 4, A0, A1);

Sulla YUN ti consiglio di saltare il pin 7 che potrebbe essere utilizzato dalla scheda wifi/ethernet per future espansioni; almeno sei sicuro che tra 1 anno se aggiorni la scheda il tuo programma funziona.
E ricorda che a differenza della UNO sui pin 10, 11, 12 e 13 non c'è l'interfaccia SPI, presente solo nel connettore ICSP, quindi usali tranquillamente.

Sì sì perfetto uso quelli per ora.. Anche perché ho già ordinato la schedina per la comunicazione i2c per lo schermo... Così mi libero di un po di pin...
Grazie mille per il consiglio lo terrò a mente.. Non si sa mai nella vita... :slight_smile: :slight_smile:

Bene ... ora ricordami ... quando devi mandare l'eMail ?

Guglielmo

P.S. : Hai seguito quanto scritto QUI e preparato la board ?

Sì la scheda e già configurata sia via wifi al mio router che via ethernet...

Deve mandare l email quando gli arriva un impulso sul pin 6 che è quello dello start...
Il pin che ho detto è quello della vecchia scheda.. Se ci sono dei problemi ovviamente si può rivedere... Io ora faccio sempre riferimento al vecchio sketch quello che ho postato prima..

Quindi praticamente in questo blocco :

    val = digitalRead(start);
    if (val == LOW) {
      delay(75); // <<<<<<<<<<<<<<<< si può provare ad abbassarlo
      val = digitalRead(start);
      if (val == LOW) {
        startmillis = millis();
        fStoContando = true; // ... si segna che ha iniziato a contare
        // Visualizza sul display l'ora a cui è partito ...
        secSt = secs;
        hrsSt = hrs;
        minSt = mins;
        //
        lcd.setCursor(3,2);
        if (hrsSt < 10) lcd.print(" ");
        lcd.print(hrsSt);
        lcd.print(":");
        if (minSt < 10) lcd.print("0");
        lcd.print(minSt);
        lcd.print(":");
        if (secSt < 10) lcd.print("0");
        lcd.print(secSt);
        lcd.setCursor(-3,3);
        lcd.print ("!!! suonato !!!");  
        //
        // <<<<<<< QUI DEVI INVIARE L'EMAIL >>>>>>>>
        //
      }

... dove ho messo il commento devi inviare l'email ... giusto ???

Guglielmo

.visto il super successo della prima edizione del blocco orologio, che sinceramente va alla perfezione

Per chi ha appena cambiato canale .... ma di che parli? :fearful:

pablos:
Per chi ha appena cambiato canale .... ma di che parli? :fearful:

Nooooo ... non mi dire che ti sei perso questo thread ... XD :grin: XD

Guglielmo

si esatto... quello è il posto giusto.... cosi viene subito visualizzato e poi viene mandata l'email.. è perfetto...

@pablos...
scusa pablos hai ragione... ma come mi ha anticipato Guglielmo ti sei perso quel thread...noooooo è impossibile.. :grin: :grin: :grin:

ok ... hai recuperato il file "TembooAccount.h" come spiegato QUI ???

Perché ti serve da includere nel codice ...

Guglielmo

diciamo che è da circa un ora che sto cercando di configurarlo ma quando vado a fare "TRY IT OUT" mi da errore

Ma hai fatto login con il tuo account ??? :astonished:

Guglielmo