Sensoristica & AVR

La tecnologia dei sensori occupa, sempre con maggiore incisività, un ruolo primario in diversi settori dove si richiede la capacità di misurare le caratteristiche dell’ambiente circostante.

La casa costruttrice Sensirion AG propone una vasta gamma di sensori 2-wire in grado di offrire prestazioni eccellenti e soluzioni tecnologiche veramente interessanti. Il sensore SHT71, con uscita digitale compensata (sensori di umidità e temperatura monolitici con uscita digitale), offre un range di misure molto ampio per la temperatura (tra -40°C e +120°C) e totale per l’umidità (0% - 100%); garantisce, inoltre, ottima accuratezza e rapido tempo di risposta. È fornito montato su un cavetto di circa 30 cm per un più comodo posizionamento. Nella figura 1 sono messi in evidenza alcuni sensori della Sensirion AG.

Figura 1: i sensori della Sensirion.

Figura 1: i sensori della Sensirion.

Sensirion  con AVR

La libreria che proponiamo in questo articolo si basa su di una versione demo fornita dalla Sensirion stessa. Possiamo raggruppare le varie chiamate software in diverse macrofunzioni utilizzate dal protocollo della Sensirion. Come mostrato di seguito.

Figura 2: comunicazione tra sensore e microcontrollore.

Figura 2: comunicazione tra sensore e microcontrollore.

 

Figura 3: protocollo di comunicazione.

Figura 3: protocollo di comunicazione.

 

Generazione della  trasmissione

Figura 6: inizio della sequenza di trasmissione

Figura 4: inizio della sequenza di trasmissione

Come possiamo leggere dal data sheet del componente, per trasmettere secondo il protocollo Sensibus è necessario spedire una sequenza chiamata “Transmission Start”. La sequenza è mostrata in figura 3 e la sua implementazione è riportata nel listato 1.

void transstart(void)
{
  enable_data();
  data_high();
  clock_low();
  DELAY(SHT_DELAY);
  DELAY(SHT_DELAY);
  clock_high();   DELAY(SHT_DELAY);
  data_low();     DELAY(SHT_DELAY);
  clock_low();    DELAY(SHT_DELAY);  DELAY(SHT_DELAY);
  clock_high();   DELAY(SHT_DELAY);
  data_high();    DELAY(SHT_DELAY);
  clock_low();
}
Listato 1

Subito dopo il segnale di Transmission Start è possibile inviare il comando verso il dispositivo  e la tabella 1 mostra i vari comandi disponibili.

TABELLA 1 pomandi disponibili verso il Sensirion

Tabella 1 - pomandi disponibili verso il Sensirion

Dalla figura vediamo che la sua realizzazione è differente dal bus I2C; infatti, in questo bus la condizione di start avviene se, mantenendo il  segnale di clock ad alto livello, si porta la linea dati a livello basso. Inoltre, in un bus I2C, oltre alla condizione di start, esiste anche quella di stop. In questo caso la linea di clock deve essere ad alto livello quando la linea dati è portata da basso ad alto. Nel nostro caso, come vediamo dalla figura 3, la condizione di start e stop dell’ I2C sono fusi nella condizione di Transmission Start con inframmezzato un ciclo di clock.

Gestione  del registro  di stato

La figura 5 pone in evidenza le particolari funzioni che sono disponibili accedendo al registro di stato; come vediamo sono possibili entrambe le operazioni di lettura e di scrittura.

Figura 7: registro di stato

Figura 5: registro di stato

Dalla figura notiamo che è possibile, attraverso  il bit 0, modificare la risoluzione utilizzata per la misura. È possibile scegliere tra due valori, ponendo il bit a zero si ottiene una risoluzione a 12 bit per valori di umidità, o su 14 bit per i valori di temperatura. Viceversa,   i valori diventano rispettivamente 8 o 12 bit. La figura 6 mostra la struttura del frame per scrivere o leggere nel registro.

Figura 8: frame per il registro di stato.

Figura 6: frame per il registro di stato.

listati 2 e 3 mostrano le possibili implementazioni. Come vediamo con la funzione transstart() si avvia la trasmissione al componente secondo il protocollo utilizzato.

//—————————————————————————————————————————
// Reads the status register with checksum (8-bit)
//—————————————————————————————————————————
char ShtReadStatus(unsigned char *p_value)
{
  unsigned char error=0;
  unsigned char checksum=0;
  transstart();                       //transmission start
  error = write_byte(STATUS_REG_R);   //send command to sensor
  *p_value = read_byte();             //read status register (8-bit)
  checksum = read_byte();             //read checksum (8-bit)
  return error;                       //error=1 in case of no
                                      //response form the sensor
}
Listato 2
//—————————————————————————————
// Writes the status register.
//Note this library only supports the default
// 14 bit temp and 12 bit humidity readings.
//—————————————-———————————————-
char ShtWriteStatus(unsigned char value)
{
  unsigned char error=0;
  transstart();                        //transmission start
  error += write_byte(STATUS_REG_W);   //send command to sensor
  error += write_byte(value);          //send value of status register
  return error;                        //error>=1 in case of no
                                       //response form the sensor
}
Listato 3


