NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » IR reciever/transmitter

August 23, 2010
by bullfrog_69r
bullfrog_69r's Avatar

I am currently working on a project to recieve and eventually transmit the signal from my tv remote control. So far I have managed to recieve the signal and acertain the rough time between pulses (using a while loop and a simple counter) but i need to be more accurate to re-transmit the signal. At the moment i cant seem to get thhe timer working to get this time. Also i was after some help with setting up the PWM in order to use it to send the base 38kHz signal used by the remote. Any help would be appreciated!

//PIN configuration
//PC0 (PCINT8) -  Buffered Infra Red Receiver (Vout)
//PC3           -  test LED
//PC4           -  test LED
//PC5           -  IR LED

uint8_t dataSize = 36;
volatile uint16_t data[36];
uint8_t started;
uint8_t count;
uint8_t sampled = 0;
uint8_t done = 0;

ISR(PCINT1_vect){
    PORTC |= (1<<PC3);
    //if we have not started, check for start bit on DATA line
    if(!started){
        if (PC0 == 0 ){
            started = 1;
            int i;
            //clear data
            for(i = 0; i< dataSize;i++){
                data[i] = 0;
            }
            return;
        }
    }
    else if(count < 36) {
        //if pin is low is start of pulse, record last timed time
        if(PC0 == 0){
            data[count] = TCNT1;
        }
        //else the pin is high and restart timer
        else if(PC2 == 1){
            TCNT1 = 0x0000;
        }
        count++;
        return;
    }
    else if(count == 36){ //pairty bit 
        //not implemented
        count++;
        PORTC &= ~(1<<PC3);
        done = 1;
        return;
    }
    else{  //stop bit
        //should check to make sure DATA line is high, what to do if not?
        started = 0;
        PORTC &= ~(1<<PC3);
        done = 1;
    }
}

void realtimeclock_setup(){
    // setup Timer1:
    TCCR1A |= (1<<WGM11);
    // clocked from CLK/1024
    // which is 14745600/1024, or 14400 increments per second
    TCCR1B |= (1<<CS10);
}

int main(){
  //initialise everything
    realtimeclock_setup();
    PCICR |= (1<<PCIE1);
    PCMSK1 |= (1<<PCINT8);
    sei();
    lcd_init();
    // LED as output
    DDRC |= (1<<PC5);
    // LED as output
    DDRC |= (1<<PC4);
    // LED as output
    DDRC |= (1<<PC3);
    // set PC0 as input
    DDRC &= ~(1<<PC0);
    // turn on internal pull up resistor for PA0
    PORTC |= (1<<PC0);
    // start up the serial port
    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    //Print searching to LCD
    while(done == 0){
        lcd_clear_and_home();
        lcd_write_string(PSTR("Searching***"));
        lcd_line_two();
        delay_ms(3000);
    }
    //print data to serial port
    int j;
    for(j = 0; j<36; j++){
        printf_P(PSTR("%d,"), data[j]);
    }
    printf_P(PSTR("\r\n\n"));
    PORTC &= ~(1<<PC3);
    PORTC |= (1<<PC4);
    return 0;
}
August 26, 2010
by bretm
bretm's Avatar

In a number of places you have code like

if(PC0 == 0){

and it seems like you're trying to read pin states that way. The values PC0, PC2, etc., are constants. PC0 will always equal 0 and PC2 will always equal 2, at least on the Nerdkits chip. What you need to do to read the state of PC2, for example to tell if it's low, is

if ((PINC & (1<<PC2)) == 0) {

You should declare the "done" variable as volatile since it's modified by the interrupt routine. Otherwise the compiler could optimize your "while(done==0)" loop into a "while(1)" loop and then omit the rest of your main routine since it's no longer reachable.

Post a Reply

Please log in to post a reply.

Did you know that you can build a digital read out (DRO) for a lathe or milling machine? Learn more...