Vai al contenuto
PLC Forum


Sonda di temperatura DS18B20 e micro - Routine di conversione della temperatura


.:Matrix:.

Messaggi consigliati

Un saluto a tutti gli iscritti del forum.

La dallas un po di tempo fa tirò fuori delle sonde di temperatura digitali con protocollo 1wire.

Sono semplici da gestire e molto precise (12bit di risoluzione).

Ho un piccolo problema per trasformare il valore decimale della temperatura.

Praticamente ho un valore, per la parte decimale, che va da 0h a Fh e che dovrei traslare da 0 a 9.

Come posso implementarla?

Grazie

Link al commento
Condividi su altri siti


Se vada 0 a F in decimale vai da 0 a 15. Ti serve una conversione binario-BCD.

Attenzione però che il 18B20, che conosco bene come il 18S20, da in uscita un codice compreso tra FC90h (-55C) e 07D0h (+125C) quindi la conversione va eseguita su 2 bytes e dopo aver effettuato il complemento se riconosciuto un valore negativo

Link al commento
Condividi su altri siti

Ciao Livio,

grazie per aver risposto così rapidamente.

Il problema è più complesso di quanto potrebbe sembrare.

Il fatto sta nella corrispondenza che i valori che rappresentano i decimali hanno un peso di 0,06125 gradi e per un grado ci sono 16 possibili posizioni intermedie.

Quindi non basta semplicemente, come tu mi hai indicato e come io avevo già provato a fare, convertire il valore da BIN a BCD, ma bisognerebbe instaurare una sorta di proporzione tra le due scale. (0-15 e 0-10)

Non so se sono stato chiaro nella spiegazione.

.:Luigi:.

Link al commento
Condividi su altri siti

No, per niente.

Hai un numero su 2 bytes. 0000h ===> 0C, 07D0h ==> 125C equivalenti a 2000 counts per 125C, cioè 0,0625C per count.

Il primo passo, dopo aver letto la temperatra è verificare se è 1xxx xxxx xxxx xxxx (negativo) o 0xxx xxxx xxxx xxxx (positivo). Se il numero è positivo moltiplchi direttamente per 625 (se lavori in real con il "C" è semplice, altrimenti devi sudare un poco tongue.gif ). Ora devi eseguire sia una divisione, sia un'operazione di modulo (quello che si indica con %). Converti i risultati delle due operazioni da binario in BCD e avrai parte intera e parte decimale pronte per la visulaizzazione.

Se la lettura è negativa devi prima effeture un'operazione di complemento.

Link al commento
Condividi su altri siti

Ciao Livio,

scusami, ma se io sono stato poco chiaro, ora tu enunci dei misteri veri e propri.:-)

Allora per ricapitolare, se ho un valore positivo delo moltiplicarlo per 625 e poi dividerlo per quanto?

Io ho fatto una prova dividendo i due byte per 16 e, scartando l'ultimo nibble, ottengo direttamente il valore di temperatura da visualizzare.

Il mio problema rimaneva l'ultimo nibble che contiene il valore decimale però con valori da 0 a F e non da 0 a 9.

Comunque, benvenga se il metodo da te proposto mi semplifica la vita.

Devi solo spiegarmi meglio le operazioni da effettuare.

Grazie.

Luigi.

Link al commento
Condividi su altri siti

Stiamo parlando entrambi del DS18B20? IO mi riferisco a questo dispositivo.

Considerando solo la parte positiva hai una misura che parte da 0 e arriva a 125C suddivisa su 2000 livelli discreti (counts) che in esadecimale si scrive 7D0.

1C vale 16 counts, cioè 10h. Se a te non interessano i decimali di grado scarta pure il nibble meno significativo, puoi scartare anche il nibble più significativo che è sempre zero. In pratica shifti a destra di 4 i due bytes (divisione per 16) ed ottieni un solo byte con numeri compresi tra 0 e 7D <==> 0-125.

A questo punto devi convertire da binario in BCD.

Domanda sai eseguire la conversione? Se no dimmi quale linguaggio usi e ti metto on line la semplice routine di conversione BinBCD (è un classico).

