Binary Clock

uhm, dovrei modificare l'hardware per provare questo.

devo fare delle ricerche approfondite. ci sarò stato qualcuno che ha usato un RTC con un Tiny.

la libreria usa giustamente il Wire!

ma, leo, una domanda, come mai hai usato la dicitura TinyWireM e non normalmente Wire nella tua libreria? In questo modo erano anche intercambiabili! Ragioni che non conosco?

La libreria TinyWire non è mica mia :stuck_out_tongue:
L'hanno chiamata così perché è una versione specifica per i Tiny. Devi sapere che i Tiny non hanno l'I2C, o per meglio dire, l'interfaccia TWI supportata via hardware. Hanno però una periferica che si chiama USI, Universal Serial Interface, che può essere "programmata" (se così si può dire) via software per poter dialogare via I2C. La TinyWireM è per i dispositivi Master, la TinyWireS per quelli Slave. L'autore della libreria, nei commenti, chiede a chi ne abbia voglia, di riunire le 2 librerie in una unica.

Tornando al micro, la TinyWire proprio perché usa l'USI, è legata ai pin 0 e 2, che se vedi sulla piedinatura presente sul datasheet, corrispondono a SDA e SCK, gli stessi segnali del TWI/I2C.

Detto questo, questo sketch lo provai mesi fa. Leggeva da un DS1307 e spediva poi via newsoftwserial ad un Arduino che replicava l'info sul PC.

Grazie Leo!

il tue esempio misto a ciò che c'è scritto nella libreria che avevo già credo mi abbiano instradato!

nel senso che, risulterebbe più semplice a questo punto non usare nessula libreria per il DS1307, ma andare a comunicare direttamente con il chip!

ho scaricato il datasheet, confrontato il tuo metodo con quello della libreria (simili), forse ho capito come funziona l'invio e la ricezione dei dati!

cosa vuol dire questo commento nella libreria?

int i = 0; //The new wire library needs to take an int when you are sending for the zero register

che poi usa qui:

DateTime RTC_DS1307::now() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(i);	
  Wire.endTransmission();
  
  Wire.requestFrom(DS1307_ADDRESS, 7);
  uint8_t ss = bcd2bin(Wire.receive() & 0x7F);
  uint8_t mm = bcd2bin(Wire.receive());
  uint8_t hh = bcd2bin(Wire.receive());
  Wire.receive();
  uint8_t d = bcd2bin(Wire.receive());
  uint8_t m = bcd2bin(Wire.receive());
  uint16_t y = bcd2bin(Wire.receive()) + 2000;
  
  return DateTime (y, m, d, hh, mm, ss);
}

Il tuo approccio è esatto. Non c'è bisogno di alcuna libreria...se vuoi per comodità puoi usare queste chiamate che duplicano quelle della libreria ma usano TinyWire:

uint16_t TimeIsSet = 0xaa55;            // Valore "speciale" per ricordare il set orologio
byte seconds,minutes,hours,             // valori prelevati dal RTC
     day_of_week,days,months;
int years;


/************************ FUNZIONI DI UTILITA' PER GESTIRE RTC DS1307 ************************ */
void DS1307_stopClock(void) {
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x00);                      // Register 0x00 holds the oscillator start/stop bit
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(DS1307_ID, 1);
  seconds = TinyWireM.receive() | 0x80;               // save actual seconds and OR sec with bit 7 (sart/stop bit) = clock stopped
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x00);
  TinyWireM.send((uint8_t)seconds);                   // write seconds back and stop the clock
  TinyWireM.endTransmission();
}

void DS1307_startClock(void) {
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x00);                      // Register 0x00 holds the oscillator start/stop bit
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(DS1307_ID, 1);
  seconds = TinyWireM.receive() & 0x7f;               // save actual seconds and AND sec with bit 7 (sart/stop bit) = clock started
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x00);
  TinyWireM.send((uint8_t)seconds);                   // write seconds back and start the clock
  TinyWireM.endTransmission();
}


