Sending Data over MQTT

Our assignment this week was to build upon the “device to database” contraption we started in class (well, no db just yet). As we had already implement something including a temperature and humidity sensor, I decided to add light to the mix. I kept it pretty simple: I added a photoresister and a 470 ohm resistor going to ground. I ran a jumper wire just before the 470 going into A3 of my MKR1000.

The “IRL” view of this setup can be viewed here:

Here's what the breadboard looks like:

(You’ll notice this does not include the LED, which I end up not utilizing in my final sketch for this assignment).

I had to very minimally modify the code in order to accomodate the additional sensor. Initially, I only made modifications to HardwareTest.ino (the sketched use in class). The results of that code here:

The code is here:

// IoT Workshop
// Send temperature and humidity data to MQTT
//
// Uses WiFi101 https://www.arduino.cc/en/Reference/WiFi101 (MKR1000)
// Uses WiFiNINA https://www.arduino.cc/en/Reference/WiFiNINA (MKR WiFi 1010)
// Arduino MQTT Client Library https://github.com/arduino-libraries/ArduinoMqttClient
// Adafruit DHT Sensor Library https://github.com/adafruit/DHT-sensor-library
// Adafruit Unified Sensor Library https://github.com/adafruit/Adafruit_Sensor
//

#include <SPI.h>
#ifdef ARDUINO_SAMD_MKR1000
#include <WiFi101.h>
#define WL_NO_MODULE WL_NO_SHIELD 
#else
#include <WiFiNINA.h>
#endif
#include <ArduinoMqttClient.h>

#include "config.h"

WiFiSSLClient net;
MqttClient mqtt(net);

// Temperature and Humidity Sensor
#include <DHT.h>
#define DHTTYPE DHT22
#define DHTPIN  7
#define photoPIN A3
DHT dht(DHTPIN, DHTTYPE);
int value; 
int maxVal = 0; 
int minVal = 1023;

String temperatureTopic = "itp/" + DEVICE_ID + "/temperature";
String humidityTopic = "itp/" + DEVICE_ID + "/humidity";
String lightTopic = "itp/" + DEVICE_ID + "/light";

// Publish every 10 seconds for the workshop. Real world apps need this data every 5 or 10 minutes.
unsigned long publishInterval = 10 * 500;
unsigned long lastMillis = 0;

void setup() {
  Serial.begin(9600);

  // Uncomment next line to wait for a serial connection
  // while (!Serial) { }
 
  // initialize temperature sensor
  dht.begin();  
  pinMode(photoPIN, INPUT);  
 
  Serial.println("Connecting WiFi");
  connectWiFi();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }

  if (!mqtt.connected()) {
    connectMQTT();
  }
  
  // poll for new MQTT messages and send keep alives
  mqtt.poll();

  if (millis() - lastMillis > publishInterval) {
    lastMillis = millis();

    float temperature = dht.readTemperature(true);
    float humidity = dht.readHumidity();
    value = analogRead(photoPIN); 

    if (value > maxVal) maxVal = value;
    if (value < minVal) minVal = value;
    int mappedValue = map(value, minVal, maxVal, 0, 100);

    Serial.print(temperature);
    Serial.print("°F ");
    Serial.print("% RH ");
    Serial.print(mappedValue);
    Serial.println(" light level");
    
    mqtt.beginMessage(temperatureTopic);
    mqtt.print(temperature); 
    mqtt.endMessage();

    mqtt.beginMessage(humidityTopic);
    mqtt.print(humidity); 
    mqtt.endMessage();

    mqtt.beginMessage(lightTopic);
    mqtt.print(mappedValue); 
    mqtt.endMessage();
  }  
}

void connectWiFi() {
  // Check for the WiFi module
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  Serial.print("WiFi firmware version ");
  Serial.println(WiFi.firmwareVersion());
  
  Serial.print("Attempting to connect to SSID: ");
  Serial.print(WIFI_SSID);
  Serial.print(" ");

  while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(3000);
  }

  Serial.println("Connected to WiFi");
  printWiFiStatus();

}

void connectMQTT() {
  Serial.print("Connecting MQTT...");
  mqtt.setId(DEVICE_ID);
  mqtt.setUsernamePassword(MQTT_USER, MQTT_PASSWORD);

  while (!mqtt.connect(MQTT_BROKER, MQTT_PORT)) {
    Serial.print(".");
    delay(5000);
  }

  Serial.println("connected.");
}

void printWiFiStatus() {
  // print your WiFi IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

It’s a modification of the TemperatureHumidity.ino code we used in class. I added a few lines to set the pinMode on A3, analogRead that pin, and publish to a new MQTT topic. You’ll also notice that I’m mapping the values I am receiving from analogRead() to values between 0 and 100. This seemed like a more intuitive way to report out light levels (rather than the range of actual values sent by the photoresistor).

You can also see how this data looks from the MQTT broker side (here’s I’m using the subscribe example shared in class):

Just the light!