ciao a tutti
sto cercando di inviare ora e data prelevati da un RTC e inviarli a un monitor seriale, il tutto utilizzando il protocollo i2c, il problema che non riesco a risolvere è: come posso inviare il numero ad es. dei minuti al display? Intendo dire: se lo mando come numero decimale o esadecimale il display lo interpreta come codice ascii e stampa il carattere corrispondente, come posso risolvere?
Qui il datasheet del monitor LCD03
grazie
Gli RTC memorizzano l'orario in BCD format, per cui devi fare la conversione per ottenerlo in formato decimale o esadecimale.
ciao Eugenio, grazie ancora, ho già la formula per trasformare in numerazione decimale il formato BCD. Il problema è che poi non riesco a mandarlo al display perchè se lo salvo in una variabile come numero e la invio con Wire.send() il display interpreta il numero come se fosse un codice ascii e stampa il relativo simbolo.
Se invio, ad es., minuti 38 il 38 lo interpreta come il codice acsii di &
.
Dovrei inviare il numero come testo o scomporlo e inviare i codici ascii dei singoli numeri
Ma a questo punto perchè non utilizzi la libreria apposita?
http://www.arduino.cc/playground/Code/LCDi2c
Se proprio non vuoi utilizzare la libreria dell'LCD, prendi i dati in formato BCD. Se non sbaglio i primi 4 bit danno l'unità, gli altri 2 bit le decine. In questo modo di ogni numero ottieni la singola cifra che puoi facilmente inviare sul display tramite il comando wire.
Esempio, il 38 è memorizzato così: 111000 i primi 4 bit danno 8, gli altri 2bit danno il 3.
Spero di essre stato chiaro.
preferisco non usare la libreria se posso, il protocollo i2c è molto semplice.
Il formato BDC dovrebbe usare 4 bit per numero, il 38 dovrebbe essere 0011 e 1000, in realtà, leggendolo con bitRead() ottengo 00100110, cioè il numero 38 in binario. Inoltre arrivano in un formato strano, i minuti arrivano fino a 90.
Non so...
4 bit per numero, il 38 dovrebbe essere 0011 e 1000
Scusa hai ragione 4 + 4.
Mi sa che commetti un errore nella lettura dell'RTC(quale hai?) perchè usi bitRead?
l'RTC è questo:http://www.robot-italy.com/product_info.php?cPath=52_71&products_id=763 la lettura la eseguo così
// reset register pointer
Wire.beginTransmission(0x68);
Wire.send(0);
Wire.endTransmission();
// request 7 bytes from ds1307
Wire.requestFrom(104, 7);
second = Wire.receive();
minute = Wire.receive();
hour = Wire.receive();
day_of_week=Wire.receive();
day = Wire.receive();
month = Wire.receive();
year = Wire.receive();
Questa è la conversione da BDC in decimale
// Convert all the BCD values that might have "tens" to decimal
int hours=hour/16* 10 + hour % 16;
int minutes=minute/16 * 10 + minute % 16;
int seconds=second/16 * 10 + second % 16;
int days=day/16 * 10 + day % 16;
int months=month/16 * 10 + month % 16;
int years=year/16 * 10 + year % 16;
perchè usi bitRead?
Perchè è il primo che mi è venuto in mente, legge un bit alla volta e lo invia a serial.print
Serial.print(bitRead(minute,7));
Serial.print(bitRead(minute,6));
Serial.print(bitRead(minute,5));
Serial.print(bitRead(minute,4));
Serial.print(bitRead(minute,3));
Serial.print(bitRead(minute,2));
Serial.print(bitRead(minute,1));
Serial.print(bitRead(minute,0));
Hai un altro metodo?
La lettura dell'RTC è giusta, perchè leggendola sul serial monitor ora e data sono corrette però non riesco a capire... :-[
Mi sa che commetti un errore nella lettura dell'RTC
Ho sbagliato, ho letto il numero già corretto per il sistema decimale...
Forse sono venuto a capo della codifica BCD...
L'RTC emette, un byte di otto bit per ogni numero (ore, minuti, giorno ecc), di questi i primi 4 sono le decine e i secondi 4 sono unità (fanno eccezione le ore) per cui, parlando di minuti, 9 è 00001001 come nella computazione binaria. Sommando 1 diventa 10 che però in binario è 00001010 mentre in BDC diventa 00010000.
Questo comporta una particolarità: se si legge per intero un numero di 8 bit in formato BCD ha sempre un valore ed una rappresentazione grafica in numerazione esadecimale che sembra in decimale, non ci sono mai le lettere.
Ad esempio 00010000 è 10 in esadecimale ma 16 in decimale, e questo vale per TUTTI i numeri in codifica BCD.
Quando recuperiamo con Wire.receive(); i minuti questi vengono rappresentati dal computer come in decimale e quindi come 16, mentre il vero valore è 10. Per questo bisogna operare una correzione ai numeri BDC.
Comunque, a questo punto devo separare i primi 4 bit dai secondi, salvarli in una variabile e mandarli al display... come?
Normalmente con highbyte e lowbyte, però su arduino questo Extracts the low-order (leftmost) byte of a variable (e.g. a word). http://www.arduino.cc/en/Reference/LowByte.
Onestamente non so dirti qual'è il comando equivalente. :-[
Ciao, io ho lo stesso LCD, e mi avevo costruito una funzioncina...
void lcdPrintInt(byte addr, int value)
{
byte printing = false;
Wire.beginTransmission(addr);
Wire.send(0);
if ((value/100)>0)//1st digit, space if zero
{
Wire.send((value/100)+48);//sends digit
value = value % 100; //chop digit away from value
printing = true;
}
else
{
Wire.send(32);//sends space
}
if ((value/10)>0)//2nd digit, space if zero
{
Wire.send((value/10)+48);//sends digit
value = value % 10; //chop digit away from value
}
else
{
if (printing)
{Wire.send(48);}//sends 0
else
{Wire.send(32);}
}
Wire.send(value + 48);//3rd digit is sent anyway
Wire.endTransmission();
}
ciao
scusa, ma value che numero è? Non può essere il valore che viene dall'RTC...
RISOLTO!!
ho trovato il modo, è anche semplice nel codice. Posto il tutto nel caso serva a qualcuno.
Mettiamo che l'RTC abbia mandato i minuti: 25 minuti che abbiamo salvato nella variabile int minutes.
In minutes quindi c'è un byte di 8 bit in formato BCD e precisamente 00100101 dove, i primi 4 bit (0010) sono le decine e cioè il numero 2 e gli ultimi 4 (0101) sono le unità, cioè il 5.
Dobbiamo mandare al display i due numeri separatamente, mandiamo prima il 5 perchè è più semplice.
Al display perchè scriva il numero 5 dobbiamo inviare l'equivalente numero nel codice ASCII, che per il 5 è il numero 53.
A questo punto prendiamo il byte salvato nella variabile minutes (00100101) e modifichiamo i 4 bit di sinistra sostituendoli con 0011, questo vale per tutti i numeri da 0 a 9, otteniamo 00110101 che in codice, questa volta binario, è proprio il numero 53.
Inviandolo al display stamperemo il numero 5.
La teoria è complicata, ma il codice semplice
bitWrite(minutes,4,1);
bitWrite(minutes,5,1);
bitWrite(minutes,6,0);
bitWrite(minutes,7,0);
Wire.send(minutes);
ho omesso tutto il codice di inizializzazione, di settaggio ecc.
Semplice no?
Per le decine è un po' più complicato dato che la sequenza 0011 va scritta nei 4 bit di sinistra, cioè proprio dove c'è il numero 2, quindi dobbiamo spostare i 4 bit di sinista a destra.
Prendiamo la nostra variabile originale minutes: 00100101, dobbiamo spostare 0010 a destra e diventa 00100010 e poi a sinistra inserire il solito 0011 e quindi diventa 00110010 che, in codice binario è il numero 50, cioè il codice ASCII di 2.
Questo è il codice per spostare i 4 bit da sinistra a destra
bitWrite(minute_decimal,0,bitRead(minute_decimal,4));
bitWrite(minute_decimal,1,bitRead(minute_decimal,5));
bitWrite(minute_decimal,2,bitRead(minute_decimal,6));
bitWrite(minute_decimal,3,bitRead(minute_decimal,7));
Poi si sostituiscono i 4 bit 0011 come nel caso delle unità.
E' tutto
P.S. lo stesso vale per i secondi, i giorni e i mesi, le ore e gli anni sono leggermente diversi
a me interesserebbe il progetto mi potresti inviare la documentazione alla seguente e-mail:albertobram@libero.it?
scusa Alberto ma ... quale documentazione? Di quale progetto?
Si tratta di leggere l'rtc e inviarlo al display, tutta la spiegazione è sopra, se vuoi dei particolari chiedi pure