IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Arduino et capteur ZH-3B


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut Arduino et capteur ZH-3B
    Bonjour à tous ,

    j'essaie de faire fonctionner un capteur ZH-03B ( series-laser-dust-module) qui sert à mesurer les particules
    et déterminer par calcul la qualité de l'air ambiant
    pour ce faire j'utilise un prg trouver sur le net dont voici une partie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    #include "CalculateAQI.h"
     
     
    SensorData CalculateAQI::getAveragedData(SensorData data) {
      return {
        PM_AE_UG_1_0: (data.PM_AE_UG_1_0 / data.numReads),
        PM_AE_UG_2_5: (data.PM_AE_UG_2_5 / data.numReads),
        PM_AE_UG_10_0: (data.PM_AE_UG_10_0 / data.numReads),
        AQI: (data.AQI / data.numReads),
        numReads: data.numReads
      };
    }
     
     
    void CalculateAQI::updateSensorData(SensorData &data, PMS::DATA newData, float AQI) {
      data.PM_AE_UG_1_0 += newData.PM_AE_UG_1_0;
      data.PM_AE_UG_2_5 += newData.PM_AE_UG_2_5;
      data.PM_AE_UG_10_0 += newData.PM_AE_UG_10_0;
      data.AQI += AQI;
      data.numReads++;
    }
     
     
    float CalculateAQI::getAQI(float I_high, float I_low, float C_high, float C_low, float C) {
      return (I_high - I_low) * (C - C_low) / (C_high - C_low) + I_low;
    }
     
    float CalculateAQI::getPM25AQI(float cPM25) {
      Breakpoints b = CalculateAQI::getPM25Breakpoints(cPM25);
      return CalculateAQI::getAQI(b.iHi, b.iLo, b.cHi, b.cLo, cPM25);
    }
     
    Breakpoints CalculateAQI::getPM25Breakpoints(float cPM25) {
      Breakpoints b;
     
      if (cPM25 <= 12) {
        b.iHi = 50;
        b.iLo = 0;
        b.cHi = 12;
        b.cLo = 0;
      } else if (cPM25 > 12 && cPM25 <= 35.4) {
        b.iHi = 100;
        b.iLo = 51;
        b.cHi = 35.4;
        b.cLo = 12.1;
      } else if (cPM25 > 35.4 && cPM25 <= 55.4) {
        b.iHi = 150;
        b.iLo = 101;
        b.cHi = 55.4;
        b.cLo = 35.5;
      } else if (cPM25 > 55.4 && cPM25 <= 150.4) {
        b.iHi = 200;
        b.iLo = 151;
        b.cHi = 150.4;
        b.cLo = 55.5;
      } else if (cPM25 > 150.4 && cPM25 <= 250.4) {
        b.iHi = 300;
        b.iLo = 201;
        b.cHi = 250.4;
        b.cLo = 150.5;
      } else if (cPM25 > 250.4 && cPM25 <= 350.4) {
        b.iHi = 400;
        b.iLo = 301;
        b.cHi = 350.4;
        b.cLo = 250.5;
      } else if (cPM25 > 350.4) {
        b.iHi = 500;
        b.iLo = 401;
        b.cHi = 500.4;
        b.cLo = 350.5;
      }
     
      return b;
    }
     
    Category CalculateAQI::getCategory(float AQI) {
      Category c;
      c.level = "Unknown";
      c.color = "black";
     
      if (AQI <= 50) {
        c.level = "Good";
        c.color = "green";
      } else if (AQI > 50 && AQI <= 100) {
        c.level = "Moderate";
        c.color = "yellow";
      } else if (AQI > 100 && AQI <= 150) {
        c.level = "Unhealthy for Sensitive Groups";
        c.color = "orange";
      } else if (AQI > 150 && AQI <= 200) {
        c.level = "Unhealthy";
        c.color = "red";
      } else if (AQI > 200 && AQI <= 300) {  
        c.level = "Very Unhealthy";
        c.color = "purple";
      } else if (AQI > 300) {
        c.level = "Hazardous";
        c.color = "maroon";
      }
     
      return c;
    }
    malheureusement étant débutant sur Arduino , je souhaiterai svp que l'on puisse m'expliquer les lignes suivantes car je ne peux utiliser le prg en l'état ( l'auteur utilisait un autre capteur
    symbolisé par <<PMS>> alors que j'utilise moi un capteur de type ZH-03B )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void CalculateAQI::updateSensorData(SensorData &data, PMS::DATA newData, float AQI) {
      data.PM_AE_UG_1_0 += newData.PM_AE_UG_1_0;
      data.PM_AE_UG_2_5 += newData.PM_AE_UG_2_5;
      data.PM_AE_UG_10_0 += newData.PM_AE_UG_10_0;
      data.AQI += AQI;
      data.numReads++;
    }


    merci mille fois
    cordialement

  2. #2
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Vous avez du code et une explication du produit ici

    https://wiki.dfrobot.com/PM2.5_laser...or_SKU_SEN0177

  3. #3
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    Bonjour,

    Non justement car il s'agit du produit ZH-03B et ce croquis que j'ai dejà testé, ne fonctionne pas
    c'est pourquoi j'essaie d'adapter avec une autre lib : << SD_ZH03B.h >>
    mais je ne sais pas la signification des lignes suivante :
    ( il semble vouloir faire une comparaison entre deux mesures )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void CalculateAQI::updateSensorData(SensorData &data, PMS::DATA newData, float AQI) {
      data.PM_AE_UG_1_0 += newData.PM_AE_UG_1_0;
      data.PM_AE_UG_2_5 += newData.PM_AE_UG_2_5;
      data.PM_AE_UG_10_0 += newData.PM_AE_UG_10_0;
      data.AQI += AQI;
      data.numReads++;
    }
    Où l'on voit apparaître le terme "PMS"
    issu de la déclaration suivante :


    C'est ce terme que je dois modifier pour l'adapter à la nouvelle lib
    d'où ma demande d'aide

    merci encore
    cordialement

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Bonsoir

    pourriez vous partager

    -> un lien vers votre capteur exact
    -> un lien vers la bibliothèque qui inclut la classe PMS

    la fonction que vous citez accumule des données dans une instance de SensorData

    Attention si j'en crois la doc technique que j'ai trouvée, les pins Rx et Tx sont en 3V max

  5. #5
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    Voici pour le capteur
    https://www.winsen-sensor.com/sensor...nsor/zh3b.html

    Lib PMS
    https://github.com/fu-hsi/pms

    Attention si j'en crois la doc technique que j'ai trouvée, les pins Rx et Tx sont en 3V max
    oui vous avez raison , j'ai effectivement fait l'impasse sur l'adaptation des signaux TX et RX


    cordialement

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Vous communiquerez en utilisant la connexion UART je suppose

    Quel Arduino avez vous choisi ? (la MEGA aura plusieurs port Série matériel donc ça rend plus robuste la communication, mais on peut s'en sortir avec un UNO en utilisant SoftwareSerial si le débit/volume de données reste faible.

    J'ai regardé la classe PMS, elle envoie par exemple le flux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73
    pour mettre le composant en sleep ce qui ne correspond pas à la spécification
    Nom : dormant.png
Affichages : 318
Taille : 174,6 Ko

    il semble que le langage de commande utilise un start byte de 0xFF ce qui n'est pas le cas de la bibliothèque

    il se peut que le module renvoie par défaut automatiquement de temps en temps les valeurs, pour s'en assurer pouvez vous faire le montage suivant (AVEC ADAPTATION DE TENSION SUR Tx et Rx, j'espère que vous ne l'avez pas grillé)
    Nom : montage.png
Affichages : 331
Taille : 633,7 Ko
    la pin 4 du module doit être connectée à D3 et la pin 5 du module doit être connectée à D2 sur l'arduino au travers d'un mécanisme d'adaptation de tension (j'ai lu à la fois 3V et 3.3V dans des guides différents donc je ne sais pas quelle est la bonne valeur... si vous avez une doc...)

    Chargez le code suivant sur votre Arduino
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <SoftwareSerial.h>
    const byte unoRx = 2; // connect to pin 5 through 5v/3v voltage adapter
    const byte unoTx = 3; // connect to pin 4 through 5v/3v voltage adapter
    SoftwareSerial zh03Serial(unoRx, unoTx);
     
    void setup() {
      Serial.begin(115200);
      zh03Serial.begin(9600);
    }
     
    void loop() {
      static byte nbBytes = 0;
      if (zh03Serial.available()) {
        byte r = zh03Serial.read();
        if (r < 0x10) Serial.write('0');
        Serial.print(r, HEX);
        if (++nbBytes >= 24) {
          nbBytes = 0;
          Serial.println();
        } else {
          Serial.write(' ');
        }
      }
    }
    Ouvrez le moniteur série à 115200 bauds et regardez si quelque chose s'affiche. Si oui copiez le et postez le ici.

  7. #7
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    Vous communiquerez en utilisant la connexion UART je suppose
    Oui tout à fait

    Quel Arduino avez vous choisi ?
    le UNO pour les tests puis à terme je voulais utiliser le WEMOS

    il se peut que le module renvoie par défaut automatiquement de temps en temps les valeurs, pour s'en assurer pouvez vous faire le montage suivant (AVEC ADAPTATION DE TENSION SUR Tx et Rx, j'espère que vous ne l'avez pas grillé)
    pour être tout a fait honnête j'ai zappé l'adaptation 5v-3v , j'ai donc pensé que j'avais grillé le module puis en faisant avec les essais avec la Lib <<PMS.h>> la reponse était toujours égale à zéro sur PM10,P2.5 et PM1.0 mais avec la lib << ZH-03B>>
    et son exemple , j'obtiens des valeurs certes basses voir même des valeurs qui augmentent le soir (?)
    j'ai donc essayé d'adapter les niveaux en TX et RX avec un pont diviseur de 10k et 15k mais çà qui ne change rien


    Chargez le code suivant sur votre Arduino
    Voici les resutats :
    ***************************************************************
    Avant de charger le code => Nom : Test lib ZH-03B.jpg
