Measuring IR for replay.

Thread Starter

AgentSmithers

Joined Jan 14, 2011
77
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:
void timer0_init()
{  
    // initialize counter
    TCNT0 = 0;
  
    // enable overflow interrupt
    TIMSK |= (1 << TOIE0);
  
    // enable global interrupts
    sei();
  
    // initialize overflow counter variable
    tot_overflow = 0;
}

int mybytesrecv = 0;
int timeinms[256];
int index = 0;
ISR(PCINT0_vect)
{
    timeinms[index] = TCNT0;
    index++;
    TCNT0=0; //reset the clock
    TCCR0B |= (1 << CS00) | (1 << CS01); //Starts Timer
    if (index>=255) //prevent overflow
    {
        TCNT0=0; //reset the clock
        TCCR0B = 0; //stop Timer
        index = 0;
    }
}

// TIMER0 overflow interrupt service routine
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect)
{
    // keep a track of number of overflows
    //tot_overflow++;
    TCCR0B = 0; //Stops Timer
    if (index >= 1)
    {
        for (int i=0;i<=index;i++)
        {
            soft_uart_send(PSTR("."));
        }
        soft_uart_send(PSTR("\r\n"));
        index = 0;
    }
}
 
Last edited:

AlbertHall

Joined Jun 4, 2014
12,625
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 1.04 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.
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.
 

Thread Starter

AgentSmithers

Joined Jan 14, 2011
77
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.
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:

dannyf

Joined Sep 13, 2015
2,197
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.
 

Thread Starter

AgentSmithers

Joined Jan 14, 2011
77
I refined the code, how is this for the ISR?
Thanks for everyone guidance.
Code:
// initialize timer, interrupt and variable
void timer0_init()
{
    // set up timer with prescaler = 256
    //TCCR0B |= (1 << CS02);
   
    // set up timer with prescaler = 8
    //TCCR0B |= (1 << CS01);
   
    // set up timer with prescaler = 1
    //TCCR0B |= (1 << CS00);
   
    // set up timer with prescaler = 64
    //TCCR0B |= (1 << CS00) | (1 << CS01);
   
    // initialize counter
    TCNT0 = 0;
   
    // enable overflow interrupt
    TIMSK |= (1 << TOIE0);
   
    // enable global interrupts
    sei();
   
    // initialize overflow counter variable
    //tot_overflow = 0;
}

int mybytesrecv = 0;
uint8_t timeinms[246];
int index = 0;
char intToStr[4];
ISR(PCINT0_vect)
{
    //TCCR0B |= (1 << CS02); //Starts Timer
    TCCR0B |= (1 << CS00) | (1 << CS01);
    timeinms[index] = TCNT0; //Micro Second every 13 ticks
    index++;
    TCNT0=0; //reset the clock
}

// TIMER0 overflow interrupt service routine
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect)
{
    // keep a track of number of overflows
    //tot_overflow++;
    TCCR0B = 0; //Stops Timer
    if (index >= 1)
    {
        soft_uart_send(PSTR("Bytes Received: "));
        itoa(index, intToStr, 10);
        soft_uart_send_dynamic((const char *)intToStr);
        soft_uart_send(PSTR("\r\n"));
       
        for (int i=1;i<=index;i++)
        {
            itoa(timeinms[i], intToStr, 10);
            soft_uart_send_dynamic((const char *)intToStr);
            soft_uart_send(PSTR(" "));   
        }
        soft_uart_send(PSTR("\r\n"));
       
        index = 0;
        memcpy(timeinms, 0, sizeof(timeinms));   
    }
}

int main(void)
{
    // connect led to pin PC0
    //DDRB |= (1 << PB4);
    memcpy(timeinms, 0, sizeof(timeinms));   
    //Start UART
    soft_uart_init();
    // initialize timer
    timer0_init();
   
    IR_DIR &= ~_BV(IR_pin); // set as input
    //IR_PORT |= _BV(IR_pin); // pull-up on
    PC_ISR_REG |= _BV(PC_ISR_BIT); // turn pin-change interrupt on
    PC_PIN_MASK |= _BV(PC_PIN_MASK_BIT); // enable trigger source pin PCINT1 (PB1)


    soft_uart_send(PSTR("Ready!\r\n"));
    while(1)
    {
        //TODO:: Please write your application code 
    }
}
 

Thread Starter

AgentSmithers

Joined Jan 14, 2011
77
Here is a sample of the data received from a controller.

Bytes Received: 1

0

Bytes Received: 108

24 62 75 59 75 60 71 62 75 59 74 60 75 59 75 59 72 62 75 59 72 63 72 63 78 250 72 62 76 59 75 60 75 59 75 59 75 59 72 63 75 59 72 63 72 63 71 62 75 60 75 59 74 61 75 59 72 63 72 62 71 63 78 252 72 59 75 59 75 59 75 59 78 253 72 60 75 59 75 59 75 59 75 59 79 252 72 59 75 59 75 60 78 250 78 250 78 252 76 250 78 253 69 63 78 250 72 145

Bytes Received: 1

0

Bytes Received: 108

25 63 71 62 74 60 72 63 71 62 72 63 72 62 71 63 72 63 71 62 72 63 75 59 78 250 71 62 75 60 71 62 72 63 71 62 71 63 72 63 71 63 72 63 71 63 72 63 71 63 72 63 71 63 72 63 71 62 72 63 71 62 78 253 68 63 72 63 72 63 71 63 78 252 68 63 72 63 71 63 72 62 71 63 78 249 72 63 71 63 72 63 78 250 78 250 78 250 78 250 78 253 69 63 78 250 74 145
 

Thread Starter

AgentSmithers

Joined Jan 14, 2011
77
Code:
void timer0_init()
{
    // set up timer with prescaler = 256
    //TCCR0B |= (1 << CS02);
   
    // set up timer with prescaler = 8
    //TCCR0B |= (1 << CS01);
   
    // set up timer with prescaler = 1
    //TCCR0B |= (1 << CS00);
   
    // set up timer with prescaler = 64
    //TCCR0B |= (1 << CS00) | (1 << CS01);
   
    // initialize counter
    TCNT0 = 0;
   
    // enable overflow interrupt
    TIMSK |= (1 << TOIE0);
   
    // enable global interrupts
    sei();
   
    // initialize overflow counter variable
    //tot_overflow = 0;
}

int mybytesrecv = 0;
uint8_t timeinms[246];
int index = 0;
char intToStr[4];
ISR(PCINT0_vect)
{
    //TCCR0B |= (1 << CS02); //Starts Timer
    if (TCCR0B == 0)
    {
        TCCR0B |= (1 << CS00) | (1 << CS01);   
    }
    else
    {
        timeinms[index] = TCNT0; //Micro Second every 13 ticks
        index++;
        TCNT0=0; //reset the clock
    }
}

// TIMER0 overflow interrupt service routine
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect)
{
    // keep a track of number of overflows
    //tot_overflow++;
    TCCR0B = 0; //Stops Timer
    if (index >= 1)
    {
        soft_uart_send(PSTR("Bytes Received: "));
        itoa(index, intToStr, 10);
        soft_uart_send_dynamic((const char *)intToStr);
        soft_uart_send(PSTR("\r\n"));
       
        for (int i=1;i<=index;i++)
        {
            itoa(timeinms[i], intToStr, 10);
            soft_uart_send_dynamic((const char *)intToStr);
            soft_uart_send(PSTR(" "));   
        }
        soft_uart_send(PSTR("\r\n"));
       
        index = 0;
        memcpy(timeinms, 0, sizeof(timeinms));   
    }
}

int main(void)
{
    // connect led to pin PC0
    //DDRB |= (1 << PB4);
    memcpy(timeinms, 0, sizeof(timeinms));   
    //Start UART
    soft_uart_init();
    // initialize timer
    timer0_init();
   
    IR_DIR &= ~_BV(IR_pin); // set as input
    //IR_PORT |= _BV(IR_pin); // pull-up on
    PC_ISR_REG |= _BV(PC_ISR_BIT); // turn pin-change interrupt on
    PC_PIN_MASK |= _BV(PC_PIN_MASK_BIT); // enable trigger source pin PCINT1 (PB1)


    soft_uart_send(PSTR("Ready!\r\n"));
    while(1)
    {
        //TODO:: Please write your application code 
    }
}
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!

Bytes Received: 145

63 78 253 69 63 78 250 72 63 78 250 72 63 78 253 69 63 71 62 72 63 72 63 71 62 72 63 78 250 72 63 72 62 71 63 72 63 71 63 72 63 72 62 71 63 72 63 71 63 72 63 72 63 71 62 72 63 71 62 78 250 71 63 72 63 71 63 72 63 72 62 71 63 72 63 71 62 71 63 72 63 71 62 72 63 71 63 72 63 71 62 71 63 75 60 71 63 72 63 78 250 77 250 71 63 72 63 72 63 78 250 72 63 71 63 71 63 72 62 71 63 78 250 71 63 72 63 78 250 72 62 71 63 72 63 78 250 78 250 78 250 71 63 72 0

Bytes Received: 145

59 79 249 76 59 79 249 75 59 78 252 73 59 78 249 76 59 75 58 76 59 79 249 76 59 75 58 78 250 75 59 76 59 76 58 75 59 76 59 75 58 76 59 76 58 75 59 76 59 76 58 76 59 75 58 75 59 76 59 78 250 79 249 76 59 75 59 76 59 75 58 75 59 75 58 75 59 76 59 75 59 76 59 75 59 75 59 76 59 75 59 76 59 75 59 76 59 75 59 78 250 75 253 75 59 75 59 75 59 74 252 76 59 75 59 76 58 75 59 75 58 78 250 75 59 75 59 78 250 75 59 75 59 78 250 78 250 75 253 79 249 78 249 75 0

Bytes Received: 145

63 78 253 72 60 78 253 72 60 78 250 76 59 78 249 75 59 75 59 71 62 79 250 75 59 76 59 78 250 75 59 75 59 72 62 71 62 75 59 72 63 75 59 75 59 75 59 75 60 72 62 75 59 74 61 75 59 78 253 72 60 75 59 75 60 72 63 75 59 75 59 75 59 71 62 76 59 75 59 75 59 71 62 75 59 72 62 75 59 72 63 72 62 73 60 75 60 72 62 79 250 78 249 76 59 72 63 73 61 78 250 75 60 75 59 73 62 75 59 71 62 79 252 72 59 75 59 78 250 72 62 79 249 75 59 75 59 75 59 72 62 74 59 75 0

Bytes Received: 145

63 79 250 75 60 78 249 72 62 79 250 75 60 78 253 73 59 72 63 78 252 72 59 75 59 72 63 75 254 75 59 74 60 72 63 72 63 72 63 75 59 75 59 76 59 72 63 72 63 72 62 75 59 72 62 72 63 78 252 71 59 78 250 73 62 75 59 75 59 75 59 75 60 75 59 71 62 76 59 75 59 75 60 75 60 75 59 75 59 75 59 75 59 71 62 75 59 72 63 78 254 75 251 75 59 72 63 75 60 78 249 71 62 75 59 75 59 72 63 75 60 78 250 75 59 75 59 78 253 72 59 78 250 79 250 72 63 75 60 75 59 78 250 75 0
[/code]
 

Art

Joined Sep 10, 2007
806
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.
 
Top