// Soluzione bella e cruda come l'ho progettata, con tutti i commenti del caso necessari commentati per capire il
// procedimento
#define DHT_PIN1 2 // Rilevatore Stanza 1
volatile int mytick = 0;
int time_now = 0;
int TCNT0_now = 0;
uint8_t data[5];
uint16_t rawTemperature;
bool negative;
float temperature;
void setup()
{
// Inizializza la comunicazione seriale
Serial.begin(9600);
// Imposto il Timer 0 in modalità CTC
TCCR0A &= ~(1 << WGM00);
TCCR0A |= (1 << WGM01);
TCCR0B &= ~(1 << WGM02);
// Imposto il Prescaler = 64
TCCR0B |= (1 << CS00);
TCCR0B |= (1 << CS01);
TCCR0B &= ~(1 << CS02);
// Imposto l'Interrupt quando TCNT0 raggiunge OCR0A
TIMSK0 |= (1 << OCIE0A);
// Imposto OCR0A
OCR0A = 249; // Questo valore insieme al prescaler 64 darà circa 1 ms di interrupt
// Abilito gli interrupt globali
sei();
}
void loop()
{
mytick = 0;
TCNT0 = 0;
DDRD |= (1 << DHT_PIN1); // Configura il pin come output
PORTD |= (1 << DHT_PIN1); // Porta il segnale a HIGH
PORTD &= ~(1 << DHT_PIN1); // Porta il segnale a LOW
time_now = mytick;
while (mytick - time_now < 2) // maggiore di 1.5ms, quindi 2 ms
{
// attesa durante la quale posso fare qualcosa
}
PORTD |= (1 << DHT_PIN1); // Porta il segnale a HIGH
time_now = mytick;
TCNT0 = 0;
while (TCNT0 < 8) // TCNT0 a passare da 0 ad 1 impiega 4us (attesa di 28us)
{
// attesa durante la quale posso fare qualcosa
}
// Serial.println(TCNT0); // infatti vale 8 qui TCNT0
DDRD &= ~(1 << DHT_PIN1); // Configura il pin come input
// Attendi che passi da High a Low
while (PIND & (1 << DHT_PIN1))
{
// Attesa durante la quale posso fare qualcosa
}
// Attendi che passi da Low ad High in 80us
while (!(PIND & (1 << DHT_PIN1)))
{
// Attesa durante la quale posso fare qualcosa
}
// Attendi che passi da High a Low in 80us
while (PIND & (1 << DHT_PIN1))
{
// Attesa durante la quale posso fare qualcosa
}
// INIZIA LA COMUNICAZIONE DEI 40 BIT DI INFORMAZIONE
// Lettura dei dati (40 bit)
uint8_t i, j;
// Lettura e conversione dei 40 bit di dati
uint8_t timeBuffer[40]; // Buffer per temporizzazione
uint8_t bitIndex = 0; // Indice per il buffer di temporizzazione
for (i = 0; i < 5; i++) {
data[i] = 0;
for (j = 0; j < 8; j++) {
// Attesa segnale HIGH
while (!(PIND & (1 << DHT_PIN1)));
// Misura la durata del segnale HIGH
TCNT0 = 0;
while (PIND & (1 << DHT_PIN1)) {
// Attesa durante la quale posso fare qualcosa
}
// Debug della Durata dei Segnali Alti
// Bufferizza il valore del timer per debug
// timeBuffer[bitIndex++] = TCNT0;
data[i] <<= 1; // Sposta i bit esistenti a sinistra per fare spazio al nuovo bit
if (TCNT0 > 10) { // Se HIGH è durato più di circa 40us
data[i] |= 1; // metto il nuovo bit ad 1 (è 0 di default)
}
}
}
// Debug della Durata dei Segnali Alti
// Stampa i valori bufferizzati
// for (i = 0; i < 40; i++) {
// Serial.println(timeBuffer[i]);
// }
// Verifica del checksum
uint8_t checksum = data[0] + data[1] + data[2] + data[3];
if (checksum == data[4])
{
rawTemperature = (data[2] << 8) | data[3];
negative = rawTemperature & 0x8000;
if (negative) {
rawTemperature &= 0x7FFF; // Rimuove il bit di segno
}
temperature = rawTemperature / 10.0;
if (negative) {
temperature = -temperature;
}
Serial.print("temperature: ");
Serial.print(temperature);
Serial.println(" °C");
}
else
{
Serial.println("Checksum error!");
}
time_now = mytick;
while (mytick - time_now < 2000) // 2 secondi
{
// attesa durante la quale posso fare qualcosa
}
}
ISR(TIMER0_COMPA_vect)
{
mytick++;
}