Skip to content

Basic v1 Bring Up Code MQTT

Dave Williams | DitroniX | G8PUO edited this page Jan 12, 2023 · 1 revision

This CWX-1 Basic Bring Up Code (ThingSpeak), Wiki page, provides basic information to connect your computer to the CWX-1 and then flash some sample code which will read the sensors and update to Domoticz via MQTT.

 

Overview

The original CWX 1 –  STEM SDK IoT (Compact Weather Station), contains a compact BME280 sensor which provides three readings, namely.

  • Barometric Pressure
  • Temperature
  • Humidity
In addition, a SFH2440 Ambient Light Sensor is fitted to measure ambient light level.
  • Light Level
These two sensors interface to an ESP-12S Series WiFi module, based on ESP8266 with built-in Flash.  The BME280 is connected to the I2C bus and the SFH2440 connects to the ESP's built-in ADC.

 

Programming / Flashing UART Control

In order to ease programming, a simple two transistor circuit is added to the board which when connected to a USB to UART module, allows the host computer to control the DTR = Reset, and RTS = Boot Mode.  This makes recompiling and flashing so much simpler as you have no button pressing.

Our USB to UART module has both of these connections.

 

Code Summary

The example bring up code will:

  • Setup the ESP prerequisites
  • Initialise WLAN
  • Initialise ThingSpeak Account / Channel
  • Initialise I/O
  • Loop (once every minute)
    • Read Temperature
    • Read Humidity
    • Read Pressure
    • Read Light
    • Update Domoticz via MQTT
Note:
  • This bring-up example code does not enable power saving or sleep.
  • You will need to enter your WiFi SSID and Password.
  • You will need to enter your MQTT Server IP address and any login details.
 

Domoticz

https://www.domoticz.com/wiki/MQTT

 

Arduino IDE Setup

Once your ThingSpeak account and channel is configured, you can then load the example code into the Arduio IDE, Compile and Flash to the ESP.   The code has been annotated to be helpful in working through and should hopefully make sense.

Should you not have Arduino IDE installed, it can be easily downloaded for Windows, Ubuntu, Linux, Mac etc via

Before you can compile the code, you will need to add the ESP8266 board and Libraries to the Arduino IDE.  Open Arduino IDE.

  • Board Manager
    • Tools > Board > Board Manager
      • type ESP8266 in the search.  Click install the ESP8266 Community.
    • Tools > Board > ESP8266 Boards. Select Generic ESP8266 Module.
    • Tools > Manage Libraries.  This will open the Library Manager.
      • type PubSubClient in the search. Click install the PubSubClient by Nick O'Leary
      • type BME280 in the search. Click install the Adafruit BME280 Library
      • type Uptime in the search. Click install the Uptime Library by Yiannis Bourkelis
Your Arduino IDE should now be setup to load the example code and successfully flash to the CWX.

 

Example Code

The below example is the CWX connected to the USB to UART. (Ignore the switch, which was used in development).

Ensure the header is plugged into the CWX the correct way round!

You will need to add sleep modes to this code in order to conserve power.

Note: DO NOT connect the battery during programming - as the battery is not isolated from the programming header 3V3.  Your CWX will totally flash and run from the UART, with no external power.

 

Remember, the Arduino IDE has a Serial Debug Monitor built in.  If you select this, it will display the printed output in a separate window.   See Tools > Serial Monitor.  (CTRL+SHIFT+M)

 

[wpdm_package id='1899']

 

/*
  Dave Williams, DitroniX 2019-2022 (ditronix.net)
  CWX 12S Compact Weather Station ESP12S SDK
  PCA v2204-106 - CWX-1_1.220406_Basic_Bring_Up_Test_Code_MQTT Firmware 1.220406 - 6th April 2022

CWX-1 Compact Weather Station - MQTT Basic Test Code for Domoticz - No Sleep Version - subscribe("domoticz/in")

The purpose of this test code is to cycle through the various main functions of the board as part of bring up testing.

This test code is OPEN SOURCE and although is is not intended for real world use, it may be freely used, or modified as needed. */

#include "Arduino.h" #include <ESP8266WiFi.h> #include <PubSubClient.h> // Search PubSubClient in Library (http://pubsubclient.knolleary.net/) #include "Wire.h" #include <Adafruit_BME280.h> #include <Adafruit_Sensor.h>

// ######### OBJECTS ######### Adafruit_BME280 bme; //BME280 connect to ESP8266 I2C (GPIO 4 = SDA, GPIO 5 = SCL) // BME280 0x76 | BMP280 0x76 | BMP180 0x77

// ######### VARIABLES / DEFINES / STATIC #########

// App String AppVersion = "v1.220406"; String AppBuild = "DitroniX CWX 12S SDK PCA v2204-106"; String AppName = "CWX Compact Weather Station - MQTT Test - No Sleep";

// WLAN WiFiClient espclient; const char* ssid = "xxx"; // network SSID (name) const char* password = "xxx"; // network password const uint32_t connectTimeoutMs = 5000; // WiFi connect timeout per AP. Increase when connecting takes longer. byte macaddress[6];

// MQTT PubSubClient client(espclient); const uint8_t mqtt_server[] = {192, 168, 0, 10}; // MQTT Server IP Address const char* mqttUser = ""; // MQTT User - if applicable const char* mqttPassword = ""; // MQTT Password - if applicable unsigned long timerDelay = 5; // Every 1 mins

// Variables char SensorResult[10]; float SensorRAW;

// **************** IO ****************

