SNL-WaterPower / siweed

Sandia Interactive Wave Energy Education Display (SIWEED)
5 stars 2 forks source link

Wave Probe Drift #107

Closed nickross4444 closed 2 years ago

nickross4444 commented 3 years ago

As the wave amplitude rises past a certain point, the wave probe readings drift upwards: image Stopping the wave maker results in the wave probe reading coming back down to normal.

Reason is unknown, but one theory is that surface tension is keeping some water on the wave probe rod. This does not explain why the maximum height would rise

ryancoe commented 3 years ago

Any chance this has to do with the moving average or some other processing you added related to #3?

nickross4444 commented 3 years ago

I don't think so, we saw the same thing before there was any processing at all.

dforbush2 commented 3 years ago

This sounds like a hardware issue or maybe some initial processing... not sure I will be much help there. One probably naive suggestion: is it possible this is related to some sort of buffer overflow? If it consistently happens at about the same time this could be the case, especially if the data type at this stage is still some kind of INT.

On the data processing side, you may be able to use a high-pass filter to get rid of the mean shift in close to real-time. Probably worth figuring out what is doing this though. It looks like it is an honest mean shift rather than a consistent trend (e.g., like a linear increase), so one quick and dirty work-around, provided this shift happens early enough in a run, would be to wait until the shift happens, detrend by the new mean, and then start whatever the test is.

nickross4444 commented 3 years ago

After some more experimentation today, this seems to be an issue on both wave probes, though they do behave slightly differently. They also may be too close together, as touching one staff changes the height value read by both staffs. As a patch for the drift issue, I've added a moving average in 10b9ed726069c0076537242dc35b8bd196e6c560 with a larger sample count that and subtracted it from the other moving average. This has the effect of keeping the data near the origin, though can definitely be optimized, and should maybe be fixed an entirely different way.

ryancoe commented 2 years ago

Please engage with @gbacelli on two items:

  1. Locations of probes causing electrical interference?
  2. Design a bandpass filter instead of the ad-hoc moving averages
DeepFriedDerp commented 2 years ago

Hi Everyone,

I have taken both the generic continuous low-pass and high-pass filters in the laplace domain and converted them into their discrete, time-domain forms. I then coded up a set of functions in matlab that will provide the framework for @nickross4444 to implement them in Java as a bandpass filter. Hopefully this will help with high frequency noise and the near-DC bias issues we are currently experiencing.

For the cross-talk between probes, I called the manufacturer and confirmed that the probes measure the time constant of an RC circuit formed by one "plate" (a conductive coating on the inside of the wave staff), the dielectric layer (the polymer or plastic material making up the outside surface of the wave staff), and the 2nd "plate" (the contact surface of the water and the outside surface of the wave staff).

This means that we have the following effective circuit formed by the two wave probes and a common ground in water: 20211214_152210

Where: R1 thru R3 are the resistive paths between each wave probe and from each wave probe to ground, and V1 & V2 are the AC signals being used by the wave probe to determine the time constant of the RC circuit. As you can see here, a change in one capacitor's capacitance will effect the RC time constant of the whole circuit, and thus the reading of the other probe (i.e. a change in water level on probe one will effect the perceived water level on probe 2).

If the conductivity of the fluid is increased (by adding salt or some other ionic solute), then the values of R1 thru R3 are driven towards 0, and the effective circuit will resemble (though not completely look like) the following: 20211214_161129 Which would help to reduce the coupling effect between the wave probes. Additionally, the manufacturer actually doesn't recommend this type of capacitive wave staff for freshwater, as any sort of biological growth or wetting agent in the water (we currently have algae or some sort of alien lifeform growing on every elastomer or plastic surface below the water line) will cause the water to cling to the wave probe surface when the water level drops, which can cause a bias and/or clipping of the troughs when a sinusoidal wave is measured.

The addition of salt would prevent a good amount of microbial growth (combined with the band-pass filtering) may help the biasing problems we are seeing and improve the cross-talk situation between the two wave probes. The only downside to this is that we'll need to source the salt, and we'll need to either paint or otherwise coat the metallic surfaces below the water line, or have Kevin rebuild some of the wetted hardware out of aluminum (including fasteners) to prevent corrosion, which will significantly accelerate once salt is added.

@ryancoe @gbacelli @dforbush2 Does this sound reasonable? Please feel free to point out any issues you see with this explanation or the proposed solutions (other than my grammar, I know its pretty terrible) :)

Thanks!

dforbush2 commented 2 years ago

