Jump to content
  • Sign Up
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);
    }

     

    User Feedback

    Recommended Comments

    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.
    Link to comment
    Share on other sites

    SveinHa skrev (12 minutter siden):

    "Parasitic mode" er ikke en anbefalt løsning

    Hvorfor?
    Hva er ulempene?
    Og: Hvor mange kan en koble på samme kabel da.

    Link to comment
    Share on other sites

    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.

    Link to comment
    Share on other sites



    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Add a comment...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.




×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.