Well system monitoring... Use Teensy?

Not open for further replies.
The RFM95 is what I got from a US eBay seller. Still selling at $9.80 ( $2.60 ship ). Mine are still wrapped awaiting time or promising code to test.

@Kurt: What is your connector and antenna? That looks like a flash on the bottom - what's the speaker feeding top U6(?) chip above R4?
Did Adafruit replace your LoRa board? Bummer the PCBS.io upload failed you - at least OSH will be good and purple. Seeed pricing looked good.

@Juan - have you done any testing 'through trees' or anything other than line of sight? I've got about 200 meters of woods I want to get through.
@Juan - have you done any testing 'through trees' or anything other than line of sight? I've got about 200 meters of woods I want to get through.

Hi defragster.
I received the modules recently and just wanted to be sure that I was getting 2 km range at the actual location. Afortunately, in my project's scenario I have line of sight. Some 300 mts downhill of the receiver however, I had a building in the way and got nothing through as expected at such a distance, but the day I received the modules I put the transmitter on the roof of a house in the middle of my neighborhood and got more than 200 meters without line of sight. I think that in your case it should be possible to achieve the distance without problems, but in my experience with the UHF band it will depend on the density of the woods, the humidity of the foliage and wind speed (the movement of the foliage doesn't help). I have to add that in my case I set the Tx power of the RN2903 at the highest allowable level. I will continue with my tests in order to find out the maximum line of sight range at different power levels and will try to include some trees and buildings interference scenarios as well. I could share the findings if you are interested.

Best regards, Juan
It will be interesting to compare different modules, to see which ones work the best:

@Defragster: I ordered mine from LowPowerLabs, which were a bit more expensive: $12.95, but last month when I ordered them on the 12 they were delivered on the 16th... Still don't have any boards to solder them on yet (Until these are done).

Yes - Adafruit did replace the bad board.

The Ant pattern should be the same as the Adafruit board: https://www.adafruit.com/products/3072 Where you can either solder in wire (and optionally GND wire) or can purchase their connector and Ant like is shown in the picture:
The Speaker and Chip are the same as I put on my RPI hat board (plus the fix). The speaker is about as small as I found on digikey(668-1132-ND) and the the Sound Amp chip (LM4862MX/NOPBCT-ND)connects to DAC0, Not very fancy, but should be able to deliver the alerts and feedback I want. Hopefully everything will work...
Another Quick update. Yesterday I started to assemble one of the boards. As I go along I always find things I will change if I build another one...

So far it looks like:


So far I have tested some of the things without installing the touch screen. I have not tested much yet, did verify I could hit the small program button and likewise the reset button. I found that Talkie works through the DAC0 and mini AMP to the speaker (after I remembered to enable power to it).

I verified I could talk to the Neopixel, which I am running on 3.3v without level shifter...

Soon will check to see if the RFM95 works.

Will probably soon hook up the screen. Have not decided if I will put in socket for it, so I can unplug and easier reuse if I decide to... Probably should. Other option is to solder it in tight, could be pretty close to RTC battery socket, sort of like:

But will probably put in spacers instead.

Lots of things to test: like does the Battery holder work for RTC.

How well will this work with display, Neopixel and LoRa using 3.3v out of Teensy? If I do a V.2 maybe add small VR.

Other things I may look at if I do a V.2 include: I screwed up labels for DAC0/1 (wrong order).

Maybe do something to not have the Neopixel come on when power is applied and the app does nothing with it... Tried simply adding a PD resistor like 20K, but still lit up.

Probably add PWM like control for backlight, probably with small transistor...

Maybe see if I can make it slightly less wide and long, such that if I wish to mount all of this in a 3d printed box, that there might be a lip that the screen rests on, with this board sliding through... Probably not necessary, but a thought...

Now back to playing around

Mainly having some fun.

Decided to mount display with connectors, so can reuse... So have spacers in it now... Also have Logic Analyzer hooked up, which is the wires below.

Screen is showing test output I did in testing my version of ILI9341 library, where I integrated in the new things like gradient fills, and the like to work both with frame buffer and without... That is when I found readRect was not working (in normal library), so fixed, which is now showing that it read the T area toward the top left and then did a writeRect toward the topRight...

next up test Touch screen (also hooked up to main SPI) and test the LoRa radio. Will probably need to update RadioHead to support SPI1, which is how I set it up...
Oops forgot to put in picture...

Update: Touch screen works.
#define TFT_DC 22
#define TFT_CS 15
#define TFT_RST -1
#define TFT_SCK 14
#define TFT_MISO 12
#define TFT_MOSI 7
#define DEBUG_PIN 13

