www.errorediridondanzaciclicodotcom

  • HOME
  • Dallas 18B20
  • BACK P.P.

  • Breve ma ultima guida all'uso delle dallas

    Qualsiasi amante del Raspi e con propensione per "la rete delle cose" incorre, prima o poi, nel processo di configurazione di una sonda di temperatura.
    Per la semplicità di uso si ricorre normalmente alle Dallas 18B20, le cosiddette sonde a "filo unico".
    Sono sonde che non richiedono un convertitore ADC (Analog to Digital Converter) e, quindi, pronte all'uso plug and play.
    Si chiamano così perche sono sonde che, anche in numero considerevole, veicolano i dati su un unico filo (più ovviamente terra e tensione) perchè in realtà la GPIO (o PLC) leggerà il codice di ogni sensore singolarmente.

    Nel caso del Raspberry si usa un GND, una tensione di 3.3 volt ed il Pin dedicato alla trasmissione One-Wire che è il numero 7. Io normalmente lascio sempre libero questo pin in qualsiasi progetto perchè in futuro potrei averne bisogno per le sonde delle temperature.
    Come già riportato da qualsiasi altro blog, anche 100 dallas richiedono sempre solo una resistenza da 4.7Kohm. Essa serve per tenere alto il segnale quando non avviene la trasmissione dei dati, come uno switch o altri devices.
    Qui sotto un disegno che mostra i collegamenti canonici e, come al mio solito, il morsetto che mostra concretamente, se volete, come collegare il tutto (uscendo dall'astrattezza grafica tipica dei tutorial o dalla temporaneità della breadbord).


    Nel disegno si vedono 3 (per ipotesi) dallas che utilizzano gli stessi fili, in serie, di un cavo cat5 (il cat6 che ho realmente utilizzato è ancora meglio perchè la sezione del singolo filo maggiore).
    Il cavo usato normalmente per le connessioni ethernet, il cat5e (per esempio) è idoneo anche per tratti lunghi. Infatti la bassa tensione (3.3 volt) non necessita di grosse sezioni di rame e la struttura ad intreccio a coppie fornisce una buona protezione dai disturbi.
    Anche la guida ufficiale delle dallas parla di cat5, sottolineando anche una caratteristica di questo cavo che vedete nel disegno. La migliore protezione dei disturbi si ha utilizzando una coppia ritorta per il GND e la VCC, prendendo poi un singolo filo per il pin.

    In caso di dallas multiple, si prende la più lontana e si collega con i tre fili. Quando poi si arriva a quella immediatamente vicina, si usa un semplice morsetto per fare una collegamento a tre (entrata, uscita da una parte e terminali della dallas dall'altra).
    Si prosegue a ritroso fino al raspberry dove, prima di entrare nella GPIO, ci sarà il morsetto finale come in figura, con la resistenza tra il pin e la VCC.
    L'uso del Cat5 (Cat6 ha sezione maggiore e, credo, anche un twist migliore) potrebbe permettere anche distanze di un 100io di metri, forse però, più certi, una 30na di metri.
    Una volta preparata la rete delle dallas, non rimane che scaricare i dati con il programma che preferite (io, Python!). Se tutti i collegamenti son ok, dovreste trovare nella directory /sys/bus/w1/devices/ un folder che inizia per 28*** e, in esso, un file che si chiama w1_slave. E' questo il file che conterrà i dati di lettura della temperatura.
    La cartella che inizia per 28 è quella specifica di ogni dallas, anche se tutte viaggiano su un unico filo.

    Qui sotto il mio script di lettura con qualche trucco per evitare i malfunzionamenti:


    Inizio dalla definizione delle directory (base_dir) su cui le dallas scrivono i valori. Aggiungo a questa radice, comune a tutti i sensori, la directory che inizia per "28", dove si trovano le dallas. In questo caso mi limito alla prima directory ("[0]").

    Completo poi la directory con il file di testo w1_slave, su cui si trovano i valori.
    Uso il try-except per il caso in cui la dallas non è collegata, rotta o qualsiasi problema hardware. Senza ciò avrei il blocco dello script.

    #reading 18b20
    base_dir = '/sys/bus/w1/devices/'
    try:
    device_folder = glob.glob(base_dir + '28*')[0]
    device_file = device_folder + '/w1_slave'
    except:
    device_file = 'no file'

    A questo punto definisco la funzione read_temp_raw(). Provo (try) ad aprire il file (w1_slave) definito sopra, se lo vedo, leggo le linee, lo chiudo e "ritorno" le linee per la fase successiva.
    Se il file non esiste "ritorno" una stringa "error".
    def read_temp_raw():
    try:
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
    except:
    lines = str("error")
    return lines

    Ora uso le linee del file per estrarre i dati di temperatura. Definisco quindi una nuova funzione (read_temp) che legge, innanzitutto, le linee del file ritornate dalla funzione precedente.
    Se le linee non sono uguali a "error" vado al passo successivo.
    In questo passo cerca la lettera t nella linea numero 2 ("[1]") e, se ok, passo al controllo successivo in cui verifico se c'è "YES" (viene scritto automaticamente dalle dallas se è tutto ok).
    Se anche questo controllo passa, lo script estrae i dati di temperatura, li converte in float, li arrotonda e, per ultimo, se è diverso il valore da 85, scrive (ritorna) il valore nel buffer.
    La temperatura di 85 è sinonimo di un errore di lettura della dallas, frequente ad esempio quando ci sono disturbi di segnale.
    A volte questo valore di 85 compare temporaneamente ad avvio del raspberry, per questo motivo, dopo avere rilevato questo errore, riprovo a cercare un valore reale di temperatura.
    I due "else" successivi ritornano dei valori numerici, anzichè stringhe con scritto error o altro perchè le stringhe mi bloccavano parti di altri script che utilizzano queste letture.
    def read_temp():

    #return lines from read_temp_raw()
    lines = read_temp_raw()
    if lines != str("error"):        #se lines non e' = 'error'
    char_pos=lines[1].find('t=')        #individua la lettere "t"
    if lines[0].strip()[-3:]=='YES':       #se c'e' YES alla fine legge normalmente e ritorna temp1
    tstring=lines[1][char_pos+2:]
    temp_c = float(tstring)/1000
    temp_c = round(temp1, 1)
    if temp_c != 85:        #85 indica un errore di lettura
    return temp_c
    else:
    time.sleep(2)
    char_pos=lines[1].find('t=')
    tstring=lines[1][char_pos+2:]
    temp_c = float(tstring)/1000
    temp_c=round(temp_c, 1)
    return temp_c

    #se non c'e' YES (NO) ritorna 88.8 (la dir esiste ancora ma c'e' NO)
    else:
    return 88.8

    #se lines = error (la dir e' sparita e read_temp_raw() non trova la dir e ritorna error), ritorna 99.9
    else:
    return 99.9