Jasper PonsStuart Roberts
Published © MIT

River Level Monitoring for Kayakers and Flash Flood Warning

Solar-powered laser rangefinder to log river levels to the cloud for flash flood warning and kayak trip planning.

AdvancedWork in progress754

Things used in this project

Hardware components

lidar lite
×1
mosfet switch
×1
solar charger board
×1
solar panel 3W 6V
×1
Electron
Particle Electron
×1
SparkFun Photon Micro OLED Shield
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
Ubidots
Ubidots
we use this to quickly and elegantly setup a control panel showing data the way we want it. Ubidots also allows us to commerialise our data. More importantly, it has controls that you can use to easily send data back to your sleeping device when it wakes up.
thingspeak channels
we used this as a cheap way to roughly display our data through particle Hub

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

photo of the circuit

this comes afte rmuch experimentation with different components, this receipe seems to work. will draw it up in fritzing later.
2018 06 08 10 50 16 films  tv p8suxmwjaw

Code

Main

C/C++
declarations, importing of libraries and local files, setup of devices and main control loop
#include "LIDARLite.h"
#include <Ubidots.h>
#include <SparkFunMicroOLED.h>
#include "math.h"

/* Ubidots */
#define TOKEN " Put here your Ubidots TOKEN"
#define UBIDOTS_VAR_ID                  " Put here your Ubidots TOKEN"
#define UBIDOTS_VAR_ID_MINUTES_OVER     " Put here your Ubidots TOKEN"

Ubidots ubidots(TOKEN);

 
 MicroOLED oled; 
bool bdebug =false;// true ;// false;// set to true to output to serial port

//unsigned long iReadingsStaleMillis = 200; // if no readings after this time then return 0

//unsigned long LastGoodReadingTaken;

int imaxdist = 2500 ; // maximum 13 meteres
int imindist = 10; // 30 cm

int iIntervalBetweenSend = 600; // time in seconds between sending readings , default is 10 minutes

//needed for smoothing readings
const int numReadings = 20;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0; 

bool isPowerGood = false;
double lipoLife = 0;
double lipoVolts = 0;

unsigned long imillisLastShowStatus, ilastreading, ilastmsg, ilasbattmsg, ilastsenttocloud;
int itimesincelastreading; // in seconds

bool bSentTocloud; //flag to indicate we have sent to cloud in this session

int iNumberOfReadingsTaken = 0;
int  iNumberOfReadingsBeforeSleep = 70;
bool bReadyToSleep;
long iTimeUntillgiveUp; //seconds until give up


bool bManualMinutesToSleepFor = false;
int iMinutesToSleepForDefault = 30; 
int iGiveUpAfterSecondsWithnoReading = 90; //90 seconds no reading then give up
int iMinutesToSleepFor = iMinutesToSleepForDefault; 
int distance;
bool bDontSleep,bDontSleepCloud;
bool bGivenup;

//---------------digital outputs/inputs---------------
//Debounce debouncer = Debounce(); 
 
//int  iLastBat;
int iOnPin = D3; // the pin that turns on the sensor power
int iPinToWake= D4; // the pin that stops it from going to sleep
int iPinBatvoltage = A4;

int iInValueForOn = HIGH;
int iInValueForOff = LOW;

int iOutValueForOn = HIGH;
int iOutValueForOff = LOW;

bool bIsOn = false;


//----------------------------needed for power control------------------
SYSTEM_MODE(AUTOMATIC);

PMIC opmic;
FuelGauge ofuel;
//---------------------------------------------------------------------

//--------------------current and voltage sensor-----------------------
//Adafruit_INA219 opowersensor; // Declare and instance of INA219
//INA226   opowersensor;
 float supplyvoltage = 0;
 float supplycurrent = 0; // Measure in milli amps
bool supplyTooLow, supplyTooHigh;

#define MAX_SUPPLY 5.4 //maximum supply voltage the lidar can tolerate
#define MIN_SUPPLY 4.7 //minimum supply voltage the lidar can tolerate


//---------------------------distance sensor-------------------------
LIDARLite myLidarLite;
bool bLidarSetup;

#include "displayfuncs.h"
#include "iofuncs.h"
#include "cloudfuncs.h"
#include "powercontrol.h"


// reset the system after 30 seconds if the application is unresponsive
ApplicationWatchdog wd(100000, System.reset);

STARTUP(fn_setuplcd()); // for the particle this runs before wifi is setup


void fn_setuplcd (){
        oled.begin();    // Initialize the OLED
        oled.clear(ALL); // Clear the display's internal memory
        
        if (bdebug)	Serial.begin(115200);
        pinMode(iOnPin, OUTPUT);
        pinMode(iPinToWake, INPUT_PULLDOWN );

        fn_TurnOnOff(false);
        iNumberOfReadingsTaken=0;
        
        iNumberOfReadingsTaken =0;  
        printTitle("RvM v1.2", 0);
        // delay(1000);
        //	pinMode(iLedPin, OUTPUT);
        //	digitalWrite(iLedPin, HIGH);
        
            //get battery life on startup
        // batteryLife = fuel.getSoC();
        
        
        //start the current and voltage sensor to get hte battery readings
        //  opowersensor.begin();
        // opowersensor.setCalibration_16V_400mA();
        
        // Configure INA226
         // opowersensor.configure(INA226_AVERAGES_16, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
          // Calibrate INA226. Rshunt = 0.01 ohm, Max excepted current = 4A
        //  opowersensor.calibrate();
       //  fn_showstatus();
       // /  wd.checkin(); // resets the AWDT count
           //check: if external power is not enought then dont start.
          //clear out the array
         for (int thisReading = 0; thisReading < numReadings; thisReading++) {readings[thisReading] = 0;} 
         
     
     }


void setup() {
    
    fn_setuppower();
    fn_ReadExternalPower(true);
    fn_showstatus();
    delay(1000);
  //  printTitle("Get cloud...",0);
  //  if (bdebug)  Serial.println("6 supplyvoltage cloud: " + String(supplyvoltage)); 
  //  delay(1000);
  //  fn_getCloudvalue (true); //check the cloud
    bLidarSetup = false;
    bSentTocloud = false;
    
   
     ilastgotareading = millis();
    if (bdebug)  Serial.println("7 supplyvoltage loop: " + String(supplyvoltage)); 
 
    */
}



void loop() {
      wd.checkin(); // resets the AWDT count
      fn_ReadExternalPower(false);
  //    fn_ReadInputs(); 
      fn_getLipoBattery();  
        
      fn_showstatus();
   //   fn_getCloudvalue (false); //check the cloud if not already checked
      
      //take a reading or send an error to the cloud if voltage is too low or too high
       if (!bReadyToSleep and !supplyTooLow and !supplyTooHigh and !bGivenup)   {  // only take readings if supply is correct
                fn_TakeReading();
          }
        
      fn_CheckgiveUp();
      fn_checksleep();
      fn_showstatus();
      
}

Credits

Jasper Pons

Jasper Pons

1 project • 1 follower
founder of www.dronescan.co and www.scanman.co.za
Stuart Roberts

Stuart Roberts

0 projects • 1 follower

Comments