I am currently working on a Turbidity meter that returns a value of the voltage from 0-5.0 (this number will change depending on how turbid the water so a lower voltage reading indicates a more turbid water).
What I am trying to do is take the voltage reading that I get and convert it to a reading that expresses the turbidity in the water (so a voltage reading of 4.8 would equal 0 to a voltage reading of 1.2 would equal 4000).
I have written some code using MicroLogic and I know that in there there is a box that looks at the incoming reading and will scale the outgoing reading between a Min and Max number that you put in (an example in MicroLogic is that I get a 4-20mA signal in and it will scale the output to mean a water level in a tank based on that 4mA = 0ft and 20mA = 12ft)
Is there a scaling code for python, or how to I go about doing this? Thanks!
You could do something like this:
def turbidity(voltage):
return 4000 - (voltage-1.2)/(4.8-1.2)*4000
print(turbidity(1.2), turbidity(2.4), turbidity(4.8))
Which would print out:
4000.0 2666.6666666666665 0.0
If you want integers instead, add an int() call like so:
4000 - int((voltage-1.2)/(4.8-1.2)*4000)
Good luck with your turbidity!
Related
I am dealing with an audio file that shows sudden spikes:
When I try to normalize the audio file, the audio program sees this spike, notices that it is at 0 dB and won't normalize the audio any more.
To solve this issue, I have applied a Limiter that limits to -3 dB. I have used both Steinberg Wavelab and Audacity Hard Limiter. Instead, they both diminish the entire audio volume.
Both do not eliminate this spike.
Edit: I have found out that "Hard Clip" in Audacity does what I need, but now I still want to finish my own approach.
So I was thinking that they perhaps do not work correctly.
Then I tried to write my own limiter in VB6 in order to have full control over what's happening.
To do that, I'm loading the audio data of a wav file like this:
(I have stripped the process down very much)
Dim nSamples() As Integer
ReDim nSamples(0 To (lCountSamples - 1))
Get #iFile, , nSamples
I have the audio data in "nSamples" now.
Dim i&
For i = 1 To UBound(nSamples)
Dim dblAmplitude As Double
dblAmplitude = nSamples(i) / 32767
Dim db As Double
db = 20 * Log10(dblAmplitude)
If db > -0.3 Then
nSamples(i)=0 'how would I lower the volume here instead of just setting it to 0???
End If
Next
I'm not sure how I could calculate the dB from the sample data in order to clip it and how to clip it to -3dB.
I have now simply tried it with settings the clipping value to "0".
However, something strange happens here: The lower part of the audio is gone:
I expected that setting a value to 0 would mute the audio, but in my case, the lower wav form is gone.
What is wrong about my approach?
Thank you!
Calculating dB from audio samples isn't that simple.
It sounds like what you want to do is find an appropriate threshold and then clip the audio with something like:
If Abs(nSamples(i)) > threshold Then
nSamples(i) = threshold * Sgn(nSamples(i))
You could set the threshold to some fixed value if it's the same for all of your audio clips. Otherwise, it might be more accurate to sort the samples and search for a large gap between points near the top and bottom to find your threshold.
I've got an Adafruit Bluefruit NRF52 hooked up to the Adafruit BNO055 9-axis orientation sensor, gathering 3 axis of absolute orientation plus 3 axis of acceleration (6 floats in total) and sending over Bluetooth through bleuart. I need the bleuart to update every 7.5 milliseconds with a new line of values, but when I run it, it doesn't print more than about 20 lines new lines of values every second. Essentially I need values to update as quickly as possible, as I am measuring very high speed, high fidelity movement.
At the start of each line I also have three digit number, which represents the calibration status of each sensor on the IMU. Each printed line looks something like:
303 68.69 4.19 -2.19 -0.12 0.14 -0.40
I am currently streaming to my iphone with the latest iOs version, which in theory can handle 7.5ms intervals.
I've read that a solution may be to buffer the values and send over in a larger chunk at larger connection intervals, but am unsure on how to do this.
My relevant Arduino code is below:
Bluefruit.setConnIntervalMS(7.5, 20);
void loop()
{
imu::Vector<3> accel =
bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
/* Get a new sensor event */
sensors_event_t event;
bno.getEvent(&event);
/* Display the floating point data */
bleuart.print(event.orientation.x);
bleuart.print("\t");
bleuart.print(event.orientation.y);
bleuart.print("\t");
bleuart.print(event.orientation.z);
bleuart.print("\t");
/* Display the floating point data for Linear Acceleration */
bleuart.print(accel.x());
bleuart.print("\t");
bleuart.print(accel.y());
bleuart.print("\t");
bleuart.print(accel.z());
bleuart.print("\n");
}
iOS doesn't actually support a 7.5ms connection interval. Check the connection parameters section (11.6) in the Apple developer guidelines. Just because you are specifying a CI that low doesn't mean that you'll actually get it. In this scenario the nRF52 is the slave and only requests an interval that low from the master (your phone). The master, if it so wishes, can completely disregard the request you make.
You'd be better off, as you've already eluded to, buffering your data and sending it via a custom characteristic. Figure out how many bytes you need and maybe you can pack a couple of readings into a single BLE write. If you're really struggling with throughput then you'll need a custom service with multiple characteristics. I recently worked on a project that streams 8 channels of data (~125Hz/16-bit) over BLE with three characteristics and this is bordering on the maximum throughput you can achieve.
As an aside: judging data throughput by the amount of lines printed per second is a big no no. Print functions typically have huge overheads and will drastically affect your measured throughput in a negative way.
Let me know if I can help further.
I have program which tracks audio signal in real time. Every processed sample I am able to read value of it in range between <-1, 1>.
I would like to create(and later display) audio level meter. From what I understand - to do it I need to keep converting my audio signal in real time, on each channel to dB and then display dB values on each channel in some graphical form of bars.
I am a bit lost how to do it and it should be simple matter. Would just normalization from <-1, 1> to <0, 1> (like... [n-sample +1]/2) and then calculating 20*log10 from each upcoming sample make it?
You can't plot the signal directly, as it always varying positive and negative.
Therefore you need to average out the strength of the signal every so many samples.
Say you're sampling at 44.1kHz, perhaps you might choose 4410 samples so you're updating your display 10 times per second.
So you calculate the RMS of your 4410 samples - see http://en.wikipedia.org/wiki/Root_mean_square
The RMS value is always positive.
You can then convert this to Db:
dBV = 20 x log10(Vrms)
This assumes that your maximum signal -1 to +1 corresponds to -1 to +1 volt. You will need to do further adjustments if not.
Everyone knows that MRTG needs at least one value to be passed on it's input.
In per-target options MRTG has 'gauge', 'absolute' and default (with no options) behavior of 'what to do with incoming data'. Or, how to count it.
Lets look at the elementary, yet popular example :
We pass cumulative data from network interface statistics of 'how much packets were recieved by the interface'.
We take it from '/proc/net/dev' or look at 'ifconfig' output for certain network interface. The number of recieved bytes is increasing every time. Its cumulative.
So as i can imagine there could be two types of possible statistics:
1. How fast this value changes upon the time interval. In oher words - activity.
2. Simple, as-is growing graphic that just draw every new value per every minute (or any other time interwal)
First graphic will be saltatory (activity). Second will just grow up every time.
I read twice rrdtool's and MRTG's docs and can't understand which option mentioned above counts what.
I suppose (i am not sure) that 'gauge' draw values as is, without any differentiation calculations (good for measuring how much memory or cpu is used every 5 minutes). And default or 'absolute' behavior tryes to calculate the speed between nearby measures, but what's the differencr between last two?
Can you, guys, explain in a simple manner which behavior stands after which option of three options possible?
Thanks in advance.
MRTG assumes that everything is being measured as a rate (even if it isnt a rate)
Type 'gauge' assumes that you have already calculated the rate; thus, the provided value is stored as-is (after Data Normalisation). This is appropriate for things like CPU usage.
Type 'absolute' assumes the value passed is the count since the last update. Thus, the value is divided by the number of seconds since the last update to get a rate in thingies per second. This is rarely used, and only for certain unusual data sources that reset their value on being read - eg, a script that counts the number of lines in a log file, then truncates the log file.
Type 'counter' (the default) assumes the value passed is a constantly growing count, possibly that wraps around at 16 or 64 bits. The difference between the value and its previous value is divided by the number of seconds since the last update to get a rate in thingies per second. If it sees the value decrease, it will assume a counter wraparound at 16 or 64 bit. This is appropriate for something like network traffic counters, which is why it is the default behaviour (MRTG was originally written for network traffic graphs)
Type 'derive' is like 'counter', but will allow the counter to decrease (resulting in a negative rate). This is not possible directly in MRTG but you can manually create the necessary RRD if you want.
All types subsequently perform Data Normalisation to adjust the timestamp to a multiple of the Interval. This will be more noticeable for Gauge types where the value is small than for counter types where the value is large.
For information on this, see Alex van der Bogaerdt's excellent tutorial
as a software engineer I am facing with some difficulties while working on a signal processing problem. I don't have much experience in this area.
What I try to do is to sample the environmental sound with 44100 sampling rate and for fixed size windows to test if a specific frequency (20KHz) exists and is higher than a threshold value.
Here is what I do according to the perfect answer in How to extract frequency information from samples from PortAudio using FFTW in C
102400 samples (2320 ms) is gathered from audio port with 44100 sampling rate. Sample values are between 0.0 and 1.0
int samplingRate = 44100;
int numberOfSamples = 102400;
float samples[numberOfSamples] = ListenMic_Function(numberOfSamples,samplingRate);
Window size or FFT Size is 1024 samples (23.2 ms)
int N = 1024;
Number of windows is 100
int noOfWindows = numberOfSamples / N;
Splitting samples to noOfWindows (100) windows each having size of N (1024) samples
float windowSamplesIn[noOfWindows][N];
for i:= 0 to noOfWindows -1
windowSamplesIn[i] = subarray(samples,i*N,(i+1)*N);
endfor
Applying Hanning window function on each window
float windowSamplesOut[noOfWindows][N];
for i:= 0 to noOfWindows -1
windowSamplesOut[i] = HanningWindow_Function(windowSamplesIn[i]);
endfor
Applying FFT on each window (real to complex conversion done inside the FFT function)
float frequencyData[noOfWindows][samplingRate/2];
for i:= 0 to noOfWindows -1
frequencyData[i] = RealToComplex_FFT_Function(windowSamplesOut[i], samplingRate);
endfor
In the last step, I use the FFT function implemented in this link: http://www.codeproject.com/Articles/9388/How-to-implement-the-FFT-algorithm ; because I cannot implement an FFT function from the scratch.
What I can't be sure is while giving N (1024) samples to FFT function as input, samplingRate/2 (22050) decibel values is returned as output. Is it what an FFT function does?
I understand that because of Nyquist Frequency, I can detect half of sampling rate frequency at most. But is it possible to get decibel values for each frequency up to samplingRate/2 (22050) Hz?
Thanks,
Vahit
See see How do I obtain the frequencies of each value in an FFT?
From a 1024 sample input, you can get back 512 meaningful frequency-levels.
So, yes, within your window, you'll get back a level for the Nyquist frequency.
The lowest frequency level you'll see is for DC (0 Hz), and the next one up will be for SampleRate/1024, or around 44 Hz, the next for 2 * SampleRate/1024, and so on, up to 512 * SampleRate / 1024 Hz.
Since only one band is used in your FFT, I would expect your results to be tarnished by side-band effects, even with proper windowing. It might work, but you might also get false positives with some input frequencies. Also, your signal is close to your niquist, so you are assuming a fairly good signal path up to your FFT. I don't think this is the right approach.
I think a better approach to this kind of signal detection would be with a high order filter (depending on your requirements, I would guess fourth or fifth order, which isn't actually that high). If you don't know how to design a high order filter, you could use two or three second order filters in series. Designing a second order filter, sometimes called a "biquad" is described here:
http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
albeit very tersely and with some assumptions of prior knowledge. I would use a high-pass (HP) filter with corner frequency as low as you can make it, probably between 18 and 20 kHz. Keep in mind there is some attenuation at the corner frequency, so after applying a filter multiple times you will drop a little signal.
After you filter the audio, take the RMS or average amplitude (that is, the average of the absolute value), to find the average level over a time period.
This technique has several advantages over what you are doing now, including better latency (you can start detecting within a few samples), better reliability (you won't get false-positives in response to loud signals at spurious frequencies), and so on.
This post might be of relevance: http://blog.bjornroche.com/2012/08/why-eq-is-done-in-time-domain.html