Sensor DHT11. Sin librería.

Hola, soy nuevo en el foro. Me llamo Jose, y estoy comenzando con Arduino por motivos de la facultad.La cuestión, es que llevo unos días liado con este sensor (DHT11) y usando la librería no da ningún problema. A principio me costó entender como se comunica Arduino con Matlab para recoger datos, pero este asunto ya me queda más o menos claro (luego publicaré un pequeño programa que solicita los datos de este sensor, realiza sus correspondientes gráficas y finalmente guarda los datos y el espacio de trabajo de matlab. Por si le sirve de utilidad a alguien.). Ahora el problema es el siguiente y el que me ha hecho llegar al foro.

Me gustaría comprender cómo realizar la toma de datos de temperatura de este sensor, pero directamente sin librerías. He leído un sinfín en google pero no encuentro información pertinente. Entiendo que este sensor trabaja por conexión I2C pero no enlazo cómo hacerlo. En clase se imparte con el TPM102, pero por motivos económicos prefiero hacer mis deducciones con este (puesto que es el que tengo).

Si alguien puede guiarme un poco se lo agradecería. Ya he buscado en google y todos utilizan librería. En ningún sitio explican cómo hacerlo manualmente.

Un saludo!.

El DHT11 transmite los datos en serie por el pin 2 (DATA) a eso se le llama el protocolo 1-wire.

Se trata de una trama de 5 bytes, donde los dos primer bytes son la humedad (parte entera y decimal), los dos siguientes bytes corresponden a la temperatura y el ultimo es la paridad (comprobación de integridad).

Electricamente lo que se hace es poner el DATA con un pullup a un pin de Arduino que configuras como salida (pinMode(2, OUTPUT); ) y pones en HIGH (digitalWrite(2, HIGH); ).

Luego cuando quieras leer pones ese pin a LOW durante 18 ms, nuevamente a HIGH por 40 us y lo reconfiguras como entrada (pinMode(2, INPUT); ) y si todo esta bien te devolverá un HIGH por 80 us. Luego tendrás que leer los 5 bytes, terminado la cual vuelves a reconfigurar el pin como salida y lo pones en HIGH

void ReadDHT(){
   byte bGlobalErr = 0;

   //Primero: ponemos a LOW durante 18 ms
   digitalWrite(2, LOW);
   delay(18);
   delay(5);  //Transisicion

   //Segundo: ponemos a HIGH durante 40us (start read)
   digitalWrite(2, HIGH);
   delayMicroseconds(40);
   
   //Tercero: Reconfigura como entrada y espera 40 us
   pinMode(2, INPUT);
   delayMicroseconds(40);
   //Si es HIGH, indicamos que hay error de tipo 1
   if (digitalRead(2))  {
      bGlobalErr = 1;
      return;
   }
   delayMicroseconds(80);
   //Si es LOW, indicamos que hay error de tipo 2
   if (!digitalRead(2)){
      bGlobalErr = 2;
      return;
   }
   //Despues de 40us en LOW debe pasar a HIGH por 80 us.
   delayMicroseconds(80);

   //Ahora lee los 5 bytes
   byte DATA[] = {0,0,0,0};
   for (byte i=0; i<5; i++){
      DATA[i] = lee_data();
   }

   //Cuarto: Reconfiguramos como salida y ponemos en HIGH
   pinMode(2, OUTPUT);
   digitalWrite(2,HIGH);

   //Comprobamos checksum
   if (DATA[4] != DATA[0]+DATA[1]+DATA[2]+DATA[3]){
      bGlobalErr = 3;
   }
};
 
//Leer un byte
byte lee_data(){
   byte result = 0;
   for (byte i=0; i<8; i++)  {
      //Esperamos hasta que HIGH, inicio byte data
      while (!digitalRead(2)){;
         delayMicroseconds(30);
      }
      //Datos debe estas HIGH durante 27 a 70us, dependiendo si un "0" o un "1"
      if (digitalRead(2)){
         respuesta |=(1<<(7-i));    //Si después de los 30us continua HIGH añadimos un 1 al byte, sino queda un "0" 
      }
      //Esperamos hasta que LOW, fin de byte data
      while (digitalRead(2));
   }
  return respuesta;
}

