Hallo,
ich habe mir an den Stecker X5 einen SFH5110 IR-Empfänger angeschlossen und mit einer RC5-Fernbedienung etwas herumgespielt.
Was dabei herausgekommen ist, ist folgendes Programm, mit dem man die Nibobee fernsteuern kann.
Viel Spass beim Ausprobieren.Code:/********************************************* *** RC5 Dekoder *** Version 1 *** *** Nibobee wird mit IR-Fernbedienung ferngesteuert. *** *** PD0=RxD verbunden mit Ausgang IR-Empfänger SFH5110 *** *** 36kHz (27,7 usek) werden mit Timer2 erzeugt. *** Der Eingang PD0 wird alle 8 * 27,7 = 222 usek *** abgefragt. *** *** LED0 (linke gelbe) = Betrieb *** LED1 (linke rote) = blinkt bei RC5 Empfang *** *** Author : H. Krause 2010 **********************************************/ #include <nibobee/iodefs.h> #include <nibobee/delay.h> #include <nibobee/led.h> #include <nibobee/usart.h> #include <nibobee/sens.h> #include <nibobee/motpwm.h> #include <stdlib.h> volatile uint8_t count36kHz; //IR-Fernbedienung PhilipsII //diese Werte können an die Fernbedienung //angepasst werden #define IRPIVor 0x1020 //Vorwärts #define IRPIRueck 0x1021 //Rückwärts #define IRPIPlus 0x1010 //schneller #define IRPIMinus 0x1011 //langsamer #define IRPIStop 0x1036 //stop #define IRPIKr 0x1034 //Kurve rechts #define IRPIKl 0x1032 //Kurve links #define IRPIPlay 0x1035 //frei /********************************************* *** Unterprogramme *********************************************/ void SerPrint (char *data) { unsigned char i = 0; while (data[i] != 0x00) { usart_putchar(data[i++]); delay(3); } } /***** RC5 ******** RC5 ********* RC5 ******************/ // ----------------------------------------------------------------------------- // Timing // ----------------------------------------------------------------------------- #define IR_SAMPLES_PER_BIT 8 /*!< 8 Samples per Bit */ #define IR_SAMPLES_PER_BIT_EARLY 7 /*!< Flanke fruehestens nach 7 Samples */ #define IR_SAMPLES_PER_BIT_LATE 10 /*!< Flanke spaetestens nach 9 Samples */ #define IR_SAMPLES_PER_BIT_MIN 2 /*!< Flanke vor 3 Samples -> paket verwerfen */ #define IR_PAUSE_SAMPLES 250 /*!< Startbit ist erst nach 200 Samples ohne */ // Pegelaenderung gueltig -- eigentlich muesste // man rund 500 Samples abwarten (50 x // Bitzeit), doch weil der Samplezaehler ein // Byte ist, beschraenken wir uns hier auf ein // Minimum von 250 Samples #define IR_PORT PORTD /*!< Port D */ #define IR_DDR DDRD /*!< DDR of Port D */ #define IR_PINR PIND /*!< Port D input */ #define IR_PIN PD0 /*!< Pin 0 */ #define RC5_COMMAND 0x103F /*!< Der Kommandobereich */ #define RC5_MASK (RC5_COMMAND) static uint8_t RC5lastsample = 0; /*!< zuletzt gelesenes Sample */ static uint8_t RC5bittimer = 0; /*!< zaehlt die Aufrufe von ir_isr() */ static uint16_t RC5data_tmp = 0; /*!< RC5-Bitstream */ static uint8_t RC5bitcount = 0; /*!< anzahl gelesener bits */ volatile uint16_t RC5data = 0; /*!< letztes komplett gelesenes RC5-paket */ volatile uint8_t enableRC5 = 0; /*!< schaltet die RC5 Abfrage ein/aus */ /********************************** * Interrupt Serviceroutine * wird alle 27.7us aufgerufen **********************************/ void IsrRC5 (void) { // sample lesen uint8_t sample = 1; //PORTB ^= (1<<PB1); //PB1=LED1 toggeln (Test) if (enableRC5 && !(count36kHz % 8)) { if ((IR_PINR & (1<<IR_PIN)) != 0) { sample = 0; } // bittimer erhoehen (bleibt bei 255 stehen) if (RC5bittimer<255) { RC5bittimer++; } // flankenerkennung if ( RC5lastsample != sample) { if (RC5bittimer <= IR_SAMPLES_PER_BIT_MIN) { // flanke kommt zu frueh: paket verwerfen RC5bitcount=0; } else { // Startbit if (RC5bitcount==0) { if ( (sample==1) && (RC5bittimer > IR_PAUSE_SAMPLES) ) { // Startbit speichern RC5data_tmp = 1; RC5bitcount++; led_set(1,1); //LED1 an } else { // error RC5data_tmp = 0; } // bittimer-reset RC5bittimer = 0; // Bits 2..14: nur Flanken innerhalb des Bits beruecksichtigen } else { if (RC5bittimer >= IR_SAMPLES_PER_BIT_EARLY) { if (RC5bittimer <= IR_SAMPLES_PER_BIT_LATE) { // Bit speichern RC5data_tmp = (RC5data_tmp<<1) | sample; RC5bitcount++; } else { // zu spaet: paket verwerfen RC5bitcount = 0; } // bittimer-reset RC5bittimer = 0; } } } } else { // keine flanke innerhalb bitzeit? if (RC5bittimer > IR_SAMPLES_PER_BIT_LATE) { // 14 bits gelesen? if (RC5bitcount==14) { RC5data = RC5data_tmp; } // paket verwerfen RC5bitcount = 0; led_set(1,0); //LED1 aus } } // sample im samplepuffer ablegen RC5lastsample = sample; } } /********************************************************* * IR-Daten lesen * @return wert von ir_data, loescht anschliessend ir_data *********************************************************/ uint16_t ReadRC5 (void) { uint16_t retvalue = RC5data; RC5data = 0; return retvalue; } /***************************************** * Init IR-System *****************************************/ void InitRC5 (void) { IR_DDR &= ~IR_PIN; // Pin auf Input IR_PORT |= IR_PIN; // Pullup an enableRC5 = 1; } /************************ RC5 Ende **************************/ /********************************************* *** Interrupt Service Routinen *********************************************/ ISR (TIMER2_COMP_vect) { //wird nicht benutzt } // Frequenzkorrektur für 36kHz (512-416 plus 3 Takte fürs Laden von TCNT2?) ISR (TIMER2_OVF_vect) { TCNT2 = 99; count36kHz ++; IsrRC5(); //RC5 Decoder aufrufen } /********************************************* *** Hauptprogramm *********************************************/ int main(void) { static unsigned int cmd; int16_t speed_l = 0; int16_t speed_r = 0; //Test //char text[7]; motpwm_init(); led_init(); sens_init(); InitRC5(); //usart_enable(); //UCSRB = _BV(RXCIE) + _BV(UDRIE) + _BV(RXEN) + _BV(TXEN); UCSRB = _BV(TXEN); //Nur Sender TxD aktivieren usart_setbaudrate(2400); // Setup Timer2 TCCR2 = (1 << WGM20)|(1 << CS20); // PhaseCorrect-PWM, no prescaling, no OC2-Pin! TCNT2 = 96; // (512-416) 36kHz @15MHz //OCR2 = 151; // (255-(208/2)) 151 ist 50:50 Compare Match für symetrische Halbwellen //TIMSK |= (1 << OCIE2)|(1 << TOIE2); // Comp und OVF-ISR enable, Overflow bei Bottom! TIMSK |= (1 << TOIE2); // OVF-ISR enable, Overflow bei Bottom! enable_interrupts(); //Test //delay(200); // wait4programmer //SerPrint("\n\r\n*** Nibobee mit RC5 ***"); led_set(0,1); delay(2000); // wait4programmer //Test //SerPrint("\n\r*** Fuehler links schalten --> Start ***"); //mit Schalten von Fühler links das Programm starten while(sens_getLeft() == 0) { delay(100); PORTB ^= (1<<PB0); } // hektisches Blinken mit LED0 led_set(0,1); //LED0 einschalten //Test //SerPrint("\n\r*** --> Start ***"); while(1) { cmd = ReadRC5(); if (cmd) { cmd &= RC5_MASK; //Test //led_set(2,1); //itoa(cmd, text, 16); //SerPrint(text); switch (cmd) { case IRPIVor: //Test //SerPrint("vor\r\n"); speed_l = speed_r = 200; break; case IRPIRueck: //Test //SerPrint("zurueck\r\n"); speed_l = speed_r = -200; break; case IRPIPlus: //Test //SerPrint("schneller\r\n"); if (speed_r > 0) { speed_l += 50; speed_r += 50; if (speed_r > 1023) speed_l = speed_r = 1023; } else { speed_l -= 50; speed_r -= 50; if (speed_r < -1023) speed_l = speed_r = -1023; } break; case IRPIMinus: //Test //SerPrint("langsamer\r\n"); if (speed_r > 0) { speed_l -= 50; speed_r -= 50; if (speed_r < 0) speed_l = speed_r = 0; } else { speed_l += 50; speed_r += 50; if (speed_r > 0) speed_l = speed_r = 0; } break; case IRPIStop: //Test //SerPrint("stop\r\n"); speed_l = speed_r = 0; break; case IRPIKr: //Test //SerPrint("Kurve rechts\r\n"); if (speed_r > 0) { speed_l += 50; speed_r -= 50; if (speed_r < 0) speed_l = speed_r = 0; } else { speed_l -= 50; speed_r += 50; if (speed_r > 0) speed_l = speed_r = 0; } break; case IRPIKl: //Test //SerPrint("Kurve links\r\n"); if (speed_r > 0) { speed_l -= 50; speed_r += 50; if (speed_r < 0) speed_l = speed_r = 0; } else { speed_l += 50; speed_r -= 50; if (speed_r > 0) speed_l = speed_r = 0; } break; case IRPIPlay: //Test //SerPrint("play taste\r\n"); break; }//end switch motpwm_setLeft(speed_l); motpwm_setRight(speed_r); }//end if (cmd) delay(100); } return(0); }
Skroete







Zitieren

Lesezeichen