Se invece vuoi anche i decimali devi salvare il nibble meno significativo, moltiplicare per 625 e dividere, ovviamente, per 10000 (o per 1000, o per 100 o per 10, o niente dipende dalla risoluzione che vuoi ottenere) che è poi la procedura che ti ho descritto prima con riferimento al "C" (più semplice). A questo punto converti la parte intera da binario a BCD ed ottieni i decimali da visualizzare.

Puoi anche fare una procedura molto grezza ma funzionale. Sommi 625 tante volte quanto vale il numero contenuto nel nibble dei decimali (for n=0, n<=x ==> y=y+625), tenendo presente che sono decimillesimi di grado.

COn una sola cifra compreso tra 0 e Fh puoi visualizzare solo temperature tra 0 e 15C, oppure tra 16 e 255 (125).

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Perfetto Livio, sei stato molto esauriente nella spiegazione.

Come linguaggio uso ASM, ed avevo già implementato la divisione per 16 ed ho anche implementato una routine di conversione BIN-BCD.

Il valore intero della temperatura, lo visualizzo già sul display.

Il problema erano solo i decimali.

Infatti, in base alle ultime indicazioni che mi hai fornito, per avere una visualizzazione dei decimi di grado dovrei moltiplicare l'ultimo nibble per 625 per poi dividerlo per 1000.

Provo a fare queste operazioni e ti faccio sapere il risultato.

P.S. dimenticavo:

sto avendo difficoltà nella lettura del codice a 64bit della sonda, nel senso che se effettuo la lettura del codice, dopo non mi effettua più la conversione della temperatura (44h).

Probabilmente sbaglio qualcosa nella sequenza dei comandi:

- inizializza sonda (impulso di reset seguito da impulso di presenza con relativa routine di mancato rilevamento della sonda);

- scrivi 33h (comando per leggere il codice);

- leggi 8 byte (il codice ritornato dalla sonda);

- inizializza sonda

- scrivi CCh (salta la rom)

- scrivi 44h (avvia la conversine della temperatura)

- inizializza sonda

- scrivi CCh

- scrivi BEh

- leggi 8 byte (legge la scratchpad)

Dove è l'errore?

Grazie.

Link al commento
Condividi su altri siti

Ti allego il "C" commentato della mia funzione per leggere la temperatura, il dispositivo è il DS18S20; differisce per precisione e formattazione dei dati ma i comandi sono identici.

RIcordo che, dopo uno "sleep" del micro alla ripresa era necessario leggere 3 volte la temperatara perchè non smepre i primi due valori erano corretti. Mi ero riproposto di indagare a fondo il problema, poi il progetto è passato in secondo piano, visto che così funzionava (è, purtroppo, la normalità sad.gif )


byte const srchrom = 0xf0;     //comando "search ROM"
byte const rdrom = 0x33;       //comando "read ROM"
byte const mtchrom = 0x55;   //comando "match ROM"
byte const skprom = 0xcc;     //comando "skip ROM"
byte const conv_t = 0x44;      //comando "converti temperatura"
byte const rd_dat = 0xbe;      //comando "leggi i dati dalla memoria"


void tem_conv(int *pnt)//lettura temperatura e memo in array punyato da "pnt"
    {
       int1 b_ack;
       int i, dato;
            b_ack = On_reset();   //invio comando di reset al DS18S20
            if ( b_ack == FALSE)
            {
                dato = skprom;    //invio il comando "skip ROM"
                DStx_byte(dato); // scrivi byte
                dato = conv_t;    //invio il comando "converti"
                DStx_byte(dato); // scrivi byte
            do
               {
                     dato = DSrx_byte();        // leggi byte
               }while (dato =! 0xff);
                set_tris_a(0b111111001);//A1 e A2 ==> output, altri input
                bit_set(port_a,1);    //forza a "1" la linea DQ
                delay_us(250);
                set_tris_a(0b111111011);      // tutti input
                On_reset();
                delay_us(250);
                dato = skprom;    //invio il comando "skip ROM"
                DStx_byte(dato);
                delay_ms(250);
                dato = rd_dat;      //invio comando "leggi i dati"
                DStx_byte(dato);
                for ( i=0; i<2; i++)
                {
                    *(pnt+i)=DSrx_byte();
                }
            }
            else
            {
                    *pnt = 0;     //non cè presenza del dispsoitivo
                    *(pnt+1) = 0;     //non cè presenza del dispsoitivo
            }
    }

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...