// ------------------------ INCLUDES ------------------------- //
#include <stdint.h>
#define DHT_PIN 4
// ----------------------- FUNCIONES ------------------------- //
void StartDHT(uint8_t* DATA);
uint8_t ReadBYTE(void);
float ReadTemp(uint8_t* DATA);
float ReadHum(uint8_t* DATA);
// ------------------- VARIABLES GLOBALES -------------------- //
char error_s;
// ------------------- VARIABLES GLOBALES -------------------- //
/*
typedef struct {
uint8_t ent;
uint8_t dec;
} BYTE_DATA;
typedef struct {
uint16_t b0 :1; // LSB
uint16_t b1 :1;
uint16_t b2 :1;
uint16_t b3 :1;
uint16_t b4 :1;
uint16_t b5 :1;
uint16_t b6 :1;
uint16_t b7 :1; // MSB BYTE 1
uint16_t b8 :1;
uint16_t b9 :1;
uint16_t b10 :1;
uint16_t b11 :1;
uint16_t b12 :1;
uint16_t b13 :1;
uint16_t b14 :1;
uint16_t b15 :1; // MSB
} BIT_DATA;
typedef union {
BYTE_DATA bytef;
BIT_DATA bitf;
} UNION_DATA;
*/
void setup() {
// put your setup code here, to run once:
// aca va la inicializacion de perifericos, buses de comunicacion etc
pinMode(DHT_PIN, OUTPUT);
Serial1.begin(115200);
}
void loop() {
if(1){// hacer q se active si toca boton
uint8_t DATA[5] = {0,0,0,0,0};
StartDHT(DATA);
// analisis de errores
switch(error_s){
case 0: // no hubo errores, imprimimos normal
break;
case 1: // aviso error tipo 1
Serial1.println("Error 1");
break;
case 2: // aviso error tipo 2
Serial1.println("Error 2");
break;
case 3: // aviso error tipo 3
Serial1.println("Error 3");
break;
}
float t = ReadTemp(DATA);
float h = ReadHum(DATA);
Serial1.print("Temperatura:");
Serial1.println(t);
Serial1.print("Humedad:");
Serial1.println(h);
delay(3000); // 2s (minimo) entre pedido de datos
}
}
void StartDHT(uint8_t* DATA){
error_s = 0;
pinMode(DHT_PIN, OUTPUT);
/*
Para que el DHT22 sepa que queremos que nos envie datos, el microcontrolador debe
"avisarle". Esto en el DHT22 se realiza de la siguiente manera, segun su datasheet:
*/
// la Raspi le avisa al DHT22 que quiere recibir datos
digitalWrite(DHT_PIN, LOW);
delay(18);
digitalWrite(DHT_PIN, HIGH);
delayMicroseconds(40);
// configuramos el PIN como INPUT para interpretar la respuesta
// del DHT y asegurarnos de que esta funcionando correctamente
pinMode(DHT_PIN, INPUT);
//analisis de la respuesta del DHT22
delayMicroseconds(40); // DHT_PIN deberia estar en LOW (0)
if(digitalRead(DHT_PIN) == HIGH){
// tenemos error tipo 1
error_s = 1;
return;
}
delayMicroseconds(80); // DHT_PIN deberia estar en HIGH (1)
if(digitalRead(DHT_PIN) == LOW){
// tenemos error tipo 2
error_s = 2;
return;
}
delayMicroseconds(40);
// tras 80us en LOW y 80us en HIGH el DHT comienza la transmision de DATOS
// leemos la data del sensor
for(int i=0; i<5; i++){
DATA[i] = ReadBYTE();
}
// seteamos DHT_PIN en su estado default
pinMode(DHT_PIN, OUTPUT);
digitalWrite(DHT_PIN, HIGH);
// chequeamos si el byte checksum es correcto (datos interpretados correctamente)
uint8_t checksum = DATA[0] + DATA[1] + DATA[2] + DATA[3];
if (checksum != DATA[4]) {
error_s = 3;
}
}
float ReadTemp(uint8_t* DATA){
/*
Segun el datasheet del DHT22, la interpretacion puede ser de dos maneras:
O nos da en el primer byte la parte entera y en el segundo la decimal, o nos da todo el numero en los dos
bytes y hay que multiplicarlo por 0.1.
*/
// CASO1
/*
float t_int;
float t_dec;
float t1;
char neg1 = 0;
UNION_DATA t_u;
// creo la instancia temp de la union de dos estructuras para
// manejar por un lado los bytes y por el otro los bits
// asigno su correspondiente valor
t_u.bytef.ent = DATA[2];
t_u.bytef.dec = DATA[3];
// lectura temperatura:
if(t_u.bitf.b7 == 1){ // temperatura < 0
t_u.bitf.b7 = 0; // lo pongo en cero (no es parte del numero) y activo flag de negativo
neg1 = 1;
}
t_dec = (float)t_u.bytef.dec;
while(t_dec >= 1){
t_dec = t_dec/10;
}
// convierto a float los enteros que representan la temp
t_int = (float)t_u.bytef.ent;
t1 = t_int + t_dec; // la parte decimal se suma dividiendo por 10 elevado a la cantidad de cifras
if (neg1 == 1){
return -t1;
}
return t1;
*/
// CASO 2
uint16_t temp_raw = (DATA[2] << 8) | DATA[3];
char neg2 = 0;
float t = (temp_raw & 0x7FFF); // asignamos el valor raw a una variable tipo float pero sin el posible 1 de <0
t *= 0.1;
if(DATA[2] & 0x80){ // teniamos un 1 en el BMS del HIGHER BYTE -> t<0
return -t;
}
return t;
}
float ReadHum(uint8_t* DATA){
// CASO 1
/*
float h_int;
float h_dec;
float h1;
UNION_DATA h_u;
// creo la instancia temp de la union de dos estructuras para
// manejar por un lado los bytes y por el otro los bits
// asigno su correspondiente valor
h_u.bytef.ent = DATA[0];
h_u.bytef.dec = DATA[1];
h_dec = (float)h_u.bytef.dec;
while(h_dec >= 1){
h_dec = h_dec/10;
}
// convierto a float los enteros que representan la temp
h_int = (float)h_u.bytef.ent;
h1 = h_int + h_dec; // la parte decimal se suma dividiendo por 10 elevado a la cantidad de cifras
return h1;
*/
// CASO 2
uint16_t hum_raw = (DATA[0] << 8) | DATA[1];
float h = ((float)hum_raw) * 0.1; // asignamos el valor raw a una variable tipo float pero sin el posible 1 de <0
return h;
}
uint8_t ReadBYTE(void){
uint8_t b = 0;
for (int i=0; i<8; i++){ // i marca el numero de bit
while (digitalRead(DHT_PIN) == LOW); // cuando se pone en HIGH es que comienza la transmision de datos
delayMicroseconds(40); // tiempo de espera para poder discernir
// MEJORAR CON millis() !!!!!!!!!!!!!!!
if (digitalRead(DHT_PIN) == HIGH){
// si pasados 30us esta en 1, el bit recibido fue un 1
// lo añado al byte b
b = b | (128 >> i);
}
// espero hasta que vuelva a bajar (indica que termino la transmision del bit actual)
// usar delay generaba problemas, tal vez por la impresicion de estos intervalos de tiempo
while (digitalRead(DHT_PIN) == HIGH);
}
return b;
}