Partage
  • Partager sur Facebook
  • Partager sur Twitter

DHT11 et Pic 16f876 mikro c

communication one wire pour capteur numérique dht11

5 mai 2014 à 12:06:54

Bonjour,

Je m'intéresse au capteur DHT11.

http://www.hostingpics.net/viewer.php?id=918188dht11pindiag.jpg

www.micro4you.com/files/sensor/DHT11.pdf

Voici mon schéma avec un Pic 16f876 de chez microchip

http://www.hostingpics.net/viewer.php?id=259534setdetestdht11.png

Je n'arrive pas à faire communiquer le DHT11 (message: no reponse from the sensor)

voici le code:

/*
 Project: Temperature and humidity measurements using DHT11
 MCU: PIC16F876
 Clock: 4.0MHz external resonator
 MCLR is enabled
 Date: Jan 10, 2012
 Written by: Rajendra Bhatt (www.embedded-lab.com)       modif: phoenix
*/

// LCD module connections
sbit LCD_RS at RB6_bit;
sbit LCD_EN at RB4_bit;
sbit LCD_D4 at RB7_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB1_bit;
sbit LCD_RS_Direction at TRISB6_bit;
sbit LCD_EN_Direction at TRISB4_bit;
sbit LCD_D4_Direction at TRISB7_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB1_bit;

sbit Data at RA0_bit;
sbit DataDir at TRISA0_bit;
char message1[] = "Temp = 00.0 C";
char message2[] = "RH   = 00.0 %";
unsigned short TOUT = 0, CheckSum, i;
unsigned short T_Byte1, T_Byte2, RH_Byte1, RH_Byte2;

void StartSignal(){
  DataDir = 0;     // Data port is output
  Data    = 0;
  Delay_ms(25);
  Data    = 1;
  Delay_us(30);
  DataDir = 1;     // Data port is input

}

unsigned short CheckResponse(){
  TOUT = 0;
  TMR2 = 0;
  T2CON.TMR2ON = 1;      // start timer
  while(!Data && !TOUT);
  if (TOUT) return 0;
  else {
   TMR2 = 0;
   while(Data && !TOUT);
   if (TOUT) return 0;
   else {
    T2CON.TMR2ON = 0;
    return 1;
   }
  }
}

unsigned short ReadByte(){
  unsigned short num = 0, t;
  DataDir = 1;
  for (i=0; i<8; i++){
   while(!Data);
   TMR2 = 0;
   T2CON.TMR2ON = 1;
   while(Data);
   T2CON.TMR2ON = 0;
   if(TMR2 > 40) num |= 1<<(7-i);  // If time > 40us, Data is 1
  }
  return num;
}

void interrupt(){
  if(PIR1.TMR2IF){
   TOUT = 1;
   T2CON.TMR2ON = 0; // stop timer
   PIR1.TMR2IF  = 0; // Clear TMR0 interrupt flag
  }
}

void main() {
  unsigned short check;
  TRISB = 0b00000000;
  PORTB = 0;
  TRISA = 0b00100001;
  INTCON.GIE = 1;    //Enable global interrupt
  INTCON.PEIE = 1;   //Enable peripheral interrupt
  // Configure Timer2 module
  PIE1.TMR2IE = 1;  // Enable Timer2 interrupt
  T2CON = 0;        // Prescaler 1:1, and Timer2 is off initially
  PIR1.TMR2IF =0;   // Clear TMR INT Flag bit
  TMR2 = 0;
  Lcd_Init();
  Lcd_Cmd(_Lcd_Clear);
  Lcd_Cmd(_LCD_CURSOR_OFF);

  do {
    Delay_ms(1000);
    StartSignal();
    check = CheckResponse();
    if (!check) {
     Lcd_Cmd(_Lcd_Clear);
     Lcd_Out(1, 1, "No response");
     Lcd_Out(2, 1, "from the sensor");
    }
    else{
   
     RH_Byte1 = ReadByte();
     RH_Byte2 = ReadByte();
     T_Byte1 = ReadByte();
     T_Byte2 = ReadByte();
     CheckSum = ReadByte();
     // Check for error in Data reception
     if (CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF))
     {
      message1[7]  = T_Byte1/10 + 48;
      message1[8]  = T_Byte1%10 + 48;
      message1[10] = T_Byte2/10 + 48;
      message2[7]  = RH_Byte1/10 + 48;
      message2[8]  = RH_Byte1%10 + 48;
      message2[10] = RH_Byte2/10 + 48;
      message1[11] = 223;     // Degree symbol
      Lcd_Cmd(_Lcd_Clear);
      Lcd_Out(1, 1, message1);
      Lcd_Out(2, 1, message2);
      }
     
      else{
       Lcd_Cmd(_Lcd_Clear);
       Lcd_Out(1, 1, "Checksum Error!");
       Lcd_Out(2, 1, "Trying Again ...");
      }
    }

  }while(1);
}



