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 progress1,665

Things used in this project

Hardware components

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

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
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)


Read more


photo of the circuit

this comes afte rmuch experimentation with different components, this receipe seems to work. will draw it up in fritzing later.



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------------------

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 );

        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() {
  //  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_ReadInputs(); 
   //   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


Jasper Pons

Jasper Pons

10 projects • 4 followers
founder of www.dronescan.co and www.scanman.co.za
Stuart Roberts

Stuart Roberts

0 projects • 1 follower


Add projectSign up / Login