1. 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.
    Dismiss Notice

Hoping someone will help me with code concerning timer

Discussion in 'Arduino' started by flat5, Apr 17, 2015.

  1. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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 (text):

    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
    }
     
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,148
    Likes:
    907
    Location:
    Rochdale UK
    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!!!
     
  3. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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: Apr 18, 2015
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,148
    Likes:
    907
    Location:
    Rochdale UK

    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..
     
  6. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    That should be helpful and maybe easier to understand and deal with than capture-compare.
    Edit: I take the second part back :)
     
    Last edited: Apr 18, 2015
  7. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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?
     
  8. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,148
    Likes:
    907
    Location:
    Rochdale UK
    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..​
     
  9. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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: Apr 18, 2015
  10. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    Clearly I don't know what I'm doing.
    Code (text):

    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: Apr 18, 2015
  11. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,148
    Likes:
    907
    Location:
    Rochdale UK
    You really should do this with an interrupt..... Polling the analogue pin isn't the best way..

    I'll need to power up my arduino on Monday!!!!
     
    Last edited: Apr 18, 2015
  12. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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.
     
  13. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    Tried pulseIn.
    Code (text):

    #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: Apr 18, 2015
  14. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,148
    Likes:
    907
    Location:
    Rochdale UK
    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..
     
  15. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    Wow! Thanks, Ian.
    I'll play with that and get back to you.
    I do not understand what the 136 represents.
    Code (text):

    #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: Apr 19, 2015
  16. be80be

    be80be Well-Known Member

    Joined:
    Aug 23, 2008
    Messages:
    4,794
    Likes:
    134
    Location:
    morristown,tn
    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.
     
  17. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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.
     
  18. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    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.
     
  19. be80be

    be80be Well-Known Member

    Joined:
    Aug 23, 2008
    Messages:
    4,794
    Likes:
    134
    Location:
    morristown,tn
    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 (text):
    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: Apr 19, 2015
  20. flat5

    flat5 Member

    Joined:
    Oct 26, 2008
    Messages:
    866
    Likes:
    8
    Location:
    Amsterdam
    be80be, thank you for your time & experience!
    I'm using two Arduino Unos. One to send, one to receive.
    Here is the sending part.
    http://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.
    http://www.electro-tech-online.com/attachments/arduino-morse-interface-png.91538/
    I will study your post more.
     
    Last edited: Apr 19, 2015
  21. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,148
    Likes:
    907
    Location:
    Rochdale UK
    The last parameter is timeout.... That is to help finding the end of the tone.. It defaults to 1 second...
     

Share This Page