Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!
  • Fermate
    Fermate

    ESP32/MQTT Tempetarur måling (8)

    Her er kode for å lese DS18B20:

     

    Sitat
    #include <OneWire.h>
    #include <DallasTemperature.h>

     

    // Temp
    #define ONE_WIRE_BUS GPIO_NUM_33
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    float Temp;

     

    void setup() {
     Serial.begin(115200);
     // Temp
     sensors.begin();
    }

     

    void loop() {
        read_temp();
        delay(1000);
      }

     

     void read_temp() {
       sensors.requestTemperatures(); // Send the command to get temperatures
      Temp=sensors.getTempCByIndex(0);// Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
      Serial.println(Temp);
    }

     

    Bibliotekene er:

    image.png

    image.png


    Dalles DS18B20 ser ut som en transistor men er egentlig en IC.
    Den finnes i TO-92 (som en liten transistor) pakning men også bygget inn i en vanntett rustfri probe med lang kabel:

     

    image.png

     

    Den er superenkel å bruke til å lese temperaturer med og koster lite.

    Det eneste den trenger er en pull-up resistor på 4,7k (Mellom + og Data)

    Spenningen kan være mellom 3 og 5,5V (Altså kan du bruke 3,3V spenningen fra ESP32en om det trengs.

     

    Mange sensorer
    Du kan koble opptil 32 stk DS18B20 etter hverandre på samme kabelen (Kun 1 pullup resistor)

    Du kan spørre etter antallet slik:

    deviceCount = sensors.getDeviceCount();
     
    Og du leser dem slik:
    Temp1=sensors.getTempCByIndex(0)
    Temp2=
    sensors.getTempCByIndex(1);
     
    image.png
     
    Alarmer
    Biblioteket inneholder også kode for alarmer om du ikke vil kode dem selv. Da må du også finne adressen til sensoren:
    DeviceAddress Temp1Addr;
    sensors.getAddress(Temp1Addr, 0);
     

    så kan du sette alarmtemperaturene:

    sensors.setHighAlarmTemp(Temp1Addr, 26.5);
    sensors.setLowAlarmTemp(Temp1Addr, 19);
     
    Og teste om alarmen er aktiv:
    if (sensors.hasAlarm(Temp1Addr)) {
    OBS Den trigger både på høy og lav så du må lese temp for å finne ut hvem.

    Leseintervaller

    Når du skal bruke den med MQTT må du bestemme deg for NÅR den skal rappportere temperaturen. 

    • Hver gang temperaturen endrer seg (mer en x grader)?
    • Fast hvert x sekund
    • Hver gang du ber om det.
    • For den har passert over/under en granse (Alarm)

     

    De to første kan hardkodes eller de kan ha en default verdi og så kan de endres med MQTT kommandoer.

     

    Interupt

    Om du skal lese dem hvert x sekund kan du bruke et interupt. 

    (Om du bruker en delay kan jo ikke ESP32 gjøre noe annet fornuftig mens den venter)

    Et interupt avbryter prosessoren med det den driver med og kjører en rutine, når rutinen er ferdig fortsetter prosessoren der den slapp.

     

    Rutinen som skal kjøres merkes med IRAM_ATTR slik at compileren legger den i instruksjons RAM for at den skal kunne kjøres raskt:

    void IRAM_ATTR onTimer(){
    itsTimeNow=1;
    }
    En slik rutine bør gjøre så lite som mulig for ikke å forstyrre prosessoren for mye. Det enkelste er å bare sette en variabel. Denne bør deklareres med voilatile for at compileren skal holde den i RAM (og ikke i et register) slik at hovedprogrammet kan lese den correct:
    volatile int itsTimeNow = 0;

     

    I hoved loop'en kan vi nå teste på denne slik:

    if (itsTimeNow==1 ) {
         read_temp();
         MQTTclient.publish("TempTestClient/Temp1", String(Temp1));
         itsTimeNow=0; // Reset
       }
     

    Timer

    ESP32 har flere (2-4) harware timere som vi kan bruke til å kalle på interuptet. Du deklarerer den slik:
    hw_timer_t *My_timer = NULL;

    og setter den til å telle slik:
    My_timer = timerBegin(0, 8000, true);
    Fordi disse timerne teller VELDIG fort har jeg her brukt en "prescaler" på 8000 som gjør at jeg kan be om et interupt hver gang den når 10000 og det vil utgjøre et sekund:
    timerAttachInterrupt(My_timer, &onTimer, true); // Kobler interupt rutinen til timeren
    timerAlarmWrite(My_timer, 100000, true); //10000 = 1 Sek Altså hvert 10sek her
    timerAlarmEnable(My_timer); //start
     
     

    Her er et forslag til MQTT kode som poster temp fra 2 sensorer på forskjellige vis:

     

    Sitat
    #define ONBOARD_LED 2
    #include <EspMQTTClient.h>
    #include <OneWire.h>
    #include <DallasTemperature.h>
     
    // Temp
    #define ONE_WIRE_BUS GPIO_NUM_23
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    int deviceCount;
    float Temp1;
    float Temp2;
    // Alarm
    DeviceAddress Temp1Addr;
    bool alarmActive = false;
     
    // Timer
    hw_timer_t *My_timer = NULL;
    volatile int itsTimeNow = 0;
     
    //MQTT
    EspMQTTClient MQTTclient(
      "ThePromisedLAN", // SSID
      "Hallelujah!", // WiFi Password
      "192.168.1.2",  // MQTT Broker server ip
      "",   // MQTTUsername Can be omitted if not needed
      "",   // MQTTPassword Can be omitted if not needed
      "TempTestClient",     // Client name that uniquely identify your device
      1883              // The MQTT port, default to 1883. this line can be omitted
    );

     

    // Interupt rutine

    void IRAM_ATTR onTimer(){ 
        Serial.println("Timer Active Nu");
        itsTimeNow=1;
    }
    //------------------------------------------
    void setup() {
      Serial.begin(115200);
     
      // Temp
     sensors.begin();
     sensors.getAddress(Temp1Addr, 0);
     sensors.setHighAlarmTemp(Temp1Addr, 26.5);
     sensors.setLowAlarmTemp(Temp1Addr, 23);
     
     // Set pin mode for test LED
     pinMode(ONBOARD_LED,OUTPUT);
     digitalWrite(ONBOARD_LED,HIGH);
     
     // MQTTclient
     MQTTclient.setKeepAlive(60);
     MQTTclient.enableHTTPWebUpdater("meg","hemmelig");
     MQTTclient.enableOTA("pwd");
     
     // Timer
     My_timer = timerBegin(0, 8000, true);
    timerAttachInterrupt(My_timer, &onTimer, true);
    timerAlarmWrite(My_timer, 100000, true); //10000 = 1 Sek
    timerAlarmEnable(My_timer);
    }

     

    //-------------------------------------------

    void loop() {
      MQTTclient.loop();

     

      // Connect status på intern LED

      if (MQTTclient.isMqttConnected()) {
        digitalWrite(ONBOARD_LED,LOW);
      } else {
       digitalWrite(ONBOARD_LED,HIGH);
      }

     

      // Les temp thvert X sekund

      if (MQTTclient.isMqttConnected()) {
       if (itsTimeNow==1 ) {
         read_temp();
         deviceCount = sensors.getDeviceCount();
         MQTTclient.publish("TempTestClient/deviceCount", String(deviceCount));
         MQTTclient.publish("TempTestClient/Temp1", String(Temp1));
         MQTTclient.publish("TempTestClient/Temp2", String(Temp2));
         Serial.println("Publish");
         itsTimeNow=0; // Reset
       }
     
        // Alarm will trigger on both High and Low
       if (sensors.hasAlarm(Temp1Addr)) {
          if (!alarmActive) {
            alarmActive=true;
            read_temp();
            Serial.println("Alarm1 On");
            MQTTclient.publish("TempTestClient/Alarm", "ON");
          }
       } else {
          if (alarmActive) {
             Serial.println("Alarm1 Off");
             MQTTclient.publish("TempTestClient/Alarm", "OFF");
            alarmActive=false;
          }
       }
      }
    }
     
    void onConnectionEstablished()
     {
     Serial.println("onConnectionEstablished");
     MQTTclient.publish("TempTestClient/status", "started");  
     
      MQTTclient.subscribe("TempTestClient/readTemp1Now", [](const String & payload) {
      Serial.print("readNow: ");
      Serial.println(payload);
      read_temp();
      MQTTclient.publish("TempTestClient/Temp1", String(Temp1));
      });
     }
     
     void read_temp() {
      sensors.requestTemperatures(); // Send the command to get temperatures
      Temp1=sensors.getTempCByIndex(0);// Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
      Temp2=sensors.getTempCByIndex(1);
      Serial.println(Temp1);
      Serial.println(Temp2);
    }

     

    Brukertilbakemelding

    Anbefalte kommentarer

    Jeg kjøpte ved en feiltakelse en haug med DS1820 fra Ali. Dette er en eldre modell som ikke er kompatibel!
     

    • Om noen har kode for ESP32 for disse hadde det vært kult om dere deler den.

     

    • DS1820 og DS18B20 skal kunne kobles med "parasite power". Dvs at IC'en henter power fra selve datalinjen og at en derfor kan klare seg med 2 ledere isteden for 3. Om noen har konkret erfaring og testede løsninger for dette (linker klarer jeg å google selv 🙂 ) hadde det være fin å høre fra dere.
    Lenke til kommentar
    Del på andre sider

    Fermate skrev (15 minutter siden):

    Hva er ulempene?

    Veldig lite energi tilgjengelig. Jeg fant ikke noen tall på det i farten men i parasitic mode så er det datalinjen i seg selv som leverer energi til sensorene og så vidt jeg forstod det så må host sende data før sensoren har energi til å svare.

    Lenke til kommentar
    Del på andre sider



    Bli med i samtalen

    Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

    Gjest
    Skriv en kommentar...

    ×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

      Du kan kun bruke opp til 75 smilefjes.

    ×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

    ×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

    ×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.




×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.