Measuring IR for replay.

Discussion in 'Embedded Systems and Microcontrollers' started by AgentSmithers, Sep 14, 2016.

  1. AgentSmithers

    Thread Starter Active Member

    Jan 14, 2011
    52
    0
    Hi everyone, I was doing some reading and I wanted to confirm that IR usually operates at 9600 baud or less. That seems kinda odd that its standardized based on my searches.

    Anyways, I have an ATTiny85 laying around and I wanted to sample the times between pauses. So doing the number crunching 9600 every second is approx. 1 bit every 0.000104 sec's AKA every 104 Microseconds or 0.104 Milliseconds.
    So in order to sample this I used a 8MHZ at a 64bit prescaler to get a decent sampling of every 0.0001 per second at around 13.020833333333334 ticks AKA 13.02 -> 13 ticks.

    With the code below that I wrote do you think this i will be enough for playblack on IR to control a subject or do I need more accuracy then what I have?

    Also when I start my project the OVF_vect is triggered twice before I even init my prescaler, is that normal?

    I assume at the next point what I need to do is chop up the timeinms by 13 to get the milliseconds then decode the bits from it correct?

    Thank you for your guidance.

    Code (Text):
    1.  
    2. void timer0_init()
    3. {  
    4.     // initialize counter
    5.     TCNT0 = 0;
    6.  
    7.     // enable overflow interrupt
    8.     TIMSK |= (1 << TOIE0);
    9.  
    10.     // enable global interrupts
    11.     sei();
    12.  
    13.     // initialize overflow counter variable
    14.     tot_overflow = 0;
    15. }
    16.  
    17. int mybytesrecv = 0;
    18. int timeinms[256];
    19. int index = 0;
    20. ISR(PCINT0_vect)
    21. {
    22.     timeinms[index] = TCNT0;
    23.     index++;
    24.     TCNT0=0; //reset the clock
    25.     TCCR0B |= (1 << CS00) | (1 << CS01); //Starts Timer
    26.     if (index>=255) //prevent overflow
    27.     {
    28.         TCNT0=0; //reset the clock
    29.         TCCR0B = 0; //stop Timer
    30.         index = 0;
    31.     }
    32. }
    33.  
    34. // TIMER0 overflow interrupt service routine
    35. // called whenever TCNT0 overflows
    36. ISR(TIMER0_OVF_vect)
    37. {
    38.     // keep a track of number of overflows
    39.     //tot_overflow++;
    40.     TCCR0B = 0; //Stops Timer
    41.     if (index >= 1)
    42.     {
    43.         for (int i=0;i<=index;i++)
    44.         {
    45.             soft_uart_send(PSTR("."));
    46.         }
    47.         soft_uart_send(PSTR("\r\n"));
    48.         index = 0;
    49.     }
    50. }
    51.  
     
    Last edited: Sep 14, 2016
  2. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    9600 baud is approximately 1 bit every 100uS (not 1mS)
    If you sample every 0.0001 Second - that is every 100uS - you are going to miss a lot of pulses unless the sampling is synchronised to the waveform you are sampling.
     
  3. AgentSmithers

    Thread Starter Active Member

    Jan 14, 2011
    52
    0
    Blast! off by ah zero. *Goes back to the drawing boards*

    Edit: I fixed my verbiage above but at 8MHZ and with a 64 prescacler 13ticks is still the correct answer.
     
    Last edited: Sep 14, 2016
  4. DNA Robotics

    Member

    Jun 13, 2014
    123
    26
    The TMFS5360 chip will sort all of that out for you. You can find them in almost any appliance that is IR remote controlled.
     
  5. dannyf

    Well-Known Member

    Sep 13, 2015
    1,821
    364
    You will likely have insufficient time to execute the timer isr, especially if index is large and your UART routines aren't interrupt driving.

    You may want to rethink your approach.
     
  6. AgentSmithers

    Thread Starter Active Member

    Jan 14, 2011
    52
    0
    I refined the code, how is this for the ISR?
    Thanks for everyone guidance.
    Code (Text):
    1.  
    2. // initialize timer, interrupt and variable
    3. void timer0_init()
    4. {
    5.     // set up timer with prescaler = 256
    6.     //TCCR0B |= (1 << CS02);
    7.    
    8.     // set up timer with prescaler = 8
    9.     //TCCR0B |= (1 << CS01);
    10.    
    11.     // set up timer with prescaler = 1
    12.     //TCCR0B |= (1 << CS00);
    13.    
    14.     // set up timer with prescaler = 64
    15.     //TCCR0B |= (1 << CS00) | (1 << CS01);
    16.    
    17.     // initialize counter
    18.     TCNT0 = 0;
    19.    
    20.     // enable overflow interrupt
    21.     TIMSK |= (1 << TOIE0);
    22.    
    23.     // enable global interrupts
    24.     sei();
    25.    
    26.     // initialize overflow counter variable
    27.     //tot_overflow = 0;
    28. }
    29.  
    30. int mybytesrecv = 0;
    31. uint8_t timeinms[246];
    32. int index = 0;
    33. char intToStr[4];
    34. ISR(PCINT0_vect)
    35. {
    36.     //TCCR0B |= (1 << CS02); //Starts Timer
    37.     TCCR0B |= (1 << CS00) | (1 << CS01);
    38.     timeinms[index] = TCNT0; //Micro Second every 13 ticks
    39.     index++;
    40.     TCNT0=0; //reset the clock
    41. }
    42.  
    43. // TIMER0 overflow interrupt service routine
    44. // called whenever TCNT0 overflows
    45. ISR(TIMER0_OVF_vect)
    46. {
    47.     // keep a track of number of overflows
    48.     //tot_overflow++;
    49.     TCCR0B = 0; //Stops Timer
    50.     if (index >= 1)
    51.     {
    52.         soft_uart_send(PSTR("Bytes Received: "));
    53.         itoa(index, intToStr, 10);
    54.         soft_uart_send_dynamic((const char *)intToStr);
    55.         soft_uart_send(PSTR("\r\n"));
    56.        
    57.         for (int i=1;i<=index;i++)
    58.         {
    59.             itoa(timeinms[i], intToStr, 10);
    60.             soft_uart_send_dynamic((const char *)intToStr);
    61.             soft_uart_send(PSTR(" "));  
    62.         }
    63.         soft_uart_send(PSTR("\r\n"));
    64.        
    65.         index = 0;
    66.         memcpy(timeinms, 0, sizeof(timeinms));  
    67.     }
    68. }
    69.  
    70. int main(void)
    71. {
    72.     // connect led to pin PC0
    73.     //DDRB |= (1 << PB4);
    74.     memcpy(timeinms, 0, sizeof(timeinms));  
    75.     //Start UART
    76.     soft_uart_init();
    77.     // initialize timer
    78.     timer0_init();
    79.    
    80.     IR_DIR &= ~_BV(IR_pin); // set as input
    81.     //IR_PORT |= _BV(IR_pin); // pull-up on
    82.     PC_ISR_REG |= _BV(PC_ISR_BIT); // turn pin-change interrupt on
    83.     PC_PIN_MASK |= _BV(PC_PIN_MASK_BIT); // enable trigger source pin PCINT1 (PB1)
    84.  
    85.  
    86.     soft_uart_send(PSTR("Ready!\r\n"));
    87.     while(1)
    88.     {
    89.         //TODO:: Please write your application code
    90.     }
    91. }
    92.  
     
  7. AgentSmithers

    Thread Starter Active Member

    Jan 14, 2011
    52
    0
    Here is a sample of the data received from a controller.

     
  8. AgentSmithers

    Thread Starter Active Member

    Jan 14, 2011
    52
    0
    Code (Text):
    1.  
    2. void timer0_init()
    3. {
    4.     // set up timer with prescaler = 256
    5.     //TCCR0B |= (1 << CS02);
    6.    
    7.     // set up timer with prescaler = 8
    8.     //TCCR0B |= (1 << CS01);
    9.    
    10.     // set up timer with prescaler = 1
    11.     //TCCR0B |= (1 << CS00);
    12.    
    13.     // set up timer with prescaler = 64
    14.     //TCCR0B |= (1 << CS00) | (1 << CS01);
    15.    
    16.     // initialize counter
    17.     TCNT0 = 0;
    18.    
    19.     // enable overflow interrupt
    20.     TIMSK |= (1 << TOIE0);
    21.    
    22.     // enable global interrupts
    23.     sei();
    24.    
    25.     // initialize overflow counter variable
    26.     //tot_overflow = 0;
    27. }
    28.  
    29. int mybytesrecv = 0;
    30. uint8_t timeinms[246];
    31. int index = 0;
    32. char intToStr[4];
    33. ISR(PCINT0_vect)
    34. {
    35.     //TCCR0B |= (1 << CS02); //Starts Timer
    36.     if (TCCR0B == 0)
    37.     {
    38.         TCCR0B |= (1 << CS00) | (1 << CS01);  
    39.     }
    40.     else
    41.     {
    42.         timeinms[index] = TCNT0; //Micro Second every 13 ticks
    43.         index++;
    44.         TCNT0=0; //reset the clock
    45.     }
    46. }
    47.  
    48. // TIMER0 overflow interrupt service routine
    49. // called whenever TCNT0 overflows
    50. ISR(TIMER0_OVF_vect)
    51. {
    52.     // keep a track of number of overflows
    53.     //tot_overflow++;
    54.     TCCR0B = 0; //Stops Timer
    55.     if (index >= 1)
    56.     {
    57.         soft_uart_send(PSTR("Bytes Received: "));
    58.         itoa(index, intToStr, 10);
    59.         soft_uart_send_dynamic((const char *)intToStr);
    60.         soft_uart_send(PSTR("\r\n"));
    61.        
    62.         for (int i=1;i<=index;i++)
    63.         {
    64.             itoa(timeinms[i], intToStr, 10);
    65.             soft_uart_send_dynamic((const char *)intToStr);
    66.             soft_uart_send(PSTR(" "));  
    67.         }
    68.         soft_uart_send(PSTR("\r\n"));
    69.        
    70.         index = 0;
    71.         memcpy(timeinms, 0, sizeof(timeinms));  
    72.     }
    73. }
    74.  
    75. int main(void)
    76. {
    77.     // connect led to pin PC0
    78.     //DDRB |= (1 << PB4);
    79.     memcpy(timeinms, 0, sizeof(timeinms));  
    80.     //Start UART
    81.     soft_uart_init();
    82.     // initialize timer
    83.     timer0_init();
    84.    
    85.     IR_DIR &= ~_BV(IR_pin); // set as input
    86.     //IR_PORT |= _BV(IR_pin); // pull-up on
    87.     PC_ISR_REG |= _BV(PC_ISR_BIT); // turn pin-change interrupt on
    88.     PC_PIN_MASK |= _BV(PC_PIN_MASK_BIT); // enable trigger source pin PCINT1 (PB1)
    89.  
    90.  
    91.     soft_uart_send(PSTR("Ready!\r\n"));
    92.     while(1)
    93.     {
    94.         //TODO:: Please write your application code
    95.     }
    96. }
    Everyone, I made a minor change to my ISR and now it appears to be spitting out a cont stream from the same button.
    Any thoughts on any way I need to improve this before I can start to create my reply code?

    Thank you!

     
  9. Art

    Distinguished Member

    Sep 10, 2007
    785
    61
    The result above looks ok, and that the remote is sending pulse coded binary (only two timing values),
    and perhaps the longer value is the space between repeat codes from holding down the button.
    The real timing doesn’t look like it would deviate much from those values.
    Some receivers are more picky than others with regard to getting those timings precise.

    I’ve encountered some where the duration of the pause was the bit value, and others where the duration of the pulse was the bit value.
     
Loading...