Etter et par år med lua og esp8266, flytter jeg meg over i Arduino-verden igjen, det vil si – esp8266 addonen for Arduino IDE
Det finnes vesentlig flere bibliotek og større community for Arduino kode, så – intet alvorligere bak.
I de senere månedene har vi arbeidet met MQTT på jobben, så – det var naturlig for meg å benytte denne tankegangen når jeg skulle oppgradere gjæringsskapet.
//craftbeerpi mqtt fermentation chamber controller, heavily based on Erick Joaquins MQTT switch code. //modified for cbpi json payload, heater/cooler and publishing of temperature // //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient //#include #include #include #include #include
void callback(char* topic, byte* payload, unsigned int length);
//EDIT THESE LINES TO MATCH YOUR SETUP
#define MQTT_SERVER "127.0.0.1" //you MQTT IP Address const char* ssid = "replace"; const char* password = "replace";
//EJ: Data PIN Assignment on WEMOS D1 R2 https://www.wemos.cc/product/d1.html // if you are using Arduino UNO, you will need to change the "D1 ~ D4" with the corresponding UNO DATA pin number
const int switchPin1 = D1; const int switchPin2 = D5; #define OWBUS D7
//onewire setup for temperature sensor OneWire oneWire(OWBUS); DallasTemperature sensors(&oneWire); DeviceAddress tempsens;
//timer for posting temperature data - time in milliseconds unsigned long interval = 500; unsigned long previousMillis = 0; unsigned long currentMillis = millis();
//buffer for handling json payloads StaticJsonBuffer<200>; jsonBuffer;
//EJ: These are the MQTT Topic that will be used to manage the state of Relays, change for your settings
char const* switchTopic1 = "home/brewery/bay1/cool"; char const* switchTopic2 = "home/brewery/bay1/heat";
//misc
WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);
void setup_sensors(){ sensors.begin(); //Serial.println(sensors.getDeviceCount(), DEC); if (!sensors.getAddress(tempsens, 0)) Serial.println("Unable to find address for Device 0"); sensors.setResolution(tempsens, 10); }
void setup() { //initialize the switch as an output and set to HIGH (off) pinMode(switchPin1, OUTPUT); // Relay Switch 1 digitalWrite(switchPin1, HIGH); pinMode(switchPin2, OUTPUT); // Relay Switch 2 digitalWrite(switchPin2, HIGH);
ArduinoOTA.setHostname("My Arduino WEMO"); // A name given to your ESP8266 module when discovering it as a port in ARDUINO IDE ArduinoOTA.begin(); // OTA initialization
//start the serial line for debugging Serial.begin(115200); delay(100);
//start wifi subsystem WiFi.begin(ssid, password); //attempt to connect to the WIFI network and then connect to the MQTT server reconnect(); delay(100); setup_sensors(); //wait a bit before starting the main loop delay(2000); }
void loop(){ currentMillis = millis(); //reconnect if connection is lost if (!client.connected() && WiFi.status() == 3) {reconnect();}
//maintain MQTT connection client.loop(); //MUST delay to allow ESP8266 WIFI functions to run delay(10); ArduinoOTA.handle(); if ((currentMillis - previousMillis) >= interval) { postTemp(); previousMillis = currentMillis; } }
void postTemp(){ sensors.requestTemperatures(); float tempC = sensors.getTempC(tempsens); Serial.print("caling "); Serial.println(String(tempC).c_str()); client.publish("home/brewery/bay1/temperature", String(tempC).c_str(), false); }
void callback(char* topic, byte* payload, unsigned int length) { //convert topic to string to make it easier to work with String topicStr = topic; //EJ: Note: the "topic" value gets overwritten everytime it receives confirmation (callback) message from MQTT //Print out some debugging info Serial.println("Callback update."); Serial.print("Topic: "); Serial.println(topicStr); Serial.println((char *)payload);
if (topicStr == "home/brewery/bay1/cool") { String state = jsonState(payload); Serial.println((char *)payload); if(state == "on") { digitalWrite(switchPin1, LOW); client.publish("home/brewery/bay1/coolConfirm", "1"); } else if (state == "off") { digitalWrite(switchPin1, HIGH); client.publish("home/brewery/bay1/coolConfirm", "0"); } } else if (topicStr == "home/brewery/bay1/heat"){ String state = jsonState(payload); if(state == "on") { digitalWrite(switchPin2, LOW); client.publish("home/brewery/bay1/heatConfirm", "1"); } else if (state == "off") { digitalWrite(switchPin2, HIGH); client.publish("home/brewery/bay1/heatConfirm", "0"); } } jsonBuffer.clear(); }
void reconnect() {
//attempt to connect to the wifi if connection is lost if(WiFi.status() != WL_CONNECTED){ //debug printing Serial.print("Connecting to "); Serial.println(ssid);
//loop while we wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
//print out some more debug once connected Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); }
//make sure we are connected to WIFI before attemping to reconnect to MQTT if(WiFi.status() == WL_CONNECTED){ // Loop until we're reconnected to the MQTT server while (!client.connected()) { Serial.print("Attempting MQTT connection...");
// Generate client name based on MAC address and last 8 bits of microsecond counter String clientName; clientName += "esp8266-"; uint8_t mac[6]; WiFi.macAddress(mac); clientName += macToStr(mac);
//if connected, subscribe to the topic(s) we want to be notified about //EJ: Delete "mqtt_username", and "mqtt_password" here if you are not using any if (client.connect((char*) clientName.c_str(),"user", "pass")) { //EJ: Update accordingly with your MQTT account Serial.print("\tMQTT Connected"); client.subscribe(switchTopic1); client.subscribe(switchTopic2); //EJ: Do not forget to replicate the above line if you will have more than the above number of relay switches }
//otherwise print failed for debugging else{Serial.println("\tFailed."); abort();} } } }
//generate unique name from MAC addr String macToStr(const uint8_t* mac){
String result;
for (int i = 0; i < 6; ++i) { result += String(mac[i], 16);
if (i < 5){ result += ':'; } }
return result; }
String jsonState(byte* payload) { JsonObject& root = jsonBuffer.parseObject(payload); if (!root.success()) { Serial.println("parseObject() failed"); } return root["state"]; }