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.
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);
}
Viel Spass beim Ausprobieren.
Skroete
Lesezeichen