If we ever intend to leave the system filled for any length of time I would stay away from salt. It will take more than aluminum fasteners to solve the corrosion problem, since any interface of dissimilar metals submerged in an electrolyte with corrode based purely on the differing voltage potentials. If we are just an hour or two at a time and we wash things down with freshwater after every use, this is probably fine. And 80/20 painting is a lot of work.

But to this end of using a chemical solution to prevent microbial growth, why not a small amount of bleach instead? This will very gradually corrode the aluminum but if it is sufficiently diluted this is probably slow enough to not be a concern. Honestly not sure which is worse, bleach or salt, on aluminum at the concentrations we would need it to prevent growth but this is probably an answerable question.

By chance did you use the 'c2d' function when building these filters? If so you may be careful to check the phase response of the developed filters. The default method of this function doesn't always do a great job of preserving phase response. I think I have had better luck with the 'Tustin' option?

DeepFriedDerp commented 2 years ago

@dforbush2

On the corrosion concern: Nick and I share this concern, and I am familiar with galvanic corrosion and how quickly it can happen, even in slightly conductive water (its currently happening on all of the non-aluminum fasteners below the water line). The trade-off is that simply adding an antimicrobial like bleach does not solve the problem of the coupled wave probes, and bleach rapidly degrades in light to a mixture of salt and sodium chlorate (which is toxic, but only to organisms with hemoglobin, so it wouldn't inhibit microbial growth). Additionally, the manufacturer warned that many antimicrobial water additive can act as a wetting agent, which will cause the same problem as the microbes in the water.

We currently have at least a gallon of non-toxic epoxy in 6585 for this project, and will probably only need a quart at maximum. Would it be enough to dip the portions off the 80/20 into the epoxy as a protective coating? Another option would be to use a block of zinc or magnesium electrically bonded to the aluminum frame to act as a sacrificial anode. The final option if we need to have both wave sensors on the assembly, would be to continue using freshwater, and switching out the wave staffs for ultrasonic wave sensors. My understanding is that Ocean Sensor Systems (the manufacturer of the wave staffs) also offers both wired and wireless versions of an ultrasonic wave sensor, which wouldn't be affected by the conditions of the water. The only downside with these sensors is that they have a certain beam angle that will dictate how close to the water's surface they have to be in order to avoid the beams of the sensors from overlapping.

At this point I'm open to any of these options.

On the c2d question: I'm actually not super familiar with typical methods for implementing a filter designed in the continuous Laplace domain on a discrete, real-time system. I converted these filters by hand on pen and paper, using a Bilinear Z-transform and then rearranging into what I think is called a constant coefficient difference equation, which allows me to represent it the filter as an update equation of the form: y[n] = a1*y[n-1] + a2*y[n-2] + ... + am*y[n-m] + b0*x[n] + b1*x[n-1] + ... + bm*x[n-m] where y is the filtered signal and x is the unfiltered signal.

Testing out a few pure sines through the bandpass filter and plotting the filtered signal with the unfiltered signal doesn't introduce enough lag to be visually detectable, but I'll modify the filter functions so that I can run it as a simulink function block and get an estimate of the phase shift for a range of frequencies. I'll post the results when I have them.

Thanks for the input!

dforbush2 commented 2 years ago

I definitely did not know all that stuff about bleach, so that was super good to know. I think dipping the 80/20 is a good option if we have the volumes needed to do it.

Maybe someone else can chime in, but the wave tank at OSU/Carderock is freshwater. This feels like a problem that must have been solved. Ultrasonic sensors are one solution that is employed but I am pretty sure at OSU they have contact-based wave gauges.

DeepFriedDerp commented 2 years ago

@dforbush2 I would imagine they have a combination of sanitizing chemicals and filtration. Pool water is sanitized with bleach, but usually includes cyanuric acid as a chlorine stabilizer to keep the bleach from rapidly breaking down. The problem with this is cyanuric acid readily reacts with melamine (melamine resins are used in a lot of thermoset plastics and some epoxy, acrylic, and polyester resins for use a surface coatings), to produce toxic byproducts that target the kidneys. There are also bromine salts that can be added, but a lot of people have pretty nasty skin reactions if the concentration of the bromine salts is slightly off. These chemicals and their efficacy at controlling microbial growth is highly dependent on water pH and calcium hardness (cyanuric acid binds to chlorine ions and releases them slowly over time, but this release time depends on the water conditions). Since we loose somewhere between 1/2" and 1" of water per week due to evaporation, maintaining pool chemistry in this way would require a lot of supporting systems, a constant supply of water, and probably a significant amount of planning and paperwork to allow the use and control the potential discharge of this pool water at Sandia (having recently worked through getting some non-toxic paint ordered and getting approved to use a hot-glue gun, I imagine trying to work through getting approvals for something that is actually toxic would be a 6-month to 1 year long process).

Additionally, its generally considered best practice to keep these capacitive wave probes as far away from each other as reasonably achievable in fresh water. In full-scale wave pools, these probes are probably kept several feet from each other at minimum, as where our probes have a maximum of 2 or 3 feet that they can be away from each other in our tank. Another potential explanation is that they are using a different wave probe design. Edinburgh Designs makes a wave gauge that can be operated in very close proximity with another gauge, but this design consists of two parallel rods immersed in the water, and the resistance between the rods being measured to indicate how much of the probe is immersed in water.

nickross4444 commented 2 years ago

Before we put too much effort into trying to fix the wave probe coupling, can someone give me a better idea as to why we need both? As far as my understanding goes, our goal with them is to 1) graph the wave height in the gui(only requires 1 probe) and 2) characterize the wavemaker.