Calcol
o  del checksum

La corretta trasmissione digitale è assicurata da un checksum a 8 bit, in questo modo possiamo garantirci sui trasferimenti incompleti o erronei. L’algoritmo di checksum è descritto in un data sheet del costruttore. Inizializzazione del microcontrollore (AVR) Prima di utilizzare la libreria è necessario programmare  i pin del microcontrollore per consentire di accedere al dispositivo della Sensirion.  Il listato 4 mostra la possibile implementazione.

//—————————————————————————————————————————
// Initialize AVR i/o pins.
//—————————————————————————————————————————
void ShtInit(void)
{
  sbi(SHT_DDR, SHT_CLOCK); // Set clock pin to output
  cbi(SHT_PORT, SHT_CLOCK); // Turn off clock pin
  disable_data();
}
Listato 4

 

Resettare il componente

A volte può succedere, per diversi motivi, di perdere la comunicazione verso il sensore. In questo caso è necessario resettare il  componente, e per svolgere questa operazione è necessario lasciare il segnale  Data alto per nove cicli di clock, successivamente si deve eseguire una transmission Start per iniziare una nuova sessione con il sensore.  È bene ricorda re che questa operazione resetta solo l’interfaccia e non pregiudica il  contenuto del registro di stato. Questa funzionalità viene svolta dalla porzione di codice presente nel listato 5.

void ShtReset(void)
{
  unsigned char i;
  enable_data();
  data_high();
  clock_low();
  for(i=0;i<10;i++)    //9 SCK cycles
  {
     clock_high();
     Delay(SHT_DELAY);
     clock_low();
     Delay(SHT_DELAY);
  }
  transstart();       //transmission start
}
Listato 5

Misura della temperatura e dell’umidità Questa operazione è compiuta dopo aver spedito il comando ‘00000101’ per rilevare l’umidità o ‘00000011’ per la temperatura; il  microprocessore deve poi aspettare fino a quando la misura non si completa. Il tempo che è necessario per prendere questi valori oscilla approssimatamene sui valori di 11 ms per valori su 8 bit, 55 ms per 12 bit e 210 ms per 14 bit. Per segnalare la fine della misura, il sensore mette in pulls down la linea dei dati entrando poi in idle mode, come possiamo vedere in figura 3 dov’è mostrato una ipotetica misura di 2353 (75,79)   in binario “0000’1001’0011’0001”.
Certamente il  micropro cessore può svolgere altri compiti e leggere la disponibilità dei dati in un momento successivo. Dalla figura vediamo che la misura è composta da tre byte: due per i valori dell’umidità calcolata e un byte per il checksum. L’ultimo byte ad essere trasferito è il valore del checksum, anche in questo caso il checksum non è strettamente richiesto; infatti, potrebbe essere tranquillamente ignorato dal microprocessore. Al termine della misura, il sensore  si pone di nuovo nello stato definito come sleep mode, in questo caso rimane in attesa per una nuova richiesta dal microprocessore. Il listato 6 mostra una possibile implementazione, dalla lettura del listato vediamo che, in caso di lettura non andata a buon fine, è restituito un valore di errore, 0xFFFF.

int ShtMeasure(unsigned char mode)
{
  unsigned int temp = 0xFFFF;
  unsigned char checksum;
  unsigned char c;
  // Signal start of communications
  transstart();
  // Request measurement
  write_byte(mode);
  // Sensor lowers the data line when measurement
  // is complete. Wait up to 2 seconds for this.
  for (c=0; c<20; c++)
  {
           if (! bit_is_set(SHT_PIN, SHT_DATA))
                                               break;
           DELAY(1000000/10);
  }
  // Read the measurement
  if (! bit_is_set(SHT_PIN, SHT_DATA))
  {
           temp = read_byte();
           temp = temp << 8;
           temp += read_byte();
           checksum = read_byte();
  }
  return temp;
}
Listato 6

Ci sono altre tre funzioni, due delle quali ad uso interno, presenti in questa libreria: due funzioni che permettono di scrivere e leggere un byte dal sensore e un’altra permette, una volta letto il valore dal sensore, di convertirlo in modalità reale. In questo modo, il valore restituito dovrà essere considerato come composto da una parte decimale e da una parte intera, per esempio il valore 2356 deve essere trattato come 23.56.

 

 

3 Commenti

  1. Andrea Garrapa Andrea Garrapa 28 gennaio 2019
  2. Giovanni Di Maria Giovanni Di Maria 28 gennaio 2019
    • Daniele Valanzuolo Daniele Valanzuolo 29 gennaio 2019

Scrivi un commento

EOS-Academy