Plant Sensor (MKR WIFI 1010 + MKR ENV Shield)

Assignment

Deploy a sensor to monitor one of the plants on the ITP floor. When you’re choosing the plant you’d like to monitor, remember you’ll need to power the MKR 1010 from a wall outlet.

Measure the following measurements from the MKR ENV shield

MeasurementUnit
temperature°F
humidity% Relative Humidity
pressurekPa
illuminancelux
uvaμW/cm2
uvbμW/cm2

First, the plant and the arduino:

Process

As I understand, we have an arduino that sends data to the mqtt broker via Wi-Fi by listening to the sensor that is attached to it. Arduino publishes the data to the broker and by subscribing to the topic on the broker we are able to see the data. When we publish a message to the broker, it shares it with the arduino.

First and foremost, I am not good at coding. I used the example TemperatureHumidityLED code and it seemed pretty simple, but it took me some time to familiarize myself with it. Temperature and humidity were already in place, and I needed to add pressure, illuminance, uva, and uvb. To do so I learned what they are from env_shield project hub.

One mistake (?) I might have made is that I introduced them as integers instead of floats. I am not sure if that has an immense impact on precision.

I did not want the values to look dull in mqtt messages, so I added a few words to make the data sound more interesting like “Temperature is 73.61°F”, instead of “73.61°F”. I wonder if this has a big impact on data collection? Perhaps I will need to change it.

Challenges

First and foremost difficulty I had was with code. Data was coming in super fast. Changing publish interval did not change anything.

Then I realized that my code was running outside the if {} statement, meaning it was running in the loop constantly. Figuring this out made me feel relieved.

And as mentioned in the above section, I tried to make the messages appear more like normal sentences. Curious if this has impact on data collection. I find that it looks better, especially in mqtt.

Thoughts

I think that this is really cool. I wonder if it works just as fast without Wi-Fi.

I made my publish interval at around 15 minutes. Mainly for testing purposes, so that I can check on data and make sure that the arduino is running well. In reality, I think publishing this data 3-4 times a day is probably good enough. Of course, it depends on the application of the sensor. If it’s an important crop or if it’s checking for leaks, then it should be collected more often.

Code

// IoT Workshop
// Send temperature and humidity data to MQTT
//
// WiFiNINA https://www.arduino.cc/en/Reference/WiFiNINA (MKR WiFi 1010)
// Arduino MKR ENV https://www.arduino.cc/en/Reference/ArduinoMKRENV
// Arduino MQTT Client  https://github.com/arduino-libraries/ArduinoMqttClient

#include <WiFiNINA.h>
#include <Arduino_MKRENV.h>
#include <ArduinoMqttClient.h>

#include "config.h"

WiFiSSLClient net;
MqttClient mqtt(net);

String temperatureTopic = "itp/" + DEVICE_ID + "/temperature";
String humidityTopic = "itp/" + DEVICE_ID + "/humidity";
String ledTopic = "itp/" + DEVICE_ID + "/led";
String soilMoistureTopic = "itp/" + DEVICE_ID + "/soil";
String pressureTopic = "itp/" + DEVICE_ID + "/pressure";
String illuminanceTopic = "itp/" + DEVICE_ID + "/illuminance";
String uvaTopic = "itp/" + DEVICE_ID + "/uva";
String uvbTopic = "itp/" + DEVICE_ID + "/uvb";

//introduction of certain things
  int humidity;
  int lux;
  int pressure;
  int temperature;
  int uva;
  int uvb;
  int illuminance;

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

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

  // Wait for a serial connection
//  while (!Serial) { }

  // initialize the shield
  if (!ENV.begin()) {
    Serial.println("Failed to initialize MKR ENV shield!");
    while (1);
  }

  // initialize ledPin as an output.
  pinMode(ledPin, OUTPUT);

  Serial.println("Connecting WiFi");
  connectWiFi();

  // define function for incoming MQTT messages
  mqtt.onMessage(messageReceived);
}

void loop() {
  int sensorValue = analogRead(A0);
  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 = ENV.readTemperature(FAHRENHEIT);
    float humidity = ENV.readHumidity();
    
    Serial.print("Temperature is ");
    Serial.print(temperature);
    Serial.print("°F ");
    Serial.print("and Humidity is ");
    Serial.print(humidity);
    Serial.println("% RH");
    Serial.print("Soil Moisture is ");
    Serial.println(sensorValue);

    mqtt.beginMessage(temperatureTopic);
    mqtt.print("Temperature is ");
    mqtt.print(temperature);
    mqtt.print("°F ");
    mqtt.endMessage();

    mqtt.beginMessage(humidityTopic);
    mqtt.print("Humidity is ");
    mqtt.print(humidity);
    mqtt.print("% RH");
    mqtt.endMessage();

    mqtt.beginMessage(soilMoistureTopic);
    mqtt.print("Soil Moisture is ");
    mqtt.print(sensorValue);
    mqtt.endMessage();

    //My code below
  
  pressure = int(ENV.readPressure());
  illuminance = int(ENV.readIlluminance());
  uva = int(ENV.readUVA());
  uvb = int(ENV.readUVB());
  delay(1000);
   //Serial for my pasta code
  Serial.print("Pressure is ");
  Serial.print(pressure);
  Serial.print(" kPa ");
  Serial.print("and Illuminance is ");
  Serial.print(illuminance);
  Serial.println(" lux");
  Serial.print("UVA is at ");
  Serial.print(uva);
  Serial.print(" μW/cm2 ");
  Serial.print("and UVB is at ");
  Serial.print(uvb);
  Serial.println(" μW/cm2");
  //Mqtt message part
  mqtt.beginMessage(pressureTopic);
  mqtt.print("Pressure is ");
  mqtt.print(pressure);
  mqtt.print(" kPa ");
  mqtt.endMessage();

  mqtt.beginMessage(illuminanceTopic);
  mqtt.print("Illuminance is ");
  mqtt.print(illuminance);
  mqtt.print(" lux");
  mqtt.endMessage();

  mqtt.beginMessage(uvaTopic);
  mqtt.print("UVA is at ");
  mqtt.print(uva);
  mqtt.print(" μW/cm2");
  mqtt.endMessage();

  mqtt.beginMessage(uvbTopic);
  mqtt.print("UVB is at ");
  mqtt.print(uvb);
  mqtt.print(" μW/cm2");
  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);
  }

  mqtt.subscribe(ledTopic);
  Serial.println("connected.");
}

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

void messageReceived(int messageSize) {
  String topic = mqtt.messageTopic();
  String payload = mqtt.readString();
  Serial.println("incoming: " + topic + " - " + messageSize + " bytes ");
  Serial.println(payload);
  if (payload.equalsIgnoreCase("ON")) {
    analogWrite(ledPin, 255);  // need analog write for older firmware
  } else if (payload.equalsIgnoreCase("OFF")) {
    analogWrite(ledPin, LOW);
  } else {

    // see if we have a brightness value
    int percent = payload.toInt();
    // check the range
    if (percent < 0) {
      percent = 0;
    } else if (percent > 100) {
      percent = 100;
    }
    // map brightness of 0 to 100 to 1 byte value 0x00 to 0xFF
    int brightness = map(percent, 0, 100, 0, 255);
    analogWrite(ledPin, brightness);
  }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s