I don't know what goes into characterizing a wavemaker, but I would guess relating the commanded height to realized height, and the wave speed, which I believe is only a function of frequency and fluid properties. The height we can do with 1 probe, and if I understand correctly we need at least 2 probes for the velocity measurement. That all being said, do we need the velocity measurement? If we do and it's only a one time characterization, could we use video footage for the characterization, and cross check that amplitude data with a single wave probe? I believe there is potential for simplifying this problem if we step back and look at the purpose of having two in the first place.

ryancoe commented 2 years ago

A couple of thoughts:

DeepFriedDerp commented 2 years ago

@dforbush2 I couldn't get the bode plots to work as intended, not sure why, but the magnitude plot results do not match the results I'm getting when I run the filter on a sample signal of sines with various frequencies. That said, I managed to do a really rough brute-force bode plot by running the bandpass filter several times with a range of pure sines of different frequencies and an amplitude of 1, and then calculating the relative magnitude and phase from the resulting plots. This obviously is not the most accurate method, but it will get us a rough estimate.

The following plot was constructed by setting the low-pass cutoff frequency to 5Hz, the high-pass cutoff frequency to 0.5Hz, and the sample frequency to 30Hz. The high-pass cutoff was chosen to significantly attenuate the DC bias, which seams to have a rise/fall time of about 6 seconds. The low-pass cutoff was chosen because I couldn't imagine us pushing our wavemaker much beyond 5Hz. The sample frequency was chosen because I think @nickross4444 has mentioned that this is the approximate step rate for our system.

image

It looks like there is a good amount of phase lead in the lower-frequencies (I verified this is actually a phase lead and not extreme lag by comparing a plot of the unfiltered vs. filtered response on a ramped-amplitude sine), which switches to a phase lag around 1.5 Hz.

@dforbush2 does this look acceptable to you? @nickross4444 correct me if I'm wrong, but I think we normally run the wave-maker between 1Hz and 3Hz, right?

nickross4444 commented 2 years ago

Frequency range is reasonably 0.5-2.5hz

dforbush2 commented 2 years ago

Hi all, As per our call yesterday, I recommend the Filter Designer Application in MATLAB for designing the band-pass filter. For simplicity's sake I recommend the IIR Butterworth Filter. image

The inputs are straightforward. The only thing that maybe is not is filter order: a bandpass filter needs one order for each pass and cutoff frequency, so increments of 2. The higher the order, the faster the attenuation to the stopbands BUT also the more significant the phase shift. The filter will be implemented as second-order sections (i.e., a 4th order filter with have 2 sections, 6th order has 3, etc). Best practice is generally to implement the lowest-order filter that can do the job to keep phase shift to a minimum over frequencies of interest.

Then, if you're happy with the magnitude and phase response, you can move over to the filter coefficients tab: image

And copy-paste the numerator, denominator, and gain from each section into the attached code (change the extension to *.m), which I hope will be readily translatable to Java, C++, whatever you need. testFilterBuild.txt

This is not theoretically different from anything Austin did, so feel free to implement whichever filter you prefer, but I think this workflow is nice in that it utilizes built-in matlab tools for more rapid iteration. Currently, there is a 4th order filter implemented.

nickross4444 commented 2 years ago

image

Sorry this is a bit crude, I just wanted to get something thrown together quickly. This is the layout:
unfiltered 0.05hz sin filtered
unfiltered 20hz sin filtered
unfiltered 3hz sin filtered
unfiltered 20hz cos and 3hz sin and DC offset filtered

The high pass doesn't seem to be doing much to me. Processing/filter_test/filter_test.pde This is the source code.

@DeepFriedDerp @dforbush2, Any suggestions?

dforbush2 commented 2 years ago

