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

Arduino MKR 1010 WiFi som MQTT klient med DS18B20 temp.sensorer


Spørsmål

Skrevet (endret)

Med MQTT i huset åpner mulighetene seg for alskens små IoT saker. Jeg har flere steder behov for 3 temperaturer og kanskje litt annet knask så jeg snekret sammen en Arduino med tempsensorer som sendes til min Mosquitto MQTT Broker og hentes derfra igjen av Node-Red og/eller HomeSeer4.

 

Selve oppkoblingen er helt basis så ikke så mye å si om den men legger nå ved et bilde. Hadde egentlig tenkt en analog/PWM 0-10V utgang styrt av en 0-100 verdi fra MQTT men det ble en 4-trinns spenningsdeler i stedet, fikk ikke til 10v i farten. 4 trinn på varmepumpen er i alle fall langt bedre enn bare av/på. "UT-INV-U" er styreboksen til varmepumpen.

bilde.thumb.png.f204d39593aeb8631afe00e910fe090c.png

 

#include <PubSubClient.h>
//#include <WiFi.h> //ESP32
#include <WiFiNINA.h> //Arduino
#include "arduino_secrets.h"
#include <DS18B20.h>
#define LED_BUILTIN 2 

DS18B20 ds(2);  //pin number of 1 Wire bus
float temps[10] = {0.0, 0.0, 0.0};  //Array for storing temperatures
int sensnum = 0;  // counter
int pinR25 = 3;
int pinR50 = 4;
int pinR75 = 5;
int pinR100 = 7;
int pinReset = 0;

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
char mqttid[] = SECRET_MQUI;
char mqttpw[] = SECRET_MQPW;

const char broker[] = "172.16.0.94";
int        port     = 1883;
const char* mySysID = "TR1ID";      //MÅ være unik innen samme mqttBroker for at LWT skal virke

const char* willTopic = "Teknisk/TR1/LWT";
const char* willMessage = "Offline";
byte willQoS = 0;
boolean willRetain = true;

//Liste over MQTT topics for publishing
char *topics[]  = {"Teknisk/TR1/TempBerederTopp",
                  "Teknisk/TR1/TempBerederBunn",
                  "Teknisk/TR1/TempTilfGulvvarme",
                  " ",
                  " ",
                  " ",
                  " ",
                  " ",
                  " ",
                  "Teknisk/TR1/VPSP-TM",
};

// Liste over topics for subscriptions
char *topicr[]  = {"Teknisk/TR1/VPSP",
                  " ",
                  " ",
                  " ",
                  " ",
                  " ",
                  " ",
};


//set interval for sending messages (milliseconds)
const long interval = 30000;
const long rtimeout = 300000;
unsigned long previousMillis = 0;
unsigned long resetMillis = millis();
unsigned long lastrecvMillis = millis();
unsigned long currentMillis = millis();

char in_message[100];
int recvVPSP = 0;
char pubs[20] = "0123.456";     // Hjelpevariabler for konvertering av format for mqtt, sett av rikelig plass til temperaturer
String s1;

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

void callback(char* topic, byte* message, unsigned int length) {
  digitalWrite(LED_BUILTIN, HIGH);
  String messageTemp;
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  lastrecvMillis = millis(); //data mottatt, reset timer for automatisk restart
  
  for (int i = 0; i < length; i++) {
    //Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println(messageTemp);
  
  // Handle the received messages
  if (String(topic) == topicr[0]) {
    recvVPSP = messageTemp.toInt();
    if (recvVPSP <8) {
    digitalWrite(pinR100, LOW);
    digitalWrite(pinR75, LOW);
    digitalWrite(pinR50, LOW);
    digitalWrite(pinR25, LOW); }
    if (recvVPSP >= 8 and recvVPSP <35) {
    digitalWrite(pinR100, LOW);
    digitalWrite(pinR75, LOW);
    digitalWrite(pinR50, LOW);
    digitalWrite(pinR25, HIGH); }
    if (recvVPSP >= 35 and recvVPSP <65) {
    digitalWrite(pinR100, LOW);
    digitalWrite(pinR75, LOW);
    digitalWrite(pinR50, HIGH);
    digitalWrite(pinR25, LOW); }
    if (recvVPSP >= 65 and recvVPSP <85) {
    digitalWrite(pinR100, LOW);
    digitalWrite(pinR75, HIGH);
    digitalWrite(pinR50, LOW);
    digitalWrite(pinR25, LOW); }
    if (recvVPSP >= 85) {
    digitalWrite(pinR100, HIGH);
    digitalWrite(pinR75, LOW);
    digitalWrite(pinR50, LOW);
    digitalWrite(pinR25, LOW); }
    PublishVPSP();
  }
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
}

int count = 0;


int ChkWiFi(){
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // failed, retry
      Serial.print(".");
      delay(5000);}
    Serial.println();
    Serial.print("Connected to network: ");
    Serial.println(ssid);
  }
}

void ChkMQTT(){
   while (!mqttClient.connect(mySysID, mqttid, mqttpw, willTopic, willQoS, willRetain, willMessage)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.state());
    delay(5000);
  }
}



void PublishVPSP(){
// Send TM til Broker (sjekk at der er liv i subscription)
  s1 = String(recvVPSP);
  s1.toCharArray(pubs,10);
  mqttClient.publish(topics[9], pubs);
// Oppdater LWT
  mqttClient.publish(willTopic, "Online");
  Serial.println("VPSP sent");
}

