Arduino Ping))) Sensor suddenly stops after showing a few results - java

I have a ping))) sensor (HC - SR04) which is connected correctly.
I start it up without being connected to ground (otherwise it doesn't even want to start) and it keeps writing 0 to the serial window (distance). Once I plug it in the ground pin, I get a few lines of correct distance readings and than it stops and hangs, no more results in the serial window, and the board itself seems to be in a fault state, and I need to unplug it from the USB, disconnect the ground, and then re-plug to the USB.
What can be the cause of the problem?
Code:
#define echoPin 2 // Echo Pin
#define trigPin 4 // Trigger Pin
#define LEDPin 13 // Onboard LED
int maximumRange = 200; // Maximum range needed
int minimumRange = 0; // Minimum range needed
long duration, distance; // Duration used to calculate distance
int currentDistance = 0;
void setup() {
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(LEDPin, OUTPUT); // Use LED indicator (if required)
}
void loop() {
/* The following trigPin/echoPin cycle is used to determine the
distance of the nearest object by bouncing soundwaves off of it. */
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
//Calculate the distance (in cm) based on the speed of sound.
distance = duration/58.2;
if (distance >= maximumRange || distance <= minimumRange){
/* Send a negative number to computer and Turn LED ON
to indicate "out of range" */
Serial.println("-1");
digitalWrite(LEDPin, HIGH);
} else {
/* Send the distance to the computer using Serial protocol, and
turn LED OFF to indicate successful reading. */
Serial.println(distance);
digitalWrite(LEDPin, LOW);
}
//Delay of 50 ms before next reading.
delay(50);
}
------------------------ UPDATE ------------------------------
It would seem that the problem is not with the sensor, but with the serial interface: I have attached an LED to the board and am giving it an analog value according to the distance. Once the Arduino gets "stuck", the LED keeps working correctly, so I guess the problem is with the Arduino shutting down the serial interface and stopping data transmission through the USB.
How can this problem be fixed?

The solution to the sensor being stuck at zero is in this link. It's the 2nd post, by docdoc. You will need to use the NewPing library which is far better.
A working code:
#include <NewPing.h>
#define TRIGGER_PIN 12
#define ECHO_PIN 11
#define MAX_DISTANCE 200
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
Serial.begin(9600);
}
void loop() {
delay(50);
unsigned int uS = sonar.ping();
pinMode(ECHO_PIN,OUTPUT);
digitalWrite(ECHO_PIN,LOW);
pinMode(ECHO_PIN,INPUT);
Serial.print("Ping: ");
Serial.print(uS / US_ROUNDTRIP_CM);
Serial.println("cm");
}
Link: http://forum.arduino.cc/index.php?topic=55119.15
NewPing link: http://playground.arduino.cc/Code/NewPing

From what you say, it looks like there is an interminent shortcut between the ground and the device... Or maybe there's a faulty component shortcuting to the ground. So my advice would be:
Is the Arduino working correctly?
Test whether the Arduino itself works flawlessly without having the sensor connected (upload a echo sketch),
Is the sensor device working correctly?
Test continuity of all soldering points (look up for a shortcut bridge between the ground and a signal),
Test with another sensor device (if you happen to have a spare) to see if the problem persists
Or try the same device with another Arduino.
About your code itself, which is not, as far as I can tell, the source of your problems, I'd advice you to change the declaration of your global constants to either:
const uint8_t maximumRange = 200; // Maximum range needed
const uint8_t minimumRange = 0; // Minimum range needed
const uint8_t currentDistance = 0;
Or use the preprocessor:
#define maximumRange 200 // Maximum range needed
#define minimumRange 0 // Minimum range needed
#define currentDistance = 0
And move:
long duration, distance; // Duration used to calculate distance
inside your loop() function. Avoiding non-constant globals as much as possible is always a good idea (though not always possible with Arduino objects).

I was able to find the cause of the problem. It seems that the Arduino's serial monitor was causing the "crash", because while using a server utility that allows the Arduino output to be used in Flash (serproxy) the Arduino performs consistently and without problems.
A video of the project is Arduino + Ping))) Sensor - Change display in application according to distance.

Related

Smoothing signal from microphone - Hearthbeat