Auriez vous un élément de réponse?

Cordialement

-
Edité par psikophoenix 6 mai 2014 à 10:04:57

  • Partager sur Facebook
  • Partager sur Twitter
5 mai 2014 à 22:45:08

Merci de m'avoir lu,

Que veux tu dire? Mon code te parait indigeste?  C'est du Mikro c.

Voulez vous que je refasse la mise en page?

D'avance merci.

  • Partager sur Facebook
  • Partager sur Twitter
5 mai 2014 à 23:41:16

Si tu regardes dans les boutons en haut de l'éditeur graphique, tu y trouveras un bouton </> qui permet d'insérer du code.

Cela permet de transformer :

#define MAX 12
int main(void) {
    if (a == MAX) {
        b++; // INC
    }
    return 0;
}

En :

#define MAX 12
int main(void) {
    if (a == MAX) {
        b++; // INC
    }
    return 0;
}

Et entre les 2, y'a pas photo.

-
Edité par lorrio 5 mai 2014 à 23:44:46

  • Partager sur Facebook
  • Partager sur Twitter
6 mai 2014 à 10:05:41

Voilà le code à été édité. Merci pour l'astuce.
  • Partager sur Facebook
  • Partager sur Twitter
7 mai 2014 à 14:23:39

voici un peu de code arduino pour le faire marcher. lien (clique)

il a fait sans timer, avec des delay, mais ça a l'air de marcher pas mal non plus.

  • Partager sur Facebook
  • Partager sur Twitter

oui. non. enfin je regarde et je te dis.

7 mai 2014 à 16:41:44

Bonjour Remace,

Je te remercie pour ta réponse. De mon coté, je ne maitrise pas l'arduino (jamais essayé). Le code est très ressemblant. Cela dit je me suis focalisé sur une partie du code:

/* Réveil du capteur */
  *ddr |= bit; // OUTPUT
  *out &= ~bit; // LOW
  delay(18); // Temps d'attente à LOW causant le réveil du capteur
  *out |= bit; // HIGH
  delayMicroseconds(40);
  *ddr &= ~bit; // INPUT

Lui utilise un timing de 18ms pour coder un "1" et 40µs pour un "0", alors que moi j'utilise 25ms et 30µs.   Je vais essayer de modifier mon code avec ces timing pour voir si cela fait une différence.

Question subsidiaire: Peut-on programmer un PIC avec du code Arduino? Il me semble que non car la puce Arduino est d'une autre architecture, mais vu que je ne connais pas ce système....

  • Partager sur Facebook
  • Partager sur Twitter
7 mai 2014 à 17:14:40

non on ne peut pas  programmer un PIC avec un programme arduino. juste qu'il donnait un algo très simple (donc facile à retranscrire en C), et qui marche.

sinon, pour les durées des états de la liaison 1-wire, il faut que tu regarde dans la doc du DHT11

  • Partager sur Facebook
  • Partager sur Twitter

oui. non. enfin je regarde et je te dis.

8 mai 2014 à 13:30:23

bonjour,

J'ai regardé le datasheet du DHT11 et 18 ms et 40µs sont correct.

J'ai fait les modifications et je n'ai pas de changement.

Je pense que je vais chercher du coté protocole one wire, il y a un post à ce sujet sur le forum.

  • Partager sur Facebook
  • Partager sur Twitter
8 mai 2014 à 13:42:45

sauf que là, ce que tu pense être un 1 ou un 0, c'est la trame de réveil du capteur. la lecture des états c'est dans la boucle for après.
  • Partager sur Facebook
  • Partager sur Twitter

oui. non. enfin je regarde et je te dis.

16 mai 2014 à 18:20:49

Ha d'accord merci pour cette précision.

Voici des nouvelles du projet:

J'ai fait un essai avec le code original et un pic 16f628A et là Tadam! CA fonctionne!

et voici mon setup,

et le code:

/*
 Project: Temperature and humidity measurements using DHT11
 MCU: PIC16F628A
 Clock: 4.0MHz external resonator
 MCLR is enabled
 Date: Jan 10, 2012
 Written by: Rajendra Bhatt (www.embedded-lab.com)
*/

// LCD module connections
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;

sbit Data at RA0_bit;
sbit DataDir at TRISA0_bit;
char message1[] = "Temp = 00.0 C";
char message2[] = "RH   = 00.0 %";
unsigned short TOUT = 0, CheckSum, i;
unsigned short T_Byte1, T_Byte2, RH_Byte1, RH_Byte2;

void StartSignal(){
  DataDir = 0;     // Data port is output
  Data    = 0;
  Delay_ms(25);
  Data    = 1;
  Delay_us(30);
  DataDir = 1;     // Data port is input

}

unsigned short CheckResponse(){
  TOUT = 0;
  TMR2 = 0;
  T2CON.TMR2ON = 1;      // start timer
  while(!Data && !TOUT);
  if (TOUT) return 0;
  else {
   TMR2 = 0;
   while(Data && !TOUT);
   if (TOUT) return 0;
   else {
    T2CON.TMR2ON = 0;
    return 1;
   }
  }
}

unsigned short ReadByte(){
  unsigned short num = 0, t;
  DataDir = 1;
  for (i=0; i<8; i++){
   while(!Data);
   TMR2 = 0;
   T2CON.TMR2ON = 1;
   while(Data);
   T2CON.TMR2ON = 0;
   if(TMR2 > 40) num |= 1<<(7-i);  // If time > 40us, Data is 1
  }
  return num;
}

void interrupt(){
  if(PIR1.TMR2IF){
   TOUT = 1;
   T2CON.TMR2ON = 0; // stop timer
   PIR1.TMR2IF  = 0; // Clear TMR0 interrupt flag
  }
}

void main() {
  unsigned short check;
  TRISB = 0b00000000;
  PORTB = 0;
  TRISA = 0b00100001;
  CMCON = 7;
  INTCON.GIE = 1;    //Enable global interrupt
  INTCON.PEIE = 1;   //Enable peripheral interrupt
  // Configure Timer2 module
  PIE1.TMR2IE = 1;  // Enable Timer2 interrupt
  T2CON = 0;        // Prescaler 1:1, and Timer2 is off initially
  PIR1.TMR2IF =0;   // Clear TMR INT Flag bit
  TMR2 = 0;
  Lcd_Init();
  Lcd_Cmd(_Lcd_Clear);
  Lcd_Cmd(_LCD_CURSOR_OFF);

  do {
    Delay_ms(1000);
    StartSignal();
    check = CheckResponse();
    if (!check) {
     Lcd_Cmd(_Lcd_Clear);
     Lcd_Out(1, 1, "No response");
     Lcd_Out(2, 1, "from the sensor");
    }
    else{
    
     RH_Byte1 = ReadByte();
     RH_Byte2 = ReadByte();
     T_Byte1 = ReadByte();
     T_Byte2 = ReadByte();
     CheckSum = ReadByte();
     // Check for error in Data reception
     if (CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF))
     {
      message1[7]  = T_Byte1/10 + 48;
      message1[8]  = T_Byte1%10 + 48;
      message1[10] = T_Byte2/10 + 48;
      message2[7]  = RH_Byte1/10 + 48;
      message2[8]  = RH_Byte1%10 + 48;
      message2[10] = RH_Byte2/10 + 48;
      message1[11] = 223;     // Degree symbol
      Lcd_Cmd(_Lcd_Clear);
      Lcd_Out(1, 1, message1);
      Lcd_Out(2, 1, message2);
      }
      
      else{
       Lcd_Cmd(_Lcd_Clear);
       Lcd_Out(1, 1, "Checksum Error!");
       Lcd_Out(2, 1, "Trying Again ...");
      }
    }

  }while(1);
}

Je vois pas où ça coince avec le 16f876.  Des idées?

-
Edité par psikophoenix 16 mai 2014 à 18:23:08

  • Partager sur Facebook
  • Partager sur Twitter
16 mai 2014 à 21:30:42

Ligne 85 du code avec le 16f628A, il y a : CMCON = 7; alors que tu ne l'as pas dans ton code.

L'erreur en viendrait-elle pas de là ?

==========

Sinon, il y a beaucoup de différence avec les bits au début, es tu sur de ton branchement ?

==========