Keep in mind that with a digital filter the start-up transients will always be a little weird. Assuming the plots are all the same scale in Y, I see: 1) modest amplitude reduction at 0.05 Hz. This is only 1/2 of the cut-off frequency, 0.1 Hz, so nominally at this order we would expect between a 2 and 3x reduction in amplitude. This seems like more than we are getting. 2) significant amplitude reduction at 20 Hz. 3) slight amplitude reduction at 3 Hz. Nominally this should be unaffected since it is within the pass-band, but a little variation is to be expected. 4). The DC offset is unaffected

All that to say: yes, the high-pass filter is not working as expected. Please double-check the actual sampling frequency vs. the one that was used in design (30 Hz). This could single-handedly explain the problem.

The other possibility is that something was lost in translating matlab --> java: please check lines 138, 140 and compare with 143 and 145. I know something had to change between the 1 and 0 indexing of the languages, but these offsets should be internally consistent?

nickross4444 commented 2 years ago

I defined the functions under the assumption this would give us what we needed: sin (2pi * hz/fs)

which looks like this:(for 0.05hz)

for (int i = 0; i < 300; i++) 
    signal.add(sin(2PI * i * 0.05 /30));  

Let me know if this doesn't look right.

My thoughts with the lines you are referring to:

  1. On the first iteration all variables(wm1 wm2 xm1 xm2) are set to zero, since no history exists.
  2. On the second iteration, kk is on the second index, and xm1 and wm1 should be set to the first index
  3. On the third iteration(and others, but in our case there is no 4th), wm1 and xm1 are the second sample, and and xm2 and wm2 the first sample.

I changed the indexing to be done relative to the buffersize(3) instead of the incrementing index(kk), which is why it looks a little strange.

@dforbush2 thoughts on the sampling frequency?

dforbush2 commented 2 years ago

That test function looks ok to me. My coding shorthand here was like this xm1 = 'x minus 1', or x from one iteration ago xm2 = 'x minus 2', or x from two iterations ago And so on for w.

With the iterations, could be a semantic distinction but to be clear: 1) first iteration, wm1, wm2, xm1, and xm2 are set to zero. 2) second iteration, wm1, xm1 should be the result of the wOut calculation from the first iteration and xm1 should be the signal input from the first iteration. 3) for all successive iterations, this sounds right. But the number of times these calculations are performed should be equal to the signal length, not 3.

It could be a looping problem: steps 1 and 2 should only execute at the very start of the test, when the buffer is empty or populated with zeros, then 3 should repeat until the whole signal is filtered.

nickross4444 commented 2 years ago

Yes, your description sounds correct, and is reflected in the java filter. I cut the iterations down to 3 as an optimization attempt since we need to run it in realtime. I realize now that since this is a second order filter, it's not so simple. From what I can now tell, each filtered sample is dependent on the 5 most recent samples, and so the inner loop could iterate 5 times over the most recent samples, and the 5th index of yOut could be taken as the output.

This makes sense to me, however changing the buffer size to the full signal proves me wrong: NOTE: the 4th x-axis was in the wrong place in the last example, sorry about that.

Buffer size 500(full signal): image Buffer size 5: image

With the full buffer, it works properly, which thoroughly confuses me. Additionally, it doesn't make sense for us to use the whole signal in realtime, so how much should we use?

@dforbush2 what do you think?

code: https://github.com/SNL-WaterPower/siweed/blob/113df322e5e24efdfa266b210be38127e4a38c03/Processing/filter_test/filter_test.pde

nickross4444 commented 2 years ago

We were able to find the issues, mainly that zeros were being introduced in more than just the beginning and yOut was being calculated too many times. We were able to get it working, and without any for loops, so it's a linear function now, which is great news for performance. Only change I think needs to be done now is recalculating the coefficients so that the upper cut off frequency is 3hz. More noise was still getting through than desired. I can probably handle this, but @dforbush2 I'll ask for help if I need it.

dforbush2 commented 2 years ago

Great job! The reason for the "For" loop in the MATLAB script was to simulate "sampling" the time-series to populate the buffers needed for the operations. In reality with data streaming in, one just needs to run the operations on the populated buffer, but getting that right is always the rub in translating these implementations.

I am happy to handle the recalculation of the cut off frequencies, but if you wanted to step through the Filter Design and Analysis tool work-flow in MATLAB (outlined above) it should be relatively straight forward. Alternatively, the order of the filter could be increased at present cut-off frequencies to attenuate the stop-bands more quickly (at the cost of more phase-shift on the ends of the pass-band).

nickross4444 commented 2 years ago

@dforbush2, would you mind taking care of those new coefficients, I've got a bit on my plate this week. I think for now we'll try sticking to the 2nd order filter, as @DeepFriedDerp and I hard coded a lot of the processing in.