void PublishAll(){
// Publiser temperaturer
  for(int i = 0; i < 3; i++){
    s1 = String(temps[i]);
    s1.toCharArray(pubs,10);
    mqttClient.publish(topics[i], pubs);
    }
// Send TM til Broker (sjekk at der er liv i subscription)
  s1 = String(recvVPSP);
  s1.toCharArray(pubs,10);
  mqttClient.publish(topics[9], pubs);
// Oppdater LWT
  mqttClient.publish(willTopic, "Online");
  Serial.println("Data sent");
}

void LesDS18B20(){
// les temperaturer inn i array
  sensnum = 0;
  while (ds.selectNext()) { 
    temps[sensnum] = ds.getTempC();
    sensnum ++;                      
  }
}

void Watchdog(){
// Reset unit
if ((currentMillis + 1000 - lastrecvMillis) >= rtimeout) {
  Serial.print("Unit RESET from program, last recv > ");
  Serial.print( rtimeout/1000);
  Serial.println(" seconds ago");
  delay(1000);
  digitalWrite(pinReset, LOW);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(pinR25, OUTPUT);
  pinMode(pinR50, OUTPUT);
  pinMode(pinR75, OUTPUT);
  pinMode(pinR100, OUTPUT);
  pinMode(pinReset, OUTPUT);
  digitalWrite(pinReset, HIGH);
  pinMode(LED_BUILTIN, OUTPUT);
  
  mqttClient.setServer(broker, port);
  mqttClient.setCallback(callback);
  
  ChkWiFi();
  ChkMQTT();
  s1 = String(topicr[0]);
  s1.toCharArray(pubs,40);
  Serial.println(pubs);
  boolean r= mqttClient.subscribe(topicr[0]);
//  boolean r= mqttClient.subscribe(pubs);
  Serial.print("subscribe ");
  Serial.print(topicr[0]);
  Serial.println(r);

  lastrecvMillis = millis(); //init timer for automatisk reset
}

void loop() {
currentMillis = millis();

ChkWiFi();
ChkMQTT();

mqttClient.loop();    //VIKTIG: Uten denne vil en ikke kunne motta subscriptions

// Kjør program på spesifisert intervall
if (currentMillis - previousMillis >= interval) {
    digitalWrite(LED_BUILTIN, HIGH);
  previousMillis = currentMillis;
  mqttClient.subscribe(topicr[0]);
  LesDS18B20();
  PublishAll();
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  }
Watchdog();
}

 

Endret av SveinHa
  • Like 2

4 svar til spørsmålet

Anbefalte innlegg

  • 0
Skrevet

På leting etter en liten bug: Hele greiene funker supert i opptil mange timer men så slutter den å motta data via subscribe/callback... Har laget en publish av mottatt verdi så jeg ser AT det skjer men ikke funnet ut hvorfor enda.

  • 0
Skrevet

Har pynta litt på koden i første innlegg, lagt til Watchdog som automatisk restarter Arduino  om der ikke mottas data fra MQTT innen 5 minutt (krever forbindelse mellom pin 0 og pin RESET).

  • 0
Skrevet (endret)

Fikk et tips av @Moskus i en annen tråd at ESP32 er mye billigere og like god som Arduino.... så da gikk der ikke så fryktelig lang tid før 10 stk ESP32Dev dukket opp i posten (en av få utenlandspakker som virkelig kommer fram for tiden).

 

Prøvde først å bare laste over den eksisterende Arduinokoden jeg hadde men det virket ikke helt... Litt småleting og jeg endret WiFi bibliotek fra WiFiNINA.h til WiFi.h og endret seriell overvåker fra 9600 til 115200 baud, det var det hele 👍 (og trykk på "BOOT" må til for det meste når koden skal lastes ned på ESPen, det slipper en på Ardino).

 

Fant en fin side her: https://dronebotworkshop.com/esp32-intro/ som bl.a. sier dette om ESP32 vs Arduino:

Sitat

It’s time to move beyond the Arduino and work with a more modern microcontroller. Today we will get started with the popular ESP32.

hqdefault.jpg
 

Introduction

When we think about using a microcontroller for a project we usually consider an Arduino. It’s inexpensive, easy to use and has a generous number of digital I/O ports, and a few analog inputs as well.

But the Arduino, for all of its wonderful benefits, is lacking in a number of areas. The first one is speed, the popular Arduino AVR series of boards run at 16 MHz. That’s certainly fast enough to build thousands of applications, but it’s a bottleneck for others.

The Arduino certainly has enough digital outputs and inputs to satisfy most requirements, and its analog inputs are also useful. But adding features like WiFi and Bluetooth requires external components.

Let’s face it, the Arduino has been around since 2005. That’s fifteen years, which in terms of technology is eons. 

The Arduino is well-loved here in the DroneBot Workshop and I’ll continue to use it for many projects and experiments. But I also feel that it’s time to explore other microcontrollers.

 

Ser ut til å bli mer ESP32 framover... og gjerne knotte mer Python framover og... ESP32 skal kunne kjøre Python greit og det kan ikke Arduino.

Endret av SveinHa
  • Like 1
  • 0
Skrevet

ESP32 kjører MicroPython greit, men det går betydelig kjappere med C++. :)

... men det er selvfølgelig avhengig av hva du skal gjøre.

 

Liker at ESP32 er to-kjernet, så kan man samle og tolke data med en kjerne, og laste opp med en annen. :D 

  • Like 1

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
Svar på spørsmålet...

×   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.