void DS1307_setTime(void) {
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x00);
  TinyWireM.send(dec2bcd(seconds) | 0x80);            // set seconds (clock is stopped!)
  TinyWireM.send(dec2bcd(minutes));                   // set minutes
  TinyWireM.send(dec2bcd(hours) & 0x3f);              // set hours (24h clock!)
  TinyWireM.send(dec2bcd(day_of_week+1));             // set dow (Day Of Week), do conversion from internal to RTC format
  TinyWireM.send(dec2bcd(days));                      // set day
  TinyWireM.send(dec2bcd(months));                    // set month
  TinyWireM.send(dec2bcd(years-2000));                // set year
  TinyWireM.endTransmission();
}

void DS1307_getTime(void) {
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x00);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(DS1307_ID, 7);                // request 7 bytes from DS1307 
  seconds = bcd2dec(TinyWireM.receive() & 0x7f);      // aquire seconds...
  minutes = bcd2dec(TinyWireM.receive());             // aquire minutes
  hours = bcd2dec(TinyWireM.receive());               // aquire hours
  day_of_week = bcd2dec(TinyWireM.receive());         // aquire dow (Day Of Week)
  day_of_week--;	                              // correction from RTC format (1..7) to lib format (0..6). Useless, because it will be overwritten
  days = bcd2dec(TinyWireM.receive());                // aquire day
  months = bcd2dec(TinyWireM.receive());              // aquire month
  years = bcd2dec(TinyWireM.receive());               // aquire year...
  years = years + 2000;                               // ...and assume that we are in 21st century!  
}

uint8_t DS1307_getCTRL(void) {
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x07);                      // set CTRL Register Address
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(DS1307_ID, 1);                // read only CTRL Register
  while(!TinyWireM.available());                      // waiting...
  return TinyWireM.receive();                         // ... and store it in ctrl
}

// Set data to CTRL Register of the DS1307 (0x07)
/*  Possibili valori da assegnare a setctrl (vedi DS1307_set_SQW_1Hz) :
 * 0x00 = disable SQW pin, 
 * 0x10 = 1Hz,
 * 0x11 = 4096Hz, 
 * 0x12 = 8192Hz, 
 * 0x13 = 32768Hz
*/
void DS1307_setCTRL(uint8_t setctrl) {
  TinyWireM.beginTransmission(DS1307_ID);
  TinyWireM.send((uint8_t)0x07);                      // set CTRL Register Address
  TinyWireM.send((uint8_t)setctrl);                   // set CTRL Register
  TinyWireM.endTransmission();
}


// Aquire data from RAM of the RTC Chip (max 56 Byte)
void DS1307_getRAM(uint8_t rtc_addr, uint8_t * rtc_ram, uint8_t rtc_quantity) {
  TinyWireM.beginTransmission(DS1307_ID);
  rtc_addr &= 63;                                     // avoid wrong adressing. Adress 0x08 is now address 0x00...
  rtc_addr += 8;                                      // ... and address 0x3f is now 0x38
  TinyWireM.send(rtc_addr);                           // set CTRL Register Address
  if ( TinyWireM.endTransmission() != 0 )
    return;
  TinyWireM.requestFrom(DS1307_ID, (int)rtc_quantity);
  while(!TinyWireM.available());                      // waiting...
  for(int i=0; i<rtc_quantity; i++) {
    rtc_ram[i] = TinyWireM.receive();                 // ... and store it in rtc_ram
  }
}

// Write data into RAM of the RTC Chip
void DS1307_setRAM(uint8_t rtc_addr, uint8_t * rtc_ram, uint8_t rtc_quantity) {
  TinyWireM.beginTransmission(DS1307_ID);
  rtc_addr &= 63;                                     // avoid wrong adressing. Adress 0x08 is now address 0x00...
  rtc_addr += 8;                                      // ... and address 0x3f is now 0x38
  TinyWireM.send(rtc_addr);                           // set RAM start Address 
  for(int i=0; i<rtc_quantity; i++) {
    TinyWireM.send(rtc_ram[i]);                       // ... and send it from rtc_ram to the RTC Chip
  }
  TinyWireM.endTransmission();
}


