LoRa Exercise
Hardware
The Arduino MKR WAN 1310 is a board that combines the functionality of the MKR Zero and LoRa / LoRaWANTM connectivity. There are also modules that allow LoRa communication for almost any device, and several other Arduino based devices with inbuilt LoRa functionality.
For the experiments below we will also need:
USB Cable
Connector Hat
LiPo Battery
Antenna
CCS811/BME280 Environmental Combo Sensor
Connection Cable
Getting started with the MKR WAN 1310
We will also need to install the Arduino Lora Library.
Downgrading the Arduino SAMD Core to version 1.8.11
The SparkFun CCS811 library is not compatible with Arduino SAMD Core version 1.8.12 and above. You need to downgrade to version 1.8.11 to compile successfully.
Step 1 — Open the Arduino IDE and go to Tools → Board → Boards Manager
Step 2 — In the search bar, type Arduino SAMD Boards
Step 3 — You will see Arduino SAMD Boards (32-bits ARM Cortex-M0+) in the list. Click on it.
Step 4 — Click the version dropdown and select 1.8.11
Step 5 — Click Install and wait for the installation to finish
Step 6 — Once installed, close the Boards Manager
Step 7 — Make sure your board is still selected: Tools → Board → Arduino MKR and Portenta Boards → Arduino MKR WAN 1310
Step 8 — Try compiling your sketch again — the TwoWire error should be gone
Note: Do not update the SAMD core if Arduino IDE prompts you to. Updating to 1.8.12 or higher will bring the error back.
The Sender Code
Adjust the topic with a very, very short name that you can filter on MQTT on Line 8.
#include <SparkFunBME280.h>
#include <SparkFunCCS811.h>
#include <SPI.h>
#include <LoRa.h>
#include <ArduinoJson.h>
int counter = 0;
const char* topic = "group1"; // define your identifier for the MQTT topic
String filterId = "iad26";
#define CCS811_ADDR 0x5B //Default I2C Address
// Global sensor objects
CCS811 myCCS811(CCS811_ADDR);
BME280 myBME280;
void setup() {
Serial.begin(9600);
delay(2000); // give serial time to connect
Serial.println("Starting setup...");
// initialize I2C bus
Wire.begin();
Serial.println("Wire OK");
if (myCCS811.begin() == false) {
Serial.println("Problem with CCS811");
} else {
Serial.println("CCS811 online");
}
// Initialize BME280
myBME280.settings.commInterface = 0;
myBME280.settings.I2CAddress = 0x77;
myBME280.settings.runMode = 3; // Normal mode
myBME280.settings.tStandby = 0;
myBME280.settings.filter = 4;
myBME280.settings.tempOverSample = 5;
myBME280.settings.pressOverSample = 5;
myBME280.settings.humidOverSample = 5;
//Calling .begin() causes the settings to be loaded
delay(10); // BME280 requires 2ms to start up.
byte id = myBME280.begin(); // Returns ID of 0x60 if successful
Serial.print("BME280 ID: 0x");
Serial.println(id, HEX);
if (id != 0x60) {
Serial.println("Problem with BME280");
} else {
Serial.println("BME280 online");
}
// Setup LoRa
Serial.println("Starting LoRa...");
Serial.println("LoRa Sender");
if (!LoRa.begin(868E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
Serial.println("LoRa OK");
delay(1000);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println("Setup done.");
}
void loop() {
// Check if CCS811 has new data ready
if (myCCS811.dataAvailable()) {
myCCS811.readAlgorithmResults();
// Pass temperature and humidity from BME280 to CCS811 for compensation
float temp = myBME280.readTempC();
float humidity = myBME280.readFloatHumidity();
float co2 = myCCS811.getCO2();
float tvoc = myCCS811.getTVOC();
myCCS811.setEnvironmentalData(humidity, temp);
StaticJsonDocument<128> data;
data["id"] = filterId;
data["topic"] = topic;
data["c"] = co2;
data["t"] = tvoc;
data["tp"] = temp;
data["h"] = humidity;
char buffer[128];
serializeJson(data, buffer);
Serial.print(buffer);
Serial.println();
// LoRa
Serial.print("Sending packet: ");
Serial.println(counter);
// Send packet
LoRa.beginPacket();
LoRa.print(buffer);
LoRa.endPacket();
counter++;
// Debug LED
digitalWrite(LED_BUILTIN, HIGH);
delay(10000);
digitalWrite(LED_BUILTIN, LOW);
}
}