const int dataPin = 2; /* Data I/O */
const int numBit = 40; /* numero data bit */
volatile uint32_t m1; // m1 per lettura sequenza
volatile int8_t stato, bit_count;
volatile uint8_t rby[5], cksum, olds;
#define FLOW 50
#define ZERO 26
#define UNO 70
#define INIZIO 80
#define SREAD 18
#define OKREAD 6
#define FERR -1
void setup()
{
Serial.begin(9600);
char tString[ 10 ];
// Inseriamo un controllo dei tempi
Serial.print( "F_CPU: " ) ;
Serial.println( ltoa( F_CPU, tString, 10 )) ;
Serial.print("CyclesMillis = ");
Serial.println(microsecondsToClockCycles(1000)); // cicli per mS
pinMode(dataPin, OUTPUT); // default Output
digitalWrite(dataPin, HIGH); // Stato riposo
for(uint8_t i = 0; i< 5; i++) rby[i]=0;
delay(1000); // Un secondo di salvaguardia
digitalWrite(dataPin,LOW); // Invio impulso di lettura
delay(SREAD); // Durata = SREAD mS
digitalWrite(dataPin,HIGH);
pinMode(dataPin, INPUT_PULLUP); // Switch dataPin come INPUT
stato=bit_count=m1=0; // Aspetto il bit_change
olds=HIGH;
attachInterrupt(digitalPinToInterrupt(dataPin), dh11in, CHANGE);
}
void loop()
{
if(stato < 0) Serial.println("Framing Error");
else if(stato == OKREAD || Serial.available( ))
{
uint8_t cksum=0;
for(uint8_t i = 0 ; i< 4; i++) cksum +=rby[i];
if(cksum == rby [4])
{
Serial.print("Umidità: ");
Serial.print(rby[0]);
Serial.print(",");
Serial.print(rby[1]);
Serial.print(" Temperatura: ");
Serial.print(rby[2]);
Serial.print(",");
Serial.println(rby[3]);
}
else Serial.println("CheckSum Error");
stato = 0;
while (Serial.available()) Serial.read();
}
}
void dh11in() {
uint32_t mx = micros();
uint8_t news = digitalRead(dataPin);
//uint8_t news = PIND & _BV(dataPin);
if(news == olds) stato = FERR;
else
{
m1 = mx-m1;
switch(stato)
{
case 0: // Attendo sequenza di L, non conto il tempo
if(news == LOW) stato++;
break;
case 1: // Attendo sequenza LH, verifico tempo
if(news == HIGH) WaitFor(INIZIO, m1);
break;
case 2: // Attendo sequenza HL, verifco tempo
if(news == LOW) WaitFor(INIZIO, m1);
break;
case 3: // Attendo sequenza LH, verifco tempo
if(news == HIGH) WaitFor(FLOW, m1);
break;
case 4: // Misuro durata H
if(news == LOW) ZeroUno(ZERO, UNO, m1);
break;
case 5: // Attendo sequenza LH, verifco tempo
if(news == HIGH)
{
WaitFor(FLOW, m1);
detachInterrupt(digitalPinToInterrupt(dataPin));
}
break;
}
m1=mx;
olds=news;
}
}
void ZeroUno(uint8_t t0, uint8_t t1, uint8_t t)
{
uint8_t i = bit_count/8;
uint8_t by = rby[i];
by <<=1;
bit_count++;
if(t < (t0+t0/2));
else if(t < (t1+t1/2)) by |=1;
else stato = FERR;
rby[i] = by;
if(bit_count >= numBit) stato = 5 ;
else stato = 3;
}
void WaitFor(uint8_t tx, uint8_t t)
{
if(t < (tx+tx/2) && t > (tx-tx/2)) stato++;
else stato = FERR;
}