uint8_t dec2bcd(uint8_t num) {
  return ((num/10 * 16) + (num % 10));
}

// Convert Binary Coded Decimal (BCD) to Decimal
uint8_t bcd2dec(uint8_t num) {
  return ((num/16 * 10) + (num % 16));
}

cosa vuol dire questo commento nella libreria?

Code:

int i = 0; //The new wire library needs to take an int when you are sending for the zero register

Semplicemente che nella nuova libreria è necessario passare un valore di tipo "int" per il codice "0" (e non un byte).
Per tinyWire non è necessario:

  TinyWireM.send((uint8_t)0x00);

Ciao

@z3us:
ha risposto a tutto dalubar :wink:

grazie dalubar!!!

mi sarà mooolto utile! in sostanza devo solo prendere le funzioni che mi occorrono! leggi e scrivi! :slight_smile:

stasera provo!

Prego :slight_smile:
Recentemente ho dovuto scontrarmi anch'io con questa problematica per un mio progetto sfizioso (Berlin clock...ma shhhh che non si sappia in giro) e cosi ho semplicemente preso i metodi che mi servivano dalla libreria originale "parsandoli" per la versione tiny.

Ho preferito, in questo caso, NON farne una libreria apposita per il semplice motivo che quando si lavora con i tiny lo spazio è importantissimo e un'intera libreria a volte fa più danno che altro, è meglio, invece, inserire solo le funzioni strettamente necessarie.

eh si, quell'orologio è anche nella mia lista!

shift register per gestire tutti i led o cosa?

