Mthokozisi Mzingaye Moyo
Published

RiverBots

Floating robots partly built from e-waste that autonomously monitor water quality.

IntermediateShowcase (no instructions)107
RiverBots

Things used in this project

Hardware components

Wio Terminal
Seeed Studio Wio Terminal
×1
Grove - I2C High Accuracy Temp&Humi Sensor (SHT35)
Seeed Studio Grove - I2C High Accuracy Temp&Humi Sensor (SHT35)
×1
Grove - Air quality sensor v1.3
Seeed Studio Grove - Air quality sensor v1.3
×1
ICR 18650-22F SAMSUNG - Re-battery: Li-Ion | MR18650
Lithium Ion Batteries
×1
DC Motor, 12 V
DC Motor, 12 V
×1

Software apps and online services

Arduino IDE
Arduino IDE
Ubidots
Ubidots

Hand tools and fabrication machines

Drill, Screwdriver
Drill, Screwdriver
SOLDERING IRON 30W 220V

Story

Read more

Schematics

Wio Schematic

Code

Main Code

C#
Reading sensor data and sending it to Ubidots
#include <PubSubClient.h>
#include <rpcWiFi.h>
#include <TFT_eSPI.h>
#include"LIS3DHTR.h"

#include "sensirion_common.h"
#include "sgp30.h"

#include <SensirionI2CSht4x.h>
#include <Wire.h>
 
LIS3DHTR<TwoWire> lis;

////Credentials
//#define WIFISSID "riverbottest"
//#define PASSWORD "123456789"
//#define TOKEN "****-WBjD8vQSzExu3QvmiCM8Nsj*******"
//#define DEVICE_LABEL "Wio-Terminal"
//#define MQTT_CLIENT_NAME "**:F7:D1:1C:A8:**"

#define WIFISSID "riverbottest"
#define PASSWORD "123456789"
#define TOKEN "****-WBjD8vQSzExu3QvmiCM8Nsj*******"
#define DEVICE_LABEL "WIO-t"
#define MQTT_CLIENT_NAME "*****c11b9ec7a000d*****"

// Assign the variable label - internal
#define VARIABLE_LABEL1 "light" 
#define VARIABLE_LABEL2 "IMUx"
#define VARIABLE_LABEL3 "IMUy"
#define VARIABLE_LABEL4 "IMUz"
#define VARIABLE_LABEL5 "sound"

// Assign the variable label  - external
#define VARIABLE_LABEL6 "voc" 
#define VARIABLE_LABEL7 "co2"
#define VARIABLE_LABEL8 "temperature" 
#define VARIABLE_LABEL9 "humidity"

const long interval = 100;
unsigned long previousMillis = 0;
 
TFT_eSPI tft;
 
char mqttBroker[] = "industrial.api.ubidots.com";
 
WiFiClient wifiClient;
PubSubClient client(wifiClient);

//TFT_eSPI tft = TFT_eSPI();
SensirionI2CSht4x sht4x;

static float temp = 0;
static float humi = 0;
 
// Space to store values to send
char str_temp[6];
char str_humi[6];

static unsigned short int VOC = 0;
static unsigned short int CO2 = 0;

// Space to store values to send
char str_voc[6];
char str_co2[6];
 
//sensor values
static int lightValue = 0;
static float imuxValue = 0;
static float imuyValue = 0;
static float imuzValue = 0;
static int soundValue = 0;
 
// Space to store values to send
static char str_light[6];
static char str_imux[6];
static char str_imuy[6];
static char str_imuz[6];
static char str_sound[6];



char payload[700];
char topic[150];
 
void callback(char* topic, byte* payload, unsigned int length){
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
}
 
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.println("Attempting MQTT connection...");
 
  // Attempt to connect
  if (client.connect(MQTT_CLIENT_NAME, TOKEN,"")) {
    Serial.println("connected");
  }
  else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 2 seconds");
    // Wait 2 seconds before retrying
    delay(2000);
    }
  }
}

void read_sgp30()
{
  while (sgp_probe() != STATUS_OK) {
      Serial.println("SGP failed");
  }
  s16 err = 0;
  sgp_measure_iaq_blocking_read(&VOC, &CO2);
  if (err == STATUS_OK) {
      Serial.print("tVOC  Concentration:");
      Serial.print(VOC);
      Serial.println("ppb");
 
      Serial.print("CO2eq Concentration:");
      Serial.print(CO2);
      Serial.println("ppm");
  } else {
      Serial.println("error reading IAQ values\n");
  }
}