Affichages : 308
Taille : 146,5 Ko (Test lib ZH-3B)

    ************************************************************************************************
    Puis avec le code proposé :
    ( attention unoRx = 3 et unoTx = 2 sinon çà ne marche pas => Nom : test.jpg
Affichages : 305
Taille : 316,9 Ko ( test.jpg)
    On peut noter que j'ai bien 0x42 en entête


    cordialement
    pascal

  8. #8
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Salut

    ( attention unoRx = 3 et unoTx = 2 sinon çà ne marche pas )
    OK la doc mentionne juste Tx et Rx mais ne dit pas de quel point de vue

    Les codes obtenus sont super encourageants (un copier collé du texte aurait été plus simple qu'une image pour exploiter) et semblent conformes à la doc qui décrit les champs

    Nom : image.png
Affichages : 297
Taille : 426,8 Ko

    donc vous pouvez extraire les 3 valeurs (qui sont rangées en Big Endian, le premier octet reçu est le poids fort) qui seraient en PM (Particulate Matter)

    PM1.0 = 3 µg/m3 --> particules très fines, peuvent passer la barrière alvéolo-capillaire

    PM2.5 = 4 µg/m3 --> particules fines, pénètrent dans les alvéoles pulmonaires

    PM10 = 4 µg/m3 --> particules d 'un diamètre aérodynamique/aéraulique dites « respirables » qui peuvent pénétrer dans les bronches

    ce qui semble correspondre aussi à ce que la bibliothèque décode:
    Nom : lib.png
Affichages : 309
Taille : 110,1 Ko

    Normalement le compte "des plus grands" comprend les compte des autres PM plus fins donc ici on a en réalité 1 en 2.5 et 3 et 1.0 ce qui fait 4

    Un document du gouvernement décrit quelques seuils:
    Nom : seuils.png
Affichages : 316
Taille : 170,8 Ko


    PS:
    La doc dit aussi
    The concentration data of PM2.5 after power on for 10 seconds is the version number
    donc il ne faut pas lire les données avant 10s (au moins le PM2.5)

  9. #9
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    Merci Jay M

    (un copier collé du texte aurait été plus simple qu'une image pour exploiter)
    mille pardons ...


    A la lecture , je n'aurai donc plus besoin de librairie et notamment celle <<PMS.h>>> ?

    pascal

  10. #10
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Disons que si vous n'utilisez pas la bibliothèque, il faudra coder la réception des 24 octets et extraire les 3 valeurs vous même (ce n'est pas très compliqué).
    il semble que le module réponde aussi à des commandes (d'après la doc), faudrait voir si ça présente un intérêt

  11. #11
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    Bonjour,

    merci encore pour vos réponses

    j'essaie de "mixer " le croquis présenté en #4 et le test présenté #6

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    //******************************
     //*Abstract: Read value of PM1,PM2.5 and PM10 of air quality
     //*Product Link: https://www.dfrobot.com.cn/goods-1113.html
     //*
     //8
     //*The RX pin on the sensor connects to pin 11 on the Arduino
     //*The TX pin on the sensor connects to pin 10 on the Arduino
     //
     //*Version:V3.1
     //*Author:Zuyang @ HUST
     //*Date:March.25.2016
     //******************************
    #include <Arduino.h>
    #include <SoftwareSerial.h>
    #define LENG 31   //0x42 + 31 bytes equal to 32 bytes
    unsigned char buf[LENG];
     
    int PM01Value=0;          //define PM1.0 value of the air detector module
    int PM2_5Value=0;         //define PM2.5 value of the air detector module
    int PM10Value=0;         //define PM10 value of the air detector module
     
    SoftwareSerial PMSerial(2, 3); // RX, TX
     
    void setup()
    {
      PMSerial.begin(9600);
      PMSerial.setTimeout(1500);
      Serial.begin(115200);
    }
     
    void loop()
    { 
       if(PMSerial.find(0x42)){
          PMSerial.readBytes(buf,LENG);
     
          if(buf[0] == 0x4d){
            if(checkValue(buf,LENG)){
              PM01Value=transmitPM01(buf); //count PM1.0 value of the air detector module
              PM2_5Value=transmitPM2_5(buf);//count PM2.5 value of the air detector module
              PM10Value=transmitPM10(buf); //count PM10 value of the air detector module
            }
          }
        }
     
        static unsigned long OledTimer=millis();
        if (millis() - OledTimer >=1000)
        {
          OledTimer=millis();
     
          Serial.print("PM1.0: ");
          Serial.print(PM01Value);
          Serial.println("  ug/m3");
     
          Serial.print("PM2.5: ");
          Serial.print(PM2_5Value);
          Serial.println("  ug/m3");
     
          Serial.print("PM1 0: ");
          Serial.print(PM10Value);
          Serial.println("  ug/m3");
          Serial.println();
        }
     
    }
    char checkValue(unsigned char *thebuf, char leng)
    {
      char receiveflag=0;
      int receiveSum=0;
     
      for(int i=0; i<(leng-2); i++){
      receiveSum=receiveSum+thebuf[i];
      }
      receiveSum=receiveSum + 0x42;
     
      if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1]))  //check the serial data
      {
        receiveSum = 0;
        receiveflag = 1;
      }
      return receiveflag;
    }
     
    int transmitPM01(unsigned char *thebuf)
    {
      int PM01Val;
      PM01Val=((thebuf[7]<<8) + thebuf[8]); //count PM1.0 value of the air detector module
      return PM01Val;
    }
     
    //transmit PM Value to PC
    int transmitPM2_5(unsigned char *thebuf)
    {
      int PM2_5Val;
      PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module
      return PM2_5Val;
      }
     
    //transmit PM Value to PC
    int transmitPM10(unsigned char *thebuf)
    {
      int PM10Val;
      PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module
      return PM10Val;
    }
    On sait que la trame comme pourtant 0x42
    or le croquis ne marche pas , j'avoue que je comprends de moins en moins


    Disons que si vous n'utilisez pas la bibliothèque...
    par contre à l'inverse si je n'ai pas le choix et que je veux faire tourner l'appli présentée en #1
    çà signifie que je dois changer la lib ?


    pascal

  12. #12
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    j'ai un peu progressé avec le croquis suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
     
    //******************************
     //*Abstract: Read value of PM1,PM2.5 and PM10 of air quality
     //*Product Link: https://www.dfrobot.com.cn/goods-1113.html
     //*
     //8
     //*The RX pin on the sensor connects to pin 11 on the Arduino
     //*The TX pin on the sensor connects to pin 10 on the Arduino
     //
     //*Version:V3.1
     //*Author:Zuyang @ HUST
     //*Date:March.25.2016
     //******************************
    #include <Arduino.h>
    #include <SoftwareSerial.h>
    #define LENG 24  //0x42 + 31 bytes equal to 32 bytes
    unsigned char buf[LENG];
     
    int PM01Value=0;          //define PM1.0 value of the air detector module
    int PM2_5Value=0;         //define PM2.5 value of the air detector module
    int PM10Value=0;         //define PM10 value of the air detector module
     
    SoftwareSerial PMSerial(2, 3); // RX, TX
     
    void setup()
    {
      PMSerial.begin(9600);
      PMSerial.setTimeout(1500);
      Serial.begin(115200);
    }
     
    void loop()
    { 
     
      if(PMSerial.find(0x42)){
          PMSerial.readBytes(buf,LENG);
     
          if(buf[0] == 0x4d){
     
           // if(checkValue(buf,LENG)){
              PM01Value=transmitPM01(buf); //count PM1.0 value of the air detector module
              PM2_5Value=transmitPM2_5(buf);//count PM2.5 value of the air detector module
              PM10Value=transmitPM10(buf); //count PM10 value of the air detector module
            //}
     
          }
     
        }
     
        static unsigned long OledTimer=millis();
        if (millis() - OledTimer >=1000)
        {
          OledTimer=millis();
     
          Serial.print("PM1.0: ");
          Serial.print(PM01Value);
          Serial.println("  ug/m3");
     
          Serial.print("PM2.5: ");
          Serial.print(PM2_5Value);
          Serial.println("  ug/m3");
     
          Serial.print("PM1 0: ");
          Serial.print(PM10Value);
          Serial.println("  ug/m3");
          Serial.println();
        }
     
    }
    char checkValue(unsigned char *thebuf, char leng)
    {
      char receiveflag=0;
      int receiveSum=0;
     
      for(int i=0; i<(leng-2); i++){
      receiveSum=receiveSum+thebuf[i];
      }
      //receiveSum=receiveSum + 0x42;
     
      if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1]))  //check the serial data
      {
        receiveSum = 0;
        receiveflag = 1;
      }
      return receiveflag;
    }
     
    int transmitPM01(unsigned char *thebuf)
    {
      int PM01Val;
      PM01Val=((thebuf[3]<<8) + thebuf[4]); //count PM1.0 value of the air detector module
      return PM01Val;
    }
     
    //transmit PM Value to PC
    int transmitPM2_5(unsigned char *thebuf)
    {
      int PM2_5Val;
      PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module
      return PM2_5Val;
      }
     
    //transmit PM Value to PC
    int transmitPM10(unsigned char *thebuf)
    {
      int PM10Val;
      PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module
      return PM10Val;
    }
    j'obtiens çà mais faire de test "checkValue()"

    PM1.0: 5 ug/m3
    PM2.5: 7 ug/m3
    PM1 0: 7 ug/m3

    PM1.0: 5 ug/m3
    PM2.5: 7 ug/m3
    PM1 0: 7 ug/m3

    PM1.0: 5 ug/m3
    PM2.5: 7 ug/m3
    PM1 0: 7 ug/m3

    mais je ne peux l'expliquer

    pascal

  13. #13
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    le code définit PMSerial comme un port série virtuel (logiciel) sur les pins 2 et 3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     SoftwareSerial PMSerial(2, 3); // RX, TX
    le début de la loop() dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      if (PMSerial.find(0x42)) {
        PMSerial.readBytes(buf, LENG);
    ce qui se traduit par, attend de voir le code 0x42 et quand il est là lire les LENG (24) prochains octets qui arrivent sur le port série et stocke les dans le buffer buf

    si vous vous souvenez 24 c'est le nombre d'octets dans la trame émise (cf l'image du post précédent). En pratique comme le 0x42 a été absorbé il n'y en a que 23 à lire donc la fonction readBytes() va attendre son timeout et vous aurez ensuite donc dans le buffer buf toutes les octets

    ils vérifient que le premier octet est bien 0x4d comme décrit dans la spec est si oui ils vont lire les octets 3,4,5,6,7 et 8 dans des fonctions adaptées en faisant une petite manipulation sur les octets: on conserve le poids faible et on lui ajoute le poids fort décalé de 8 positions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ((thebuf[7] << 8) + thebuf[8]);
    pour refabriquer un nombre sur 2 octets et ainsi extraire PM1.0, PM2.5 et PM10

  14. #14
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    966
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 966
    Par défaut
    Merci Jay M

    on conserve le poids faible et on lui ajoute le poids fort décalé de 8 positions
    Pourquoi ne lire pas directement les octets concernés plutôt que d'effectuer un décalage ?
    si par exemple, je prends PM1.0 = data 4 = Byte 11et byte 12
    actuellement je comprends qu'il se positionne en 3 puis ajoute 8 pour lire le byte 11
    pourquoi ne pas se positionner directement en 11
    quel intérêt ?
    j'avoue que çà m'échappe...

    de plus dans le croquis le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    checkValue(unsigned char *thebuf, char leng)
    ne fonctionne pas pourtant , il cible bien la chaine correspondante


    Cordialement
    pascal



    pascal

  15. #15
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    en fait ils ne vont pas lire les bons octets parce que selon la spec ils sont entre 11 et 16

    le c'est un décalage des bits pour les placer en octet de poids fort

Discussions similaires

  1. Projet Arduino multi capteurs
    Par lololebricoleur dans le forum Arduino
    Réponses: 0
    Dernier message: 16/04/2021, 01h09
  2. Réponses: 5
    Dernier message: 03/09/2019, 10h18
  3. Réponses: 0
    Dernier message: 21/05/2018, 21h14
  4. Réponses: 5
    Dernier message: 22/11/2017, 19h31
  5. Arduino projet Capteur
    Par AGP100 dans le forum Arduino
    Réponses: 2
    Dernier message: 24/06/2016, 17h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo