This is outputting a large number that is the same for different 'tone' intervals.
I don't have a clue what I'm doing wrong. I'm a rank beginner at 'C'.
Code:
const int AudioThreshold = 400; // compare level for audio signal
const int analogPin = 0; // Analog input pin for audio morse code
unsigned long startTime = 0; // analog pin goes high, start timer
unsigned long currentTime = 0; // while analog pin is high keep counting milliseconds
unsigned long dotTime = 0; // analog pin is now low so compute on time by subtracting start time from stop time
unsigned long wpm = 0; // convert dot time to words per minute
void setup()
{
Serial.begin(9600);
Serial.println("Morse event timer");
}
void loop()
{
while (analogRead(analogPin) < AudioThreshold) // wait for tone
{}
startTime = millis();
while (analogRead(analogPin) > AudioThreshold) // while tone is heard do nothing
{}
currentTime = millis(); // record time that tone stops
dotTime = currentTime - startTime; // in milliseconds how long the tone sounded
wpm = 1200 / dotTime; // convert and report in wpm
Serial.println(wpm);
delay(1000); // for now, to limit garbage on screen
}
Tone??? You are looking for a square wave... Morse is short beep or long beep BUT!! the beeps will be a frequency so if the frequency is middle C (262 Hz) then the result will always be the same.
You need to filter the frequency so you can monitor the length of the tone... If you read up on capture compare you can monitor morse on that module.. Either way.. The analogue input may not be the way to go!! I would use the pulseIn() function to see if I can read it better!!!
Thank you for your help, Ian. I did not mean to make a frequency counter
I had weeks ago considered this problem and decided to go ahead anyway because I did not see how to get around it.
Then I forget the issue! How stupid!
'capture compare' OK, thanks again.
Somehow I have to ignore (?) the fast change and find the slower one.
Edit:
It seems something else is happening. I use a remote control to make the 'dit' on another Arduino that has a sounder. I find if I just drop the remote on the table the same number is displayed every time. Same number as the beep.
'4294967295'
If you look at SIRC ( Nigel has one in his tutorials ) you can better understand how to read frequency pulses... Infrared receivers read sort and long pulses encoded onto a 38Khz carrier frequency... Much the same..
After one cycle through the 'while' a frequency time is established. I'll call it 'freq'.
What code will allow the time count to acumulate till the tone stops for at least 1.5 * freq?
Will this allow me to capture the time the tone is sounded?
If it were me.... I would have the tone coming in on an interrupt pin.. Once an edge is detected start the timer.. If the next rising edge is before the duration of "tone" place it in the count.... If the "tone duration timeout then the whole pulse is detected. You will need to know approximate "tone" frequency!!
wait for rising edge..
start count..
start tone timer..
if next edge is within "tone" time
Count increase.
restart tone timer..
else
Count finished..
store counter with respect to pulse length..
restart counter..
I'll try to absorb that.
The analog 0 pin with threshold is successful for input. I can reliably receive Morse at up to 200 wpm so far.
Problem with using (over using) interrupts is the Arduino Uno does not share them well.
For instance, I did not find a way to use the tone generator and IR receiver in the same sketch.
Had to gate a 555 oscillator instead.
Like I said, the approximate frequency is established (in a perfect world) by the first count.
I assume that a reference of 1.5 that time will be a good minimum count time to see if the tone cycles are being counted instead of the silence. Of course this could end up being a dit or dah. That still has to be determined.
I'm trying to figure if switch case, or while do, or if else, statements ... which is best for this?
I kinda suck at programming. I'm finding this very difficult.
const int AudioThreshold = 400; // compare level for audio signal
const int analogPin = 0; // Analog input pin for audio morse code
unsigned long startTime = 0; // analog pin goes high, start timer
unsigned long currentTime = 0; // while analog pin is low keep counting milliseconds
unsigned long dotTime = 0; // analog pin is low for longer than quietTime so assume //tone has stopped. dotTime=currentTime-startTime
unsigned long wpm = 0; // convert dot time to words per minute
unsigned long freq = 0;
unsigned long quietTest = 0;
bool var = false;
void setup()
{
Serial.begin(9600);
Serial.println("Morse event timer");
}
void loop()
{
while (analogRead(analogPin) < AudioThreshold) // wait for tone
{}
startTime = millis();
while (analogRead(analogPin) > AudioThreshold) // while tone is heard do nothing
{}
freq = millis() - startTime; // time of one event (tone cycle?)
quietTest = freq * 1.7; // don't want multiples of half cycles
switch (var) // don't know what to use the variable for in this routine
{
case 1: // is it ok to have only one case?
delay(quietTest);
currentTime = millis();
if (analogRead(analogPin) < AudioThreshold) // still quiet?
{
break;
}
}
dotTime = currentTime - startTime; // in milliseconds how long the tone sounded
wpm = 1200 / dotTime; // convert and report in wpm
freq = 1 / dotTime;
Serial.print(freq);
Serial.println(" freq");
Serial.print(dotTime);
Serial.println(" dotTime");
Serial.print(wpm);
Serial.println(" wpm");
Serial.println();
delay(1000); // for now, to limit garbage on screen
}
results of four tests:
Morse event timer
0 freq
4294964378 dotTime
0 wpm
The long number has nothing to do with pitch, I believe.
Like I said, if I tap the remote on the table the mic picks up the sound and the sketch spits out the same long number.
In this version I see the number gets a little lower each time. No idea what is happening.
There's 3 things you need to know looks like you got two of them found. What happens is your tone is like a switch bouncing very fast so you need to test for the pin to go low over time that lets you skip tone going low from the carrier and catch it high peaks.
Thank you for your email, Ian.
I tried to implement your ideas but results using analog input are so far useless.
In spite of that the decoder works very well and will be able to decode 'off the air' data when the NE567 IC arrives.
Thank you, be80be. That has been implemented (or worked on) in the earlier sketches.
#9
At this point I'm looking for a meaningful count of anything.
Analog in does not seem to be the route. PulseIn does seem to work.
The frequency of the tone is 262 Hz that's what you posted in post 14 shows that a dit is about 32 mS long and dat is 100 mS long.
But the tone is not a long high its a gated pulse with a start low and ending low.
So you want your code to catch the times it high to make the dit and the dat till the gate goes low.
I would hook my scope up and see what a dit dat dit looks like then it be easy to write the code
But you could do like this just some changes to match you timing its in basic I did it four years ago if you can give me the time of the dit and the dat and how long between each I could write the same code for arduino
Code:
start:
While (IR_mod = 1) //loop while high
i = 0
Wend
While (IR_mod = 0) //loop while low
i = i + 1
DelayUS (200)
Wend
If i <= 10 GoTo start //if to short goto start
If i >= 14 GoTo start //if to long goto start
i = 0 // reset count
loop = 0
For loop = 0 To 6 //was 7 but thats too long need a 6 here for 7 loops LOL
IR_cmd = IR_cmd >>1 // this gets the 0 bits
While (IR_mod = 1)
i = 0
Wend
While (IR_mod = 0)
i = i + 1
DelayUS (200)
Wend
If (i >= 6) Then
IR_cmd = (IR_cmd Or $40) //this gets the 1 bits
End If
Next
Cls
LCD.Write("IR_cmd = ", BinToStr(IR_cmd))
DelayMS(250)
//leds = IR_cmd // this is just a test that outputs the binary
// value to leds on portb
Wend