1. Seeeduino LoRaWAN: The Microcontroller

1.1. Description

Seeeduino LoRaWAN is an Arduino development board with LoRaWan protocol embedded, through which you can get started quickly to experience LoRa's advantage in the field of IoT. 

Click here for more information.


Item Value
Microcontroller ATSAMD21G18, 32-Bit ARM Cortex M0+
Operating Voltage 3.3V
Digital I/O Pins 20
PWM Pins All but pins 2 and 7
UART 2 (Native and Programming)
Analog Input Pins 6, 12-bit ADC channels
Analog Output Pins 1, 10-bit DAC
External Interrupts All pins except pin 4
DC Current per I/O Pin 7 mA
Flash Memory 256 KB
SRAM 32 KB
EEPROM None
Clock Speed 48 MHz
Lenght 68 mm
Width 53 mm
Weight 19.6g(without GPS), 19.9(with GPS)

Table 1. Seeeduino LoRaWAN Specification

1.2. Compatibility Issues

The colors are working on the RGB LCD, but the text is missing. This may be due to a voltage incompatibility.

2. Grove - Sunlight Sensor

2.1. Description

Link: https://wiki.seeedstudio.com/Grove-Sunlight_Sensor/

The Grove - Sunlight Sensor measures ambient light intensity, including visible, infrared, and UV light, making it suitable for environmental monitoring applications. It can be used in smart gardening or weather stations to adjust lighting conditions or track sunlight exposure accurately.

Specification Value
operating voltage 3.0 - 5.5 V
Working current 3.5 mA
Default I2C Adress 0x60
operating Temperature -45 - +85°C

Table 2: Specification

2.2. Step 1: Connect the hardware

Figure 1. Hardware setup of the Grove - Sunlight Sensor

2.3. Step 2: Download library

Download library here: https://github.com/Seeed-Studio/Grove_Sunlight_Sensor/tree/master

Add the library to the Arduino IDE

2.4. Step 3: Run Example Code

Example Code for the Sunlight Sensor
/*
    This is a demo to test Grove - Sunlight Sensor library

*/

#include <Wire.h>

#include "Arduino.h"
#include "SI114X.h"

#define PIN_GROVE_POWER 38

SI114X SI1145 = SI114X();

void setup() {
    pinMode(PIN_GROVE_POWER, OUTPUT);
    digitalWrite(PIN_GROVE_POWER, 1);

    Serial.begin(115200);
    Serial.println("Beginning Si1145!");

    while (!SI1145.Begin()) {
        Serial.println("Si1145 is not ready!");
        delay(1000);
    }
    Serial.println("Si1145 is ready!");
}

void loop() {
    Serial.print("//--------------------------------------//\r\n");
    Serial.print("Vis: "); Serial.println(SI1145.ReadVisible());
    Serial.print("IR: "); Serial.println(SI1145.ReadIR());
    //the real UV value must be div 100 from the reg value , datasheet for more information.
    Serial.print("UV: ");  Serial.println((float)SI1145.ReadUV() / 100);
    delay(1000);
}

2.5. Sensor Output in the Serial monitor:

Figure 2. Sensor Output in the Serial Monitor

3. Grove - Capacitive Moisture Sensor (Corrosion Resistant)

3.1. Description

The Grove - Capacitive Moisture Sensor (Corrosion Resistant) is a soil moisture sensor based on capacitance changes. Compared with resistive sensors, capacitive sensors do not require direct exposure of the metal electrodes, which can significantly reduce the erosion of the electrodes. Hence, we call it Corrosion Resistant.

Typical Applications:

  • Soil moisture detection
  • Automatic watering of plants

Source


Item Value
Operating Voltage 3.3V / 5V
Output Interface Analog
Length 92.1mm
Width 23.5mm
Height 6.5mm
size L: 40mm W: 20mm H: 13mm
Weight 10.6g
Package size L: 150mm W: 100mm H: 15mm
Gross Weight 19g

Table 2. Capacitive Moisture Sensor Specification

3.2. Image of the hardware setup

Figure 3. The setup at home. Seeeduino LoRaWAN + Capacitive Moisture Sensor

3.3. Source code


Test Code for Grove - Capacitive Moisture Sensor
/*
  Grove - Capacitive Moisture Sensor Test Code
  For Seeeduino LoRaWAN
*/

// The Seeeduino LoRaWAN requires pin 38 to be turned HIGH to power the Grove ports
#define PIN_GROVE_POWER 38

// Define the analog pin the sensor is connected to
const int sensorPin = A0; 

void setup() {
  // Initialize serial communication at 9600 baud rate
  Serial.begin(9600);

  // Power up the Grove connectors
  pinMode(PIN_GROVE_POWER, OUTPUT);
  digitalWrite(PIN_GROVE_POWER, 1);
  
  Serial.println("Moisture Sensor Test Initialized");
  
  // A short delay to let the sensor stabilize after powering up
  delay(1000); 
}

void loop() {
  // Read the analog value from the sensor
  int sensorValue = analogRead(sensorPin);

  // Option 1: Just print the number (Simplest for the plotter)
  // Serial.println(sensorValue);

  // Option 2: Print with a label so the plotter gives it a nice legend
  // Notice there are NO spaces before or after the colon!
  Serial.print("Moisture:");
  Serial.println(sensorValue);

  // Wait for 1 second before taking the next reading
  delay(1000);
}

3.4. The unit of measure of all observations of the sensor

The standard unit of measurement for the capacitive moisture sensor is not specified in the documentation. 

3.5. Serial Monitor & Serial Plot Observations



4. Grove - Water Level Sensor (10 cm)

Link: https://wiki.seeedstudio.com/Grove-Water-Level-Sensor/

The Water Level Sensor detects the water level on a length of 10 cm. It is completely water proof and uses capacitive pads to detect water levels with high accuracy.

Specification Value
Input voltage 3.3V / 5V
Measurement Accuracy +-5mm
Working Temperature Range -40°C - + 105°C
I2C Adresses 0x78 and 0x77
Interface I2C
Dimensions 20mm x 133 mm

Table 3. Specification - Water Level Sensor

4.1. Hardware Connection

Required Hardware:

  • Seeeduino V4.2
  • Base Shield
  • Grove - Water Level Sensor

Required Steps:

  1. Plug Grove - Water Level Sensor to I2C port of Grove - Base Shield.
  2.  Plug Grove - Base Shield into Seeeduino.
  3. Connect Seeeduino to a PC via a USB cable.

4.2. Run Example Code

Example Code for Water Level Sensor
#include <Wire.h>

#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif

unsigned char low_data[8] = {0};
unsigned char high_data[12] = {0};


#define NO_TOUCH       0xFE
#define THRESHOLD      100
#define ATTINY1_HIGH_ADDR   0x78
#define ATTINY2_LOW_ADDR   0x77

void getHigh12SectionValue(void)
{
  memset(high_data, 0, sizeof(high_data));
  Wire.requestFrom(ATTINY1_HIGH_ADDR, 12);
  while (12 != Wire.available());

  for (int i = 0; i < 12; i++) {
    high_data[i] = Wire.read();
  }
  delay(10);
}

void getLow8SectionValue(void)
{
  memset(low_data, 0, sizeof(low_data));
  Wire.requestFrom(ATTINY2_LOW_ADDR, 8);
  while (8 != Wire.available());

  for (int i = 0; i < 8 ; i++) {
    low_data[i] = Wire.read(); // receive a byte as character
  }
  delay(10);
}

void check()
{
  int sensorvalue_min = 250;
  int sensorvalue_max = 255;
  int low_count = 0;
  int high_count = 0;
  while (1)
  {
    uint32_t touch_val = 0;
    uint8_t trig_section = 0;
    low_count = 0;
    high_count = 0;
    getLow8SectionValue();
    getHigh12SectionValue();

    Serial.println("low 8 sections value = ");
    for (int i = 0; i < 8; i++)
    {
      Serial.print(low_data[i]);
      Serial.print(".");
      if (low_data[i] >= sensorvalue_min && low_data[i] <= sensorvalue_max)
      {
        low_count++;
      }
      if (low_count == 8)
      {
        Serial.print("      ");
        Serial.print("PASS");
      }
    }
    Serial.println("  ");
    Serial.println("  ");
    Serial.println("high 12 sections value = ");
    for (int i = 0; i < 12; i++)
    {
      Serial.print(high_data[i]);
      Serial.print(".");

      if (high_data[i] >= sensorvalue_min && high_data[i] <= sensorvalue_max)
      {
        high_count++;
      }
      if (high_count == 12)
      {
        Serial.print("      ");
        Serial.print("PASS");
      }
    }

    Serial.println("  ");
    Serial.println("  ");

    for (int i = 0 ; i < 8; i++) {
      if (low_data[i] > THRESHOLD) {
        touch_val |= 1 << i;

      }
    }
    for (int i = 0 ; i < 12; i++) {
      if (high_data[i] > THRESHOLD) {
        touch_val |= (uint32_t)1 << (8 + i);
      }
    }

    while (touch_val & 0x01)
    {
      trig_section++;
      touch_val >>= 1;
    }
    SERIAL.print("water level = ");
    SERIAL.print(trig_section * 5);
    SERIAL.println("% ");
    SERIAL.println(" ");
    SERIAL.println("*********************************************************");
    delay(1000);
  }
}

