UNO R4 Wifi sensors send data to Blynk cloud

Hello everybody,

I just wanted to share my code and fritzing file for a little project of mine. Here I wanted to measure parameters relevant for hydroponic plant cultivation. I have connected an UNO R4 Wifi with the following sensors:

  • pH
  • EC
  • water temperature
  • temperature/humidity
  • light

The code also enables you to send the data to your Blynk cloud. You have to fill in your specific information for the fields with XXXXXXXXX. Please ignore or delete the Udp parts.

/***************************************************
  This is an example for the HTU21D-F Humidity & Temp Sensor

  Designed specifically to work with the HTU21D-F sensor from Adafruit
  ----> https://www.adafruit.com/products/1899

  These displays use I2C to communicate, 2 pins are required to
  interface
 ****************************************************/
#define BLYNK_PRINT Serial

/* Fill in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "XXXXXXXXXX"
#define BLYNK_TEMPLATE_NAME "XXXXXXXXX"
#define BLYNK_AUTH_TOKEN "XXXXXXXXXXXX"

#include <Wire.h>
#include "Adafruit_HTU21DF.h"
#include <BH1750.h>
#include <DallasTemperature.h>

//Wifi Setup
#include <WiFiS3.h>
#include <SPI.h>
#include <BlynkSimpleWifi.h>

int status = WL_IDLE_STATUS;
//#include "arduino_secrets.h"
#define SECRET_SSID "XXXXXXX"
#define SECRET_PASS "XXXXXXXXXX"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;  // your network SSID (name)
char pass[] = SECRET_PASS;  // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;           // your network key index number (needed only for WEP)

unsigned int localPort = XXXX;  // local port to listen on

char packetBuffer[256];                 //buffer to hold incoming packet
char ReplyBuffer[] = "acknowledged\n";  // a string to send back

WiFiUDP Udp;
//WifiSetup



#define ONE_WIRE_BUS 6  //water temperature
// Connect Vin to 3-5VDC
// Connect GND to ground
// Connect SCL to I2C clock pin (A5 on UNO)
// Connect SDA to I2C data pin (A4 on UNO)
OneWire oneWire(ONE_WIRE_BUS);  //water temperature

Adafruit_HTU21DF htu = Adafruit_HTU21DF();
BH1750 lightMeter;
DallasTemperature sensors(&oneWire);  //water temperature

#define TdsSensorPin A0    //TDS meter
#define VREF 3.3           // analog reference voltage(Volt) of the ADC
#define SCOUNT 30          // sum of sample point
int analogBuffer[SCOUNT];  // store the analog value in the array, read from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0, copyIndex = 0;
float averageVoltage = 0, tdsValue = 0, temperature = 25;
IPAddress remoteIp(5,189,182,151);
unsigned int remotePort = 5000; //NEW

//pH:
#define SensorPin A1         //pH meter Analog output to Arduino Analog Input 1
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10], temp;



void setup() {
  Serial.begin(9600);
  //WfiSetup
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }

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

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to WiFi");
  printWifiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  Udp.begin(localPort);

  //WifiSetUp
  Serial.println("HTU21D-F test");

  Wire.begin();
  lightMeter.begin();
  sensors.begin();               //water temperature
  pinMode(TdsSensorPin, INPUT);  //TDS meter

  Serial.println(F("BH1750 Test begin"));
  if (!htu.begin()) {
    Serial.println("Couldn't find sensor!");
    while (1)
      ;
  }
    Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  // You can also specify server:
  //Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, "blynk.cloud", 80);
  //Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, IPAddress(192,168,1,100), 8080);

  
}

void loop() {
  
  Blynk.run();
  
  Udp.beginPacket(remoteIp, remotePort);  //Wifi
  //pH:
  for (int i = 0; i < 10; i++)  //Get 10 sample value from the sensor for smooth the value
  {
    buf[i] = analogRead(SensorPin);
    delay(10);
  }
  for (int i = 0; i < 9; i++)  //sort the analog from small to large
  {
    for (int j = i + 1; j < 10; j++) {
      if (buf[i] > buf[j]) {
        temp = buf[i];
        buf[i] = buf[j];
        buf[j] = temp;
      }
    }
  }
  avgValue = 0;
  for (int i = 2; i < 8; i++)  //take the average value of 6 center sample
    avgValue += buf[i];
  float phValue = (float)avgValue * 5.0 / 1024 / 6;  //convert the analog into millivolt
  phValue = 3.5 * phValue;                           //convert the millivolt into pH value
  Serial.print("pH:");
  Serial.print(phValue, 2);
  Serial.println(" ");
  Udp.print(" "); 
  Udp.print(phValue, 2);
  Udp.print("*"); 
  //digitalWrite(2, HIGH);
  delay(800);

  float temp = htu.readTemperature();
  float rel_hum = htu.readHumidity();
  float lux = lightMeter.readLightLevel();
  Serial.print("Temp: ");
  Serial.print(temp);
  Serial.print(" C");
  Serial.println("\t\t");
  Serial.print("Humidity: ");
  Serial.print(rel_hum);
  Serial.println(" \%");
  Serial.print("Light: ");
  Serial.print(lux);
  Serial.println(" lx");
  //Udp.print("Temp: ");
  Udp.print(temp);
  Udp.print("*");
  //Udp.println("\t\t");
  //Udp.print("Humidity: ");
  Udp.print(rel_hum);
  Udp.print("*");
  //Udp.print("Light: ");
  Udp.print(lux);
  Udp.print("*");
  //Udp.endPacket(); // Änderung 31.05
  //sensorData = analogRead(phValue); // this is an example of reading sensor data
  Blynk.virtualWrite(V1, lux);
  Blynk.virtualWrite(V6, phValue);
  Blynk.virtualWrite(V3, temp);
  Blynk.virtualWrite(V5, rel_hum);
  delay(3000);

  sensors.requestTemperatures();  //water temperature

  Serial.print("Celsius water temperature: ");
  // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
  Serial.print(sensors.getTempCByIndex(0));
  Serial.print(" - Fahrenheit water temperature: ");
  Serial.println(sensors.getTempFByIndex(0));
  //Udp.print("Celsius water temperature: ");
  Udp.print(sensors.getTempCByIndex(0));
  Udp.print("*");
  //Udp.println(sensors.getTempFByIndex(0));
  Blynk.virtualWrite(V0, sensors.getTempCByIndex(0));
  delay(3000); 

  //TDS meter
  static unsigned long analogSampleTimepoint = millis();
  if (millis() - analogSampleTimepoint > 40U)  //every 40 milliseconds,read the analog value from the ADC
  {
    analogSampleTimepoint = millis();
    analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin);  //read the analog value and store into the buffer
    analogBufferIndex++;
    if (analogBufferIndex == SCOUNT)
      analogBufferIndex = 0;
  }
  static unsigned long printTimepoint = millis();
  if (millis() - printTimepoint > 800U) {
    printTimepoint = millis();
    for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
      analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
    averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0;                                                                                                   // read the analog value more stable by the median filtering algorithm, and convert to voltage value
    float compensationCoefficient = 1.0 + 0.02 * (temperature - 25.0);                                                                                                                //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
    float compensationVolatge = averageVoltage / compensationCoefficient;                                                                                                             //temperature compensation
    tdsValue = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5;  //convert voltage value to tds value
    //Serial.print("voltage:");
    //Serial.print(averageVoltage,2);
    //Serial.print("V   ");
    Serial.print("TDS-Value:");
    Serial.print(tdsValue, 0);
    Serial.println("ppm");
    //Udp.print("TDS-Value:");
    Udp.print(tdsValue, 0);
    Udp.print("*");
    Blynk.virtualWrite(V2, tdsValue);
  }
  Udp.endPacket();
}
int getMedianNum(int bArray[], int iFilterLen) {
  int bTab[iFilterLen];
  for (byte i = 0; i < iFilterLen; i++)
    bTab[i] = bArray[i];
  int i, j, bTemp;
  for (j = 0; j < iFilterLen - 1; j++) {
    for (i = 0; i < iFilterLen - j - 1; i++) {
      if (bTab[i] > bTab[i + 1]) {
        bTemp = bTab[i];
        bTab[i] = bTab[i + 1];
        bTab[i + 1] = bTemp;
      }
    }
  }
  if ((iFilterLen & 1) > 0)
    bTemp = bTab[(iFilterLen - 1) / 2];
  else
    bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
  return bTemp;
  
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Please try it out for yourself and give me some feedback :slight_smile:

1 Like

Nice! :slight_smile:
You should publish it on Arduino's Project Hub https://projecthub.arduino.cc/

Great idea! Just did that!

Just a note: as mentioned elsewhere, while it's quite common to use while (!Serial) {} to make sure the Serial port is available to print stuff on it, this instruction will block your script if your Arduino is not connected to a USB port, i.e., is not connected to a computer. So if you power your board directly from, say a battery, the execution will never go past that line.

A better option is to use:
while (!Serial && millis() < 3000) {}

This way, if you're not connected to a computer, after 3 seconds, your sketch will continue to the loop function and will send your data to Blynk.

1 Like