Dernier point à vérifier : la fréquence est-elle la même pour ces 2 PIC ?

  • Partager sur Facebook
  • Partager sur Twitter
17 mai 2014 à 0:33:01

pour la fréquence, selon son commentaire en début de programme, oui c'est un oscillateur externe à 4MHz.
  • Partager sur Facebook
  • Partager sur Twitter

oui. non. enfin je regarde et je te dis.

17 mai 2014 à 10:44:12

Bonjour,

Oui la fréquence est la même pour les deux, je l'ai fait exprès pour ne pas avoir à recalculer toute les temporisations.

Pour CMCON=7: C'est peut-être bien cela, mais si j'essaye de flasher le16F876 avec, j'ai un message d’erreur. (ce paramètre sert visiblement à désactiver les comparateurs et n'est pas pris en charge par le 16f876)

Pour les bits du début, J'ai fait les modifications dans le programme afin de correspondre au schéma de mon montage car les branchements et caractéristiques des pattes sont différents d'une puce à l'autre.

Je vais creuser de ce coté, merci pour votre aide.

  • Partager sur Facebook
  • Partager sur Twitter
17 mai 2014 à 12:06:15

remace a écrit:

pour la fréquence, selon son commentaire en début de programme, oui c'est un oscillateur externe à 4MHz.

Ce n'est pas parce qu'il y a un oscillateur externe à 4Mhz que le coeur est à 4MHz.

Il peut très bien y avoir un diviseur de fréquence interne qui abaisse à 1Mhz ou une PLL interne qui l'augmente à 16MHz.

Donc le traitement de l'entrée d'horloge est à vérifier aussi.

  • Partager sur Facebook
  • Partager sur Twitter
17 mai 2014 à 13:17:59

sauf que prescaler et PLL sont en général configurés dans le code au tout début. et là, aucune action sur le registre de config des horloges dans le code, à part le prescaler du timer 2.

-
Edité par remace 17 mai 2014 à 13:18:24

  • Partager sur Facebook
  • Partager sur Twitter

oui. non. enfin je regarde et je te dis.

17 mai 2014 à 14:48:21

Sauf que c'est quand même deux pic différents.

Peut être que sur l'un, le prescaler est à 1 par défaut et que sur l'autre, il est à 4.

Donc si rien n'est fait, il est tout à fait possible que l'un soit à 4Mhz, l'autre à 1Mhz.

Le problème reste entier, même si c'est peu probable que ce soit le cas.

-
Edité par lorrio 17 mai 2014 à 14:48:33

  • Partager sur Facebook
  • Partager sur Twitter
20 avril 2016 à 0:27:08

Comment je peux le convertir avec le PIC16F877 ou  PIC16F877A
  • Partager sur Facebook
  • Partager sur Twitter
20 avril 2016 à 8:26:15

C'est un peu vague comme question non ?

Tu veux convertir quoi avec le PIC16F877?

Dans quel but ?

  • Partager sur Facebook
  • Partager sur Twitter
21 avril 2016 à 21:46:31

Dans le cadre d'un projet en Micro ,d'ailleur ce code ne cesse a afficher "no reponse from the sensor"
qu'est-ce je fais en contre partie ?
  • Partager sur Facebook
  • Partager sur Twitter
22 avril 2016 à 1:35:23

commence par ouvrir un topic, en donnant ton code dans la balise prévue à cet effet, et un aperçu de ton montage (schéma partiel fritzing, petit texte qui explique, etc...)

parce que là on comprend pas ce que tu veux, à part que tu arrive pas à lire un capteur, dont on ne connait pas la référence.

  • Partager sur Facebook
  • Partager sur Twitter

oui. non. enfin je regarde et je te dis.

19 juillet 2019 à 4:10:54

bonjour je suis débitant en langage C pour microcontrôleur PIC  j'ai un problème j'ai programmé un afficheur LCD  avec le compilateur mikroC la simulation sur proteus fonctionne bien mais sur une plaque a essai mon afficheur ne m'affiche pas des caractères.quelqu'un peut m'aider? merci

-
Edité par TonyDavisGuelordAkono 19 juillet 2019 à 4:19:46

  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2019 à 15:26:34

Bonjour,

Tu devrais aller voir ici, on y parle PIC.

  • Partager sur Facebook
  • Partager sur Twitter
Le 25 juillet 2016, j'ai essayé une Ford Mustang.
31 juillet 2019 à 9:15:08

Bonjour,

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter