Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
skruglewicz
Published

Edible Algae Growing Cycle Monitor

I've decided to come up with a system that will help grow Spirulina Algae in a self contained space.

IntermediateFull instructions providedOver 1 day414

Things used in this project

Hardware components

Seeed Studio LoRaWAN Dev Kit
Seeed Studio LoRaWAN Dev Kit
×1
Grove - LoRa Radio 433MHz
Seeed Studio Grove - LoRa Radio 433MHz
×1
Grove starter kit plus for Intel Edison
Seeed Studio Grove starter kit plus for Intel Edison
×1
Grove - Relay
Seeed Studio Grove - Relay
×1

Software apps and online services

Edge Impulse Studio
Edge Impulse Studio
Seeed Studio Quick Start with SenseCAP K1100 - The Sensor Prototype Kit (Beta)
Getting Started with Seeed Studio LoRaWAN Dev Kit

Story

Read more

Code

E5-light_exposure_main.ino

Arduino
Implementation of the light exposure firmware used to maintain the ideal light exposure to grow the spirulina.
#include <Arduino.h>
#include "disk91_LoRaE5.h"
#include "RTC_SAMD51.h"
#include "DateTime.h"
#include"TFT_eSPI.h"

TFT_eSPI tft;     // TFY object
RTC_SAMD51 rtc;   //RTC OBJECT

int x = 0; //global used to count x pixels and increment by 20

int sensorPin = 0;

Disk91_LoRaE5 lorae5(&Serial); // Where the AT command and debut traces are printed

#define Frequency DSKLORAE5_ZONE_US915
/*
Select your frequency band here.
DSKLORAE5_ZONE_EU868
DSKLORAE5_ZONE_US915
 */

// char deveui[] = "";
// char appeui[] = "";
// char appkey[] = "";

void display_line(String msg)
{
  static int16_t x; //global used to count x pixels and increment by 20

  char buffer[50];
  sprintf(buffer,"current screen x pixel:%d ",x);
  Serial.println(buffer);

  //check if this is the last line
  if (x == 240)
  {
    tft.fillScreen(TFT_BLACK); //Black background
    tft.drawRect( 0,2,320,240,TFT_GREEN);
    x=0;
  } 
  tft.drawString(msg, 2, x); 
  x = x + 20;
}

void data_decord(int val, uint8_t data[2])
{ 
  data[0] = val >> 8 & 0xFF;
  data[1] = val & 0xFF;
}

void SendValue(int val)
{
  static uint8_t data[2] = { 0x00 };  //Use the data[] to store the values of the sensors
  
  //print the value to send
  char buffer[50];
  sprintf(buffer,"Value To Send: %d ",val);
  Serial.println(buffer);
  display_line(buffer);

  data_decord(val, data);

  if ( lorae5.send_sync(              //Sending the sensor values out
        8,                            // LoRaWan Port
        data,                         // data array
        sizeof(data),                 // size of the data
        false,                        // we are not expecting a ack
        7,                            // Spread Factor
        14                            // Tx Power in dBm
       ) 
  ) {
      Serial.println("Uplink done");
      display_line("Uplink done");

      if ( lorae5.isDownlinkReceived() ) {
        Serial.println("A downlink has been received");
        display_line("A downlink has been received");
        if ( lorae5.isDownlinkPending() ) {
          Serial.println("More downlink are pending");
          display_line("More downlink are pending");
        }
      }
  }else{
    Serial.println("Uplink FAILED.. DATA not sent");
    display_line("Uplink FAILED.. DATA not sent");
  }
}
void LightON()
{
  digitalWrite(0, HIGH); //on
  display_line("Light Set: ON");
}

void LightOFF()
{
  digitalWrite(0, LOW);  // off
  display_line("Light Set: OFF");
}

bool IsLightON()
{
  int light = analogRead(WIO_LIGHT);  //Get the Wio Terminal light value.
 
  //print the light value
  char buffer[50];
  sprintf(buffer,"Light Value: %d ",x);
  Serial.println(buffer);
  display_line(buffer);

// send the current light value
  SendValue(light);
  
  if (light < 100) {return false;}
  else {return true;}
}


void setup(void)
{ 
  rtc.begin();

  //TFT    
  tft.begin();
  tft.setRotation(3);
  tft.setTextSize(2); 

  // RTC setup
  DateTime now = DateTime(F(__DATE__), F(__TIME__));
  Serial.println("adjust time!");
  rtc.adjust(now);
 
  pinMode(0, OUTPUT); 
  Serial.begin(9600);
  uint32_t start = millis();
  while ( !Serial && (millis() - start) < 1500 );  // Open the Serial Monitor to get started or wait for 1.5"
  
  // init the library, search the LORAE5 on port 1 LEFT Grove port
  if ( ! lorae5.begin(DSKLORAE5_SWSERIAL_WIO_P1) ) {
    Serial.println("LoRa E5 Init Failed");
    display_line("LoRa E5 Init Failed");
    while(1); 
  }  

  // Setup the LoRaWan Credentials
  if ( ! lorae5.setup(
        Frequency,
        deveui,
        appeui,
        appkey
     ) ){
    Serial.println("LoRa E5 Setup Failed");
    display_line("LoRa E5 Setup Failed");
 
    while(1);         
  }
}
 

void loop(void)
{
// get the current time and get the currtent Hour and Minute from the rtc object
DateTime now = rtc.now();
DateTime hr = now.hour();
DateTime mins = now.minute();


Serial.print("current time:   ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.println(now.minute(), DEC);


//sprintf( time )
char buffer[50];
sprintf(buffer,"current time: %d:%d",hr,mins); ///?????
String current_Time = String(buffer);
display_line(current_Time);
Serial.println(current_Time);


//Set up some 
tft.fillScreen(TFT_BLACK); //Black background
tft.drawRect( 0,2,320,240,TFT_RED);
tft.setTextSize(1);   
int16_t x = 0;

display_line("Starting - on the next hour" );


// // start on the next hour
// // loop every min until mins = 00
//   if ( mins != zeroMins ) {
//     delay(1000*60);
//     while(1); 
//   }  

// Check if it's in the proper time range (between 7pm and 10pm every night.)  else wait for an hour
if ((hr >= 19 or hr <= 10) and mins <= 45)
  {
    LightON();
    //SendValue(HIGH);

    //Check if the light is actually ON If not, then send a message to the display (for now, but I could sent an alert in the future)
    if ( ! IsLightON() ){   
      //Send a message to display "Light should be on But it is not"
      Serial.println('Light should be on But it is not');
      display_line("Light should be ON But it is not");
    } else {
      //Send a message to display "  OK the light is on 
      Serial.println('OK the light is on');
      display_line("OK the light is ON");
    }
    
    delay(2700000); // 45 minutes

    LightOFF();
    //SendValue(LOW);

    delay(900000);  // 15 minutes 

  } else
  {
    Serial.println('SLEEP for an HOUR');
    display_line("Sleep for 45 minutes");
    delay(2700000); // 45 minutes
    display_line("Sleep for 15 minutes");
    delay(900000);  // 15 minutes 
  }

}

E5-light_exposure_Test.ino

Arduino
This will test if my design is working to "Maintain the right Amount of light exposure"
#include <Arduino.h>
#include "disk91_LoRaE5.h"
#include "RTC_SAMD51.h"
#include "DateTime.h"

int sensorPin = 0;

Disk91_LoRaE5 lorae5(&Serial); // Where the AT command and debut traces are printed

#define Frequency DSKLORAE5_ZONE_US915
/*
Select your frequency band here.
DSKLORAE5_ZONE_EU868
DSKLORAE5_ZONE_US915
DSKLORAE5_ZONE_AS923_1
DSKLORAE5_ZONE_AS923_2
DSKLORAE5_ZONE_AS923_3
DSKLORAE5_ZONE_AS923_4
DSKLORAE5_ZONE_KR920
DSKLORAE5_ZONE_IN865
DSKLORAE5_ZONE_AU915
 */

// char deveui[] = "";
// char appeui[] = "";
// char appkey[] = "";


void data_decord(int val, uint8_t data[2])
{ 
  data[0] = val >> 8 & 0xFF;
  data[1] = val & 0xFF;
}

void SendValue(int val)
{
  static uint8_t data[2] = { 0x00 };  //Use the data[] to store the values of the sensors

  data_decord(val, data);

  if ( lorae5.send_sync(              //Sending the sensor values out
        8,                            // LoRaWan Port
        data,                         // data array
        sizeof(data),                 // size of the data
        false,                        // we are not expecting a ack
        7,                            // Spread Factor
        14                            // Tx Power in dBm
       ) 
  ) {
      Serial.println("Uplink done");

      if ( lorae5.isDownlinkReceived() ) {
        Serial.println("A downlink has been received");
        if ( lorae5.isDownlinkPending() ) {
          Serial.println("More downlink are pending");
        }
      }
  }else{
    Serial.println("Uplink FAILED.. DATA not sent");
  }
}
void LightON()
{
  digitalWrite(0, HIGH); //on
}

void LightOFF()
{
  digitalWrite(0, LOW);  // off
}

bool IsLightON()
{
  int light = analogRead(WIO_LIGHT);  //Get the Wio Terminal light value.
  Serial.print("Light Value: "); Serial.println(light);
  if (light < 100) {return false;}
  else {return true;}
}

RTC_SAMD51 rtc;   //RTC OBJECT

void setup(void)
{ 
    rtc.begin();
    
  // RTC setup
  DateTime now = DateTime(F(__DATE__), F(__TIME__));
  Serial.println("adjust time!");
  rtc.adjust(now);
 
  pinMode(0, OUTPUT); 
  Serial.begin(9600);
  uint32_t start = millis();
  while ( !Serial && (millis() - start) < 1500 );  // Open the Serial Monitor to get started or wait for 1.5"
  
  // init the library, search the LORAE5 on port 1 LEFT Grove port
  if ( ! lorae5.begin(DSKLORAE5_SWSERIAL_WIO_P1) ) {
    Serial.println("LoRa E5 Init Failed");
    while(1); 
  }  

  // Setup the LoRaWan Credentials
  if ( ! lorae5.setup(
        Frequency,
        deveui,
        appeui,
        appkey
     ) ){
    Serial.println("LoRa E5 Setup Failed");
 
    while(1);         
  }
}
 

void loop(void)
{
// get the current time and get the currtent Hour and Minute from the rtc object
DateTime now = rtc.now();
DateTime hr = now.hour();
DateTime mins = now.minute();

Serial.print("current time:   ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.println(':');


// Check if it's in the proper time range (between 7pm and 10pm every night.)  else wait for an hour
if ((hr >= 19 or hr <= 10) and mins <= 45)
  {
    LightON();
  
    SendValue(HIGH);

    //Check if the light is actually ON If not, then send a message to the display (for now, but I could sent an alert in the future)
    if ( ! IsLightON() ){   
      //Send a message to display "Light should be on But it is not"
      Serial.println('Light should be on But it is no');
    } else {
      //Send a message to display "  OK the light is on 
      Serial.println('OK the light is on');
    }
    
    delay(2700000); // 45 minutes

    LightOFF();

    SendValue(LOW);

    delay(900000);  // 15 minutes 

  } else
  {
    delay(2700000); // 45 minutes
    delay(900000);  // 15 minutes 
  }

}

relay-test.ini

Arduino
Short firmware to test the Grove Relay
void setup() {
  pinMode(0, OUTPUT);    // sets the digital pin 13 as output
}

void loop() {
  digitalWrite(0, HIGH); // sets the digital pin 13 on
  delay(1000);            // waits for a second
  digitalWrite(0, LOW);  // sets the digital pin 13 off
  delay(1000);            // waits for a second
}

E5-relay-test1.ino

Arduino
Basic Grove Relay example
void setup() {
  pinMode(0, OUTPUT);    // sets the digital pin 13 as output
}

void loop() {
  digitalWrite(0, HIGH); // sets the digital pin 13 on
  delay(1000);            // waits for a second
  digitalWrite(0, LOW);  // sets the digital pin 13 off
  delay(1000);            // waits for a second
}

E5_RTC_TEST.ino

Arduino
This test demonstrates how to use the built-in RTC functionality inside the SAMD51 core within Wio Terminal.
#include "RTC_SAMD51.h"
#include "DateTime.h"
 
RTC_SAMD51 rtc;
void setup()
{
    rtc.begin();
 
    Serial.begin(115200);
 
    while (!Serial)
    {
        ;
    }
 
    DateTime now = DateTime(F(__DATE__), F(__TIME__));
    Serial.println("adjust time!");
    rtc.adjust(now);
 
    now = rtc.now();
 
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
 
    DateTime alarm = DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second() + 15);
 
    rtc.setAlarm(0,alarm); // match after 15 seconds
    rtc.enableAlarm(0, rtc.MATCH_HHMMSS); // match Every Day
 
    rtc.attachInterrupt(alarmMatch); // callback whlie alarm is match
 
}
 
void loop()
{
}
 
void alarmMatch(uint32_t flag)
{
 
    Serial.println("Alarm Match!");
    DateTime now = rtc.now();
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
}

Credits

skruglewicz

skruglewicz

24 projects • 10 followers
I am now a retired Senior Software Engineer with a Bachelor’s of Science Degree in Computer Science from Boston University.

Comments