Creative Commons BY-NC-ND 2.5Questo sito e tutto il suo contenuto sono distribuiti sotto la licenza Creative Commons Attribuzione - Non Commerciale - Non opere derivate 2.5 Italia e con le condizioni d'uso definite nel disclaimer: siete pregati di leggere entrambi questi documenti prima di usufruire dei contenuti di questo sito. Per alcuni contenuti è necessaria una registrazione gratuita: non è necessario pagare e non è necessario accumulare punteggi per accedere agli articoli e scaricare i sorgenti: basta solo essere onesti. Se volete che questo sito continui a rimanere attivo, a contribuire ogni giorno alla diffusione della cultura libera, non copiate il materiale per ripubblicarlo in altri luoghi. Se volete partecipare su settorezero e rendere le vostre idee, i vostri progetti, fruibili da tutti senza limitazioni potete farlo tranquillamente.

Corso di programmazione PICMicro in C – Approfondimenti – Il bus One-Wire. Ricavare il ROM Code

Autore: Giovanni Bernardo | Data pubblicazione: 22 settembre 2010
Categorie: dsPIC / PIC24 PICmicro 10/12/16 PICmicro 18 Sensori

In un articolo precedente abbiamo visto come interfacciare Arduino ad una sonda di temperatura DS18S20. Su Arduino l’impresa è stata abbastanza facile in quanto esistono librerie già pronte. Per par condicio ora vedremo ora come fare la stessa cosa con i picmicro, ma un po’ alla volta dal momento che personalmente non ho trovato librerie già pronte e fatte bene. A tal proposito riprendo le informazioni già scritte per il protocollo 1-wire (che è la modalità di comunicazione digitale utilizzata appunto dalla sonda di temperatura DS18S20) cercando di approfondirle in maniera da renderne chiaro il funzionamento e per poter essere d’aiuto nello scriversi una propria libreria anche per altri dispositivi che non siano necessariamente picmicro.

Per fare gli esempi mi riferirò al datasheet della sonda DS18S20

Il protocollo 1-wire, inventato dalla Dallas Semiconductor è sostanzialmente un protocollo di comunicazione seriale asincrono half-duplex: su di un unico filo viaggiano tutti i segnali (Tx e Rx) e non c’è una linea di clock. Una delle peculiarità di tale protocollo prevede che i dispositivi che la utilizzano possano funzionare anche in modalità parassita: la tensione di alimentazione può essere prelevata dalla stessa linea dati riducendo a 2 i fili necessari per il collegamento (GND + linea dati).

Questa funzione è molto più comoda di quello che possa sembrare. I dispositivi ibutton, ad esempio, che sono semplici “bottoni di memoria”, la sfruttano in maniera egregia: lo stesso case di rivestimento del bottone costituisce i due pin di collegamento.

La modalità di funzionamento parassita è ottenuta tramite un condensatore, interno al dispositivo, che si carica durante la transizione a livello logico alto della linea dati e quindi fornisce energia alla circuiteria interna per tutte le fasi successive. Questa funzione  in alcuni casi permette addirittura di eludere ancor più i disturbi dato che questi non possono essere captati dalla linea di alimentazione. Questa modalità, però, a volte può causare problemi in quanto alcune procedure potrebbero richiedere un tempo superiore al tempo di scarica del condensatore interno. Avviene in pratica che il condensatore si scarica mentre le operazioni non sono ancora terminate causando bei grattacapi (es.: casi in cui bisogna leggere e scrivere in celle di memoria eeprom che richiedono più tempo e un maggiore assorbimento). Questo problema può essere evitato in vari modi: vedremo tra poco come.

Il funzionamento del protocollo 1-wire concettualmente è abbastanza semplice: la linea dati è collegata ad I/O open-drain, per cui c’è una resistenza di pull-up, comune a tutti i dispositivi, che tiene la linea dati normalmente a livello logico alto (questa resistenza è in genere da 4.7KΩ).