Ho da poco ultimato la progettazione elettronica (quella software è senz'altro più semplice).
3 SR sono più che sufficienti. Il mio berlin clock gestirà ben 72 led ad alta luminosità con adattamento automatico della luminosità ambientale e giochi di luce per le festività :slight_smile:
Just for fun... of course :smiley:

Grande!

poi voglio vederlo! e visto che siamo pure "vicini" magari pure di presenza! Mi pare che anche MauroTec Sia Siculo!

Certamente!
A dire il vero, essendo più che altro un "esercizio" di progettazione (hw & sw) non gli sto' dando una priorità particolare (ci sono altre cose ben più utili che devo fare prima), ma di certo quanto prima lo realizzerò (ormai ho deciso che deve stare appeso nel mio studio :D), e sarò, quindi, lieto di mostrartelo.

Ebbene funziona!

dopo un'oretta di prove sulle temporizzazioni da usare per leggere l'RTC e poi scrivere sul SAA, ho fatto una prova a "non aspettare" e quindi interpellare l'RTC e scrivere l'ora sul display a piena velocità, senza attese o delay!

tutto funziona perfettamente!

adesso manca solo la parte della regolazione dell'ora tramite tasti esterni. (per ora l'ho impostata con un'altra programma)

il codice attuale è il seguente! non sarà magari snello, ma occupa meno di 2K.

////////Include////////////////
#include <TinyWireM.h>
#include <USI_TWI_Master.h>

////ADDRESS////////////////
byte saa1064 = 0x38;
byte DS1307 = 0x68;

////Dichiarazioni//////////



////Variabili///////////
byte Digit1, Digit2, Digit3 = 0;

byte seconds,minutes,hours,             
     day_of_week,days,months;
int years;



void setup()
{

 // RTCsetTime();
  
  TinyWireM.begin();
  delay(200);
  initDisplay();
  clearDisplay();
  
}


void loop()
{
 
  RTCgetTime();
  delay(200);
  
  Digit1 = seconds;
  Digit2 = minutes;
  Digit3 = hours;
   
  adaptBCD();
  displayDigits();
}

/////Funzioni SAA1064

void initDisplay()
{
    TinyWireM.beginTransmission(saa1064);
    TinyWireM.send(B00000000); 
    TinyWireM.send(B01000111); 
    TinyWireM.endTransmission();
}

void displayDigits() {
  

    TinyWireM.beginTransmission(saa1064);
    TinyWireM.send(2);
    TinyWireM.send(Digit1); 
    TinyWireM.send(Digit2); 
    TinyWireM.send(Digit3);
    //Wire.send(B00000000);
    TinyWireM.endTransmission();
  
}

void clearDisplay()

{
    TinyWireM.beginTransmission(saa1064);
    TinyWireM.send(1); 
    TinyWireM.send(0); 
    TinyWireM.send(0); 
    TinyWireM.send(0); 
    TinyWireM.send(0); 
    TinyWireM.endTransmission();
}


///Funzioni RTC DS1307

void RTCsetTime(void) {
    TinyWireM.beginTransmission(DS1307);
    TinyWireM.send((uint8_t)0x00);
    TinyWireM.send(dec2bcd(seconds) | 0x80);            
    TinyWireM.send(dec2bcd(minutes));                   
    TinyWireM.send(dec2bcd(hours) & 0x3f);              
    TinyWireM.send(dec2bcd(day_of_week+1));             
    TinyWireM.send(dec2bcd(days));                      
    TinyWireM.send(dec2bcd(months));                    
    TinyWireM.send(dec2bcd(years-2000));                
    TinyWireM.endTransmission();
}

void RTCgetTime(void) {
    TinyWireM.beginTransmission(DS1307);
    TinyWireM.send((uint8_t)0x00);
    TinyWireM.endTransmission();
    TinyWireM.requestFrom(DS1307, 7);                 
    seconds     = bcd2dec(TinyWireM.receive() & 0x7f);      
    minutes     = bcd2dec(TinyWireM.receive());             
    hours       = bcd2dec(TinyWireM.receive());               
    day_of_week = bcd2dec(TinyWireM.receive());  day_of_week--;	                              
    days        = bcd2dec(TinyWireM.receive());                
    months      = bcd2dec(TinyWireM.receive());              
    years       = bcd2dec(TinyWireM.receive());  years = years + 2000;                                 
}

////BCD2DEC & DEC2BCD

uint8_t dec2bcd(uint8_t num) {
  return ((num/10 * 16) + (num % 10));
}
uint8_t bcd2dec(uint8_t num) {
  return ((num/16 * 10) + (num % 16));
}

/////ADAPT BCD////////

void adaptBCD() {
  
  if(Digit1 > 9) {
  Digit1 = Digit1 + 6; }
  if(Digit1 > 25) {
  Digit1 = Digit1 + 6; }
  if(Digit1 > 41) {
  Digit1 = Digit1 + 6; }
  if(Digit1 > 57) {
  Digit1 = Digit1 + 6; }
  if(Digit1 > 73) {
  Digit1 = Digit1 + 6; }
  
  if(Digit2 > 9) {
  Digit2 = Digit2 + 6; }
  if(Digit2 > 25) {
  Digit2 = Digit2 + 6; }
  if(Digit2 > 41) {
  Digit2 = Digit2 + 6; }
  if(Digit2 > 57) {
  Digit2 = Digit2 + 6; }
  if(Digit2 > 73) {
  Digit2 = Digit2 + 6; }
  
  if(Digit3 > 9) {
  Digit3 = Digit3 + 6; }
  if(Digit3 > 25) {
  Digit3 = Digit3 + 6; }
  if(Digit3 > 41) {
  Digit3 = Digit3 + 6; }
  if(Digit3 > 57) {
  Digit3 = Digit3 + 6; }
  
}

si accettano commenti o correzioni! :smiley:

Ottimo :slight_smile: Perchè non posti un video del binary clock in funzione?

dopo un'oretta di prove sulle temporizzazioni da usare per leggere l'RTC e poi scrivere sul SAA, ho fatto una prova a "non aspettare" e quindi interpellare l'RTC e scrivere l'ora sul display a piena velocità, senza attese o delay!

Immagino che tu ti riferisca a quel delay(200) che interroga l'RTC ogni 0,2s. In effetti il problema della temporizzazione c'è...l'ideale sarebbe di avere un segnale esterno sincronizzato con l'RTC che dica esattamente "quando" leggere e aggiornare il display (qualunque esso sia).
E infatti questo segnale c'è. Io, personalmente, in un grosso progetto che impiega un 328 (pieno "a tappo") ho risolto usando il pin 3 7 del DS1307 come uscita a 1Hz che da il sync al MCU, in modo da avere il riferimento "preciso" sul momento di refresh.
Il lato negativo è che impegna un pin del micro, ma finora non è stato mai un problema. La soluzione è semplice e funzionale, soprattutto permette di essere sfruttata per attivare una serie di azioni temporizzate (ogni ora, ogni minuto, ogni giorno, etc...) con molta facilità.
E' la stessa soluzione che sto usando anche per il "berlin" :slight_smile:

grazie Dalubar!

no, mi riferivo al fatto che prima avevo inserito alcuni delay tra le varie azioni: Cancella display, chiedi l'ora all'RTC, invia tutto al display!

non andava! lampeggiava tutto e basta! si vede che gli faceva male!

ho tolto tutti i delay, lasciando solo quello che vedi (magari faccio una prova a togliere pure lui!) e in più non cancello più il display, lo sovrascrivo e basta!

Ho infatti scoperto che inviando un nuovo Byte al display, lui lo aggiorna in automatico, senza dover prima inviare 0!

dall'altra sera va tranquillo, e non si notano sfarfallii o discrepanze nei secondi! pertanto, per questo progetto non utilizzerò il pin del "sincrono"! ma faccio tesoro della tua dritta per i prossimi orologi! :wink:

Per la natura del tuo progetto va benissimo così. :stuck_out_tongue_closed_eyes:
Il problema del sincro si avverte solo quando il processore si deve occupare di molte altre cose oltre a gestire l'RTC. In quel caso non ci si può permettere il "lusso" di sprecare prezioso tempo prezioso nell'interrogazione di un dispositivo I2C (e occupare di conseguenza il canale) se non vi è una reale necessità, oppure, men che meno, utilizzare istruzioni "delay" che bloccherebbero inevitabilmente l'esecuzione dello sketch.
Se avrai necessità di qualche "dritta" per questa cosa (magari per il prossimo clock), chiedi pure. :slight_smile:

che ve ne pare?

frontale appena fresato. tra led e frontale ho inserito un foglio opacizzante tirato via da un vecchio monitor da pc LCD.

la foto non crea quest'effetto, ma di presenza l'occhio viene ingannato dalla profondità dell'incisione creando una sorta di effetto 3D! si ha l'impressione che i simboli balzino fuori dal piano!

Effetto del tutto imprevisto, ma favoloso!!! viene anche quasi da lasciarlo bianco!

L'orologio è molto bello!
Ma quei simboli sono presi a caso o hanno un significato? :sweat_smile:

grazie leo!

i simboli possiamo dire che sono presi a caso! perche è il Font di Stargate, la serie tv fantasy. Non rappresentano nulla in realtà, ma come accennavo prima, serve solo per occultare maggiormente che si tratta di un orologio!

e poi fà figo :wink:

ho quasi finito, devo solo attacarlo, posizionare connettore di alimentazione e il pulsante e lo posso attaccare al muro! :slight_smile:

Idea SUPERfiga quella dei simboli incomprensibili che potrebbero significare qualcosa ma che invece non dicono una mazza! XD XD XD

Bravo, davvero un bell'effetto :slight_smile:

Avessi anch'io una fresa...altro che mettersi a segare uno per uno i listelli in legno da 4cm...