Project tutorial
FPGArdening v3 by Guntas Singh

FPGArdening v3 by Guntas Singh © GPL3+

A weather monitor that measures 10 environmental properties and sends data to Blynk and over HDMI on the Vidor 4000 (HDMI is still in beta)

  • 869 views
  • 0 comments
  • 1 respect

Components and supplies

Necessary tools and machines

Apps and online services

About this project

This is going to be a summarised tutorial (one which is rather short).

In this tutorial, I'm gonna show you guys how to build a working weather station that can measure temp, humidity, pressure, luminance and the concentration of PM2.5 particulate matter in the environment, along with a STEMMA soil sensor to measure soil moisture (in analog) and soil temperature. This project also contains 2x Li-Ion batteries: 1 for powering the watering pump, and the other one for the Vidor. The values are sent to Blynk and allow for remote control of your project, if it is outside and you're at home, and for indoor watering, you can use Blynk or plug it into an HDMI port on your TV (The HDMI is just added to demonstrate the FPGA's power, you can disable it if you want by commenting out the entire void tv(); and tv (float,...); section).

Wiring:

MKR ENV Shield

Just attach it/ plug it onto the top of the Vidor 4000, respecting the proper orientation of the pins.

STEMMA soil sensor

SDA --> SDA female pin

SCL --> SCL female pin

VCC --> VCC female pin

GND --> GND male pin

SPS30

VDD --> 5V female pin

RX of SPS30 --> TX female pin on Vidor

TX of SPS30 --> RX female pin on Vidor

SEL --> NC (not connected)

GND --> GND female pin

TIP120Transistor

Base --> Pin 7 female

Collector --> Pump Ground

Emitter --> Battery ground

Motorpump

Positive (red wire) --> Battery positive

Ground (Black wire) --> Collector of TIP120

Li-Ionbattery

Positive --> Motor positive

Ground --> Emitter of TIP120 transistor

Code

Now, upload the code given in the FPGArdening section at the end of the project

Values displayed

On Blynk:

Temperature (ENV)

Humidity

Pressure

PM2.5 particulate number concentration

Soil temperature

Soil moisture

Pump activation through remote I/O control

On TV (still in beta mode)

Temperature (ENV)

Humidity

Pressure

Soil temperature

Soil moisture

Code

FPGArdening codeArduino
Upload it to the Vidor and open up the Serial Monitor to visualise the values sent to Blynk and HDMI.
#include "VidorGraphics.h"
#include "Vidor_GFX.h"

Vidor_GFX  vdgfx;

#include <Wire.h>
#include <SPI.h>
#include <Arduino_MKRENV.h>
#include <Adafruit_seesaw.h>
#include <sps30.h>

Adafruit_seesaw ss;

SPS30 sps30;

#define SP30_COMMS Serial1


#include <SPI.h>
#include <WiFiNINA.h>
#include <BlynkSimpleWiFiNINA.h>
BlynkTimer timer;

#define BLYNK_PRINT Serial

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YFirMXKTJpc2LDRXLt23MucsxeuiZXml";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "guntas0_2.4GHz";
char pass[] = "0505183207";

void ErrtoMess(char *mess, uint8_t r);
void Errorloop(char *mess, uint8_t r);
void GetDeviceInfo();
bool read_all();

void setup()
{
  // Debug console
  Serial.begin(115200);
  Serial1.begin(115200);

  // Let's start by initializing the FPGA
  if (!FPGA.begin()) {
    Serial.println("Initialization failed!");
    while (1) {}
  }

  sps30.EnableDebugging(0);

  if (! sps30.begin(SP30_COMMS))
    Errorloop((char *) "could not initialize communication channel.", 0);
  if (! sps30.probe()) Errorloop((char *) "could not probe / connect with SPS30.", 0);
  else  Serial.println(F("Detected SPS30."));

  // reset SPS30 connection
  if (! sps30.reset()) Errorloop((char *) "could not reset.", 0);

  if (sps30.start() == true) Serial.println(F("Measurement started"));
  else Errorloop((char *) "Could NOT start measurement", 0);

  GetDeviceInfo();

  if (!ss.begin(0x36)) {
    Serial.println("ERROR! seesaw not found");
  } else {
    Serial.print("seesaw started! version: ");
    Serial.println(ss.getVersion(), HEX);
  }

    // Let's discover which version we are running
  int version = FPGA.version();
  Serial.print("Vidor bitstream version: ");
  Serial.println(version, HEX);

  // Let's also ask which IPs are included in this bitstream
  FPGA.printConfig();

  Blynk.begin(auth, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);

  timer.setInterval(1000L, update_);

}

void loop()
{
  Blynk.run();
  timer.run();

}
void update_() {
  //FPGA.begin();
  uint8_t ret;
  struct sps_values val;
  float tempC = ss.getTemp();
  uint16_t soil_data = ss.touchRead(0);
  float temperature = ENV.readTemperature();
  float humidity    = ENV.readHumidity();
  float pressure    = ENV.readPressure();
  float illuminance = ENV.readIlluminance();

  ret = sps30.GetValues(&val);

  Blynk.virtualWrite(V1, tempC);
  Blynk.virtualWrite(V3, soil_data);
  Blynk.virtualWrite(V5, temperature);
  Blynk.virtualWrite(V7, humidity);
  Blynk.virtualWrite(V9, pressure);
  Blynk.virtualWrite(V11, illuminance);
  Blynk.virtualWrite(V13, val.NumPM2);

  Serial.println("printing data: ");
  Serial.println("temp: ");
  Serial.println(temperature);
  Serial.println("°C ; Humidity: ");
  Serial.println(humidity);
  Serial.println("%, Pressure: ");
  Serial.println(pressure);
  Serial.println("soil Moisture: ");
  Serial.println(soil_data);
  Serial.println("Soil Temp in °C: ");
  Serial.println(tempC);
  Serial.println("Number of PM2.5 particles");
  Serial.println(val.NumPM2);

  tv (tempC, soil_data, temperature, humidity, pressure, illuminance);
}

void tv(float tempC, uint16_t sm, float temp, float h, float ap, float lux) {

  vdgfx.fillRect(0, 0, 640, 480, vdgfx.Yellow ());

  vdgfx.text.setColor(vdgfx.Green());
  vdgfx.text.setAlpha(187);
  vdgfx.text.setSize(2);
  vdgfx.text.setCursor(15, 40);
  vdgfx.print("FPGArdening");

  vdgfx.text.setCursor(15, 80);
  vdgfx.print("Stats");

  vdgfx.text.setColor(vdgfx.Blue());
  vdgfx.text.setAlpha(255);
  vdgfx.text.setSize(1);
  vdgfx.text.setCursor(15, 140);
  vdgfx.print("Temperature: ");
  vdgfx.print(temp); vdgfx.print(" C");

  vdgfx.text.setCursor(15, 200);
  vdgfx.print("Humidity: ");
  vdgfx.print(h); vdgfx.print("%");

  vdgfx.text.setCursor(15, 260);
  vdgfx.print("Air Pressure: ");
  vdgfx.print(ap); vdgfx.print(" hPa");

  vdgfx.text.setCursor(15, 320);
  vdgfx.print("Soil Moisture: ");
  vdgfx.print(sm); vdgfx.print("%");

  vdgfx.text.setCursor(15, 400);
  vdgfx.print("Soil Temp in *C: ");
  vdgfx.print(tempC); vdgfx.print("*C");

  vdgfx.text.setCursor(15, 420);
  vdgfx.print("Luminance: ");
  vdgfx.print(lux); vdgfx.print("Analog");

  vdgfx.text.setColor(vdgfx.Blue());
  vdgfx.text.setAlpha(120);
  vdgfx.text.setSize(1);
  vdgfx.text.setCursor(15, 460);
  vdgfx.print("FPGArdening v3 by Guntas");
}

void Errorloop(char *mess, uint8_t r)
{
  if (r) ErrtoMess(mess, r);
  else Serial.println(mess);
  Serial.println(F("Program on hold"));
  for (;;) delay(100000);
}

void ErrtoMess(char *mess, uint8_t r)
{
  char buf[80];

  Serial.print(mess);

  sps30.GetErrDescription(r, buf, 80);
  Serial.println(buf);
}

void GetDeviceInfo()
{
  char buf[32];
  uint8_t ret;
  SPS30_version v;

  //try to read serial number
  ret = sps30.GetSerialNumber(buf, 32);
  if (ret == ERR_OK)  {
    Serial.print(F("Serial number : "));
    if (strlen(buf) > 0)  Serial.println(buf);
    else Serial.println(F("not available"));
  }
  else
    ErrtoMess((char *) "could not get serial number.", ret);

  // try to get product name
  ret = sps30.GetProductName(buf, 32);
  if (ret == ERR_OK)  {
    Serial.print(F("Product name : "));

    if (strlen(buf) > 0)  Serial.println(buf);
    else Serial.println(F("not available"));
  }
  else
    ErrtoMess((char *) "could not get product name.", ret);

  // try to get version info
  ret = sps30.GetVersion(&v);
  if (ret != ERR_OK) {
    Serial.println(F("Can not read version info"));
    return;
  }

  Serial.print(F("Firmware level: "));  Serial.print(v.major);
  Serial.print("."); Serial.println(v.minor);

  if (SP30_COMMS != I2C_COMMS) {
    Serial.print(F("Hardware level: ")); Serial.println(v.HW_version);

    Serial.print(F("SHDLC protocol: ")); Serial.print(v.SHDLC_major);
    Serial.print("."); Serial.println(v.SHDLC_minor);
  }

  Serial.print(F("Library level : "));  Serial.print(v.DRV_major);
  Serial.print(".");  Serial.println(v.DRV_minor);
}

Comments

Similar projects you might like

Mobile Weather Station Being Powered by Solar Energy

Project tutorial by Kutluhan Aktar

  • 8,051 views
  • 0 comments
  • 17 respects

Customer Limiting Shop Door Assistant V3 - IoT version

Project tutorial by Harry Anderson

  • 3,470 views
  • 6 comments
  • 15 respects

Arduino Leonardo ETH v3 and MySQL Direct Insert

Project tutorial by amirso

  • 3,537 views
  • 1 comment
  • 3 respects

Using DHT11

by arcaegecengiz

  • 119,465 views
  • 35 comments
  • 61 respects

Arduino / ESP8266 RS485 MODBUS Anemometer

Project in progress by philippedc

  • 27,605 views
  • 10 comments
  • 24 respects
Add projectSign up / Login