Vs: 1-wire for dummies
repomies sanoi:
Verkoille on helppo pistää asynkroninen konversiokäsky jokaiselle, sitten vain nukkuu sen 750ms ja lukee kaikkien verkkojen anturit kerralla. Oleellista on laittaa jokaiselle verkolle kutsu setWaitForConversion(false).
Tavoitteenani on tehdä yksi-anturi-per-verkko tyyppinen anturivikojen sattuessa hieman helpommin huollettava ratkaisu, joka kuitenkin lukee antureita nopeasti. Toki anturit voisi laittaa kaikki samaan piuhaan ja ne saa siitä nopsasti luettua, mutta kyllä tähtimallisessa verkossa on puolensa.. anturin osoitteella ei ole siinä mitään väliä, ei tarvitse selvitellä että mikä anturi on mikäkin.
Antureiden "paikkojen" selvittäminen tosiaan on edessä jos laittaa samaan väylään enemmän kuin yhden anturin. Selvittämisen voi tehdä esim. lämmittämällä yhtä anturia kerrallaan sormien välissä ja seuraamalla muutosta lukutuloksissa. Koska laitoin ilpin ympärille 7 anturia niin pidin välttämättömänä laittaa ne kiinni vain yhdellä ohuella johdolla jotta se häiritsee mahdollisimman vähän puhallusilman liikettä.
Samoin asensin vain yhden johdon ala- ja yläkerran välille (siinäkin oli tekemistä). Näin siis käytäntö ei aina salli tuota helpompaa yksi anturi / yksi johto asennustapaa.
Anturien lukeminen tosiaan on tehtävä niin että lähettää niille ensin konversiopyynnön, odottaa > 750 ms ja lukee.
Konversiopyynnön voi lähettää kaikille väylän antureille kerralla:
void StartConversion (byte bus, byte pow, OneWire dss) {
dss.reset();
dss.skip(); // the skip-command addresses all sensors on the bus
dss.write(0x44, pow); // convert temp (in parasite mode pow = 1, in +5V mode pow = 0)
}
Tein ohjelman 1 s loopin pohjalle jolloin on helppo lähettää pyyntö ja seuraavalla kierroksella lukea kaikki anturit perä perää.
if (i == 1) { // once in every tm seconds, start temperature conversion
for (j1 = 0; j1 < maxbus; j1++) { // initiate temp conversion on all buses
if (numsensor[j1] > 0) // only if bus reset did not fail (= no sensors)
StartConversion ( j1, 0, dss[j1]);// conversion takes about 750 ms, all sensors in parallel
if (i == 2) { // read all sensors
for (j1 = 0; j1 < maxbus; j1++) { // j1 = bus number
for (j2 = 0; j2 < numsensor[j1]; j2++){ // j2 = sensor number
for (n = 0; n < 8; n++){
oneaddr[n] = addr[j1][j2][n]; // temporary address array
}
byte e = RdTemp (oneaddr, dss[j1]); // read one DS18B20
if (e == 1) // crc error
e = RdTemp (oneaddr, dss[j1]);
if (e == 1) {
sendString(t6);
}
else {
char tempreadings[] = "E0S0b0:00b1:00";
char th[3];
tempreadings[1] = '0' + j1;
tempreadings[3] = '0' + j2;
sprintf(th, "%2x", temp[0]);
tempreadings[7] = th[0];
tempreadings[8] = th[1];
sprintf(th, "%2x", temp[1]);
tempreadings[12] = th[0];
tempreadings[13] = th[1];
sendString(tempreadings);
sent_mess_count += 1;
}
}
}
}
byte RdTemp( byte addr[8], OneWire dss) { // read one sensor
byte m1;
dss.reset(); // the sequence is: 1) reset 2) ROM command 3) function command
dss.select(addr); // ROM command = match ROM = address
dss.write(0xBE); // function command = read scratchpad
for ( m1 = 0; m1 < 9; m1++) // read all 9 bytes for crc check
temp[m1] = dss.read();
if ( OneWire::crc8 ( temp, 8 ) != temp[8])
return 1;
else return 0;
}
Mittasin loopin suoritusajan ja siihen meni ~ 1 ms silloin kun ym. komennot ei osu kohdalle (loopissa on toki muutakin koodia). Ym. kohdalla aikaa kului 4 ms ja 100 ms (8 x DS18B20).