void setup() {
  SERIAL.begin(115200);
  Wire.begin();
}

void loop()
{
  check();
}

4.3. Output

4.3.1. Setup for testing the sensor

4.3.2. Results of the Sensor

5.  Grove - Temperature, Humidity, Pressure and Gas Sensor (BME680)

5.1. Description

The Grove – BME 680 is a multiple function sensor which can measure temperature, pressure, humidity and gas at the same time.


Measurement Variable Unit
Temperature Degree Celsius [°C]
Humidity Percent [%]
Pressure Kilopascal [kPa]
Gas
(air quality)
Kiloohm [kΩ]



Specification Value
Input voltage 3.3V / 5V
Operating Range -40 ~ +85°C; 
0 - 100 % r.H.;
300 - 1100 hPa
Interface I2C, SPI
I2C Adresses 0x76 (default) / 0x77 (optional)

source: seedstudio

5.2. Compatibility Issues

  • Accurate gas measurements require Arduino boards with larger memory capacity; they are not reliable when using the Seeeduino LoRaWAN.

  • For stable and precise results, the Arduino system should run continuously for approximately 2 hours before taking measurements.

5.3. Resources

5.4. Hardware Setup

  • Microcontroller: Seeeduino LoRaWAN
  • Grove - 16x2 LCD Display
  • Sensor- and display connection: I²C
  • Power supply: 5 V USB

5.5. Source Code

Test Code for Grove - BME680 with LCD 16x2
#include <Wire.h>
#include "rgb_lcd.h"
#include "seeed_bme680.h"

#define PIN_GROVE_POWER 38
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10
#define IIC_ADDR  uint8_t(0x76)

rgb_lcd lcd;
Seeed_BME680 bme680(IIC_ADDR);

const int colorR = 255;
const int colorG = 0;
const int colorB = 0;

void setup() {
    pinMode(PIN_GROVE_POWER, OUTPUT);
    digitalWrite(PIN_GROVE_POWER, 1);
    delay(100);

    Serial.begin(9600);

    // init lcd
    lcd.begin(16, 2);
    lcd.setRGB(colorR, colorG, colorB);
    lcd.print("Initializing...");

    // init bme680
    if (!bme680.init()) {
        Serial.println("BME680 init failed!");
        lcd.clear();
        lcd.print("Sensor Error");
    } else {
        Serial.println("BME680 init success!");
        lcd.clear();
        lcd.print("Sensor Ready!");
    }
    
    delay(2000);
    lcd.clear();
}

void loop() {

        if (bme680.read_sensor_data()) {
        Serial.println("Failed to perform reading :(");
        return;
    }
    Serial.print("temperature ===>> ");
    Serial.print(bme680.sensor_result_value.temperature);
    Serial.println(" C");
    lcd.setCursor(0, 0);
    lcd.print("temp: ");
    lcd.setCursor(9, 0);
    lcd.print(bme680.sensor_result_value.temperature);
    lcd.print(" C");

    Serial.print("humidity ===>> ");
    Serial.print(bme680.sensor_result_value.humidity);
    Serial.println(" %");
    lcd.setCursor(0, 1);
    lcd.print("rel hum: ");
    lcd.print(bme680.sensor_result_value.humidity);
    lcd.print(" %");

    delay(8000);
    lcd.clear();

    Serial.print("pressure ===>> ");
    Serial.print(bme680.sensor_result_value.pressure / 1000.0);
    Serial.println(" KPa");
    lcd.setCursor(0, 0);
    lcd.print("press: ");
    lcd.setCursor(8, 0);
    lcd.print(bme680.sensor_result_value.pressure / 1000.0);
    lcd.print(" KP");


    Serial.print("gas ===>> ");
    Serial.print(bme680.sensor_result_value.gas / 1000.0);
    Serial.println(" Kohms");
    lcd.setCursor(0, 1);
    lcd.print("gas: ");
    lcd.setCursor(7, 1);
    lcd.print(bme680.sensor_result_value.gas / 1000.0);
    lcd.print(" KO");

    delay(5000);
    lcd.clear();
}

