Go Down

Topic: Programmazione avanzata arudino (Read 2291 times) previous topic - next topic

Subsea

Buona sera a tutti!
Inizio questo topic per capire qualcosa in più su come interfacciare i sensori con Arduino senza usare librerie già pronte.
Per esempio, per usare il sensore DHT11 (o il DHT22) cosa bisogna "fare"? oppure per il DS18B20, come fare per "sentire cosa dice"?
Finchè si tratta di valori analogici con una semplice conversione si trova il dato cercato, ma come districarsi tra datasheet e protocolli?
Probabilente continuerò ad usare librerie già esistenti, ma vorrei provare a capire qualcosa in più del semplice scomapatta libreria.
Scusate per la confusione spero capiate cosa intendo, ma, in caso contrario, provvederò a rendermi più esplicito. XD
Grazie mille!

leo72

La risposta è semplice: devi scriverti tu il codice  ;)

A parte gli scherzi, una libreria è un modo semplificato per fare qualcosa usando del codice scritto da altri.
Ad esempio, l'interfacciarsi con i tuoi sensori DHTxx.

Come si deve fare? Devi partire dal datasheet del componente e studiarti innanzi tutto come lavora, poi come si collega ed infine come dialogarci. A questo punto devi metterti lì e replicare via software il modo di comunicarci che hai studiato sul datasheet. Potrebbe essere facile come no. Ad esempio, se hai un componente che comunica via One-Wire, ti prendi la libreria One-Wire e poi spedisci i comandi che il sensore accetta e poi leggi sempre con quella libreria cosa esso "dice".
La One-Wire ti semplifica la vita perché è una libreria che implementa un protocollo di comunicazione. Se poi ti trovi anche la libreria che gestisce quel componente (es. DS18B20) sei a cavallo: includi 2 lib e sei a posto.
Ma se vuoi scriverti tutto da solo, devi:
1) scriverti il software per implementare la comunicazione One-Wire
2) scriverti il codice per comunicare con il DS18B20.

Capisci bene che con il tempo che sprechi a fare queste cose avevi già scritto il tuo programma usando le librerie fatte da altri  ;)

Subsea

#2
Aug 27, 2013, 11:10 pm Last Edit: Aug 27, 2013, 11:13 pm by SUBSEA Reason: 1
Grazie mille Leo!
Sì, io facevo un discorso giusto per capire, poi magari nell'applicazione pratica userò librerie pronte.
Possiamo far l'esempio del DHT11? http://www.micro4you.com/files/sensor/DHT11.pdf è il data, da cosa capisco come lavora?
Se permetete, provo a rispondermi da solo :smiley-yell:: fine pagina 5, inizio 6. Dice che trasmette 40 bit, ma io come faccio a capire quando e quale è il bit? come faccio a farlo capire ad arduino? :(

leo72

E' tramite il protocollo One-Wire. Devi prenderti le specifiche del protocollo, studiartele e replicare il protocollo via software. A questo punto, avendo il protocollo di comunicazione, gestire quei 40 bit diventa compito del protocollo.
Ecco come avere quei 40 bit:
Quote
When MCU sends a start signal, DHT11 changes from the low-power-consumption mode to the running-mode, waiting for MCU completing the start signal. Once it is completed, DHT11 sends a response signal of 40-bit data that include the relative humidity and temperature information to MCU. Users can choose to collect (read) some data. Without the start signal from MCU, DHT11 will not give the response signal to MCU. Once data is collected, DHT11 will change to the low-power-consumption mode until it receives a start signal from MCU again.

Quindi prima ti scrivi la One-Wire, poi con questa interroghi il chip. E poi il tuo codice troverà i dati in base a quei 40 bit.

Ecco perché ti dico che è sempre meglio, quando si può, evitare di reinventare la ruota  ;)

Subsea

#4
Aug 27, 2013, 11:28 pm Last Edit: Aug 27, 2013, 11:32 pm by SUBSEA Reason: 1
ok, quindi si usa il one-wire, e quindi quasi sicuramente libreria, ma cosa darebbe fuori, già i dati leggibili?
P.s. Per le specifiche del protocollo, wikipedia?


