AVR-GCC. IR decoder.

Πρόσφατα σκέφτηκα να κατασκευάσω ένα απλό κύκλωμα για να ελέγχω με τηλεχειρισμό (παλιό χειριστήριο υπέρυθρων τηλεόρασης) μία συσκευή. Στην διαδικασία εγγραφής του κώδικα που θα καταλάβαινε την “γλώσσα” του χειριστηρίου έπεσα και στο παρακάτω καταπληκτικό project.

IRMP

Τεκμηρίωση του ATmega8.
Τεκμηρίωση του TSOP17xx.
Consumer IR.
Philips RC-5.
Κωδικοποίηση Manchester.

Το τηλεχειριστήριο που είχα στην διάθεση μου ήταν ένα Philips που έκανε χρήση του πρωτοκόλλου (της ίδιας εταιρίας) RC-5. Ο κώδικας όπως είπαμε στηρίζετε στο IRMP. Τρία τα βασικά αρχεία του κώδικα. Το irmp.c, irmp.h και irmpconfig.h. Το αρχείο που πειράζουμε είναι το irmpconfig.h που μπορούμε να ορίσουμε τα πρωτόκολλα που θέλουμε να έχουμε υποστήριξη (30 στον αριθμό), το pin που θα συνδέεται με τον αισθητήρα υπέρυθρων (TSOP17xx) κ.τ.λ. Τα αρχεία είναι πολύ καλά τεκμηριωμένα (στα Αγγλικά). Το πρόγραμμα δοκιμής που βλέπουμε παρακάτω αποκωδικοποιεί τα δεδομένα που λαμβάνει ο ATmega8 από το TSOP17xx και τα μεταφέρει μέσω της σειριακής θύρας στον υπολογιστή.

Τα αρχεία του κώδικα.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include "uart.h"
#include "irmpconfig.h"
#include "irmp.h"


/*Η παρακάτω δήλωση ελέγχει αν στον compiler έχουμε βάλει την παράμετρο F_CPU.
  Αν όχι, την περνά. */

#ifndef F_CPU
    #warning "H F_CPU den exei oristei 8a parei thn timh 8000000"
    #define F_CPU 8000000UL  //  Use unsigned long
#endif

#define BAUD 9600UL //Ρυθμός Baud

// Υπολογισμοί.
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // ”Έξυπνη” στρογγυλοποίηση
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))   // Πραγματικός Ρυθμός Baud
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)    // Σφάλμα ανά 1000 μέρη.

#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
    #error To sfalma ston ry8mo Baud einai megalytero toy 1%, mataiosh!
#endif

#define US (1000000 / F_INTERRUPTS)


void timer1_init (void);


//adjust UARTsendChar() function for stream
static int UARTsendstream(char c, FILE *stream);
//----set output stream to UART----
static FILE uart_str = FDEV_SETUP_STREAM(UARTsendstream, NULL, _FDEV_SETUP_WRITE);

static int UARTsendstream(char c , FILE *stream){
    uart_putc(c);
    return 0;
}


int main(void){

    IRMP_DATA irmp_data;

    // Αρχικοποίηση του UART.
    uart_init(UART_BAUD_SELECT(BAUD,F_CPU));
    stdout = &uart_str;


    // Αρχικοποίηση IRMP.
    irmp_init();

    // Αρχικοποίηση Timer/Counter1.
    timer1_init();

    DDRB |= (1<<PB0);   //PB0 ως έξοδος.

    sei(); // Ενεργοποίηση των interrupt.

    while(1){

        PORTB &= ~(1<<PB0);

        if (irmp_get_data (&irmp_data)){

          _delay_ms(25);

          PORTB |= (1<<PB0);

         printf_P(PSTR("Protocol:%2d | Address: %5u | Command: %3u | Flags: %d\n") \
                      ,irmp_data.protocol, irmp_data.address, irmp_data.command \ 
                      ,irmp_data.flags);

          _delay_ms(25);

        };
    };

    return 0;

}


void timer1_init (void){

    OCR1A = (F_CPU / F_INTERRUPTS) - 1;  // Compare value: 1/15000 of CPU frequency
    TCCR1B = (1<<WGM12)|(1<<CS10);       // Λειτουργία CTC, Prescaler 1

    TIMSK |= (1<<OCIE1A);                // Ενεργοποίηση Interrupt ταύτισης.
}


ISR(TIMER1_COMPA_vect){

  (void) irmp_ISR();

}

Για το τηλεχειριστήριο που ήθελα να χρησιμοποιήσω βλέπουμε πως όταν πιέζω την μείωση ήχου το πρόγραμμα παράγει:

Protocol: 7 | Address: 16 | Command: 17 | Flags: 1

Αν δούμε στην σελίδα της Wikipedia για το RC-5 η εντολή για την μείωση ήχου είναι όντως 17. Η τιμή flags μας δείχνει αν πιέζουμε συνεχώς το πλήκτρο ή όχι στο τηλεχειριστήριο. Ας δούμε λίγο πως φαίνεται το σήμα που στέλνει το τηλεχειριστήριο στο παλμογράφο. Για να καταλάβετε ποιο εύκολα την τιμή των bit ρίξτε μια ματιά στην κωδικοποίηση Manchester στην σελίδα της Wikipedia.

Advertisements
This entry was posted in AVR, Electronics and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

One Response to AVR-GCC. IR decoder.

  1. Siddharth Sharma says:

    Couldn’t Really understand the code but it sounded interesting. Please can you explain the proper logic used in each of the protocols and how did you differentiate between the two different protocols.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s