My Tide Vane Project

My project is to determine whether the tide is rising or falling in real time by using a ping sensor and looking at the last ten minutes of height change. An either or UP arrow of LEDs or a DOWN arrow would result. The statements within a for loop would require a 2D array of ten rows and three columns. The first column is the height measurement, the second column is the difference between the oldest height measurement nine minutes ago and the new measurement. The third column is simply a +1. or a -1. , the sum of which will determine the rising or falling direction. The assumption is that ten minutes is enough time for an accurate measurement in a mid-tide range where tide is significant.
To achieve a one minute delay between measurements I plan to include four 15,000 millisecond delays to total one minute.
I believe I have to declare a 2D array and populate it with any data to get through the first ten minutes.
int myArray [10][3] = {6.1,+.3,+1.;6.1,+.3,+1;6.1,+.3,+1;6.2,+.2,+1;6.2,+.2,+1; 6.3,+.1,+1;6.3+.1+1;6.3,+.1,+1;6.4,+0.,+1;6.4,+.0,+1}
Make a new measurement of H, the height of the device above the water surface, say 5.2. Compare this to the oldest data point 6.4. The difference 6.4-5.2=1.2 . Because the sign is positive, the third element of the array for this row is +1 . The new incoming row is incoming (5.2,1.2,+1)
Now I must manually reorder the array to add the new value
lastRow [9] = lastRow [8]
lastRow [8] = lastRow [7]
lastRow [7] = lastRow [6]
lastRow [6] = lastRow [5]
lastRow [5] = lastRow [4]
lastRow [4] = lastRow [3]
lastRow [3] = lastRow [2]
lastRow [2] = lastRow [1]
lastRow [1] = lastRow [0]
lastRow [0] = incoming Row

The final use of the data is to sum up the third column which in this case is +10. This is intended to light the UP arrow for one minute. Since four 15 second delays are included in the steps of the statement the loop is complete and can go to a new measurement.
I need help with writing the code to handle this array as described. If you have any code elements or can help me in any I would appreciate it.

int myArray [10][3] = {6.1,+.3,+1.;6.1,+.3,+1;6.1,+.3,+1;6.2,+.2,+1;6.2,+.2,+1; 6.3,+.1,+1;6.3+.1+1;6.3,+.1,+1;6.4,+0.,+1;6.4,+.0,+1}

Be sure to let us know how well storing floats in an int array works for you. Not too well is going to be my guess.

That is not how to initialize a 2D array, by the way.
Three separate 1D arrays would make life one whole lot easier. That’s one as in an int value…

Yeah, I'd just use 3 single dimension arrays. I would also recommend not doing all those copies when you get a new data element so that the old one "rolls off". A better way is to use an index that points to the last row used. Each time you write a wrote, you increment the index. And if you increment the index past the end, you'll have to reset it to the beginning (usually 0). This way you're just overwriting the oldest entry and not doing all those copies.

Have you some way to eliminate the effect of waves - ideally before the ping sensor takes its readings?

Perhaps have the ping sensor inside a pipe with the bottom deep in the water. But I don’t know if the pipe will adversely effect the ping sensor.

What is the maximum range of spring tides?


I want to try to get a device that works for an 18 inch tide. Since the direction is only meaningful at mid tide, I assumed a ten measurement average direction would eliminate ripples. When I get the code I need to work I will be able to work on variations.
The comments I got today are helpful.

Doesn't your sensor get effected by waves ?

Its probably possible to average out the wave height, but you will need to effectively "ping" all the time to build up enough data to get rid of the "noise" of the waves.

Unless you intend using an external SD card to store each sample, you will probably need to use some sort of "rolling" averaging system to remove the wave "noise" because the Arduino doesn't have enough ram to store a lot of samples.

I suspect what you will need to do is run some sort of sampling / averaging system for perhaps one or two minutes to attempt to get an average of tide height without too much wave "noise"

Then wait 5 or 10 mins, and take another reading using the same averaging system. and compare these to values.

BTW. When you say ping, do you mean ultrasonic ping?

What transducer are you using, Most of the cheap ones have very limited range (I bought one a while ago and it just manages around 2m) However I know there are high power ones which are much more expensive that are used by the radio controlled drones guys for height measurement and they work up to 50+ft

I want to try to get a device that works for an 18 inch tide.

I’m just curious to know where you are measuring the tides. I had assumed a range of 2 to 4 metres.


My project is to determine whether the tide is rising or falling in real time by using a ping sensor and looking at the last ten minutes of height change.

If you only want to know if the tide is coming in/going out then you just need a real time clock, latitude/longitude & a formula. If your worried the RTC will loose/gain time then use a radio controlled clock module to sync it with every so often.

I would think that you could have an active ping that would run continuous, then calculate level by averaging the peak and valley of a wave.

I would be curious how a water pressure sensor would work ? in a vessel of water that is stationary, we have had a guy on here report level changes of less than a fraction of a mm.

I see now that I only need a single array that records nine height measurements. I will use millimeters to achieve the necessary precision in an integer and a running total to compound the measurements into a consensus of either five up or down indications. Wave action and ripples should average out.
What I need is the code to "roll off" the oldest measurement and replace it with the new measurement. What would that code look like?

for a simple version of a bucket brigade


analogread the ping sensor


float v;
const int persistance = 12000;

v = (float)analogRead(0);  //pin a0
for (q=0; q<30000; q++)
  v = ( (persistance-1)*v + (float)analogRead(0) )/persistance;
  delayMicros(950); //change this  

That ends up with a value v showing the rolling exponentially smoothed average of about 12 of the past 30 seconds, without introducing big data arrays. I’m not sure how big your persistance may go within the constraint of 16 bit integer datatype, but you don’t need to throw in a measurement every ms as happens with this small delay.

Simplest is moving average : the way you do is good.
and yes simplest way is moving the array, however it is very slow, but good understandable.

However i would use a filter: take a sample every second
if ((millis()-1000)=oldtime)
if counter=>60
move array
array[0]= total
if array[9]+hysteresis > array[0] {rising=1; falling=0;}
if array[9]-hysteresis < array[0] {rising =0; falling=1;}


What an elegant solution!! You amazed me with simplicity. Why wait for a time frame your eye can detect when you can measure in ms and record levels in millimeters.
I'm using a four pin trigger and echo sensor. So there are only four pins to define. What else do I need for a full sketch?