This project will guide you through setting up a cellular weather station using the Lark Weather Station kit, which will collect environmental data and integrate it with Qubitro for real-time monitoring and automation.
- Lark Weather Station Kit:The Lark Weather Station Kit is an all-in-one, portable educational weather device that simplifies atmospheric data collection and is compatible with popular development boards like Arduino, micro:bit, and ESP32.
- BeetleMicrocontroller: The Beetle ESP32 C6 is a coin-sized, low-power IoT development board with a 160MHz RISC-V processor, supporting Wi-Fi 6, Bluetooth 5, Zigbee 3.0, and Thread 1.3 protocols for versatile connectivity options.
- BluesIoT: Blues offers a seamless device-to-cloud experience with JSON-based APIs, and the ability to send data from any device to any cloud without the hassle of AT commands
- Qubitro Cloud: Qubitro is a developer-friendly, end-to-end cloud platform designed for building and operating scalable IoT experiences, enabling efficient device data collection, processing, and activation.
- Connect the Beetle ESP32-C6 with the LARK kit via the Gravity connector cable.
- Then connect the development board to your computer using a micro-USB cable.
- Open the Arduino IDE and select the appropriate board and port from the Tools menu.
- Next, we must install the LARK libraries to communicate with the Lark via Beetle ESP32-C6.
Lark Weather Station Public library
- After the library installation, you can see the demo sketch in the examples folder.
- Let's upload the GET DATA sketch to the Beetle ESP32 C6 and verify the serial terminal response.
NOTE: Change the Mode switch from 1 to 0 in the sketch to enable the I2C communication
#include "DFRobot_LarkWeatherStation.h"
#if defined(ARDUINO_AVR_UNO) || defined(ESP8266)
#include <SoftwareSerial.h>
#endif
#define DEVICE_ADDR 0x42
#define MODESWITCH /*UART:*/ 1 /*I2C: 0*/
#if MODESWITCH
#if defined(ARDUINO_AVR_UNO) || defined(ESP8266)
SoftwareSerial mySerial(/*rx =*/4, /*tx =*/5);
DFRobot_LarkWeatherStation_UART atm(&mySerial);
#else
DFRobot_LarkWeatherStation_UART atm(&Serial1);
#endif
#else
DFRobot_LarkWeatherStation_I2C atm(DEVICE_ADDR, &Wire);
#endif
void setup(void) {
#if MODESWITCH
//Init MCU communication serial port
#if defined(ARDUINO_AVR_UNO) || defined(ESP8266)
mySerial.begin(115200);
#elif defined(ESP32)
Serial1.begin(115200, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
Serial1.begin(115200);
#endif
#endif
Serial.begin(115200);
while (atm.begin() != 0) {
Serial.println("init error");
delay(1000);
}
Serial.println("init success");
atm.setTime(2024, 6, 10, 23, 59, 0);
}
void loop(void) {
Serial.println("----------------------------");
Serial.print(atm.getValue("Temp"));
Serial.println(atm.getUnit("Temp"));
Serial.print(atm.getValue("Humi"));
Serial.println(atm.getUnit("Humi"));
Serial.print(atm.getValue("Speed"));
Serial.println(atm.getUnit("Speed"));
Serial.println(atm.getValue("Dir"));
Serial.print(atm.getValue("Altitude"));
Serial.println(atm.getUnit("Altitude"));
Serial.print(atm.getValue("Pressure"));
Serial.println(atm.getUnit("Pressure"));
Serial.println("----------------------------");
Serial.println(atm.getInformation(true));
delay(100);
}
Here is the serial terminal response:
The next step is to add one more sensor to collect more environmental data on the Beetle ESP32 C6. For this, we will use the multipurpose environmental sensor from DFRobot.
This sensor can collect temperature, humidity, barometric pressure, altitude, ultraviolet intensity, and ambient light intensity. This is a perfect combination to integrate into our application.
Here is the demo sketch that can read the data from the environmental sensor and print it via the serial terminal.
#include "DFRobot_EnvironmentalSensor.h"
DFRobot_EnvironmentalSensor environment(SEN050X_DEFAULT_DEVICE_ADDRESS,&Wire);
int led = 15;
void setup() {
Serial.begin(115200);
pinMode(led, OUTPUT);
while (environment.begin() != 0) {
Serial.println(" Sensor initialize failed!!");
delay(1000);
}
Serial.println(" Sensor initialize success!!");
}
void loop() {
//Print the data obtained from sensor
Serial.println("-------------------------------");
Serial.print("Temp: ");
Serial.print(environment.getTemperature(TEMP_C));
Serial.println("C");
Serial.print("Temp: ");
Serial.print(environment.getTemperature(TEMP_F));
Serial.println("F");
Serial.print("Humidity: ");
Serial.print(environment.getHumidity());
Serial.println(" %");
Serial.print("Ultraviolet intensity: ");
Serial.print(environment.getUltravioletIntensity());
Serial.println(" mw/cm2");
Serial.print("LuminousIntensity: ");
Serial.print(environment.getLuminousIntensity());
Serial.println(" lx");
Serial.print("Atmospheric pressure: ");
Serial.print(environment.getAtmospherePressure(HPA));
Serial.println(" hpa");
Serial.print("Altitude: ");
Serial.print(environment.getElevation());
Serial.println(" m");
Serial.println("-------------------------------");
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
Here is the Arduino serial terminal response:
You can see the temperature, humidity, barometric pressure, altitude, ultraviolet intensity, and ambient light intensity.
3️⃣Blues IoT Integration with Beetle ESP32 C6:Now our Beetle can read all our weather station data as well as environmental data. The next thing is to relay our data to the cloud servers. For this purpose, we can utilize the Blues to send our data to the cloud.
Blues devices can be connected via both UART as well as I2C, In this demo we can utilize the I2C for easy integration.
Once the hardware setup is done, just navigate to the Notehub | Projects and create a new project.
Just copy the ProductUID, we need to use this in our Beetle ESP32 C6 to communicate with the Notehub.
Here is a simple sketch that can communicate the Beetle ESP32 C6 with Blues Notehub.
#include <Notecard.h>
#define usbSerial Serial
#define PRODUCT_UID "com.gmail.pradeeplogu26:cellular_weather_station" // "com.my-company.my-name:my-project"
#define myProductID PRODUCT_UID
Notecard notecard;
void setup()
{
usbSerial.begin(115200);
const size_t usb_timeout_ms = 3000;
for (const size_t start_ms = millis(); !usbSerial && (millis() - start_ms) < usb_t imeout_ms;)
;
notecard.setDebugOutputStream(usbSerial);
notecard.begin();
J *req = notecard.newRequest("hub.set");
if (myProductID[0])
{
JAddStringToObject(req, "product", myProductID);
}
JAddStringToObject(req, "mode", "continuous");
notecard.sendRequestWithRetry(req, 5); // 5 seconds
}
void loop()
{
J *req = notecard.newRequest("note.add");
if (req != NULL)
{
JAddBoolToObject(req, "sync", true);
J *body = JAddObjectToObject(req, "body");
if (body != NULL)
{
JAddNumberToObject(body, "temp", 10);
JAddNumberToObject(body, "voltage", 20);
JAddNumberToObject(body, "count", 30);
}
notecard.sendRequest(req);
}
// Delay between samples
delay(15 * 1000); // 15 seconds
}
Here is the serial terminal response from the Arduino IDE.
And below you can see the response from the Blues Notehub.
Here is the complete sketch that can send our sensor data to Blues Notehub.
#include <Notecard.h>
#include <stdlib.h>
#include "DFRobot_EnvironmentalSensor.h"
#include "DFRobot_LarkWeatherStation.h"
#define usbSerial Serial
#define PRODUCT_UID "com.gmail.pradeeplogu26:cellular_weather_station" // "com.my-company.my-name:my-project"
#define myProductID PRODUCT_UID
DFRobot_EnvironmentalSensor environment(/*addr = */ SEN050X_DEFAULT_DEVICE_ADDRESS, /*pWire = */ &Wire);
int led = 15;
#define DEVICE_ADDR 0x42
DFRobot_LarkWeatherStation_I2C atm(DEVICE_ADDR, &Wire);
Notecard notecard;
void setup() {
usbSerial.begin(115200);
pinMode(led, OUTPUT);
while (atm.begin() != 0) {
Serial.println("init error");
delay(1000);
}
while (environment.begin() != 0) {
usbSerial.println(" Sensor initialize failed!!");
delay(1000);
}
usbSerial.println(" Sensor initialize success!!");
const size_t usb_timeout_ms = 3000;
for (const size_t start_ms = millis(); !usbSerial && (millis() - start_ms) < usb_timeout_ms;)
;
notecard.setDebugOutputStream(usbSerial);
notecard.begin();
J* req = notecard.newRequest("hub.set");
if (myProductID[0]) {
JAddStringToObject(req, "product", myProductID);
}
JAddStringToObject(req, "mode", "continuous");
notecard.sendRequestWithRetry(req, 5); // 5 seconds
}
void loop() {
digitalWrite(led, HIGH);
delay(10);
digitalWrite(led, LOW);
delay(10);
//Print the data obtained from sensor
usbSerial.println("-----------------------------------------------------------------------");
usbSerial.println("----------------Cellular Weather Station with LARK---------------------");
usbSerial.println("-----------------------------------------------------------------------");
Serial.println(atm.getTimeStamp());
usbSerial.print("Temp: ");
usbSerial.print(environment.getTemperature(TEMP_C));
usbSerial.println("C");
usbSerial.print("Temp: ");
usbSerial.print(environment.getTemperature(TEMP_F));
usbSerial.println("F");
usbSerial.print("Humidity: ");
usbSerial.print(environment.getHumidity());
usbSerial.println(" %");
usbSerial.print("Ultraviolet intensity: ");
usbSerial.print(environment.getUltravioletIntensity());
usbSerial.println(" mw/cm2");
usbSerial.print("LuminousIntensity: ");
usbSerial.print(environment.getLuminousIntensity());
usbSerial.println(" lx");
usbSerial.print("Atmospheric pressure: ");
usbSerial.print(environment.getAtmospherePressure(HPA));
usbSerial.println(" hpa");
usbSerial.print("Altitude: ");
usbSerial.print(environment.getElevation());
usbSerial.println(" m");
digitalWrite(led, HIGH);
delay(10);
digitalWrite(led, LOW);
delay(10);
usbSerial.print("Temp_Lark: ");
usbSerial.print(atm.getValue("Temp"));
usbSerial.println("C");
usbSerial.print("Humidity_Lark: ");
usbSerial.print(atm.getValue("Humi"));
usbSerial.println(" %");
usbSerial.print("Atmospheric pressure_Lark: ");
usbSerial.print(atm.getValue("Pressure"));
usbSerial.println(" hpa");
usbSerial.print("Altitude_Lark: ");
usbSerial.print(atm.getValue("Altitude"));
usbSerial.println(" m");
usbSerial.print("Wind_Speed_Lark: ");
usbSerial.print(atm.getValue("Speed"));
usbSerial.println(" m/s");
usbSerial.print("Wind_Direction_Lark: ");
usbSerial.println(atm.getValue("Dir"));
digitalWrite(led, HIGH);
delay(10);
digitalWrite(led, LOW);
delay(10);
String Temp = atm.getValue("Temp");
String Humi = atm.getValue("Humi");
String Pres = atm.getValue("Pressure");
String Alti = atm.getValue("Altitude");
String Speed = atm.getValue("Speed");
String Dir = atm.getValue("Dir");
const char* cString0 = Temp.c_str();
const char* cString1 = Humi.c_str();
const char* cString2 = Pres.c_str();
const char* cString3 = Alti.c_str();
const char* cString4 = Speed.c_str();
const char* cString5 = Dir.c_str();
JNUMBER num0 = atof(cString0);
JNUMBER num1 = atof(cString1);
JNUMBER num2 = atof(cString2);
JNUMBER num3 = atof(cString3);
JNUMBER num4 = atof(cString4);
digitalWrite(led, HIGH);
delay(10);
digitalWrite(led, LOW);
delay(10);
J* req = notecard.newRequest("note.add");
if (req != NULL) {
JAddBoolToObject(req, "sync", true);
J* body = JAddObjectToObject(req, "body");
if (body != NULL) {
JAddNumberToObject(body, "Temperature", environment.getTemperature(TEMP_C));
JAddNumberToObject(body, "Humidity", environment.getHumidity());
JAddNumberToObject(body, "UV", environment.getUltravioletIntensity());
JAddNumberToObject(body, "LUX", environment.getLuminousIntensity());
JAddNumberToObject(body, "Pressure", environment.getAtmospherePressure(HPA));
JAddNumberToObject(body, "Altitude", environment.getElevation());
JAddNumberToObject(body, "Temperature_Lark", num0);
JAddNumberToObject(body, "Humidity_Lark", num1);
JAddNumberToObject(body, "Speed_Lark", num4);
JAddStringToObject(body, "Wind_Dir_Lark", cString5);
JAddNumberToObject(body, "Pressure_Lark", num2);
JAddNumberToObject(body, "Altitude_Lark", num3);
}
notecard.sendRequest(req);
}
digitalWrite(led, HIGH);
delay(10);
digitalWrite(led, LOW);
delay(10);
// Delay between samples
delay(60 * 1000); // 15 seconds
}
Below you can see the response from the Arduino serial terminal.
Finally, you can see the complete data on Blues Notehub.
Once the data reaches Notehub, we will use Qubitro to visualize and make an alert function based on the received data.
4️⃣Qubitro Integration:Navigate to the Qubitro Portal and create a new project.
Then, select Blues as the data source.
Next, you can see the webhook credentials that we need to connect with Blues Notehub.
Let’s move on to the Blues Notehub’s route page.
Here, we have to create a new HTTP/HTTPS route and add the details as same as in the Qubitro.
Once you have enabled the route, look at the events in the Notehub.
As you can see the green tick means, all our connections are good. Next, just open the Qubitro portal and look for the devices.
Then, just navigate to the Storage tab and look for the data. Here you can see all the incoming data from the Blues device.
We can specify the data that we need. For that go to the route in Blues and at the bottom, define which data should move to Qubitro.
After the payload successfully transfers to Qubitro, open the Qubitro portal to monitor the incoming data.
We can visualize the data via the Qubitro dashboard. First, navigated to the Observability section and created a new dashboard.
Then, click on edit and added the widgets as needed.
Next, add the widget with the data points, making it straightforward to comprehend the data levels.
Then, add a standard gauge to check and visualize the alert level.
Finally, use map widgets for GPS mapping.
This was my final dashboard, which shows the location of my base station and the slave node’s status.
In this section, I added a rule function to alert users when an anomaly is detected. To do this, I navigated to the function in the Qubitro portal and then selected the rule section.
Then I created a new rule.
Here I used Webhooks. I entered all the basic details and moved to the next page.
Then, I opened the webhook site and copied the webhook URL.
Next, I pasted the URL to the Qubitro rule page.
Then I selected the conditions. For this condition, my rule will trigger when my Temperature level is greater than 33.
Below is the webhook response.
At this point, you could use Twilio or Mailgun to send a customized SMS or email to alert you.
7️⃣Solar Power SetupUtilizing renewable energy sources is not only environmentally friendly but also adds autonomy to your projects. In this section, we’ll explore how to power your weather station using a solar panel, ensuring it remains operational even in remote locations without access to the electrical grid.
✅Wrap-up:In conclusion, the blog details a comprehensive guide to setting up a cellular weather station using the Lark Weather Station kit, integrated with Qubitro for real-time monitoring and automation. The project is well-suited for enthusiasts and professionals alike, offering a hands-on approach to IoT development with a focus on environmental data collection. The use of the Beetle ESP32 C6 microcontroller, along with the Blues IoT device, provides a robust platform for data transmission to the cloud, ensuring seamless connectivity and ease of use.
Comments