This workshop will enable you to set up an Arduino LoRa board (MKR1310) to upload data from some simple sensors to the Things Network over LoRaWAN (a low power, long range wireless protocol).

You will make use of the DHT22 Humidity and Temperature (digital) sensor.

Requires from Library Manager:

The Arduino SAMD MKR1310 board support is also required in the Boards Manager

First launch the Arduino IDE. To familiarise yourself with the Arduino platform you will first load a basic blink sketch from the examples that are distributed with the Arduino IDE.

Load the following sketch:
File -> Examples -> Basics -> Blink

Ensure board set to Arduino Leonardo:
Tool -> Boards -> BoardManager -> Arduino Leonardo

Ensure the correct port for the Arduino Leonardo has been selected:
Tools -> Port:...

Now upload the sketch using the upload button (as shown below)

If you look at the Arduino board you should see the built in LED blinking every second.

Wire up the circuit as shown in the diagram below:

Enter the following code in the sketch

/*
  MKR1310 MQTT temperature monitor with LCD display
  Duncan Wilson
  2022-8-11

  Uses the following libraries:
  Grove LCD Backlight
  DHT 
  MKRWAN

  DHT on VCC, GND and Pin D2
  LCD on 5V, GND and SDA / SCL - note, blank screen means power is 3.3V
*/

#include <Wire.h>
#include "rgb_lcd.h"
#include "DHT.h"
#include <MKRWAN.h>

#define DHTPIN 2     // what digital pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// Set your AppEUI and AppKey for connecting over Lora to The Things Network
const char *appEui = "xxx";
const char *appKey = "xxx";

#define freqPlan TTN_FP_EU868

// Initialise the LCD
rgb_lcd lcd;

// Initialise the DHT sensor
DHT dht(DHTPIN, DHTTYPE);
float h = 0.0; // initialise the humidity with zero value
float t = 0.0; // initialise the humidity with zero value

// Initialise the Lora connection to TTN
LoRaModem modem;
int modem_timer = 60;


void setup()
{

  Serial.begin(115200);

  // set up the LCD's number of columns and rows and background colour
  lcd.begin(16, 2);
  lcd.setRGB(100, 100, 100);
  lcd.print("Starting...");
  
  // start the DHT sensor
  dht.begin();
  delay(1000);

  // make connection to TTN
  while (!modem.begin(EU868)) delay(1000);
  lcd.setCursor(0, 0);
  lcd.print("Joining TTN,");
  lcd.setCursor(0, 1);
  lcd.print("please wait...");
  modem.joinOTAA(appEui, appKey);

  lcd.setCursor(0, 0);
  lcd.print("Setup complete.");

  // wait a second and start main loop
  delay(1000);
}

void loop()
{
  // Read Temperature and Humidity levels (float h and t)
  updateDHT();
  
  // print the DHT values to the LCD screen
  // if temperature value is out of bounds change screen colour
  setBackground();
  // set the cursor to column 0, line 0 (note: line 0 is the first row, since counting begins with 0):
  lcd.setCursor(0, 0);
  lcd.print("Temp: " + String(t) + " C   ");
  lcd.setCursor(0, 1);
  lcd.print("Humi: " + String(h) + " %   ");
  if(modem_timer%2){
    lcd.setCursor(15, 1);
    lcd.print("_");
  }
  

  // send temperature to TTN every 1 minute
  if(modem_timer > 59){
    send2TTN();
    modem_timer = 0;
  }
  
  // wait a second and start next reading
  delay(1000);
  modem_timer++;
}

void send2TTN(){

  uint16_t ttn_temp = round(100 * t);
  uint16_t ttn_humi = round(100 * h);

  byte payload[4];
  payload[0] = highByte(ttn_temp);
  payload[1] = lowByte(ttn_temp);
  payload[2] = highByte(ttn_humi);
  payload[3] = lowByte(ttn_humi);

  int err;
  modem.beginPacket();
  modem.write(payload, sizeof(payload));
  err = modem.endPacket(true);
  if (err > 0) {
    Serial.println("Message sent correctly!");
  } else {
    Serial.println("Error sending message :(");
  }

}

void setBackground() {
  // if the temperature is above 21 then red, if less than 18 blue, otherwise green
  lcd.setRGB(0, 200, 0);
  if (t > 21) {
    lcd.setRGB(200, 0, 0);
  } else if (t < 18) {
    lcd.setRGB(0, 0, 200);
  }

}

void updateDHT()
{
  // Reading temperature or humidity takes about 250 milliseconds
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
}


void printDHT()
{

  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.println(" *C ");

}

Check the code has been entered correctly by compiling the code. If you see a message ‘Done compiling' it indicates the code has compiled sucessfully.

Added to the telegraf config file hosted on the TIG server:

# Read metrics from MQTT topic(s)
[[inputs.mqtt_consumer]]
  ## MQTT broker URLs to be used. The format should be scheme://host:port,
  servers = ["tcp://eu1.cloud.thethings.network:1883"]
  client_id = "ttn_telegraf_casa0014"

  ## Username and password to connect MQTT server.
  username = "mkr1310dht@ttn"
  password = "COPY FROM TTN APPLICATION"

  ## Topics that will be subscribed to.
  topics = [
    "v3/mkr1310dht@ttn/devices/#"
    ]
  data_format = "json"

Example query for influxdb / grafana display:

SELECT mean("uplink_message_decoded_payload_temperature") FROM "mqtt_consumer" WHERE ("topic" =~ /mkr1310dht*/) AND $timeFilter GROUP BY time($__interval), "topic" fill(null)

test server: http://celab0014-pi-ucjtdjw.local:3000