/ * Bibliot eca DHT //CPP Licencia de MIT escrito por Adafruit Industries * / # incluye
" DHT.h "
# define
MIN_INTERVAL
2000
DHT :: DHT ( DHT ( uint8_t uint8_t pin, pin, uint8_t uint8_t tipo, tipo, uint8_t uint8_t recuento) recuento) { _pin = pin; _type = tipo; # Ifdef Ifdef __AVR __AVR _bit = digitalPinToBitMask (pin); _port = digitalPinToPort digitalPinToPort (pin); (pin); # endif _maxcycles = microsecondsToClockCycles microsecondsToClockCycles ( ( 1000 1000 ); );
// Tiempo de espera de
1 milisegundo // lectura de pulsos del sensor DHT. // Tenga en cuenta que el conteo ahora se ignora ya que el algoritmo de lectura DHT se ajusta // basó en la velocidad del procesador. } void
DHT :: begin ( begin ( void void ) ) {
// configurar los pines! pinMode (_pin, pinMode (_pin, INPUT_PULLUP INPUT_PULLUP); ); // El uso de este valor asegura que millis () - lastreadtime será // > = MIN_INTERVAL de inmediato. Tenga en cuenta que esta tarea se ajusta, // pero también la resta. _lastreadtime _lastreadti me = -MIN_INTERV -MIN_INTERVAL; AL; DEBUG_PRINT ( DEBUG_PRINT ( " Ciclos máximos de reloj: " ); " ); DEBUG_PRINTLN (_maxcycles (_maxcycles, , DEC); } // booleano S == Escala. Verdadero == Fahrenheit; False == Celcius flotante
DHT :: readTemperat readTemperature ure ( ( bool bool S, S, bool bool force) force) {
flotar f flotar f = NAN; if ( if ( leer leer (forzar)) (forzar)) { switch (_type) switch (_type) { caso DHT11: caso DHT11: f = datos [ 2 ]; si (S) si (S) { f = convertCtoF (f); } romper ; romper ;
caso DHT22: caso DHT22: caso DHT21: caso DHT21: f = datos [ 2 ] y 0x7F 0x7F ; ; f * = 256 256 ; ; f + = datos [ 3 ]; f * = 0.1 0.1 ; ; if (datos if (datos [ 2 ] y 0x80 0x80 ) ) { f * = - 1 ; } si (S) si (S) { f = convertCtoF (f); } romper ; romper ; } } devolver f; devolver f; } flotador
DHT :: convertCtoF ( convertCtoF ( flotador flotador c) c) {
devolver c devolver c * 1.8 1.8 + + 32 32 ; ; } flotante
DHT :: convertFtoC ( convertFtoC ( float float f) f) {
return (f return (f - 32 32 ) ) * 0.55555 0.55555 ; ; } flotar
DHT :: readHumidity readHumidity ( ( fuerza de bool bool ) ) {
flotar f flotar f = NAN; if ( if ( leer leer ()) ()) { switch (_type) switch (_type) { caso DHT11: caso DHT11: f = datos [ 0 ]; romper ; romper ; caso DHT22: caso DHT22: caso DHT21: caso DHT21: f = datos [ 0 ]; f * = 256 256 ; ; f + = datos [ 1 ]; f * = 0.1 0.1 ; ; romper ; romper ; } } devolver f; devolver f; } // boolean isFahrenheit: True == Fahrenheit; False == Celcius flotar
DHT :: computeHeatI computeHeatIndex ndex ( ( float temperatura, flotar
percentHumidity, bool bool isFahrenheit) isFahrenheit) { // Usando las ecuaciones de Rothfusz y Steadman // http://www.w http://www.wpc.ncep.noaa pc.ncep.noaa.gov/html/he .gov/html/heatindex_equa atindex_equation.shtml tion.shtml
flotar hola; flotar hola; if (! if (! isFahrenhei isFahrenheit) t) temperatura = convertCtoF (temperatur (temperatura); a); hi = 0,5 0,5 * * (temperatura de + 61,0 61,0 + + ((temperatura - 68,0 68,0 ) ) * 1,2 1,2 ) ) + (percentHumidity * 0.094 0.094 )); )); si (hi> si (hi> 79 79 ) ) { hola = - 42.379 42.379 + + 2.04901523 * temperatura + 10.14333127 * porcientoHu porcientoHumedad medad + - 0.22475541 0.22475541 * * temperatura * porcentajeHumedad + - 0.00683783 0.00683783 * * pow pow (temperatura, (temperatura, 2 ) + - 0.05481717 0.05481717 * * pow pow (porcentaje (porcentaje de humedad, 2 ) + 0.00122874 * pow (temperatur (temperatura, a, 2 ) * percentHumidity percentHumidity + 0.00085282 * temperatura * pow pow (porcentaje (porcentaje de humedad, 2 ) + - 0.00000199 0.00000199 * * pow pow (temperatura, (temperatura, 2 ) * pow pow (porcentaje (porcentaje de humedad, 2 ); if ((percentHumidity if ((percentHumidity < 13 13 ) ) && (temperatu (temperature> re> = 80.0 80.0 ) ) && (temperature <= 112.0 112.0 )) )) hi - = (( 13.0 13.0 -% -% Humidity) * 0.25 0.25 ) ) * sqrt sqrt (( (( 17.0 17.0 - abs (temperatura - 95.0 95.0 )) )) * 0.05882 0.05882 ); ); else
if ((percentHumi ((percentHumidity> dity> 85.0 85.0 ) ) && (temperature> = 80.0 80.0 ) ) &&
(temperature <= 87.0 87.0 )) )) hi + = ((% Humidity - 85.0 85.0 ) ) * 0.1 0.1 ) ) * (( 87.0 87.0 - temperatura) * 0.2 ); } el regreso esFahrenheit? regreso esFahrenheit? hola: convertFtoC convertFtoC (hi); (hi); } boolean DHT :: read ( read ( bool bool force) force) { // Verifica si el sensor fue leído hace menos de dos segundos y regresa temprano // para usar la última lectura. uint32_t currenttime uint32_t currenttime = millis millis (); (); if (! if (! force && ((currenttime - _lastreadtime) < 2000 2000 )) )) { devolver _lastresult; devolver _lastresult; // devuelve la última medición correcta } _lastreadtime = hora actual; // Restablece los 40 bits de los datos recibidos a cero. datos [ 0 ] = datos [ 1 ] = datos [ 2 ] = datos [ 3 ] = datos [ 4 ] = 0 ; // Enviar señal de inicio. Consulte la hoja de datos de DHT para obtener un diagrama de señal completo: // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%2 0sensor%20AM2302.pdf // Entrar en el estado de alta impedancia para permitir que el pull-up eleve el nivel de la línea de datos y // comienza el proceso de lectura.
digitalWrite (_pin, ALTO); retraso ( retraso ( 250 250 ); ); // Primero establece la línea de datos baja durante 20 milisegundos. pinMode (_pin, pinMode (_pin, OUTPUT); digitalWrite (_pin, BAJO); retraso ( retraso ( 20 20 ); ); uint32_t ciclos uint32_t ciclos [ 80 80 ]; ]; { // Desactiva las interrupcion interrupciones es temporalmente porque las siguientes secciones son cronometradas críticas // y no queremos ninguna interrupción. interrupción. Bloqueo de bloqueo de interrupción; // Finaliza la señal de inicio configurando la línea de datos en alto durante 40 microsegundos. digitalWrite (_pin, ALTO); delayMicroseconds ( delayMicroseconds ( 40 40 ); ); // Ahora comienza a leer la línea de datos para obtener el valor del sensor DHT. pinMode (_pin, pinMode (_pin, INPUT_PULL INPUT_PULLUP); UP); delayMicroseconds ( delayMicroseconds ( 10 10 ); );
// Demora un poco para que el sensor tire de
la línea de datos baja. // Primero se espera una señal baja para ~ 80 microsegund microsegundos os seguido de una señal alta // por ~ 80 microsegund microsegundos os de nuevo. if ( if ( expectPulse expectPulse (LOW) (LOW) == 0 ) { DEBUG_PRINTLN ( DEBUG_PRINTLN ( F ( " Tiempo de espera en espera de pulso inicial de la señal de inicio " )); " )); _lastresult = falso falso ; ; devolver _lastresult; devolver _lastresult; } if ( if ( expectPulse expectPulse (HIGH) (HIGH) == 0 ) { DEBUG_PRINTLN ( DEBUG_PRINTLN ( F ( " Tiempo de espera esperando pulso alto de la señal de inicio " )); " )); _lastresult = falso falso ; ; devolver _lastresult; devolver _lastresult; } // Ahora lee los 40 bits enviados por el sensor. Cada bit se envía como 50 // Pulso bajo de microsegundo microsegundos s seguido de un pulso alto de longitud variable. Si el // alto pulso es ~ 28 microsegundos, entonces es un 0 y si es ~ 70 microsegundos // entonces es un 1. Medimos el recuento de ciclos del pulso inicial de 50us bajo // y usar eso para compararlo con el conteo cíclico del pulso alto para determinar
// si el bit es un 0 (conteo de ciclo de estado alto recuento de ciclo de estado bajo). Tenga en cuenta que para velocidad todo // los pulsos se leen en una matriz y luego se examinan en un paso posterior. for ( for ( int int i i = 0 ; i < 80 80 ; ; i + = 2 ) { ciclos [i] = expectPulse (LOW); ciclos [i + 1 ] = expectPulse (ALTO); } } // El código crítico de tiempo ahora está completo. // Inspeccione los pulsos y determine cuáles son 0 (conteo de ciclo de estado alto recuento de ciclo de estado bajo). for ( for ( int int i i = 0 ; i < 40 40 ; ; ++ i) { uint32_t lowCycles uint32_t lowCycles = ciclos [ 2 * i]; uint32_t highCycles uint32_t highCycles = ciclos [ 2 * i + 1 ]; if ((lowCycles if ((lowCycles == 0 ) || (highCycles == 0 )) { DEBUG_PRINTLN ( DEBUG_PRINTLN ( F ( " Tiempo de espera esperando pulso " )); _lastresult = falso falso ; ; devolver _lastresult; devolver _lastresult; } datos [i / 8 ] << = 1 ; // Ahora compara los tiempos de ciclo bajo y alto para ver si el bit es 0 o 1. if (highCycles> if (highCycles> lowCycles) { // Los ciclos altos son mayores que 50us bajo recuento cíclico, debe ser un 1. datos [i / 8 ] | = 1 ; } // Si bien los ciclos altos son menores que (o igual a, un caso raro) los 50us bajos // recuento de ciclos por lo que este debe ser un cero. Nada necesita ser cambiado en el // datos almacenados. } DEBUG_PRINTLN ( DEBUG_PRINTLN ( F ( " Recibido: " )); " )); DEBUG_PRINT (datos DEBUG_PRINT (datos [ 0 ], HEX); DEBUG_PRINT DEBUG_PRINT ( ( F ( " , " )); " )); DEBUG_PRINT (datos DEBUG_PRINT (datos [ 1 ], HEX); DEBUG_PRINT DEBUG_PRINT ( ( F ( " , " )); " )); DEBUG_PRINT (datos DEBUG_PRINT (datos [ 2 ], HEX); DEBUG_PRINT DEBUG_PRINT ( ( F ( " , " )); " )); DEBUG_PRINT (datos DEBUG_PRINT (datos [ 3 ], HEX); DEBUG_PRINT DEBUG_PRINT ( ( F ( " , " )); " )); DEBUG_PRINT (datos DEBUG_PRINT (datos [ 4 ], HEX); DEBUG_PRINT DEBUG_PRINT ( ( F ( " =? " )); " )); DEBUG_PRINTLN ((datos DEBUG_PRINTLN ((datos [ 0 ] + datos [ 1 ] + datos [ 2 ] + datos [ 3 ]) & 0xFF , 0xFF , HEX); // Verificamos que leemos 40 bits y que la suma de comprobación coincide. coincide.
if (data if (data [ 4 ] == ((data [ 0 ] + data [ 1 ] + data [ 2 ] + data [ 3 ]) & 0xFF )) 0xFF )) { _lastresult = verdadero verdadero ; ; devolver _lastresult; devolver _lastresult; } else { else { DEBUG_PRINTLN ( DEBUG_PRINTLN ( F ( " Error de suma de comprobación! " )); _lastresult = falso falso ; ; devolver _lastresult; devolver _lastresult; } } // Esperar que la línea de señal esté en el nivel especificado por un período de tiempo y // devuelve un recuento de ciclos de bucle gastados en ese nivel (este ciclo puede ser // usado para comparar el tiempo relativo de dos pulsos). Si es más de un milisegundo // Cesa sin el nivel de cambio, la llamada falla con una respuesta de 0. // Esto está adaptado de la función pulseInLong de Arduino (que solo está disponible) // en las últimas versiones de IDE): // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/a rduino/wiring_pulse.c uint32_t
DHT :: expectPulse ( expectPulse ( nivel de bool bool ) ) {
uint32_t recuento uint32_t recuento = 0 ; // En las plataformas AVR, use acceso directo al puerto GPIO, ya que es mucho más rápido y mejor // para capturar pulsos que tienen una longitud de 10 microsegund microsegundos: os: # Ifdef Ifdef __AVR __AVR uint8_t portState uint8_t portState = nivel? _bit: 0 ; while ((* while ((* portInputRegister portInputRegister (_port) (_port) & _bit) == portState) { if (count if (count ++> = _maxcycles) { return
0 ; // Excedió el tiempo de espera, error.
} } // De lo contrario recurrir a digitalRead (esto parece ser necesario en ESP8266 // en este momento, ¿quizás errores en las funciones de acceso directo al puerto?). # else while ( while ( digitalRead (_pin) == nivel) { if (count if (count ++> = _maxcycles) { return } }
0 ; // Excedió el tiempo de espera, error.
# endif recuento de devolución devolución ; ; }
//.h
/ * Biblioteca DHT Licencia de MIT escrito por Adafruit Industries * / # ifndef ifndef DHT_H DHT_H # define
DHT_H
# si si ARDUINO> ARDUINO> = 100 # incluye
" Arduino.h "
# else # incluye
" WProgram.h "
# endif // Descomentar para habilitar la impresión de buenos mensajes de depuración. // #define DHT_DEBUG // Definir dónde se imprimirá la salida de depuración. # define
DEBUG_PRINTER serial
// Configurar macros de impresión de depuración. # Ifdef Ifdef DHT_DEBUG DHT_DEBUG # define
DEBUG_PRINT (...) {DEBUG_PRINTER. imprimir imprimir (__VA_ARGS__); (__VA_ARGS__); }
# define
DEBUG_PRINTLN (...) DEBUG_PRINTLN (...) {DEBUG_PRINTER. println println (__VA_ARGS__); (__VA_ARGS__); }
# else # define
DEBUG_PRINT (...) {}
# define
DEBUG_PRINTLN (...) DEBUG_PRINTLN (...) {}
# endif // Definir tipos de sensores. # define
DHT11
11
# define
DHT22
22
# define
DHT21
21
# define
AM2301
clase
21
DHT { DHT {
público: DHT ( DHT ( uint8_t uint8_t pin, pin, uint8_t uint8_t tipo, tipo, uint8_t uint8_t cuenta cuenta = 6 ); void
begin ( begin ( void void ); );
flotante
readTemperature ( readTemperature ( bool bool S S = falso falso , , bool bool force force = falso falso ); );
float
convertCtoF ( convertCtoF ( float float ); );
float
convertFtoC ( convertFtoC ( float float ); );
float
computeHeatIndex ( computeHeatIndex ( temperatura flotante flotante , , porcentaje
flotanteHumidity , bool bool isFahrenheit isFahrenheit = true true ); ); float
readHumidity ( bool bool force force = false false ); );
boolean read read ( ( bool bool force force = false false ); ); privado: uint8_t data uint8_t data [ 5 ];
uint8_t _pin, uint8_t _pin, _type; # Ifdef Ifdef __AVR __AVR // Utilice acceso directo a GPIO en un AVR de 8 bits, así que realice un seguimiento del puerto y de la máscara de bits // para el pin digital conectado al DHT. Otras plataformas usarán digitalRead. uint8_t _bit, uint8_t _bit, _port; # endif uint32_t _lastreadti _lastreadtime, me, _maxcycles; bool _lastresult; bool _lastresult; uint32_t
expectPulse ( nivel de bool bool ); );
}; clase
InterruptLock { InterruptLock {
público: InterruptLock () InterruptLock () { no Interrumpir (); Interrumpir (); } ~ InterruptLock () InterruptLock () { interrupts (); interrupts (); } }; # endif