#define CS_PIN  8
#define TIRQ_PIN  3
XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);

Update2: I think there is a problem with my RFM95 setup. For some reason I thought I needed D5 for IRQ, but it is D0... Can jumper probably. Also may look at library to see if it maters which pin...
Last edited:
Quick update:

Forgot to mention, that I earlier made a version of Radiohead that supports SPI1.
It is in my fork/branch of Pauls version that I updated to support SPI transactions. I also added the ability for SPI1...

I did a copy of their Hardware_spi object, that uses SPI1. So I can now do:
RH_RF95 rf95(RFM95_CS, RFM95_INT, hardware_spi1);

In my case not using default SPI1 pins so I have:
  if (!rf95.init())
As I mentioned above, I made a mistake on which Data line of the RFM95 to use. So I soldered a pin into the D0 hole of the castellated pin for D0 and then ran a jumper to a pin connected up to Teensy Pin 2... Now my board is able to talk to a Feather M0 RFM95 board...

More notes if I do a V0.2
As I mentioned, playing around with a version 0.2. I fixed the hook up for the RM95 to use the right data pin, plus made sure no signals run in the area for battery. I also hooked up Rest pin of Teensy to reset of Display, also have been playing around with the hookup for the backlight, to allow turn on/off or PWM... Current setup for that is now using two MOSFET.

Still experimenting, probably next try assembling one of the circuit current measure daughter boards to verify it works and/or any other changes I want to make