I'm working on project using oximeter.I want to smooth it out so I can use it for calculating hearthbeat. I'm gathering raw data from microphone , I put them in new array, lets say, sData[].
Signal is really crazy and jumps all over the plot as expected, so i tried smoothing it using moving average. So my main code looks something like this.
writeAudioDataToFile();
for (int a = 0; a < sData.length; a++) {
tempAvg += Math.abs(sData[a]);
if (a % numberOfSamplesAveraged == 0) { //Average from x samples
if (myIndex > SAMPLE_SIZE - 1) {
myIndex = 0;
}
tempAvg = tempAvg / numberOfSamplesAveraged;
if (tempAvg > 500) {
newDataArray[myIndex] = 500;
}else{
newDataArray[myIndex] = tempAvg;
} //This is suppose to clear the high peaks.
Log.d("isRecording - Average from " + numberOfSamplesAveraged + " numbers.", "newDataArray[" + myIndex + "] = " + newDataArray[myIndex]);
tempAvg = 0;
myIndex++;
}
}
notifier.notifyObservers();
Log.d("Notifier", "Notifier Fired!");
Thread.sleep(20); //Still experimenting with this value
It looks so messy, but the plot (I'm using AndroidPlot btw) looks good but it is so inaccurate so I can't calculate the hearthrate from it. It has so much "Bounce" in "high" state. I found on internet that some kind of filter (Maybe IIR filter) will do the job. So i just wanna ask you guys how can i achieve a nice smooth chart? Is IIR filter the way to go? Is there any free applet/lib to smoothen it out?
This is my first question here so I'm really sorry if it is badly written.
If you will need any more information to help me, just ask.
Here is a picture how my chart looks like now.
http://oi62.tinypic.com/2uf7yoy.jpg // Cant post images im new here.
This is a lucky one though.
I need smoother output.
Noises, which occur at measurement, have high frequency. You should filter your signal, that is you should retain low frequency part of signal and suppress high frquency part of signal. You can do it, making a low-pass filter. It could be, for example, first-order inertial model. I suggest make a pass-band till ~~10 kHz, since people hear sound from 2 kHz to 20 kHz. Then appriopriate sample time is 0,0001 sec (0,1 ms). Discrete model has following equation:
y[k] = 0.9048*y[k-1] + 0.09516*u[k-1],
where u is a measured vector (directly from microphone, input in our filter),
and y is a vector you want to analyze (so output from our filter).
As you can see,, you can calculate a sample number 1, and you can just assign 0 to the sample number 0. After all, you can try to plot y vector.

Arduino port stuck on full power

I am working on a system that rings a bell when someone decides to ring it or it is timed. This also includes emergency bells, such as when there is an earthquake threat or an armed intruder. On the armed intruder bell it rings for .5 seconds (500ms) and then waits 1.5s (1500ms) and repeats. However, on the fourth cycle the bell gets stuck on and will stay on until I turn the arduino off. I have tried many ways of trying to fix it but it will not work. I will post my code below and could someone have a look and see what is wrong with it?
Thank you!
Java for loop:
for(int i = 0; i < 21; i++) {
out.write("500".getBytes("UTF-8"));
out.flush();
Thread.sleep(2000);
}
Arduino Code:
int Relay = 13;
//The pin that the relay is attached to
//int time;
//Creates temp variable
void setup() {
Serial.begin(9600);
pinMode(Relay, OUTPUT);
}
void loop() {
while(true) {
//Check if data has been sent from the computer:
if (Serial.available()) {
int time;
//Assign serial value to temp
time = Serial.parseInt();
//Output value to relay
delay(1000);
digitalWrite(Relay, HIGH);
delay(time);
digitalWrite(Relay, LOW);
}
}
}
You might try putting a small delay into the if-loop, after checking and before reading from the Serial (just a few ms. Maybe put your 1000ms delay at the beginning). As the data arrive serialized, and you check with a high frequency, it might be, that the program starts reading out data before everything is received.
I don't know how exactly Serial.parseInt() works, but maybe try:
out.write("500\n".getBytes("UTF-8"));
in your Java-loop

Echo/delay algorithm just causes noise/static?

There have been other questions and answers on this site suggesting that, to create an echo or delay effect, you need only add one audio sample with a stored audio sample from the past. As such, I have the following Java class:
public class DelayAMod extends AudioMod {
private int delay = 500;
private float decay = 0.1f;
private boolean feedback = false;
private int delaySamples;
private short[] samples;
private int rrPointer;
#Override
public void init() {
this.setDelay(this.delay);
this.samples = new short[44100];
this.rrPointer = 0;
}
public void setDecay(final float decay) {
this.decay = Math.max(0.0f, Math.min(decay, 0.99f));
}
public void setDelay(final int msDelay) {
this.delay = msDelay;
this.delaySamples = 44100 / (1000/this.delay);
System.out.println("Delay samples:"+this.delaySamples);
}
#Override
public short process(short sample) {
System.out.println("Got:"+sample);
if (this.feedback) {
//Delay should feed back into the loop:
sample = (this.samples[this.rrPointer] = this.apply(sample));
} else {
//No feedback - store base data, then add echo:
this.samples[this.rrPointer] = sample;
sample = this.apply(sample);
}
++this.rrPointer;
if (this.rrPointer >= this.samples.length) {
this.rrPointer = 0;
}
System.out.println("Returning:"+sample);
return sample;
}
private short apply(short sample) {
int loc = this.rrPointer - this.delaySamples;
if (loc < 0) {
loc += this.samples.length;
}
System.out.println("Found:"+this.samples[loc]+" at "+loc);
System.out.println("Adding:"+(this.samples[loc] * this.decay));
return (short)Math.max(Short.MIN_VALUE, Math.min(sample + (int)(this.samples[loc] * this.decay), (int)Short.MAX_VALUE));
}
}
It accepts one 16-bit sample at a time from an input stream, finds an earlier sample, and adds them together accordingly. However, the output is just horrible noisy static, especially when the decay is raised to a level that would actually cause any appreciable result. Reducing the decay to 0.01 barely allows the original audio to come through, but there's certainly no echo at that point.
Basic troubleshooting facts:
The audio stream sounds fine if this processing is skipped.
The audio stream sounds fine if decay is 0 (nothing to add).
The stored samples are indeed stored and accessed in the proper order and the proper locations.
The stored samples are being decayed and added to the input samples properly.
All numbers from the call of process() to return sample are precisely what I would expect from this algorithm, and remain so even outside this class.
The problem seems to arise from simply adding signed shorts together, and the resulting waveform is an absolute catastrophe. I've seen this specific method implemented in a variety of places - C#, C++, even on microcontrollers - so why is it failing so hard here?
EDIT: It seems I've been going about this entirely wrong. I don't know if it's FFmpeg/avconv, or some other factor, but I am not working with a normal PCM signal here. Through graphing of the waveform, as well as a failed attempt at a tone generator and the resulting analysis, I have determined that this is some version of differential pulse-code modulation; pitch is determined by change from one sample to the next, and halving the intended "volume" multiplier on a pure sine wave actually lowers the pitch and leaves volume the same. (Messing with the volume multiplier on a non-sine sequence creates the same static as this echo algorithm.) As this and other DSP algorithms are intended to work on linear pulse-code modulation, I'm going to need some way to get the proper audio stream first.
It should definitely work unless you have significant clipping.
For example, this is a text file with two columns. The leftmost column is the 16 bit input. The second column is the sum of the first and a version delayed by 4001 samples. The sample rate is 22KHz.
Each sample in the second column is the result of summing x[k] and x[k-4001] (e.g. y[5000] = x[5000] + x[999] = -13840 + 9181 = -4659) You can clearly hear the echo signal when playing the samples in the second column.
Try this signal with your code and see if you get identical results.

Arduino bat sensor registers too many times

I need to progam an Arduino for a project, and I thought I'd add something fancy, a LED color changing thingy. The LED has a sort of cyclus in which it changes colors, which takes about 40 seconds to do so. Though, the bat sensor, that makes the LED burn, registers the whole time and tells the LED a couple of times a second to go on, again. The LED never gets the time to change color and only stays the first color.
I have no idea how to fix this. I was trying to give the LED a delay or something, but apparently I did that wrong. The code so far is this;
//Pin which triggers ultrasonic sound.
const int pingPin = 13;
//Pin which delivers time to receive echo using pulseIn().
int inPin = 12;
//Range in cm which is considered safe to enter, anything
//coming within less than 5 cm triggers the red LED.
int safeZone = 10;
//LED pin numbers
int redLed = 3, greenLed = 5;
void setup() {
//Initialize serial communication
Serial.begin(9600);
//Initializing the pin states
pinMode(pingPin, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(greenLed, OUTPUT);
}
void loop()
{
//Raw duration in milliseconds, cm is the
//converted amount into a distance.
long duration, cm;
//Sending the signal, starting with LOW for a clean signal 2 staat voor reactie.
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
//Setting up the input pin, and receiving the duration in
//microseconds for the sound to bounce off the object in front.
pinMode(inPin, INPUT);
duration = pulseIn(inPin, HIGH); //Documentation for pulseIn():
//http://www.arduino.cc/en/Reference/PulseIn
//Convert the time into a distance
cm = microsecondsToCentimeters(duration);
//Printing the current readings to the serial display
Serial.print(cm);
Serial.print("cm");
Serial.println();
//If het is groter dan 10 dan gaat het lichtje uit
//else het is binnen bepaalde cm dan gaat het aan van 0 naar 255.
if(cm>10)
{
analogWrite(redLed, 0);
}
else{
analogWrite(redLed, map(cm,0,10,255,0));
dela
}
if(cm>5)
{
analogWrite(greenLed, 0);
}
else{
analogWrite(greenLed, map(cm,0,5,255,0));
}
delay(100);
}
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
But it still needs some kind of delay thing I think. I'm not sure what the sensor I'm using is called but it has two rounds with sensors in them, one sends and one receives, it measures how long it takes to receive back the sound and in my code I translate that to cm.
I hope you can help and understand what my problem is since my knowledge of this language is very poor.
Set a timeout value for pulseIn. Otherwise the program gets stuck in the line duration = pulseIn(inPin, HIGH); as you don't get the chance to send out another ultrasonic pulse if the previous ultrasonic pulse did not result in an echo.
In this case, the maximum range is 10 cm (20 cm travel distance for the sound pulse) so the timeout value can be set accordingly (s is distance, v is velocity and t is time):
s = v * t => t = s / v = 2 * 0.1 m / 343.2 m/s = 582.8 µs
The speed of sound is assumed to be in dry air at 20 °C.
Allowing for the width of the outgoing pulse of 2 µs the total time would then be 584.8 µs.
Instead of
duration = pulseIn(inPin, HIGH);
use
duration = pulseIn(inPin, HIGH, 585);
Other notes:
The outgoing pulse is very short, intended to be 2 µs.
digitalWrite() is quite slow, on the order of 5 µs so the actual pulse may be longer than 2 µs. Even so, the ultrasonic transducer may not be able to start up in such a short time.
Even if the outgoing pulse is longer than you think it is, it is on the order of a single period (if the ultrasonic transducer operates at 100 kHz the period is 10 µs)
Try to experiment with longer ranges and longer outgoing pulses to be sure this is not the problem.
Use delay(ms) to delay for 40 ms as required. That will shut the Arduino for 40 ms before it gets to process any data from the ultrasonic sensor.

Java audio effects - Distortion algorithm on Android

I'm working on an application for android that does some real-time processing of audio from the mic. The sampling and playback is working effectively, but I am having difficulty with implementing the first audio effect - distortion. The audio comes in buffers of shorts, so each time one of these is received I attempt to map the values to the full size of a signed short, and then essentially clip these values if they are above a certain level. The audio that comes from this is certainly distorted, but not in a desirable way. I've included my code for accomplishing this. Can anyone see an error here?
public void onMarkerReached(AudioRecord recorder) {
// TODO Auto-generated method stub
short max = maxValue(buffers[ix]);
short multiplier;
if(max!=0)
multiplier = (short) (0x7fff/max);
else
multiplier = 0x7fff;
double distLvl =.8;
short distLvlSho = 31000;
short max2 =100;
for(int i=0;i<buffers[ix].length;i++){
buffers[ix][i]=(short) (buffers[ix][i]*multiplier);
if(buffers[ix][i]>distLvlSho)
buffers[ix][i]=distLvlSho;
else if(buffers[ix][i]<-distLvlSho)
buffers[ix][i]=(short)-distLvlSho;
buffers[ix][i]=(short) (buffers[ix][i]/multiplier);
}
The buffers array is a 2D array of shorts, and the processing is to be done on just one of the array-within-arrays, here buffers[ix].
As far as I see in the end what you get is just a clipping of the source with a clip threshold which follows the proportion clipThr/max(input)=distLvlSho/0x7fff. most of the input this way is basically unchanged.
If you actually wanted to distort the signal you should apply some kind nonlinear function to the whole signal (plus eventually clipping near sample max to simulate the analog saturation)
A few simple models for distortion are listed in this book : http://books.google.it/books?id=h90HIV0uwVsC&printsec=frontcover#v=onepage&q&f=false
The simplest is a simmetrical soft clipping (see page 118). Here's your method modified with that soft clip function, see if it fits your needs for distorted sound (I tested it by making up a few sinusoids on input and using excel to plot the output)
In the same chapter you'll find a simple tube modeling and a fuzz filter modeling (there are a few exponentials on those so if performance is an issue you might want to approximate those).
public void onMarkerReachedSoftClip(short[] buffer) {
double th=1.0/3.0;
double multiplier = 1.0/0x7fff; // normalize input to double -1,1
double out = 0.0;
for(int i=0;i<buffer.length;i++){
double in = multiplier*(double)buffer[i];
double absIn = java.lang.Math.abs(in);
if(absIn<th){
out=(buffer[i]*2*multiplier);
}
else if(absIn<2*th){
if(in>0)out= (3-(2-in*3)*(2-in*3))/3;
else if(in<0)out=-(3-(2-absIn*3)*(2-absIn*3))/3;
}
else if(absIn>=2*th){
if(in>0)out=1;
else if(in<0)out=-1;
}
buffer[i] = (short)(out/multiplier);
}
}
If you multiply 2 short integers, the result requires a long integer or the result can overflow.
e.g. 1000 * 1000 = 1000000 , which is too big for a 16-bit short integer.
So you need to perform a scaling operation (divide or right shift) before you convert the multiplication result to a short value for storage. Something like:
result_short = (short)( ( short_op_1 * short_op_2 ) >> 16 );

Categories

Resources