In una linea di comunicazione 1-wire viene identificato un dispositivo Master (che gestisce le comunicazioni) e uno o più dispositivi Slave (che rispondono solo se interrogati). Non essendoci un clock i dispositivi dovranno comunicare in tempi prestabiliti (come avviene sulla RS232, con la sola differenza che qui non si può selezionare il baudrate e la linea di comunicazione è una sola). La restrizione su tali tempi diviene più forte nel caso in cui si utilizzi la modalità di alimentazione parassita: non possiamo correre il rischio che la sonda si trovi col condensatore scarico e quindi disalimentata.

Per evitare i problemi di scarica del condensatore in modalità parassita, si può fornire temporaneamente una situazione di “strong-pullup” ottenuta mediante un mosfet pilotato dal dispositivo master. Il mosfet in pratica, entrando in conduzione, elude la resistenza di pullup collegando la linea direttamente al positivo di alimentazione e garantendo, quindi, un maggior apporto di corrente:

Altre volte, invece, basta mettere una resistenza di pull-up di valore più basso. E’ comunque forse più facile alimentare il dispositivo in maniera normale senza complicarsi troppo la vita (e qualora il dispositivo lo permetta – l’iButton per esempio non lo permette):

I Tempi

Prima di cominciare ogni comunicazione, il dispositivo master deve emettere un segnale di reset. Il master configura il pin dedicato alla comunicazione come uscita e la linea dati viene tenuta a livello logico basso per almeno 480µS. Questa operazione serve ad indicare ai dispositivi presenti sul bus che è presente il Master ed è pronto per operare. Passato questo tempo, il master configura il pin come ingresso (alta impedenza) e si mette quindi in “ascolto”: in queste condizioni la linea si trova a livello logico alto grazie alla resistenza di pullup. Nel momento in cui i dispositivi sulla linea rilevano che dopo i 480µS di livello basso si ha una transizione a livello alto per almeno 15 – 60µS, allora inviano un impulso di presenza: portano la linea a livello basso per un tempo variabile tra 60 e 240µS. Il Master rileva questa condizione e capisce che sulla linea c’è almeno un dispositivo 1-wire:

La comunicazione sul bus 1-wire avviene per Time Slots, ovvero per “porzioni di tempo”. Ci sono i Time Slots di scrittura e i Time Slots di lettura. Un singolo Time Slot (sia esso di lettura o di scrittura) interessa un singolo bit di dati da trasferire, una comunicazione intera, quindi, è costituita da più Time Slots in sequenza.

Un time slot di scrittura dura dai 60 ai 120µS massimo. Quando dovrà essere trasmesso un bit ad 1 la linea dati viene tenuta a livello basso per massimo 15µS, per il resto del tempo la linea verrà tenuta alta dalla resistenza di pullup. Quando dovrà essere trasmesso un bit a 0 la linea dati viene tenuta a livello basso per massimo 60µS (quindi un tempo più alto). Tra un time slot e il successivo ci deve essere almeno 1µS di “recupero” in cui la linea viene tenuta a livello alto. Ogni bit, inoltre, viene inviato dopo aver messo la linea a livello basso per almeno 1µS:

I time slots di lettura sono complementari. Il Master “avvia” un time slot di lettura portando la linea a livello basso per almeno 1µS dopodichè rilascia il bus (ovvero si mette in stato di alta impedenza) consentendo ai dispositivi di prendere il controllo della linea e quindi rispondere. I dati inviati dai dispositivi slave dovranno essere campionati dopo 15µS che il master ha portato la linea a livello basso. I dati sono inviati in gruppi di 8 bit a partire dal più significativo verso il meno significativo.

La lettura della libreria scaricabile dagli iscritti in fondo all’articolo, abbondantemente commentata, dovrebbe farvi capire come è semplice implementare queste funzioni via software. Teniamo conto che, allo stato attuale, i picmicro non hanno una periferica 1wire hardware e francamente non la trovo una cosa necessaria.

Per ottenere un corretto funzionamento, inoltre, è necessario fare uso di librerie Delay molto precise. Per questa libreria ho utilizzato le librerie “Enanched Precision” che si trovano sul sito microchipc.com

Il ROM code

I dispositivi Slave sono identificati da un indirizzo a 64bit (8 bytes). Il primo byte dell’indirizzo (il byte più significativo) contiene il CRC (controllo di errore), i successivi 6 bytes (dal più significativo al meno significativo) contengono il numero seriale del dispositivo e l’ultimo byte contiene l’identificativo della “famiglia” a cui appartiene il dispositivo (esempio: 0x28=DS18B20, 0x10=DS18S20).

In questa pagina: http://owfs.sourceforge.net/family.html sono contenuti gli identificativi delle famiglie di vari dispositivi 1Wire, con i loro comandi

Nel caso in cui sul bus sia presente più di un dispositivo il Master dovrà conoscere a priori l’indirizzo di ogni dispositivo sulla linea. Nel protocollo 1-Wire sono definiti alcuni comandi chiamati  ROM commands che servono appunto al riconoscimento/rilevazione degli indirizzi dei dispositivi presenti sul bus. Se invece sulla linea è presente un unico dispositivo, esiste un comando chiamato Skip Rom che serve appunto per evitare di inviare l’indirizzo della periferica e quindi è implicito che i comandi saranno diretti all’unico dispositivo presente.

Libreria

Per gli utenti di settorezero metto a disposizione una libreria che ci permetterà di interfacciarci con il bus 1wire (per la lettura della sonda DS18S20 dovrete aspettare ancora un altro po’!). La libreria è molto semplice e per ora prevede unicamente 4 funzioni di alto livello:

unsigned char OWReset(void); // esegue il reset della linea
unsigned char OWReadByte(void); // legge un byte dalla linea
void OWWriteByte(char val); // scrive un byte sulla linea
void OWReadRom(unsigned char *ID); // memorizza nell'array ID il ROM code del SINGOLO dispositivo sulla linea

Non dovrebbe essere necessario specificare più di quanto non sia già stato scritto nelle note.  La libreria va modificata per il proprio pic agendo sul file onewire.h cambiando unicamente le due definizioni:

16
17
#define    DQ      RC5      // Pin dati sul quale sono collegate le linee DQ dei dispositivi 1-wire
#define    TRIS_DQ    TRISC5     // Registro TRIStato relativo alla porta usata per DQ

Nel main dovremo includere le routine di Delay, necessarie per il funzionamento corretto della libreria e unicamente “onewire.h”.

Avendo a disposizione un dispositivo 1Wire possiamo incominciare a determinarne il rom code, operazione che sarà comunque necessaria nel caso in cui successivamente vorremo collegare su un solo bus 1wire più dispositivi.

Ricaviamo il ROM code

In allegato, in fondo all’articolo, c’è un codice sorgente utilizzante la libreria 1Wire e che permette di rilevare il ROM code di un dispositivo 1Wire. Il codice è compilato per pic16F877A montato su scheda FreedomII ma lo potete semplicemente adattare ad un qualsiasi pic munito di UART in quanto il ROM code verrà appunto inviato sulla UART e letto da un qualsiasi programma terminale.

Supponendo di avere una sonda di temperatura (DS18S20 o DS18B20) procederemo a collegarla in questo modo (modalità alimentazione parassita):

In pratica, il pin DQ della sonda andrà direttamente al pin RC5 del picmicro e gli arriverà Vdd tramite la resistenza di pullup da 4.7KΩ. Utilizzando la FreedomII andremo a sfruttare anche il pulsante BT1, collegato al pin RB4: premendo il pulsante si avvierà la funzione di lettura del ROM code.

Preparato il circuito e caricato sul pic il programma, andremo ad aprire HyperTerminal, scegliendo la giusta porta COM alla quale abbiamo collegato la FreedomII ed impostando i seguenti parametri di comunicazione:

Di default la porta COM verrà aperta. Dando alimentazione alla Freedom apparirà la seguente schermata:

Premendo il pulsante BT1 viene richiamata la funzione per la lettura del ROM code: come specificato funziona solo se sul dispositivo è presente un unico dispositivo 1wire.

La funzione OWReadRom memorizza gli 8 bytes del rom code nell’array ID, dichiarato all’inizio del Main. Successivamente l’array viene scansionato e stampato a video utilizzando la funzione printf:

printf("0x0%X",ID[a]);

come vedete ho utilizzato lo specificatore di formato %X che serve a riportare il byte in formato esadecimale con le lettere maiuscole (%x, invece, lo riporta in esadecimale con le lettere minuscole).

Nella funzione printf ho anteposto manualmente lo 0x (o lo 0x0 se il numero è minore di 16 in modo da anteporre uno zero all’unica cifra esadecimale restituita) : in questo modo otteniamo una stringa che poi possiamo facilmente copiare ed incollare nel nostro programma che successivamente andrà a sfruttare il dispositivo:

Il programma legge il primo byte (0x10 nel mio esempio) e da qui capisce di che tipo di dispositivo si tratta. Ovviamente non potevo elencare tutti i dispositivi 1wire e mi sono limitato alle due sonde di temperatura e agli ibuttons, le altre famiglie le potete trovare nel link che ho postato più in alto.

Links

Application Note 1199 della Microchip sul bus 1-wire

Downloads

PDFRileva ROM Code dispositivi 1Wire (13.55 kB - 259 downloads)

PDFLibrerie 1Wire (4.31 kB - 207 downloads)

L'articolo ti è piaciuto o ti è stato utile per risolvere un problema? SettoreZero è realizzato soltanto con contenuti originali: tutti gli articoli sono curati con passione dagli autori e nulla viene copiato da altri siti. Supporta e mantieni in vita SettoreZero con una donazione: basta soltanto un caffè o una birra. Puoi supportare SettoreZero anche con uno dei progetti elencati nella sezione servizi o partecipare anche tu con un tuo articolo/progetto personale.

Se desiderate che SettoreZero continui a rimanere gratuito e fruibile da tutti, non copiate il nostro materiale e segnalateci se qualcuno lo fa.

