We are 4 students electrical engineering working on a Covid-19 related project, however we have some difficulties working with Arduino as we have little to no experience with it (we do have experience with C/C++ however).
We're supposed to design a wireless CO2-sensornetwork which could be used in a school for example. To read the CO2 values we use the SparkFun_SCD30_Arduino_Library. Then we want to send them via LoRa to our gateway. For this we use the Beelan-LoRaWAN library. Both work fine separately, but when we try to combine them, we encounter some problems with the Serial monitor. It's basically as if the loop()-function only runs one time, because it only sends 1 packet with our CO2 value (and at the gateway we also only receive 1 packet). We've tried changing the baud rate or adding some delays here and there, but that doesn't seem to work. However, if we uncomment the first line in the loop()-function which prints "loop", all seems to work fine, but only for a while. Unfortunately, we cannot seem to find what causes this.
(I left out the ABP credentials for our LoRa device)
#include <lorawan.h>
#include <Wire.h>
#include <SparkFun_SCD30_Arduino_Library.h>
SCD30 scd30;
//ABP Credentials
const char *devAddr = "";
const char *nwkSKey = "";
const char *appSKey = "";
const unsigned long interval = 10000;
unsigned long previousMillis = 0; // will store last time message sent
char myStr[5];
const sRFM_pins RFM_pins = {
.CS = 10,
.RST = 7,
.DIO0 = 6,
.DIO1 = 8,
.DIO2 = 5,
.DIO5 = 9,
};
void setup() {
Serial.begin(115200);
while (!Serial);
Wire.begin();
// Setup loraid access
if (!lora.init()) {
Serial.println("RFM95 not detected");
delay(5000);
return;
}
// Set LoRaWAN Class change CLASS_A or CLASS_C
lora.setDeviceClass(CLASS_A);
// Set Data Rate
lora.setDataRate(SF8BW125);
// set channel to random
lora.setChannel(MULTI);
// Put ABP Key and DevAddress here
lora.setNwkSKey(nwkSKey);
lora.setAppSKey(appSKey);
lora.setDevAddr(devAddr);
// Setup CO2 sensor
if (!scd30.begin()) {
Serial.println("Failed to find SCD30 chip");
while (1) {
delay(10);
}
}
Serial.println("SCD30 Found!");
if (!scd30.setMeasurementInterval(10)) {
Serial.println("Failed to set measurement interval");
while (1) {
delay(10);
}
}
}
void loop() {
//Serial.println("loop");
// Check interval overflow
if (millis() - previousMillis > interval) {
previousMillis = millis();
if (scd30.dataAvailable()) {
// Read CO2 value and cap at 9999
uint16_t CO2 = min(scd30.getCO2(), 9999);
// Convert to string as sendUplink() requires a string as input. Only use 4 (+1) characters to minimalise data throughput.
snprintf(myStr, sizeof myStr, "%d", CO2);
Serial.print("Sending: ");
Serial.println(myStr);
lora.sendUplink(myStr, strlen(myStr), 0, 1);
} else {
//Serial.println("No data");
}
}
// Check Lora RX
lora.update();
}
Hardware used:
Arduino Uno
SCD30 sensor
SX1276RF1JAS (LoRa)
#include <lorawan.h>
//ABP Credentials
const char *devAddr = "";
const char *nwkSKey = "";
const char *appSKey = "";
const unsigned long interval = 10000; // 10 s interval to send message
unsigned long previousMillis = 0; // will store last time message sent
unsigned int counter = 0; // message counter
char myStr[50];
const sRFM_pins RFM_pins = {
.CS = 10,
.RST = 7,
.DIO0 = 6,
.DIO1 = 8,
.DIO2 = 5,
.DIO5 = 9,
};
void setup() {
// Setup loraid access
Serial.begin(9600);
while (!Serial);
if (!lora.init()) {
Serial.println("RFM95 not detected");
delay(5000);
return;
}
// Set LoRaWAN Class change CLASS_A or CLASS_C
lora.setDeviceClass(CLASS_A);
// Set Data Rate
lora.setDataRate(SF8BW125);
// set channel to random
lora.setChannel(MULTI);
// Put ABP Key and DevAddress here
lora.setNwkSKey(nwkSKey);
lora.setAppSKey(appSKey);
lora.setDevAddr(devAddr);
}
void loop() {
// Check interval overflow
if (millis() - previousMillis > interval) {
previousMillis = millis();
sprintf(myStr, "Counter-%d", counter);
Serial.print("Sending: ");
Serial.println(myStr);
lora.sendUplink(myStr, strlen(myStr), 0, 1);
counter++;
}
// Check Lora RX
lora.update();
}
As expected, this sends a packet every 10 seconds which is received by our gateway.
This is the code for the CO2 sensor:
#include <Wire.h>
#include "SparkFun_SCD30_Arduino_Library.h"
SCD30 airSensor;
void setup()
{
Serial.begin(115200);
Serial.println("SCD30 Example");
Wire.begin();
if (airSensor.begin() == false)
{
Serial.println("Air sensor not detected. Please check wiring. Freezing...");
while (1)
;
}
//The SCD30 has data ready every two seconds
}
void loop()
{
if (airSensor.dataAvailable())
{
Serial.print("co2(ppm):");
Serial.print(airSensor.getCO2());
Serial.print(" temp(C):");
Serial.print(airSensor.getTemperature(), 1);
Serial.print(" humidity(%):");
Serial.print(airSensor.getHumidity(), 1);
Serial.println();
}
else
Serial.println("Waiting for new data");
delay(500);
}
As expected, this prints out the data every 2 seconds.
Both functions work separately (even when simultaneously connected to the Arduino Uno). As for the "loop", it goes for a few times (4 or 5 times so 40-50 seconds) before also getting stuck. I just noticed that it also doesn't actually send the packet (even though I'm sure it did yesterday). It prints "Sending: xxx" on the Serial, but nothing is received at the gateway so it's likely that the update()-function at the end isn't even reached. The Serial Monitor stops for a split second after the "Sending: xxx" line before it restarts completely (so "SCD30 found" is repeated which suggests the Arduino resets itself I suppose?). Also at the start it prints this message twice.
In the attachment you'll find the schematic of the SX1276RF1JAS. However, I don't think there's a problem with the wiring, as they work perfectly fine separately (while the wiring doesn't change), but I might be wrong.
I was concerned that there might be a clash between the devices both using the same pin. Doesn't look like it.
The length of Mystr makes me nervous, maybe make it a bit bigger, eight perhaps.
If that doesn't work, you're reduced to divide and conquer I think. Perhaps try a version that has the CO2 detector declared and initialized but don't read it, just sending a constant string via LoRa and see if that's stable.
I made the myStr longer (8) but it still doesn't work.
I now started from the LoRa code (with the only changes that myStr is 8 long and instead of sending a counter just sending "Hello"). This works fine. Now I added the line #include <SparkFun_SCD30_Arduino_Library.h> and weird things start happening in the Serial monitor (see image). This is for 6 packets, which strangely all arrive perfectly at our LoRa gateway (see image, indeed 48 65 6C 6C 6F corresponds to "Hello").
Here is the code:
#include <lorawan.h>
#include <SparkFun_SCD30_Arduino_Library.h>
//SCD30 scd30;
//ABP Credentials
const char *devAddr = "";
const char *nwkSKey = "";
const char *appSKey = "";
const unsigned long interval = 10000;
unsigned long previousMillis = 0; // will store last time message sent
char myStr[8];
const sRFM_pins RFM_pins = {
.CS = 10,
.RST = 7,
.DIO0 = 6,
.DIO1 = 8,
.DIO2 = 5,
.DIO5 = 9,
};
void setup() {
// Setup loraid access
Serial.begin(9600);
while (!Serial);
if (!lora.init()) {
Serial.println("RFM95 not detected");
delay(5000);
return;
}
// Set LoRaWAN Class change CLASS_A or CLASS_C
lora.setDeviceClass(CLASS_A);
// Set Data Rate
lora.setDataRate(SF8BW125);
// set channel to random
lora.setChannel(MULTI);
// Put ABP Key and DevAddress here
lora.setNwkSKey(nwkSKey);
lora.setAppSKey(appSKey);
lora.setDevAddr(devAddr);
}
void loop() {
// Check interval overflow
if (millis() - previousMillis > interval) {
previousMillis = millis();
sprintf(myStr, "Hello");
Serial.print("Sending: ");
Serial.println(myStr);
lora.sendUplink(myStr, strlen(myStr), 0, 1);
}
// Check Lora RX
lora.update();
}