Skip to content

Basic v1 Bring Up Code ThingSpeak

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

Overview

The original CWX 1 –  STEM SDK IoT (Compact Weather Station), contained 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 ThingSpeak
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 Channel ID and Write API Key.
 

ThingSpeak Account and Channel

ThingSpeak is an Internet of Things Cloud based mechanism to easily take data from IoT devices and then display graphs, plots, meters etc. to users on computers, tables and phone apps. You can also interface to Google , Alexa etc.

You can learn more at a later date but ThingSpeak also allows you to make rules on sensor data and take action based on that.  This could be to send a message on a set alert etc.

 

 

You will need to

    • Create a FREE ThingSpeak account (this proves four free channels - each with eight fields)
    • Create a new Channel.   (These can be found 'MyChannels').
    • Enter the Fields as shown below. (These are located on the Channels Settings tab).
    • Enter your ThingSpeak ChannelNumber = Channel ID and WriteAPIKey = Write API Key, in the sample code.  (These can be found on the APIKeys tab).
    • If you wish your readings to be viewable to the public, change the Channel Sharing options (i.e. Share channel view with everyone).

 

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 ThingSpeak in the search. Click install the ThingSpeak by MathWorks.
      • 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.

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!

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.

 

Example Code

This code is an example, with an output as seen on the GB3FW page.  Please feel free to download this and update as needed.

The code includes some preamble to assist learning and diagnosis.

You will need to add sleep modes to this code in order to conserve 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='1680']

/*
  Dave Williams, DitroniX 2019-2022 (ditronix.net)
  CWX 12S Compact Weather Station ESP12S SDK
  PCA v2202-104 - Test Code Firmware 1.220318 - 18th March 2022

As used on SCART ATV Group - GB3FW CWX 12S Compact Weather Station.

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.

Note: SLEEP is not enabled in this Basic Bring Up Code Example */

#include "Arduino.h" #include <ESP8266WiFi.h> #include "ThingSpeak.h" #include "Wire.h" #include <Adafruit_BME280.h> #include <Adafruit_Sensor.h> #include "uptime_formatter.h" // https://github.com/YiannisBourkelis/Uptime-Library

// ######### 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.220318"; String AppBuild = "DitroniX CWX 12S SDK PCA v2202-104"; String AppName = "GB3FW Compact Weather Station";

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

// ThingSpeak unsigned long myChannelNumber = xxxx; const char * myWriteAPIKey = "xxxx";
unsigned long timerDelay = 60; // Every 1 mins

// Variables char SensorResult[10]; float SensorRAW; float TemperatureC; float Humidity; int Pressure; int LightMeter;

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

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

// **************** OUTPUTS **************** #define LED_Status 2 // Define ESP Output Port LED (This is dev use only and is inverted)

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

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

void scan_i2c_devices() { // 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)."); }

void InitialiseWLAN() {

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

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

  WiFi.mode(WIFI_STA); 
  WiFi.setAutoReconnect(true);
  WiFi.persistent(true);
  
  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("");

  // Stabalise
  delay(5000);  
  
  // Initialise ThingSpeak Connection
  ThingSpeak.begin(client);  // Initialize ThingSpeak
  Serial.println("Initialised ThingSpeak");
      
  }

}

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

// ######### 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);    

// WLAN
InitialiseWLAN();

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

Serial.println(""); 

}

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

// Get 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);
ThingSpeak.setField(1, SensorResult);    
    
// Get Humity % and round to no decimal places
Humidity = round(bme.readHumidity());
dtostrf(Humidity,5,0,SensorResult);      
Serial.print("Humidity (%): ");
Serial.println(SensorResult);
ThingSpeak.setField(2, SensorResult);    

// Get Pressure and round to no decimal places
Pressure = (bme.readPressure() / 100.0F);
Pressure = round(Pressure);
Serial.print("Pressure (hPa): ");
Serial.println(Pressure);
ThingSpeak.setField(3, Pressure);    

// Get Light Reading
LightMeter = analogRead(ADC);
Serial.print("Light: ");    
Serial.print(LightMeter ); // data output from the photoresistor (0-1024)
Serial.println("");    
ThingSpeak.setField(4, LightMeter );
   
// Update ThingSpeak
ThingSpeak.setStatus(AppVersion + " Last: " + uptime_formatter::getUptime());
Serial.println("System Uptime " + uptime_formatter::getUptime()); 

// Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
// pieces of information in a channel.  Here, we write to field 1.
int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

if(x == 200)
{
  Serial.print ("Channel ");
  Serial.println(String(myChannelNumber) + " update successful.");
  Serial.println("");
} else {      
  Serial.println("Problem updating channel. HTTP error code " + String(x));      
  Serial.println("Restarting ESP .... ");
  ESP.restart();

 }

 // Hearbeat LED    digitalWrite(LED_Status, LOW); // turn the LED on (HIGH is the voltage level)     delay(500); // wait for a second    digitalWrite(LED_Status, HIGH); // turn the LED off by making the voltage LOW

   // Loop Delay     delay(timerDelay * 1000); }