Era mas fácil.. todos usan la librería pues tu podrias haber leído como lo hace la librería para terminar plagíandola porque vamos que no vas a hacer nada distinto de lo que la liibrería hace.

Se entiende la idea?

Además buscas el datasheet del DHT11 y claramente encontrarás como es la trama que KIKE_GL ha explicado.

Google: DHT11 datasheet y sale esto link

Página 5. explica todo.

Ya había pensado lo de copiar la librería, pero no entiendo muchas cosas que se hace en ella. Son muchas funciones y te diría que incluso lo he intentado hacer, pero se me hace muy difícil a la comprensión.

Respecto a lo del Datasheet también lo tengo más que mirado, antes incluso de preguntar ya lo había repasado muchas veces; pero soy novato con Arduino y con la electrónica en general y a primera vista tampoco sabía plasmar la información del fabricante en código. Lo de Kike_GL es lo que iba buscando. Con ese fragmento y con el Datasheet creo que puedo entender el funcionamiento. Muchas gracias a ambos por la ayuda.

Me surge alguna duda ¿porqué en el segundo paso pones a HIGHT durante 40us?. Es decir, ¿porqué 40?
Edito: La pregunta queda resuelta puesto que disponemos de Datasheets diferentes. Este es el otro

Y otra cosa, ¿en el tercer paso y en el cuarto, porqué almacenas el estado (HIGHT o LOW) como un error?

Gracias nuevamente. Y saludos!.

Gallegosan:
Me surge alguna duda ¿porqué en el segundo paso pones a HIGHT durante 40us?. Es decir, ¿porqué 40?

Asi se hace el pedido de datos al DHT11.

Gallegosan:
Y otra cosa, ¿en el tercer paso y en el cuarto, porqué almacenas el estado (HIGHT o LOW) como un error?

Son errores de transmision que pueden ocurrir, asi que terminado el proceso debes revisar si la variable bGlobalErr continua en 0, si no es asi hubo algun error. Es para el analisis.

Bueno, conforme lo dicho. Expongo el código del trabajo de la facultad para que sirva de guía e información a aquellos que estén interesados.

El enunciado era el control de un sensor (en mi caso escogí el DHT11), mediante una aplicación de appdesigner.

Funcionalidades que incluye la aplicación:
Escoger puerto serie.
Conectar y desconectar con arduino.
Panel de información con los datos de conexión a arduino.
Seleccionar periodo de medición.
Mostrar en tiempo real una gráfica con los valores medidos de temperatura.
Muestra la temp. máxima y mínima.
Alarma para un rango dado de temperatura.
Guardar los datos leídos en un archivo .m de matlab para su posterior tratamiento.

Aquí tenéis el resultado:

Para arduino lo implementé sin librería. Pero aquí tenéis un ejemplo más sencillo empleando librerías públicas:

#include <dht.h>

dht DHT;

// Definimos PIN para transferencia de datos
#define DHT11_PIN 7

void setup() {
  //Iniciamos comunicación con el puerto serie
  Serial.begin(9600);
  Serial.setTimeout(50);
}

void loop() {
     if (Serial.available() > 0)
   {
      String str = Serial.readStringUntil('\n');
      int data = str.toInt();
            Serial.print(data);

     for (int i=0; i<data; i++) {
     int chk = DHT.read11(DHT11_PIN);
     //Serial.print('\n'); 
     Serial.println(DHT.temperature);
     Serial.println(DHT.humidity);
     delay(1500);
      }
   }
  Serial.end();
}

Saludos!.

Y aquí tenéis el archivo de Matlab con AppDesigner.

trabalho_3_appdes_exported.pdf (45.4 KB)