From d6f911bf4f8531fe3ea92d8e008bd97ba45d2af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Grennerat?= Date: Tue, 15 Jul 2025 01:20:35 +0200 Subject: [PATCH] Working safe reading --- main.c | 149 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 72 insertions(+), 77 deletions(-) diff --git a/main.c b/main.c index f61a44d..68985f0 100644 --- a/main.c +++ b/main.c @@ -21,108 +21,103 @@ #pragma config DEBUG = ON #pragma config PLLEN = 0 - +// Pins define #define DHT22_PIN_DIR TRISAbits.TRISA4 #define DHT22_DATA PORTAbits.RA4 #define CTRL_1 PORTAbits.RA5 #define CTRL_2 PORTAbits.RA2 +// Clock frequency (used for __delay_xx) #define _XTAL_FREQ 8000000 +// Utils macro for waiting a pin state for DHT22_DATA, returning 1 if timed out. +#define waitDHTOrRet(up) TMR0 = 0; while(DHT22_DATA != (up)){ if(TMR0 > 240) return 1; } -void startSignal() { - __delay_ms(5); // Attendre 5 ms pour stabiliser. Durée trame = 4ms +uint8_t dhtBytes[5]; // 2 first bytes: humidity, 2 following: temperature, 5th: checksum +// Reads the DHT, returns 0 if error +int readDHT() { + // Empty old payload + for(uint8_t i = 0; i < 5; i++){ + dhtBytes[i] = 0; + } + + // Wait for an old payload eventually aborted to end (lasts about 4ms) + __delay_ms(5); - // Signal de départ : bas pendant au moins 1 ms - DHT22_PIN_DIR = 0; // 0 = sortie donc à 0 - __delay_ms(1); // Attendre 1 ms + // Sends the start signal: low for at least 1ms, then high for 20 to 40us + DHT22_PIN_DIR = 0; // configure as output, then set it as 0 (= LATAbits.LATA4). + __delay_ms(2); + DHT22_PIN_DIR = 1; // configure as input, then set it as 1 (through pullup). + __delay_us(40); + + // Check DHT start response + waitDHTOrRet(0); // DHT pulls low + waitDHTOrRet(1); // DHT pulls high for 80ms + __delay_us(40); + waitDHTOrRet(0); // DHT pulls low + + // Read the 5 DHT payload bytes in dhtBytes + for (uint8_t n = 0; n < 5; n++) { + for (int8_t i = 7; i >= 0; i--) { + waitDHTOrRet(1); // Wait for up + CTRL_1 = 1; + waitDHTOrRet(0); // Wait for low. Waited time is TMR0. + CTRL_1 = 0; - // Signal de départ : haut pendant 20-40 µs - DHT22_PIN_DIR = 1; // 1 = entrée donc haut grace au pullup - __delay_us(30); // Attendre 30 µs -} - -// Fonction pour lire un octet du DHT22 -uint8_t readByte(int n) { - uint8_t byte = 0; - for (uint8_t i = 0; i < 8; i++) { - TMR1H = 0; // Réinitialise le Timer1 - TMR1L = 0; - while (!DHT22_DATA); - CTRL_1 = 1; - //T1CONbits.TMR1ON = 1; - TMR0 = 0; - while (DHT22_DATA); - //T1CONbits.TMR1ON = 0; - CTRL_1 = 0; - //uint16_t pulseWidth = (uint16_t) (TMR1H << 8) | (uint16_t) TMR1L; // Lit la valeur du Timer1 - //byte <<= 1; // Décale le byte de 1 bit à gauche - if (TMR0 > 50) { // Si l'impulsion est supérieure à 50 µs, c'est un 1 - byte |= 1; + if (TMR0 > 50) { // Low: 26-28us High: 70us + dhtBytes[n] |= 1 << i; + } } } - return byte; + return 0; } - -// Fonction pour lire l'humidité et la température -uint8_t lire(signed char* humidite, signed char* temp) { - startSignal(); - uint8_t humidityHigh = readByte(1); - uint8_t humidityLow = readByte(2); - uint8_t temperatureHigh = readByte(3); - uint8_t temperatureLow = readByte(4); - uint8_t checksum = readByte(5); - - if (checksum != (humidityHigh + humidityLow + temperatureHigh + temperatureLow)) { - return 1; // Erreur de checksum +// Fetches humidity & temp from DHT, returns 0 if error +int fetchClimate(int8_t* humidity, int8_t* temperature) { + if(readDHT()) return 1; + + uint8_t checksum = dhtBytes[0] + dhtBytes[1] + dhtBytes[2] + dhtBytes[3]; + if (dhtBytes[4] != checksum) { + return 1; // Checksum error } + + uint16_t hum = (((uint16_t) (dhtBytes[0])) << 8) | ((uint16_t) dhtBytes[1]); + *humidity = (int8_t) (hum / 10); - uint16_t humidity = (uint16_t) (humidityHigh << 8) | (uint16_t) humidityLow; - *humidite = (signed char)(humidity / 10); - - uint16_t temperature = (uint16_t) (temperatureHigh << 8) | (uint16_t) temperatureLow; - if (temperature & 0x8000) { // Si le bit de signe est à 1, la température est négative - temperature = -(temperature & 0x7FFF); + uint16_t temp = (((uint16_t) (dhtBytes[2])) << 8) | ((uint16_t) dhtBytes[3]); + if (temp & 0x8000) { // If high bit is 1, temperature is negative. + *temperature = - (int8_t) ((temp & 0x7FFF) / 10); + }else { + *temperature = (int8_t) (temp / 10); } - *temp = (signed char)(temperature / 10); - - return 0; // Lecture réussie + + return 0; } void main() { - // Configuration de l'horloge interne à 1MHz + // 8MHz internal clock OSCCON = 0b01110000; - // Configuration des broches - APFCONbits.T1GSEL = 0b0; // Timer1 sur RA4 - TRISA = 0b11011011; // Configure RA2 et RA5 en sortie 0 = sortie - ANSELA = 0b00000011; // Configure les broches utiles digital I/O + // Ping config + TRISA = 0b11011011; // Declare RA2 and RA5 as output (bit = 0) + ANSELA = 0b00000011; // Declare used pins as digital I/O (bit = 0) WPUA = 0b00010000; // Active la résistance de pull-up sur RA4 - LATAbits.LATA4 = 0b0; // RA4 est en sortie - - // Configuration du Timer1 - T1CON = 0b00000000; // Timer1 est éteint initialement - T1CONbits.TMR1CS = 0b01; // Source d'horloge est Fosc => 1MHz - T1CONbits.T1CKPS = 0b11; // Pas de division de l'horloge - T1GCONbits.T1GSS = 0b00; // Timer1 gate pin T1G - T1GCONbits.T1GPOL = 0b1; // Polarité du gate control est active haut - T1GCONbits.T1GTM = 0b0; // Mode du gate toggle désactivé - T1GCONbits.T1GSPM = 0b1; // Single gate désactivé - T1GCONbits.TMR1GE = 0; // Pas de gate control - T1CONbits.TMR1ON = 0; // Démarrage du Timer1 - PIR1bits.TMR1GIF = 0; // Efface le flag d'interruption du gate control + LATAbits.LATA4 = 0; // Declare RA4 output value as 0 (only effective when DHT22_PIN_DIR = 0) - OPTION_REGbits.PSA = 0; // Prescaler pour T0 + // Timer 0 config + OPTION_REGbits.PSA = 0; // Enable prescaler + OPTION_REGbits.PS = 0b000; // 1/2 prescaler + OPTION_REGbits.TMR0CS = 0; // Use internal clock + OPTION_REGbits.TMR0SE = 0; // Increment on rising edge + - // Boucle principale while (1) { - signed char humidite = 0; - signed char temperature = 0; + int8_t hum = 0; + int8_t temp = 0; - lire(&humidite, &temperature); - - int x = 0; - - __delay_ms(100); + int is_error = fetchClimate(&hum, &temp); + if(is_error){ + __delay_ms(5000); + } + __delay_ms(200); } }