leo72


ok, quindi si usa il one-wire, e quindi quasi sicuramente libreria, ma cosa darebbe fuori, già i dati leggibili?

Sì, assemblati in quei 40 bit in un certo ordine, compreso un CRC di controllo, da cui poi tu devi estrarli e ricomporre l'informazione.

Subsea

Quindi dice già temperatura e umidità? E la conversione da bit a leggibile la fa il one wire? Ultima cosa su wiki ce scritto già come interpretare i dati? E questi dati come arrivano? 001101 ecc? Se si, come Vanno riconosciuti da Arduino? Grazie ancora per la pazienza! :smiley-sweat: :smiley-mr-green:

leo72


Quindi dice già temperatura e umidità?

Così dice il datasheet. Pag. 5

Quote

E la conversione da bit a leggibile la fa il one wire?

No. One-Wire è il canale di trasmissione. La conversione la fa l'algoritmo che spedisce le richieste al sensore e che riceve i dati da questo. Che sia una lib già fatta o un tuo codice, il succo non cambia.

Quote

Ultima cosa su wiki ce scritto già come interpretare i dati? E questi dati come arrivano? 001101 ecc? Se si, come Vanno riconosciuti da Arduino? Grazie ancora per la pazienza! :smiley-sweat: :smiley-mr-green:

Continui a fare confusione fra canale di  trasmissione e dati trasmessi su quel canale  ;)
I dati ogni sensore li spedisce secondo un proprio protocollo di trasmissione, nel caso del DHT11 è scritto nel PDF che hai linkato (pag 5):
Quote
Data format: 8bit integral RH data + 8bit decimal RH data + 8bit integral T data + 8bit decimal Tdata + 8bit check sum. If the data transmission is right, the check-sum should be the last 8 bit of "8 bit integral RH data+
8 bit decimal RH data + 8 bit integral T data + 8 bit decimal T data"

Subsea

Grazie ancora, approfitterò ancora un po' della tua esperienza.
Quote
La conversione la fa l'algoritmo che spedisce le richieste al sensore e che riceve i dati da questo. Che sia una lib già fatta o un tuo codice, il succo non cambia.
questo algoritmo quindi prende questi
Quote
Data format: 8bit integral RH data + 8bit decimal RH data + 8bit integral T data + 8bit decimal Tdata + 8bit check sum. If the data transmission is right, the check-sum should be the last 8 bit of "8 bit integral RH data+
8 bit decimal RH data + 8 bit integral T data + 8 bit decimal T data
e li rende leggibili. Ma Arduino come fa a sapere quale è un bit? glielo dice il one wire? e poi, questi bit sono 0 e 1, giusto? come faccio a dire: bene, dopo 8 0 o 1 che ti arrivano fermali e converti da binario a decimale (se così bisogna fare)?

leo72

Un consiglio, per capire certe cose spesso è meglio vederle che sentirle  ;)
Quindi prendi la lib One-Wire ed una lib che accede ai DHTxx e studiati i sorgenti.

Subsea

ok, provo a fare così, poi se non capisco chiedo! quindi, preparatevi!!! XD


Subsea

#13
Sep 05, 2013, 02:58 pm Last Edit: Sep 05, 2013, 03:05 pm by leo72 Reason: 1
rieccomi! Allora, intanto quale file devo aprire? :smiley-sweat:
Proviamo col .h
Code: [Select]
private:
 uint8_t data[6];
 uint8_t _pin, _type, _count;
 boolean read(void);
 unsigned long _lastreadtime;
 boolean firstreading;

public:
 DHT(uint8_t pin, uint8_t type, uint8_t count=6);
 void begin(void);
 float readTemperature(bool S=false);
 float convertCtoF(float);
 float readHumidity(void);

};

E' qui che legge i bit? mmmm, credo di no. Proviamo con questo:
Code: [Select]
DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
 _pin = pin;
 _type = type;
 _count = count;
 firstreading = true;
}

void DHT::begin(void) {
 // set up the pins!
 pinMode(_pin, INPUT);
 digitalWrite(_pin, HIGH);
 _lastreadtime = 0;
}

//boolean S == Scale.  True == Farenheit; False == Celcius
float DHT::readTemperature(bool S) {
 float f;

 if (read()) {
   switch (_type) {
   case DHT11:
     f = data[2];
     if(S)
      f = convertCtoF(f);
     
     return f;
   case DHT22:
   case DHT21:
     f = data[2] & 0x7F;
     f *= 256;
     f += data[3];
     f /= 10;
     if (data[2] & 0x80)
f *= -1;
     if(S)
f = convertCtoF(f);

     return f;
   }
 }
 Serial.print("Read fail");
 return NAN;
}

float DHT::convertCtoF(float c) {
return c * 9 / 5 + 32;
}

float DHT::readHumidity(void) {
 float f;
 if (read()) {
   switch (_type) {
   case DHT11:
     f = data[0];
     return f;
   case DHT22:
   case DHT21:
     f = data[0];
     f *= 256;
     f += data[1];
     f /= 10;
     return f;
   }
 }
 Serial.print("Read fail");
 return NAN;
}


boolean DHT::read(void) {
 uint8_t laststate = HIGH;
 uint8_t counter = 0;
 uint8_t j = 0, i;
 unsigned long currenttime;

 // pull the pin high and wait 250 milliseconds
 digitalWrite(_pin, HIGH);
 delay(250);

 currenttime = millis();
 if (currenttime < _lastreadtime) {
   // ie there was a rollover
   _lastreadtime = 0;
 }
 if (!firstreading && ((currenttime - _lastreadtime) < 2000)) {
   return true; // return last correct measurement
   //delay(2000 - (currenttime - _lastreadtime));
 }
 firstreading = false;
 /*
   Serial.print("Currtime: "); Serial.print(currenttime);
   Serial.print(" Lasttime: "); Serial.print(_lastreadtime);
 */
 _lastreadtime = millis();

 data[0] = data[1] = data[2] = data[3] = data[4] = 0;
 
 // now pull it low for ~20 milliseconds
 pinMode(_pin, OUTPUT);
 digitalWrite(_pin, LOW);
 delay(20);
 cli();
 digitalWrite(_pin, HIGH);
 delayMicroseconds(40);
 pinMode(_pin, INPUT);

 // read in timings
 for ( i=0; i< MAXTIMINGS; i++) {
   counter = 0;
   while (digitalRead(_pin) == laststate) {
     counter++;
     delayMicroseconds(1);
     if (counter == 255) {
       break;
     }
   }
   laststate = digitalRead(_pin);

   if (counter == 255) break;

   // ignore first 3 transitions
   if ((i >= 4) && (i%2 == 0)) {
     // shove each bit into the storage bytes
     data[j/8] <<= 1;
     if (counter > _count)
       data[j/8] |= 1;
     j++;
   }

 }

 sei();
 
 /*
 Serial.println(j, DEC);
 Serial.print(data[0], HEX); Serial.print(", ");
 Serial.print(data[1], HEX); Serial.print(", ");
 Serial.print(data[2], HEX); Serial.print(", ");
 Serial.print(data[3], HEX); Serial.print(", ");
 Serial.print(data[4], HEX); Serial.print(" =? ");
 Serial.println(data[0] + data[1] + data[2] + data[3], HEX);
 */

 // check we read 40 bits and that the checksum matches
 if ((j >= 40) &&
     (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) ) {
   return true;
 }
 

 return false;

}


AIUTOOO!! e' pieno di unit8!!!! :)

leo72

Per favore non urlare....  :smiley-roll:
Inoltre sono uint8, non unit8... Se conosci il C, sai che uint8 è l'unsigned char, che in Arduino corrisponde al tipo "byte".

Go Up