5.6. Serial Monitor, Serial Plot Observations and LCD Output


6. Water Flow Sensor

6.1. General Description

Link: https://wiki.seeedstudio.com/Water-Flow-Sensor/

6.2. Hardware Connection

Required components

  • Seeeduino Board
  • Base shield
  • Water Flow Sensor

Figure: Water flow sensor - Hardware connection


#include <Wire.h>

#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif

unsigned char low_data[8] = {0};
unsigned char high_data[12] = {0};


#define NO_TOUCH       0xFE
#define THRESHOLD      100
#define ATTINY1_HIGH_ADDR   0x78
#define ATTINY2_LOW_ADDR   0x77

void getHigh12SectionValue(void)
{
  memset(high_data, 0, sizeof(high_data));
  Wire.requestFrom(ATTINY1_HIGH_ADDR, 12);
  while (12 != Wire.available());

  for (int i = 0; i < 12; i++) {
    high_data[i] = Wire.read();
  }
  delay(10);
}

void getLow8SectionValue(void)
{
  memset(low_data, 0, sizeof(low_data));
  Wire.requestFrom(ATTINY2_LOW_ADDR, 8);
  while (8 != Wire.available());

  for (int i = 0; i < 8 ; i++) {
    low_data[i] = Wire.read(); // receive a byte as character
  }
  delay(10);
}

void check()
{
  int sensorvalue_min = 250;
  int sensorvalue_max = 255;
  int low_count = 0;
  int high_count = 0;
  while (1)
  {
    uint32_t touch_val = 0;
    uint8_t trig_section = 0;
    low_count = 0;
    high_count = 0;
    getLow8SectionValue();
    getHigh12SectionValue();

    Serial.println("low 8 sections value = ");
    for (int i = 0; i < 8; i++)
    {
      Serial.print(low_data[i]);
      Serial.print(".");
      if (low_data[i] >= sensorvalue_min && low_data[i] <= sensorvalue_max)
      {
        low_count++;
      }
      if (low_count == 8)
      {
        Serial.print("      ");
        Serial.print("PASS");
      }
    }
    Serial.println("  ");
    Serial.println("  ");
    Serial.println("high 12 sections value = ");
    for (int i = 0; i < 12; i++)
    {
      Serial.print(high_data[i]);
      Serial.print(".");

      if (high_data[i] >= sensorvalue_min && high_data[i] <= sensorvalue_max)
      {
        high_count++;
      }
      if (high_count == 12)
      {
        Serial.print("      ");
        Serial.print("PASS");
      }
    }

    Serial.println("  ");
    Serial.println("  ");

    for (int i = 0 ; i < 8; i++) {
      if (low_data[i] > THRESHOLD) {
        touch_val |= 1 << i;

      }
    }
    for (int i = 0 ; i < 12; i++) {
      if (high_data[i] > THRESHOLD) {
        touch_val |= (uint32_t)1 << (8 + i);
      }
    }

    while (touch_val & 0x01)
    {
      trig_section++;
      touch_val >>= 1;
    }
    SERIAL.print("water level = ");
    SERIAL.print(trig_section * 5);
    SERIAL.println("% ");
    SERIAL.println(" ");
    SERIAL.println("*********************************************************");
    delay(1000);
  }
}

void setup() {
  SERIAL.begin(115200);
  Wire.begin();
}

void loop()
{
  check();
}


7. Extra - Anything other Wiki function you want to try out

Ursprüngliche FROST Tabelle:


Name GroupNo Thing DevEUI Sensor ObservedProperty LppChannelNr FROST Datastream IDs
Simon Strohmeier 10 Urban Gardening Planting Space 1

TTN: 8765182202E81E0F

Grove - Sunlight Sensor Visible light (lm) 4 1783


SWM: Infrared light (lm) 5 1784



Ultraviolett light (UV index) 6 1785



Grove - Capacitive Moisture Sensor (Corrosion Resistant) Soil moisture 8 1786



Grove - Water Level Sensor (10 cm) Water level (cm) 10 1787



Grove - Temperature, Humidity, Pressure and Gas Sensor (BME680) Temperature (°C) 1 1780



Relative Humidity (%) 2 1781



Pressure (kPa) 3 1815



Water Flow Sensor Water Flow (L/h) 9 1788



Ultrasonic sensor Distance (cm) 7 1782


I like cheese!

the last page update 09.08.2026 11:15



  • No labels