Morning
I'm currently building a project that sends sensor data from an SGP30 through LoRa (MKR1300) to LoRa (ESP32) out to wifi and up to Blynk (Or any other platform).
Im using IDE to create the nested object called DRONE with 4 data points on the sender node.
JsonObject data = doc.createNestedObject("DRONE");
data["CO2"] = co2;
data["TVOC"] = tvoc;
data["H2"] = h2;
data["Ethanol"] = etha;
serializeJson(doc, droneData);
Serial.println(droneData);
Then I'm trying to split / read the data back out on the receiver node
droneData = LoRa.readString();
Serial.print(droneData);
}
String droneData = LoRa.readStringUntil(':');
LoRa.read(); // Throw away the space
if (droneData.endsWith("CO2"))
String co2 = LoRa.readStringUntil(' ');
if (droneData.endsWith("TVOC"))
String tvoc = LoRa.readStringUntil(' ');
if (droneData.endsWith("H2"))
String h2 = LoRa.readStringUntil(' ');
if (droneData.endsWith("Ethanol"))
String etha = LoRa.readStringUntil(' ');
But im not getting any data stored in the strings ?.
This is the total String read as one
13:42:46.355 -> with Value Received packet 1428{"DRONE":{"CO2":0,"TVOC":0,"H2":6.713018778e10,"Ethanol":1.864621128e15}} with RSSI -37
J-M-L
February 3, 2024, 9:15am
2
it seems you have two droneData
Strings ?
Don't post snippets (Snippets R Us! )
I did REM that first string out when trying to split the data out. Just enabled it to show the full string of data J. It compiles OK but i'm missing something obvious.
Do I need to declare the values outside the loop as strings ?.
J-M-L
February 3, 2024, 9:29am
4
you need to post the full code, then we can provide meaningful information...
Ive done it from the Setup down to leave out all the passwords etc
void setup()
{
// Debug console
Serial.begin(115200);
// You can also specify server:
// Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, IPAddress(192,168,1,100), 8080);
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, "blynk.cloud", 8080);
//Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, IPAddress(192,168,1,100), 8080);
// Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, "blynk.cloud", 80);
// Setup a function to be called every second
timer.setInterval(1000L, myTimerEvent);
//reset OLED display via software
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("LORA RECEIVER ");
display.display();
Serial.println("LoRa Receiver Test");
//SPI LoRa pins
SPI.begin(SCK, MISO, MOSI, SS);
//setup LoRa transceiver module
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(BAND)) {
Serial.println("Starting LoRa failed!");
while (1);
}
Serial.println("LoRa Initializing OK!");
display.setCursor(0,10);
display.println("LoRa Initializing OK!");
display.println("");
display.display();
}
void loop()
{
Blynk.run();
timer.run();
// You can inject your own code or combine it with other sketches.
// Check other examples on how to communicate with Blynk. Remember
// to avoid delay() function!
//try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
//received a packet
Serial.print("Received packet ");
//read packet
while (LoRa.available())
{
droneData = LoRa.readString();
Serial.print(droneData);
}
String droneData = LoRa.readStringUntil(':');
LoRa.read(); // Throw away the space
if (droneData.endsWith("CO2"))
String co2 = LoRa.readStringUntil(' ');
if (droneData.endsWith("TVOC"))
String tvoc = LoRa.readStringUntil(' ');
if (droneData.endsWith("H2"))
String h2 = LoRa.readStringUntil(' ');
if (droneData.endsWith("Ethanol"))
String etha = LoRa.readStringUntil(' ');
//print RSSI of packet
int rssi = LoRa.packetRssi();
Serial.print(" with RSSI ");
Serial.println(rssi);
Serial.print(" with Value ");
Blynk.virtualWrite(V5, "0.55455");
// +++++++++++++++++++++++++++
}
}
J-M-L
February 3, 2024, 9:36am
6
please use code tags correctly - I've fixed your two posts for your but if you have a multi line code segments then use three backticks
Ok will do thanks J, I don't normally post up code and learning every day.
J-M-L
February 3, 2024, 9:38am
8
this empties the received Lora buffer
so when you try to read more
it's not going to work, there is nothing left to read.
you need to parse the data you read in the first place from the String you got
(sending a binary structure rather than a String would probably make your life easier)
J, I've parsePacket() which has given me the droneData string as a full string. But Ive Rem'd that out then to just leave the code below, but still with no luck.
While LoRa Available, and then String droneData = Lora.readstring
Is that the right way to do it ?.
Id like to keep the code easy to read as possible for others in my team to be able to understand and edit it for their projects
J-M-L
February 3, 2024, 9:55am
10
the typical code to receive something is this
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
Serial.print("Received packet '");
// read packet
while (LoRa.available()) {
Serial.print((char)LoRa.read());
}
}
where the bytes of the packet are dumped onto the Serial monitor one by one in the while loop.
In a real code, you would not dump them and do nothing with the bytes, you would store them in some memory buffer and then in order to parse what you received, you'd need to know what the sender has sent.
➜ Do you have the sender's code? do you know what to expect?
void setup() {
//initialize Serial Monitor
Serial.begin(115200);
//reset OLED display via software
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("LORA SENDER ");
display.display();
Serial.println("LoRa Sender Test");
//SPI LoRa pins
SPI.begin(SCK, MISO, MOSI, SS);
//setup LoRa transceiver module
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(BAND)) {
Serial.println("Starting LoRa failed!");
while (1);
}
Serial.println("LoRa Initializing OK!");
display.setCursor(0,10);
display.print("LoRa Initializing OK!");
display.display();
delay(2000);
Serial.println(F("Enviro Drone SGP30 Sensor Start"));
// Initialize I2C bus
Wire.begin();
Wire.setClock(400000);
// Initialize sensor
while (! sgp.begin()) {
Serial.println(F("Error: Could not detect SGP30 sensor"));
// display.println("SGP30 Error");
delay(3000);
}
}
void loop() {
String droneData;
// send data once every 10 seconds
if (millis() - lastTime >= 10000)
{
uint32_t start = millis();
Serial.print("time: \t");
Serial.println(start);
Serial.print(millis() - start);
Serial.println("Read SGP30 sensor.");
sgp.measure(true);
float co2 = sgp.getCO2();
float tvoc = sgp.getTVOC();
float h2 = sgp.getH2();
float etha = sgp.getEthanol();
Serial.print(co2);
Serial.print("\t");
Serial.print(tvoc);
Serial.print("\t");
Serial.print(h2);
Serial.print("\t");
Serial.print(etha);
Serial.println();
//Following code creates the serialized JSON string to send to the LoRa Receiver
//using ArduinoJson library
StaticJsonDocument <200> doc;
JsonObject data = doc.createNestedObject("DRONE");
data["CO2"] = co2;
data["TVOC"] = tvoc;
data["H2"] = h2;
data["Ethanol"] = etha;
serializeJson(doc, droneData);
Serial.println(droneData);
//This prints the JSON to the serial monitor screen
//and can be commented out
Serial.print("Sending packet: ");
Serial.println(counter);
//Send LoRa packet to receiver
LoRa.beginPacket();
LoRa.print(counter);
LoRa.print(droneData);
LoRa.endPacket();
display.clearDisplay();
display.setCursor(0,0);
display.println("LORA SENDER");
display.setCursor(0,20);
display.setTextSize(1);
display.print("LoRa packet sent.");
display.setCursor(0,30);
display.print("Counter:");
display.setCursor(50,30);
display.print(counter);
display.display();
counter++;
delay(10000);
}
}
J-M-L
February 3, 2024, 10:25am
12
OK so you are sending a JSON formatted packet.
The Lora library has a packet size limited to 255 if I remember correctly, you send something like this
{"DRONE":{"CO2":0,"TVOC":0,"H2":6.713018778e10,"Ethanol":1.864621128e15}}
so it should fit
(you probably should limit the precision to 2 digits after the decimal point when you send the data)
on the receiving end try this code
int packetSize = LoRa.parsePacket();
if (packetSize) {
char payload[packetSize+1];
int pos = 0;
while (LoRa.available()) payload[pos++] = LoRa.read();
payload[packetSize] = '\0';
StaticJsonDocument<100> doc;
DeserializationError error = deserializeJson(doc, payload, packetSize);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
JsonObject droneObj = doc["DRONE"];
float co2 = droneObj["CO2"];
float tvoc = droneObj["TVOC"];
float h2 = droneObj["H2"];
float ethanol = droneObj["Ethanol"];
Serial.print("CO2 = "); Serial.println(co2);
Serial.print("TVOC = "); Serial.println(tvoc);
Serial.print("H2 = "); Serial.println(h2);
Serial.print("Ethanol = "); Serial.println(ethanol);
}
of course you'll need to include ArduinoJSON in the receiver
Awesome J I will try this later today and report back. Thanks for your help and time mate.
J, Tried the code and its receiving the packet but, its saying deserialisation() failed: invalid input.
Any further ideas ?
J-M-L
February 5, 2024, 12:14pm
15
can you print the payload to see what's really in there?
So now Ive changed it to just send the 4 values as LoRa print commands with headings
LoRa Sender
Serial.print(millis() - start);
Serial.println("Read SGP30 sensor.");
sgp.measure(true);
float co2 = sgp.getCO2();
float tvoc = sgp.getTVOC();
float h2 = sgp.getH2();
float etha = sgp.getEthanol();
Serial.print(co2);
Serial.print("\t");
Serial.print(tvoc);
Serial.print("\t");
Serial.print(h2);
Serial.print("\t");
Serial.print(etha);
Serial.println();
Serial.print("Sending packet: ");
Serial.println(counter);
// +++++++++++++++++++++++++++++++ Send LoRa packet to receiver
LoRa.beginPacket();
// +++++++++++++++++++++++++++++++ LoRa.print(counter);
LoRa.print(": CO2 = ");
LoRa.print(co2);
LoRa.print(": TVOC = ");
LoRa.print(tvoc);
LoRa.print(": H2 = ");
LoRa.print(h2);
LoRa.print(": Ethanol = ");
LoRa.print(etha);
LoRa.endPacket();
So I'm trying my best to unpack it at present using the following :
Receiver Node
while (LoRa.available())
{
LoRalabel = LoRa.readString();
Serial.println(LoRalabel);
String LoRaLabel = LoRa.readStringUntil(': ');
LoRa.read(); // Throw away the space
if (LoRaLabel.endsWith("CO2 = "))
String Co2 = LoRa.readStringUntil(': ');
if (LoRaLabel.endsWith("TVOC = "))
String tvoc = LoRa.readStringUntil(': ');
if (LoRaLabel.endsWith("H2 = "))
String h2 = LoRa.readStringUntil(': ');
if (LoRaLabel.endsWith("Ethanol = "))
String etha = LoRa.readStringUntil(' ');
Serial.print("CO2 = "); Serial.println(Co2);
Serial.print("TVOC = "); Serial.println(tvoc);
Serial.print("H2 = "); Serial.println(h2);
Serial.print("Ethanol = "); Serial.println(etha);
J-M-L
February 6, 2024, 5:21pm
19
you have two characters the colon and a space in there
it would probably be easier to read the full message and then parse it
horace
February 9, 2024, 9:35am
20
avoid posting image of screen text output - it wastes space, is difficult to read and copy from - copy the text and post it using code tags </>
using a couple of TTGO LoRa32 SX1276 OLED I transmitted text
: CO2 = 433.00: TVOC = 96.00: H2 = 0.26: Ethanol = 0.17
and to parse the LoRa received data used sscanf, e.g.
//read packet
Serial.print("Received packet ");
while (LoRa.available()) {
LoRaLabel = LoRa.readString();
Serial.println(LoRaLabel);
int parsed = sscanf(LoRaLabel.c_str(),
": CO2 = %f: TVOC = %f: H2 = %f: Ethanol = %f", &Co2, &tvoc, &h2, ða);
Serial.print("CO2 = ");
Serial.println(Co2);
Serial.print("TVOC = ");
Serial.println(tvoc);
Serial.print("H2 = ");
Serial.println(h2);
Serial.print("Ethanol = ");
Serial.println(etha);
}
receiver displays
Received packet : CO2 = 433.00: TVOC = 96.00: H2 = 0.26: Ethanol = 0.17
CO2 = 433.00
TVOC = 96.00
H2 = 0.26
Ethanol = 0.17
however, as recommend by @J-M-L , I would transmit and receive a binary structure - see need-advice-on-a-home-project
Edit: remember on an ESP32 you can use Serial.printf() rather lines of Serial.print()s, e.g.
Serial.printf("\nCO2 = %.2f TVOC = %.2f H2 = %.2f Ethanol = %.2f", Co2, tvoc, h2, etha);
displays
CO2 = 433.00 TVOC = 96.00 H2 = 0.26 Ethanol = 0.17