Then maybe order new set from either OSHPark or maybe Seeed as they have 20% off, or maybe PCBs.io again, but not sure what state they are in...
Wondering what is a reasonably clean way to code up getting a reasonable idea of how much current (if any) I am measuring from lets say 4 Current sensors (https://www.sparkfun.com/products/11005)
I have it setup with load resistors and voltage divider and the like as to make sure the voltage stays positive and (hopefully) stays below 3.3v.

I have code at init time that does a bunch of analog reads and tries to calculate what the zero point, mins and maxs...

I then have code that while running takes several analog readings over some time and keeps a sum of the (value-center)squared and then at some point takes the sqrt of the sum/count.. To get a rough RMS like value.

While I may not get a totally accurate value, my main purpose is to try to detect when things like Well pumps turn on and off, so I can probably set a pretty large fudge factor. I may also want to know more about how it turns off. Did it suddenly turn off, like went from some value like 40 to zero quickly, in which case assumption is maybe float valve or like turn it off, or did the power drop off over a bit of time as the well went dry and as such pump used less power at which the pump saver circuit kicked in and turned off the pump (which tells me the tank is probably not full).

Note: Using T3.6 here. I also want the same processor to also handle displaying data to PJRC touch screen, plus send data over LoRa radio to other display, plus maybe log data to SDCARD...

What I am wondering about is decent way to do the sampling of the 4 analog inputs currently on A13, 14, 15, 16 to do RMS like calculations. Is it better to do analogReads on each of these sensors at some constant interval (right now have on interval timer), or better to round robin and only sample one at a time? OK to sample a rather slower pace over a longer period of time lets say something like 250ms? Or better to do a lot of quick analog readings on one of them figure out bounds of one or two cycles and compute on it...

Again just wondering if others have wondered down this rabbit hole and which route they took...

Quick Question - are the four sensors monitoring the same pump - or a series of pumps running independently - together?

My 240V (1.5 HP?) pump is shallower than yours. The ON spike hits just over 15 A and dropped to probably a steady state under 13A - around 12.5A IIRC. I don't know what kind of drop you'd see from a lost load racing the pump - I expect it would be significant maybe 50%? You could probably take an RC motor ( which I assume you have ?) and see that. Maybe you could set up a benchtop system test with current monitor on some motors - better than playing with 240V far from the house where you can't just 'play' with the system { without flooding or breaking something very expensive }. Anyway you can tap into the 'request for water' float switch - then you'd know when you could sleep or wake the system - and also know that signal didn't drop but the pumps did.
I am actually thinking of monitoring 4 different things. The first two are Well pumps. I have two wells. The majority of the time they will both turn on at the same time... That is the float switch in the tank will trigger (120v) and goes to a connector box (more or less a set of relays), that enables the power to the two wells. If the tank fills, the switch will turn off and both will turn off. However if mid summer and well levels have dropped and we are using a lot of water, than it is possible that the two pumps will turn off while the float switch still gives power. They will then delay for some amount of time waiting for the well to recharge... I am only measuring one leg of each of these pumps.

Third pump is to pressure pump supplying water to buildings. Fourth is to see how much the heater is running in my pump house...

Yes I expect that there will be a surge when the pumps turn on. It may be a good think to keep track of how much these surges are over time to see if something is changing with the pumps.

As you said I could probably detect a lot with just the float switch, which does not take a lot of power.

Right now at times in my office I am measuring some with Space heater or Soldering station, but these don't take anything near what the pumps will.

But right now just trying out different ways to layout the code to try to do reasonable job of knowing when power is on and off...
Back to figuring a better way to read in the Analog data. I am probably way overdue to convert over to using ADC library instead of analogRead! :eek:

Right now working my way through understanding how best to use the library. Again I am using A13-16, So they are on ADC1, 0, 0, 1

Trying to decide if it makes more sense to model it more over the Interval Timer or DMA mode.
Right now looking over the specs and ADC library to see if it would make sense to maybe use the DMA . Again AC so sine wave 60hz.

So would it make sense to setup DMA operation to maybe read N samples example 128 on ADC0 (init to A14) and 128 on ADC1 on (A13), and
hopefully easily find out when the DMA has filled the buffers, then maybe stop the ADC, switch them to the other two pins, and start up again,
Maybe to other buffers.

Then maybe scan the buffers to decide if any current is running (min and max near fudge factor of center voltage of 3.3/2), else calculate an RMS value... maybe whole buffer
or maybe have code scan for where it crosses zero points and only do whole half cycles...

Anyway lots of stuff to figure out. Suggestions are very welcome!
Not quite sure what your goal is other than system state monitoring. For simple current monitoring of a pump to determine it's state (none = off, low = cavitating, normal = running, high = locked rotor) I would adjust my sample interval and count to be an integral # of 60 Hz cycles, subtract the mean, and calc the RMS of the buffer. Then, simple thresholding would give that pump's state.

Your pump tender handles the cavitation, and locked rotor is so unlikely that you may choose to ignore it and let the fuses/breakers handle it. So you're left with pretty much on/off monitoring. It's unlikely that either your pumps or heater will cycle faster than every 5 seconds, so take a 2 cycle sample (33.3 mS) every 5 seconds or so. A 1 kHz sample rate should be plenty to get a good RMS value. If the pump happens to turn on or off during the sample window you'll get a abnormal reading, but you can infer the cause by comparing it to the prior & following readings (eg: prev=off, current=high/start, next=normal/run).

Pretty low bandwidth stuff. I wouldn't turn to DMA unless it's out of academic curiosity. Fun project nevertheless.
Time again to revisit this thread :eek:

As again this last week, my Storage Tank was empty (2800 gallons) again. Still not 100% sure why yet. Highest probability is that one of the outside buried Hydrants is leaking, probably at the newer garden. Currently have all outside water turned off at the Pump house. Could be issues with Wells, although both appear to still work, could be we were simply using too much water...

Last time I was going to use the current sensors, but never felt comfortable using those Sparkfun current sensors on live 220v circuits...

This time, I am thinking KISS. As @dgranger mentioned, probably simply need to know if the pumps are on or off.

For the Two wells, they are currently wired something like:

<110v circuit - goes to float valve in tank, which then when it has power makes connections for both 220 circuits going to both pumps>
|____220 V goes to pump controller...
|____ Pump saver - Two Input AC lines for both power leads of 220, plus two Outputs, which the pump saver monitors and turns off....
|_____ Pump

Note; the order of Pump controller and Pump Saver I think is different depending on the two wells. One well the pump controller is actually in the wellhead...

So: Was thinking, I could tap into both Pump savers. On one of them I would tap to both: L1 In and L1 Out and on the other probably just L1 Out.

Would probably run these wires to maybe a simple 4 outlet box (need to run a Neutral and GND as well). Note: I can probably so find a location to tap into the Pressure pumps wiring as well and run that over as the 4th line...

Next question would be how to convert the 110v AC to 3.3v or 5v DC? Maybe the simplest method would be to hook the 4 lines as AC plugs and use something like a simple USB power wart for each circuit... Is there a simpler/Safer way? I don't want to put much load on the Pump saver side as to screw up it's logic to know when to cut power...

Anyway maybe if I simple enough I might actually do something!

Note that I am NOT a EE so filter my input accordingly.

There are a number of ways to detect a/c on/off status and your wall wart idea is a reasonably good one.

I would advise that any solution you consider has isolation between the a/c mains and the Teensy. Here's an interesting thread that uses a very simple circuit to generate an opto-isolated digital output that pulses at the a/c rate: simple-ac-detect-circuit.

The code side for the above looks pretty trivial as well.

Hope this helps,
Thanks @jwatte as reply on Trossen Robotics forum, as I said that seams like the simplest solution.

Another option as mentioned by @ dgranger and use an opto-isolated circuit like what was mentioned in the thread: http://www.avrfreaks.net/forum/simple-ac-detect-circuit

I think the end diagram that person used was:

There was an additional suggestion to the above image to:
Move the vertical diode to the right hand side of the horizontal diode and cut the dissipation in 68k resistor in half.
Not sure if he meant left hand side of resistor? Or the user updated the diagram...
I believe the diagram doesn't reflect the suggestion, which is to move the vertical diode between the horizontal diode and the opto.
Thanks again,

Right now I am trying using the current sensors... I had someone on another forum suggest that it was probably safer to use the current sensors which does not make any modifications to AC circuits, nor bring in AC currents into my display unit area... Than to go with the other approach and setup to need to modify lets say 4 220v AC circuits in order to tap into them...

SO I purchased 3 more of the current sensors, this time on EBay with the ones that most of the write ups were about (https://www.ebay.com/itm/112305044704) which say for up to 100amps.

I made an updated small board for them, where I put in a 22ohm resistor connected to a 100 ohm variable resistor as the load resistor, so I can adjust the voltage output depending on how much current each of these items take... Right now I have it mid point, so about 72 ohms.. Today I took the cover off the circuit panel and connected 4 current sensors and they are giving me some readings. Currently my code is not fully calculating the true RMS amps, but it is giving me values when the different pumps turn on...

Also today I finally tried to see if the two display boards would talk to each other, with one in the well house and the other in my office. They have Lora RM95 chips in them with external ANT. After I had the first up and running in the pump house, I went back to my office and plugged in the 2nd one and it quickly showed the current Temp/Hum in the well house... SHT31 unit :D

Code still needs lots of work, plus I want to redo the connections for connecting the current sensor board (which has screw connections) to the display which simply had break of pins... As those connections dif not appear to be secure...

But at least it is showing promise and progress...
Seeing the Lora work is good. Will allow status/progress without all the hiking :)

Is there an exposed single hot wire available to grab the current from?
Yes - good to see LoRA working. Still need to do walking, as will need to debug hang... Update Code... Would be nice to be able to remote program it... Too bad I don't have wifi out there... Then could hook up RPI or ESP... To talk to it...

As I mentioned, I think the SHT31 code is hanging. So should try to debug it. and/or maybe should put in some watchdog code that if loop is not called within... reboot...

But first will maybe pull in the Adafruit code directly into my sketch, and use i2c_t3 or Wire with hopefully some timeouts are recovery code...
I decided to make a few mods to my display board that was similar to Frank's flex board, to make things connect a little better.

I converted over to screw terminals for the sensors. I added spot to connect the SHT31D directly to board, plus changed the backlight circuit to be closer to what Frank had... Mine was not working overly well... So ordered up a new set of boards today. At times wondered if I should have instead, setup the thing in the well house to be something the only collects the data and then sends it back to the house. Maybe something like the Helium Ethernet like stuff (Sparkfun)...

But while waiting I will hopefully fix some of the other issues.
Just thought I would mention, that I received the boards back from OSHPark, and the parts from Digikey, and assembled one of them, still need to do lots of testing.

I also 3d printed a prototype box to hold it, in order to see if I had all of the holes in the right spots. I decided that some of them needed updating. Besides I want the final box to be 3d printed using some T-Glase filament, which I tried again and was having difficulties getting the first layer to stick... So ordered some glue stick stuff... I still need to update my quick and dirty top piece. Will remeasure gaps sizes.

The board has a T3.6 on it, plus RFM95, plus edge connector, Neopixel, LM4862 amp (DAC0) and speaker, coin cell connector, SHT31and of course connection to touch screen... AND screw terminal connections to wire up to the well monitor board where I plug in up to 4 current sensors

A few pictures...



With Display:

3d Box:

And it inside the box:

Anyway having some fun... but I need to get back to playing with Turtle.
Another quick update. Finally printed updated box with T-Glase. Took a few attempts to get it to stick to plate of 3d printer...

It may not look as clean as black, but what is fun is how it works with light. That is I propped the older board into it and you can see how the neopixel changes the box:

Code wise, I verified that the new boards TFT backlight support is working. That is I can now control the brightness of the backlight. I have it dim down every 10 seconds until a minimum and go back to full brightness if I touch the display.

Also started playing again with the Analog Input from the current sensors. Up till now I have been using an Interval timer to do the sensor reading. Each interval I read in the previous values for two Analog Reads, and then issue the start of the other two... But was wondering about trying DMA instead. So I tried the ADC ringBufferDMA test, I edited it to use one of the Analog pins I was using and it did not appear to work (I verified that the pin I choose to test was on ADC0 as the test was setup...

Also I really did not need ring buffer as I just want to read in so many samples at some interval. In my case thought if the Interval was set to (60*50), that would give me at 60hz AC, 50 samples per cycle, which should be sufficient. And if I read 100 samples, that should give me two complete cycles... I thought I could try something like this, and then alternate between the two pins on each ADC...

So I hacked up a test app, that so far just tries one of the 4, using DMA and PDB... Still needs cleaning up.
#include <ADC.h>
#include <DMAChannel.h>
#define BUFFER_SIZE 100

ADC adc;
volatile DMAMEM uint16_t adc0_buf[BUFFER_SIZE]; // buffer 1...
volatile uint8_t adc0_busy = 0;
DMAChannel adc0_dma;

extern void adc0_dma_isr(void);

void setup() {
  while (!Serial && millis() < 3000) ;
  Serial.println("Test DMA Analog Read");

  // Initialize the
  adc.setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED, ADC_0); // change the conversion speed
  adc.setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED, ADC_0); // change the sampling speed

  // Lets setup Analog 0 dma
  adc0_dma.source((volatile uint16_t&)ADC0_RA);
  adc0_dma.destinationBuffer(adc0_buf, sizeof(adc0_buf));
  adc0_dma.triggerAtHardwareEvent (DMAMUX_SOURCE_ADC0);
  NVIC_DISABLE_IRQ(IRQ_PDB); // we don't want or need the PDB interrupt

  Serial.printf("First Read of A14: %d\n", adc.analogRead(A14));


void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("Enter any key to run sample");
  while (Serial.read() == -1) ;
  while (Serial.read() != -1) ;
  Serial.println("Start Sample");
  uint32_t start_time = millis();
  adc0_busy = 1;
  memset((void*)adc0_buf, 0, sizeof(adc0_buf));
  adc.adc0->startPDB(60 * 50);
  while (adc0_busy) ;
  Serial.printf("Sample completed: %d\n", millis()-start_time);
  for (int i = 0; i < BUFFER_SIZE; i++) {
    Serial.printf("%4u ", adc0_buf[i]);
    if ((i % 20) == 19) Serial.println();


void adc0_dma_isr(void)
  adc0_busy = false;

But it does show some promise. That is I a sensor setup on power cord that I have a solder station plugged into.

If I run the sample and power turned off:
Enter any key to run sample
Start Sample
Sample completed: 33
2025 2025 2025 2026 2027 2025 2027 2027 2026 2025 2025 2025 2027 2024 2025 2025 2027 2024 2025 2026 
2026 2025 2026 2026 2024 2025 2027 2026 2026 2023 2025 2025 2026 2024 2025 2025 2024 2024 2025 2024 
2024 2025 2025 2025 2025 2024 2026 2025 2025 2024 2026 2025 2025 2025 2025 2025 2026 2025 2025 2025 
2024 2025 2025 2025 2025 2026 2025 2025 2024 2025 2025 2024 2024 2026 2025 2024 2024 2027 2026 2026 
2024 2024 2025 2025 2024 2025 2025 2025 2024 2025 2024 2025 2025 2025 2025 2026 2024 2025 2025 2024
Now with station turned on:
Enter any key to run sample
Start Sample
Sample completed: 33
1986 1986 1989 1991 1991 1986 1992 1996 1999 2006 2012 2019 2029 2034 2039 2046 2051 2054 2056 2059 
2063 2062 2063 2064 2067 2065 2062 2062 2061 2058 2060 2057 2055 2052 2047 2040 2033 2024 2017 2009 
2005 1999 1996 1992 1987 1985 1985 1984 1987 1986 1984 1987 1989 1990 1992 1992 1992 1998 1997 2006 
2011 2019 2029 2035 2041 2046 2052 2055 2057 2060 2061 2063 2064 2063 2064 2065 2063 2061 2061 2060 
2059 2058 2056 2052 2048 2041 2033 2026 2016 2010 2007 2000 1996 1991 1988 1986 1986 1986 1986 1986
Still a few more things to try with sample code here:

a) Detect if power is on/off OR how much power: Could do simple test that if the code looks pretty flat (no highs or lows) off or (max-min) > threshold ON... Or could do some form of RMS calculation...

b) Setup to read both ADCs at the same time...

c) cleanup - Don't like I am simply using straight analogRead to prime the register for correct channel....

d) Setup to alternate between two groups. Read group 1 in, initiate group 2, process group 1 data...

Or just continue the old way...
Not open for further replies.