Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Hoping someone will help me with code concerning timer

Status
Not open for further replies.

flat5

Member
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'
 
Last edited:
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..
 
That should be helpful and maybe easier to understand and deal with than capture-compare.
Edit: I take the second part back :)
 
Last edited:
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.
 
Last edited:
Clearly I don't know what I'm doing.
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 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

0 freq
4294962344 dotTime
0 wpm

0 freq
4294959962 dotTime
0 wpm

0 freq
4294957907 dotTime
0 wpm
 
Last edited:
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.
 
Tried pulseIn.
Code:
#include "Arduino.h"
int pin = 7;
unsigned long pulseTime = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("Sound event timer using pulseIn");
  pinMode(pin, INPUT);
}

void loop()
{
  pulseTime = pulseIn(pin, HIGH);
  if (pulseTime > 0)
  {
  Serial.print(pulseTime);
  Serial.println(" pulse time");
  Serial.println();
  delay(1000); // for now, to limit garbage on screen
  }
}
Probably meaningless results:
89 pulse time

73 pulse time

88 pulse time

61 pulse time

50 pulse time

86 pulse time

50 pulse time

56 pulse time

Again, tapping remote on table gives about the same result.
 
Last edited:
No! Not meaningless... 50~86 is a bit high... That's an average of 68 uS on the high... @ 7khz....

put pulsin() in a loop and every time the function returns a 0, then that's the end of the tone..

while(pulsein(pin,HIGH,) )count++;

Then count * 136uS = tone length..
 
Wow! Thanks, Ian.
I'll play with that and get back to you.
I do not understand what the 136 represents.
Code:
#include "Arduino.h"
int pin = 7;
unsigned long toneLength = 0;
unsigned long count = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("Sound event timer using pulseIn");
  pinMode(pin, INPUT);
}

void loop()
{
  while (pulseIn(pin, HIGH))count++; // did not compile with second comma
  toneLength = count * 136;
  {
  Serial.print(toneLength);
  Serial.println(" tone length in microseconds");
  Serial.println();
  delay(1000); // for now, to limit garbage on screen
  toneLength = 0;
  count = 0;
  }
}

received data:
3 dits:
32232 tone length in microseconds
32232 tone length in microseconds
32504 tone length in microseconds

3 dahs:
100232 tone length in microseconds
99824 tone length in microseconds
99960 tone length in microseconds

True frequency is 1.029 kHz
 
Last edited:
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
 
Last edited:
be80be, thank you for your time & experience!
I'm using two Arduino Unos. One to send, one to receive.
Here is the sending part.
https://www.electro-tech-online.com/threads/tone-irreceive-problem.144299/#post-1216730
Presently set to 20 wpm. I have altered the sketch so that pressing remote key 1 sends a dit. Pressing 2 sends a dah.

True frequency is 1.029 kHz

The mic preamp collector (decoder) to scope shows more like a sine wave than square wave.
For the purposes of this thread input D7 works better than A0 but otherwise the preamp can be found here.
https://www.electro-tech-online.com/attachments/arduino-morse-interface-png.91538/
I will study your post more.
 
Last edited:
while (pulseIn(pin, HIGH))count++; // did not compile with second comma
The last parameter is timeout.... That is to help finding the end of the tone.. It defaults to 1 second...
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top