// Define I2C (Expansion Port) #define I2C_SDA 4 #define I2C_SCL 5

// **************** OUTPUTS **************** #define LED_Status 2 // Define ESP Output Port LED

// **************** INPUTS **************** #define ADC A0 // Define ADC (0 DC - 1V DC)

// ######### FUNCTIONS #########

// Scan I2C Devices void scan_i2c_devices() { Serial.print("Scanning I2C\t"); byte count = 0; Serial.print("Found Devices: "); Serial.print(" Devices: "); for (byte i = 8; i < 120; i++) { Wire.beginTransmission(i); if (Wire.endTransmission() == 0) { Serial.print(" (0x"); Serial.print(i, HEX); Serial.print(")\t"); count++; delay(1); } }
Serial.print("Found "); Serial.print(count, HEX); Serial.println(" Device(s)."); }

// Initialise WLAN void InitialiseWLAN() {

WiFi.mode(WIFI_STA); 

if(WiFi.status() != WL_CONNECTED){  // Connect or reconnect to WiFi
  Serial.println("Attempting to connect to SSID: " + String(ssid));

  WiFi.begin(ssid, password); 
  
  // Let Stabalise
  delay(5000);     

  WiFi.setAutoReconnect(true);
  WiFi.persistent(false);
  
  Serial.println("WLAN SSID \t " + String(ssid)) + "(Wifi Station Mode)";
  Serial.printf("WLAN IP \t %s\n", WiFi.localIP().toString().c_str()); 
  Serial.printf("WLAN GW \t %s\n", WiFi.gatewayIP().toString().c_str());
  Serial.printf("WLAN MASK \t %s\n", WiFi.subnetMask().toString().c_str());
  Serial.println("WLAN MAC \t " + WiFi.macAddress());
  Serial.println("");
  }

}

// Initialise Temperature Sensor void InitialiseTemperatureSensor(){ // BME280 if (!bme.begin(0x76)) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); // while (1); } }

// MQTT Callback void callback(char* topic, byte* message, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); String messageTemp;

for (int i = 0; i &lt; length; i++) {
  Serial.print((char)message[i]);
  messageTemp += (char)message[i];
}
Serial.println(); 

}

void ReconnectMQTT() {

// WLAN
if(WiFi.status() != WL_CONNECTED){
  InitialiseWLAN(); 
  }

    // Stabalise
  delay(1000);  
  
  // Initialise MQTT Connection
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Serial.println("Initialised MQTT");
        
// Loop until we're reconnected
while (!client.connected()) {
  Serial.print("Attempting MQTT connection...");
  // Attempt to connect
  if (client.connect("espclient")) {
    Serial.println("    MQTT Connected &amp; Subscribing");
    Serial.println(""); 
    // Subscribe
    client.subscribe("domoticz/in");  //Topic
  } else {
    Serial.print("      MQTT Failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
    // Wait 5 seconds before retrying
    delay(5000);
  }
}

}

// ######### SETUP ######### void setup() {

//Stabalise
delay(500);   

// Initialize UART:
Serial.begin(115200, SERIAL_8N1);  //115200  
while (!Serial);
Serial.println(""); 
Serial.println(AppVersion + " Initialized");
Serial.println(AppBuild);
Serial.println(AppName);
Serial.println(""); 

// LED
pinMode(LED_Status, OUTPUT);    

// Initialize I2C 
Wire.begin(I2C_SDA, I2C_SCL);
scan_i2c_devices();    
InitialiseTemperatureSensor();

// WLAN
if(WiFi.status() != WL_CONNECTED){InitialiseWLAN();}
Serial.println(""); 

}

// ######### LOOP ######### void loop() {

// MQTT
if (!client.connected()) { 
  ReconnectMQTT(); 
} else {

  // WLAN Info
  Serial.printf("WLAN IP \t %s   MQTT Connected\n", WiFi.localIP().toString().c_str()); 
      
  // Temperature ºC and round to 1 decimal place
  SensorRAW = bme.readTemperature();
  dtostrf (SensorRAW, 5, 1, SensorResult);
  sprintf (SensorResult, "%s", SensorResult);
  Serial.print("Temperature (ºC): ");  Serial.println(SensorResult);
  client.publish("cwx/temperature", SensorResult);
      
  // Humity % and round to no decimal places
  SensorRAW = round(bme.readHumidity()); 
  dtostrf(SensorRAW,5,0,SensorResult);      
  Serial.print("Humidity (%): ");   Serial.println(SensorResult);
  client.publish("cwx/humidity", SensorResult);    
  
  // Pressure and round to no decimal places
  SensorRAW = (bme.readPressure() / 100.0F);
  dtostrf(SensorRAW,5,0,SensorResult); 
  Serial.print("Pressure (hPa): "); Serial.println(SensorResult);
  client.publish("cwx/pressure", SensorResult);  
  
  // Light Reading
  SensorRAW = analogRead(ADC);
  dtostrf(SensorRAW,5,0,SensorResult);
  Serial.print("Light: ");  Serial.print(SensorResult ); 
  Serial.println("");    
  client.publish("cwx/lightmeter", SensorResult);  
     
  Serial.println(""); 
  }
        
// Hearbeat LED
digitalWrite(LED_Status, LOW);   // turn the LED on (HIGH is the voltage level)
delay(250);                       // wait for a second
digitalWrite(LED_Status, HIGH);    // turn the LED off by making the voltage LOW

// Loop Delay
delay(timerDelay * 1000);

}