Puoi andare alla fine dell'articolo e lasciare un commento. I trackback e i ping non sono attualmente consentiti.

  1. #1 da frabeltra il 25 marzo 2011

    Ciao, bell’esempio d cui sono partito per organizzare il mio lavoretto.

    avrei bisogno di mettermi in contatto con Giovanni Bernardo,
    avrei una domanda inerente all’LCD utilizzato un un’altro esempio e poi vorrei passarti il mio file one-wire (originario dal tuo, ma implementato di altre nuove funzioni; a dire il vero ne mencano solo 2.)

    la mia mail è donalisio@yahoo.com

    • #2 da Giovanni Bernardo il 25 marzo 2011

      Ciao sono io, dimmi pure. Se hai realizzato qualcosa di completo puoi anche inviare il tuo lavoro e lo pubblichiamo col tuo nome, vai all’area “i vostri progetti”

      • #3 da frabeltra il 27 marzo 2011

        ciao, non riesco a trovare in commercio (negozio/on-line) l’LCD ke hai utilizzato tu nel tu esempio, l’ LM032L.
        dove lo posso trovare?

        ci sono altri modelli simili più facilmente reperibili; in genere io acquisto su futura elettronico o rs componenti.

        una altra domanda, hai mai utilizzato la funzione random? se si, mi potresti dire quali librerie caricare?
        finisco di commentare la libreria e poi la invio.

        grazie mille

        • #4 da Giovanni Bernardo il 27 marzo 2011

          Non capisco a quale display ti riferisci. No la funzione random non l’ho mai usata

          • #5 da frabeltra il 28 marzo 2011

            l’LCD forse sono riuscito a trovarlo su futura elettronica, il compnente da te descritto è l’Hitachi HS44780, ma è difficile capire se i display messi in vendita montano quel particolare componente.

            per il random mi sono quasi aggiustato, con l’int su time0 aumento un contatore ran++; e poi quando devo generare un numero a caso lo pesco da li con un pasio di or e xor! ;)

            faccio magari un file un po commentato e un esempio e poi lo carico sul sito

          • #6 da Giovanni Bernardo il 28 marzo 2011

            Il controller si chiama HD44780, non HS, in ogni modo sta scritto che il controller è quello in parecchie parti dell’articolo. Ma quella è la sigla del controller, poi è ovvio che ogni produttore al display che fa mette la sua sigla. Anche perchè il display è costituito da controller più altra roba.
            Con il tuo sistema non so se davvero riesci ad ottenere una cosa davvero random. Per generare i numeri random la via più affidabile è gestire il rumore proveniente dal convertitore A/D. Qui trovi un esempio: http://home.comcast.net/~orb/details.html

          • #7 da paco il 9 marzo 2012

            Ciao Gianni, buona sera.
            Volevo chiederti se con le tue routine si possono leggere i dati della temperatura dalla ds18B20.
            Sto usando un pic16f84A, a cui ho collegato un display LCD 2×24 sulla PORTB.

            Le impostazioni in one-wire.h sono:
            #define DQ RB6
            #define TRIS_DQ TRISB6

            Nel main, invece, ho scritto quanto segue:
            OWReset();
            OWWriteByte(0xCC);
            OWWriteByte(0x44); // Avvia conversione
            DelayBigMs(800);

            OWReset();
            OWWriteByte(0xCC); // SKIP_ROM
            OWWriteByte(0xBE); // Leggi dallo READ_SCRATCHPAD

            temp = OWReadByte(); //byte 0
            temp = (OWReadByte() << 8) + temp; //byte 1

            //— Stampa su Lcd
            etc…

            Il risultato è che il valore visualizzato è negativo e non cambia mai.
            Hai qualche suggerimento da propormi?

          • #8 da paco il 12 marzo 2012

            Ehm, non so sia consono o meno riferire a tal proposito, ma ho trovato una soluzione che mi ha fatto “deporre le armi” (per il momento).
            Qui ( http://jwandrews.co.uk/files/controller.zip ) ho trovato un archivio di file che hanno risolto la questione.
            Non sono totalmente soddisfatto poichè le funzioni implementate utilizzano le routine di delay __delay_ms e __delay_us di htc.h. Ho provato a sostituirne le chiamate con le routine DelayMs() e DelayUs() ma ho ottenuto lo stesso risultato che ottenevo l’altro ieri usando la tua implemementazione. A questo punto mi sorge la domanda: perchè la versione con DelayMs() e DelayUs() non hanno funzionato?

            Ciao!

          • #9 da Giovanni Bernardo il 12 marzo 2012

            le funzioni DelayMs e simili sono errate, non forniscono il ritardo impostato ma quasi il doppio. Ne abbiamo parlato tempo fa.

  2. #10 da frabeltra il 28 marzo 2011

    riapro un nuovo topic altrimenti non si legge + nulla!

    si, il controller è l’HD44780, o solo sbagliato nello scrivere; lo sapevo ke il controller non è la basetta con tutto l’LCD, ma quando io trovo in vendita: “LCD 16X2 etc…….” io non so quale controller utilizzano e quindi non so se poi e utilizzabile con le tue libreria.
    ora ho visto un display su futura elettronica che dice che monta il controlle HD44780, e quindi dovrebbe andare bene.

    per il random ti invio la mia unzione al + presto, poi me leggo bene l’articolo e vedo come lo posso utilizzare; cumunque se utilizzi l’A/D il PIC ne deve essere provvisto il PIC 16F628 x esempio non lo ha!

    per le prove che o fatto i numeri cambiano (a vole si ripetono, ma in genere sono differenti! non è il massimo, ma è quello che ho/so potuto fare! peri vedrò di migliorare!)

    • #11 da Giovanni Bernardo il 28 marzo 2011

      Come specificato nell’articolo relativo al display, non esiste solo l’HD44780 ma ne esistono molti altri compatibili e in genere nessuno lo specifica perchè è implicito che quando si parla di display 16×2 è riferito a un controller HD44780 o compatibile. E’ anche vero che esistono altri controller diversi per display a caratteri ma mi risulta che sono in disuso.

      • #12 da frabeltra il 31 marzo 2011

        Io spero in bene, ho comperato 4 display 2*20caratteri sul sito RS
        l?LCD con cip della “Sitronix” modello “ST7066”,
        sul sito della RS c’era scritto compatibile con HD44780, quando arriva provo e poi ti faccio sapere

  3. #13 da @Marco@ il 10 aprile 2011

    Ciao!
    Innanzitutto complimenti per il sito e il lavoro che stai facendo. Avrei bisogno di un aiuto se possibile. Sto ripassando con i tuoi tutorial un po’ di cose apprese anni fa, e volevo in particolare usare questo per provare degli iButton. Modificando il tuo programma, in fase di compilazione ottengo un errore sulle routine di delay, in particolare i messaggi che ottengo sono:

    Error [103] G:\Documenti\Elettronica\Programmi Pic\iButtonTest01\delay.h; 70.39 #error: please define PIC_CLK correctly
    Error [103] G:\Documenti\Elettronica\Programmi Pic\iButtonTest01\delay.h; 124.39 #error: please define PIC_CLK correctly
    Error [103] G:\Documenti\Elettronica\Programmi Pic\iButtonTest01\delay.h; 200.39 #error: please define PIC_CLK correctly

    ovviamente nei miei sorgenti PIC_CLK è definito. Ho poi osservato che lo stesso errore lo ottengo compilando i tuoi sorgenti. In pratica ho creato un progetto in MPLAB includendo i file .c e .h nel tuo archivio. Sto usando MPLAB 8.46 e il compilatoe Hi-Tech 9.70.
    Probabilmente non sto considerando qualcosa io e se hai un suggerimento, è sicuramente ben accetto.
    Ti ringrazio
    Marco

  4. #15 da paco il 12 marzo 2012

    Bene, quindi mi stai dicendo che la libreria di delay presente in quest’articolo non va bene perchè poco precisa?
    Si si, potresti dirmi dove ne hai/avete parlato?
    Te ne sarei grato, solo per capire cosa dovrei utilizzare da oggi in poi…

    Grazie ancora e scusa il disturbo.

    • #16 da Giovanni Bernardo il 12 marzo 2012

      Si. è una libreria vecchia che risale agli inizi degli studi sui pic fatti con Sergio Fiocco. Mi pare che ne parlammo proprio li sul suo forum, ora non ricordo. Se ti servono routine piu precise vedi nella sezione Picmicro -> librerie ci sono routine ultraprecise. Altrimenti se ti servono ritardi fissi, cioè devi usare DelayMs(costante), puoi usare le routine di delay di Hitech C. Basta che dichiari _XTAL_FREQ (con l’underscore davanti) e usi le funzioni __delay_ms e __delay_us. A te la scelta, sta tutto qua a portata di mano.

  5. #17 da agric il 9 aprile 2013

    Salve Giovanni
    Sto approfondendo il protocollo one-wire . Leggendo ho trovato una incongruenza tra l’articolo e il software

    dall’articolo “I dati sono inviati in gruppi di 8 bit a partire dal più significativo verso il meno significativo.”

    nel software avviene il contrario , prima legge la famiglia di appartenenza e in ultimo il CRC

    a parte questo particolare , un bell’articolo complimenti

Devi essere collegato per lasciare un commento.

  1. Ancora nessun trackback
settorezero.com e il logo Zroid™ ©2007÷2015 Giovanni Bernardo - E' vietata la copia e la distribuzione anche parziale dei contenuti di questo sito web senza l'esplicito consenso dell'autore.
I contenuti di settorezero.com sono distribuiti sotto una licenza Creative Commons Attribuzione-Non Commerciale-Non Opere derivate 2.5 Italia a cui vanno aggiunte le condizioni d'uso definite nel disclaimer.
settorezero.com e tutti i suoi contenuti sono tutelati dalla legge sul diritto d'autore per cui i trasgressori sono perseguibili a norma di legge. Settorezero fa uso dei cookie leggi l'informativa estesa.
Creative Commons BY-NC-ND 2.5
Il tema di questo sito è basato sul tema Fusion per wordpress, realizzato originariamente da digitalnature e fa uso del plugin Wassup per il computo delle statistiche. Per contattare l'autore siete pregati di utilizzare la sezione contatti.
Per essere aggiornato con tutte le novità di settorezero.com seguici anche anche su Facebook Twitter Tumblr Blogspot Youtube.