void read_sht40()
{
  uint16_t error;
  char errorMessage[256];
  error = sht4x.measureHighPrecision(temp, humi);
  if (error) {
      Serial.print("Error trying to execute measureHighPrecision(): ");
      errorToString(error, errorMessage, 256);
      Serial.println(errorMessage);
  } else {
      Serial.print("Temperature:");
      Serial.print(temp);
      Serial.print("\t");
      Serial.print("Humidity:");
      Serial.println(humi);
  }
}



 
//Reading built-in sensor values
void read_builtin()
{
  lightValue = analogRead(WIO_LIGHT);
  Serial.print("Light = ");
  Serial.println(lightValue);
 
  imuxValue = lis.getAccelerationX();
  Serial.print("IMU_x = ");
  Serial.println(imuxValue);
  imuyValue = lis.getAccelerationY();
  Serial.print("IMU_y = ");
  Serial.println(imuyValue);
  imuzValue = lis.getAccelerationZ();
  Serial.print("IMU_z = ");
  Serial.println(imuzValue);
 
  soundValue = analogRead(WIO_MIC);
  Serial.print("Sound = ");
  Serial.println(soundValue);
}
 
//Sending data to Ubidots
void send_data()
{
  dtostrf(lightValue, 4, 0, str_light);
  dtostrf(imuxValue, 4, 3, str_imux);
  dtostrf(imuyValue, 4, 3, str_imuy);
  dtostrf(imuzValue, 4, 3, str_imuz);
  dtostrf(soundValue, 4, 0, str_sound);
  
  dtostrf(temp, 4, 2, str_temp);
  dtostrf(humi, 4, 2, str_humi);
  
  dtostrf(VOC, 4, 0, str_voc);
  dtostrf(CO2, 4, 0, str_co2);
 
  if (!client.connected()) {
    reconnect();
  }
 
  // Builds the topic
  sprintf(topic, "%s", ""); // Cleans the topic content
  sprintf(topic, "%s%s", "/v2.0/devices/", DEVICE_LABEL);
 
  //Builds the payload
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL1); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_light); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);
 
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL2); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_imux); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);
 
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL3); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_imuy); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);
 
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL4); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_imuz); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);
 
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL5); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_sound); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);

  //Builds the payload
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL6); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_voc); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  Serial.println(payload);
  delay(500);
 
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL7); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_co2); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  Serial.println(payload);
  delay(500);


//Builds the Temp and Humidity payload
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL8); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_temp); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);
 
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL9); // Adds the variable label
  sprintf(payload, "%s%s", payload, str_humi); // Adds the value
  sprintf(payload, "%s}", payload); // Closes the dictionary brackets
  client.publish(topic, payload);
  delay(500);
 
  client.loop();
}
 
void setup() {
  Serial.begin(115200);
  
  lis.begin(Wire1);
  pinMode(WIO_MIC, INPUT);
  pinMode(WIO_LIGHT, INPUT);

  while (sgp_probe() != STATUS_OK) {
      Serial.println("SGP failed");
  }
  sgp_set_absolute_humidity(13000);
  sgp_iaq_init();

  Wire.begin();
  sht4x.begin(Wire);
 
  tft.begin();
  tft.setRotation(3);
  tft.setTextSize(2);
  tft.fillScreen(TFT_BLACK);
 
  lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); //Data output rate
  lis.setFullScaleRange(LIS3DHTR_RANGE_2G);
 
//  while(!Serial);
 
  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
 
  Serial.println("Connecting to WiFi...");
  tft.drawString("Connecting to WiFi...",20,120);
  WiFi.begin(WIFISSID, PASSWORD);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    WiFi.begin(WIFISSID, PASSWORD);
  }
 
  tft.fillScreen(TFT_BLACK);
  tft.drawString("Connected to the WiFi",20,120);
 Serial.println("Connected to WiFi...");
 
  delay(1000);
  client.setServer(mqttBroker, 1883);
  client.setCallback(callback);
 
}
 
void loop() {
  read_builtin();   //Reading buile-in sensor values
  read_sgp30();    //Reading sgp30 sensor values
  read_sht40();    //Reading sht40 sensor values
  send_data();   //Sending data to Ubidots
  delay(5000);
}

K1100 Kit Code

Add automatic recognition of Grove Sensors in K1100 Kit, display data, and send to the cloud

Credits

Mthokozisi Mzingaye Moyo

Mthokozisi Mzingaye Moyo

1 project • 0 followers
Tech & Water entrepreneur with a civil and water engineering background. I have two years in development and it started as a hobby
Thanks to Thamsanqa Mpofu.

Comments