After receiving the sensecap K1100 kit from seed, I try all of the modules capability. And fortunately I have a Xiao RP2040 and an extra lora e5 module.
With these module in mind I will try to make a sensor node that transmit environment data via P2P protocol.
In this project I also use the Xiao grove shield as the grove expander and make the project more neat.
The lora node transmitter consist of two grove sensor which is SGP30 grove sensor and SHT40 grove sensor. These sensors have the capability to sense the air quality and Temperature Humidity.
before going further make sure to install these libraries and the board definition for the xiao RP2040 using the links below:
- SGP30 library
- SHT40 library
- RP2040 board definition from earlephilhower
- One last library called sensirion core can be installed from library manager
The connection is fairly simple, just daisy chain the module using the I2C port And you're good to go.
Then you just need to upload this code
#include <Arduino.h>
#include <SoftwareSerial.h>
#include "sensirion_common.h"
#include "sgp30.h"
#include <SensirionI2CSht4x.h>
#include <Wire.h>
SoftwareSerial e5(D1, D2);
SensirionI2CSht4x sht4x;
static char recv_buf[512];
static bool is_exist = false;
static int at_send_check_response(char *p_ack, int timeout_ms, char *p_cmd, ...)
{
int ch = 0;
int index = 0;
int startMillis = 0;
va_list args;
memset(recv_buf, 0, sizeof(recv_buf));
va_start(args, p_cmd);
e5.printf(p_cmd, args);
Serial.printf(p_cmd, args);
va_end(args);
delay(200);
startMillis = millis();
if (p_ack == NULL)
{
return 0;
}
do
{
while (e5.available() > 0)
{
ch = e5.read();
recv_buf[index++] = ch;
Serial.print((char)ch);
delay(2);
}
if (strstr(recv_buf, p_ack) != NULL)
{
return 1;
}
} while (millis() - startMillis < timeout_ms);
return 0;
}
static int node_send(uint32_t timeout)
{
static uint16_t count = 0;
int ret = 0;
char data[32];
char cmd[128];
s16 err = 0;
u16 tvoc_ppb, co2_eq_ppm;
err = sgp_measure_iaq_blocking_read(&tvoc_ppb, &co2_eq_ppm);
if (err == STATUS_OK) {
Serial.print("tVOC Concentration:");
Serial.print(tvoc_ppb);
Serial.println("ppb");
Serial.print("CO2eq Concentration:");
Serial.print(co2_eq_ppm);
Serial.println("ppm");
} else {
Serial.println("error reading IAQ values\n");
}
uint16_t error;
char errorMessage[256];
float temperature;
float humidity;
error = sht4x.measureHighPrecision(temperature, humidity);
if (error) {
Serial.print("Error trying to execute measureHighPrecision(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("Temperature:");
Serial.print(temperature);
Serial.print("\t");
Serial.print("Humidity:");
Serial.println(humidity);
}
memset(data, 0, sizeof(data));
sprintf(data, "%04X,%04X,%04X,%04X", tvoc_ppb, co2_eq_ppm, int(temperature),int(humidity));
sprintf(cmd, "AT+TEST=TXLRPKT,\"5345454544%s\"\r\n", data);
ret = at_send_check_response("TX DONE", 2000, cmd);
if (ret == 1)
{
//send Airquality
Serial.print("Sent successfully!\r\n");
}
else
{
Serial.print("Send failed!\r\n");
}
return ret;
}
void setup(void)
{
s16 err;
u16 scaled_ethanol_signal, scaled_h2_signal;
Serial.begin(115200);
// while (!Serial);
e5.begin(9600);
uint16_t error;
char errorMessage[256];
sht4x.begin(Wire);
uint32_t serialNumber;
error = sht4x.serialNumber(serialNumber);
if (error) {
Serial.print("Error trying to execute serialNumber(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("Serial Number: ");
Serial.println(serialNumber);
}
while (sgp_probe() != STATUS_OK) {
Serial.println("SGP failed");
while (1);
}
while (sgp_probe() != STATUS_OK) {
Serial.println("SGP failed");
while (1);
}
/*Read H2 and Ethanol signal in the way of blocking*/
err = sgp_measure_signals_blocking_read(&scaled_ethanol_signal,
&scaled_h2_signal);
if (err == STATUS_OK) {
Serial.println("get ram signal!");
} else {
Serial.println("error reading signals");
}
err = sgp_iaq_init();
Serial.print("ping pong communication!\r\n");
if (at_send_check_response("+AT: OK", 100, "AT\r\n"))
{
is_exist = true;
at_send_check_response("+MODE: TEST", 1000, "AT+MODE=TEST\r\n");
at_send_check_response("+TEST: RFCFG", 1000, "AT+TEST=RFCFG,866,SF12,125,12,15,14,ON,OFF,OFF\r\n");
delay(200);
}
else
{
is_exist = false;
Serial.print("No E5 module found.\r\n");
}
}
void loop(void)
{
if (is_exist)
{
//node_send_then_recv(2000);
node_send(2000);
delay(3000);
}
}
To try this node I am gonna use P2P protocol with the wio terminal as the data receiver. Plug another lora e5 module to the right grove port of the wio terminal and upload this code
#include <Arduino.h>
#include"TFT_eSPI.h"
#include <SoftwareSerial.h>
SoftwareSerial e5(0, 1);
static char recv_buf[512];
static bool is_exist = false;
TFT_eSPI tft;
TFT_eSprite spr = TFT_eSprite(&tft); //sprite
static int at_send_check_response(char *p_ack, int timeout_ms, char *p_cmd, ...)
{
int ch = 0;
int index = 0;
int startMillis = 0;
va_list args;
memset(recv_buf, 0, sizeof(recv_buf));
va_start(args, p_cmd);
e5.printf(p_cmd, args);
Serial.printf(p_cmd, args);
va_end(args);
delay(200);
startMillis = millis();
if (p_ack == NULL)
{
return 0;
}
do
{
while (e5.available() > 0)
{
ch = e5.read();
recv_buf[index++] = ch;
Serial.print((char)ch);
delay(2);
}
if (strstr(recv_buf, p_ack) != NULL)
{
return 1;
}
} while (millis() - startMillis < timeout_ms);
return 0;
}
static int recv_prase(void)
{
char ch;
int index = 0;
memset(recv_buf, 0, sizeof(recv_buf));
while (e5.available() > 0)
{
ch = e5.read();
recv_buf[index++] = ch;
Serial.print((char)ch);
delay(2);
}
if (index)
{
char *p_start = NULL;
char data[32] = {
0,
};
int rssi = 0;
int snr = 0;
p_start = strstr(recv_buf, "+TEST: RX \"5345454544");
if (p_start)
{
spr.fillSprite(TFT_BLACK);
p_start = strstr(recv_buf, "5345454544");
if (p_start && (1 == sscanf(p_start, "5345454544%s,", data)))
{
data[16] = 0;
int tvoc;
int co2;
int temp;
int humi;
char *endptr;
char *endptr1;
char *endptr2;
char *endptr3;
char datatvoc[5] = {data[0], data[1],data[2], data[3]};
char dataco2[5] = {data[4], data[5], data[6], data[7]};
char datatemp[5] = {data[8], data[9], data[10], data[11]};
char datahumi[5] = {data[12], data[13],data[14], data[15]};
tvoc = strtol(datatvoc, &endptr, 16);
co2 = strtol(dataco2, &endptr1, 16);
temp = strtol(datatemp, &endptr, 16);
humi = strtol(datahumi, &endptr1, 16);
spr.createSprite(100, 30);
spr.setFreeFont(&FreeSansBoldOblique12pt7b);
spr.setTextColor(TFT_WHITE);
spr.drawNumber(tvoc, 0, 0, 1);
spr.pushSprite(15, 100);
spr.deleteSprite();
spr.createSprite(150, 30);
spr.setFreeFont(&FreeSansBoldOblique12pt7b);
spr.setTextColor(TFT_WHITE);
spr.drawNumber(co2, 0, 0, 1);
spr.pushSprite(150, 100);
spr.deleteSprite();
spr.createSprite(150, 30);
spr.setFreeFont(&FreeSansBoldOblique12pt7b);
spr.setTextColor(TFT_WHITE);
spr.drawNumber(temp, 0 , 0 , 1);
spr.pushSprite(180, 185);
spr.deleteSprite();
spr.createSprite(100, 30);
spr.setFreeFont(&FreeSansBoldOblique12pt7b);
spr.setTextColor(TFT_WHITE);
spr.drawNumber(humi, 0, 0, 1);
spr.pushSprite(15, 185);
spr.deleteSprite();
Serial.print("data received displaying on the wio terminal");
Serial.print("\r\n");
}
p_start = strstr(recv_buf, "RSSI:");
if (p_start && (1 == sscanf(p_start, "RSSI:%d,", &rssi)))
{
String newrssi = String(rssi);
Serial.print(rssi);
Serial.print("\r\n");
}
p_start = strstr(recv_buf, "SNR:");
if (p_start && (1 == sscanf(p_start, "SNR:%d", &snr)))
{
Serial.print(snr);
Serial.print("\r\n");
}
return 1;
}
}
return 0;
}
static int node_recv(uint32_t timeout_ms)
{
at_send_check_response("+TEST: RXLRPKT", 1000, "AT+TEST=RXLRPKT\r\n");
int startMillis = millis();
do
{
if (recv_prase())
{
return 1;
}
} while (millis() - startMillis < timeout_ms);
return 0;
}
void setup(void)
{
tft.begin();
tft.setRotation(3);
Serial.begin(115200);
// while (!Serial);
e5.begin(9600);
Serial.print("Receiver\r\n");
tft.fillScreen(TFT_BLACK);
tft.setFreeFont(&FreeSansBoldOblique12pt7b);
tft.setTextColor(TFT_RED);
tft.drawString("TVoC", 7 , 65 , 1);
tft.drawString("CO2", 165 , 65 , 1);
tft.setFreeFont(&FreeSansBoldOblique12pt7b);
tft.setTextColor(TFT_RED);
tft.drawString("Humi", 7 , 150 , 1);
tft.setFreeFont(&FreeSansBoldOblique12pt7b);
tft.setTextColor(TFT_RED);
tft.drawString("Temp:", 165 , 150 , 1);
tft.setFreeFont(&FreeSansBoldOblique18pt7b);
tft.setTextColor(TFT_WHITE);
tft.drawString("E5 Receiver", 50, 10 , 1);
if (at_send_check_response("+AT: OK", 100, "AT\r\n"))
{
is_exist = true;
at_send_check_response("+MODE: TEST", 1000, "AT+MODE=TEST\r\n");
at_send_check_response("+TEST: RFCFG", 1000, "AT+TEST=RFCFG,866,SF12,125,12,15,14,ON,OFF,OFF\r\n");
delay(200);
}
else
{
is_exist = false;
Serial.print("No E5 module found.\r\n");
}
}
void loop(void)
{
if (is_exist)
{
node_recv(2000);
}
}
I also printed a plate for the xiao transmitter lora node and this is the result
Comments