Nochmals hallo,
bei der Bee werden den PINS 26 bis 29 (also PC4 - PC7) für die Taster verwendet.
Ist es möglich an diesen Pins je 2 IR-Sender und Empfänger anzuschliessen? Das wäre gut, denn dann könnte ich auf die "Fühler" verzichten.
Hallo,
ich will euch noch meine neueste Anwendung zeigen.
Die Bee bleibt innerhalb der schwarzen Linie und weicht Hindernissen aus:
http://www.youtube.com/watch?v=zkHDD5SZ50U
Nochmals hallo,
bei der Bee werden den PINS 26 bis 29 (also PC4 - PC7) für die Taster verwendet.
Ist es möglich an diesen Pins je 2 IR-Sender und Empfänger anzuschliessen? Das wäre gut, denn dann könnte ich auf die "Fühler" verzichten.
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Super, dann werde ich die Taster ablöten, und dann 2x2 Infrarot-DIODEN vom Typ SFH415-U und 2 Stk. IR-TRANSISTOR vom Typ SFH5110 an den PINs anschliessen.
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
Hallo
TCNT2 += 99;
Tolle und prompte Umsetzung und vorbildliche Dokumentation. Ob meine aktuelle Fernbedienung RC5 kann werde ich damit mal testen.
Gruß
mic
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Hallo,
mir ist es lieber, wenn die Bee auf dem 3. Punkt rollt anstatt rutscht und habe mir kurzerhand aus einer ausgedienten Andrückrolle eines Kassettenrekorders eine drehbare Rolle gebastelt.
Hallo
Ich habe meine alte RC 5-Dekodierung vom asuro ausgegraben. Sie liest nach dem Erkennen eines Signals stur die 14 RC5-Bits ein:
Das funktioniert dann so:Code:// nibobee mit RC5 steuern 17.1.01 mic // RC5-Funktion aus: https://www.roboternetz.de/phpBB2/ze...=287750#287750 #define ddr_acs_led_l DDRA // Anoden der IR-LEDs links #define port_acs_led_l PORTA #define pin_acs_led_l (1<<PA2) #define ddr_acs_led_r DDRA // rechts #define port_acs_led_r PORTA #define pin_acs_led_r (1<<PA3) #define ddr_acs_36kHz DDRC // Kathoden der IR-LEDS mit 36kHz getaktet #define port_acs_36kHz PORTC #define pin_acs_36kHz (1<<PC2) #define ddr_acs_tsop DDRC // Eingang IR-Empfänger #define port_acs_tsop PINC // Achtung, das ist ein Eingang! #define pin_acs_tsop (1<<PC3) #include <nibobee/iodefs.h> #include <nibobee/led.h> volatile uint8_t count36kHz; volatile uint8_t acs=0; void Sleep(uint8_t pause); void Msleep(uint16_t pause); void ACSData(uint16_t *data); void ACS_init(void); int main(void) { //uint16_t data[2]; // Speicher für ACS-Werte led_init(); ACS_init(); led_set(0,1); Msleep(2000); // wait4programmer led_set(0,0); //port_acs_led_l |= pin_acs_led_l; //while(1); unsigned int count, temp; // Zaehler, IR-Kommando unsigned char daten[14], ir_status; // IR-Datenspeicher, IR-Eingangspegel while(1) { temp=0; while (port_acs_tsop & pin_acs_tsop); //warten auf die Flanke des Startbits led_set(2,1); // Alarmstufe ROT: ein Zeichen ist im Anflug led_set(0,0); for (count=0; count<14; count++) { // im Gesamten warten wir auf 14 RC5-Bits // Die RC5-Bitlaenge beträgt 1,778 ms. Bei 36 Takten pro Millisekunde ergibt das 36*1,778 = 64 Sleep(48); // Information einlesen nach 3/4 der Bitlaenge ir_status=(port_acs_tsop & pin_acs_tsop); // Pegel Speichern if (ir_status) daten[count]='1'; else daten[count]='0'; // und merken if (ir_status) temp |= (1 << (13-count)); // das MSB(=mostsuefikantbit) zuerst while (ir_status == (port_acs_tsop & pin_acs_tsop)); // Bit gelesen, warten auf naechste Flanke } temp=temp/2 & 0xf; // Die Info steht in den Bits 1-4 led_set(2,0); // Daten gelesen /* #define pow1 150 // Langsame Geschwindigkeit #define pow2 200 // Schnelle Geschwindigkeit switch (temp) { case 1: MotorDir(FWD,FWD); MotorSpeed(pow1,pow2); break; case 2: MotorDir(FWD,FWD); MotorSpeed(pow2,pow2); break; case 3: MotorDir(FWD,FWD); MotorSpeed(pow2,pow1); break; case 4: MotorDir(BREAK,FWD); MotorSpeed(0,pow1); break; case 5: MotorDir(BREAK,BREAK); MotorSpeed(0,0); break; case 6: MotorDir(FWD,BREAK); MotorSpeed(pow1,0); break; case 7: MotorDir(RWD,BREAK); MotorSpeed(pow1,0); break; case 8: MotorDir(RWD,RWD); MotorSpeed(pow1,pow1); break; case 9: MotorDir(BREAK,RWD); MotorSpeed(0,pow1); break; default: MotorDir(BREAK,BREAK); MotorSpeed(0,0); break; } */ while(temp--) // temp mal blinken { Msleep(500); led_set(3,1); Msleep(200); led_set(3,0); } led_set(0,1); } return(0); } ISR (TIMER2_COMP_vect) { port_acs_36kHz ^= pin_acs_36kHz; // IR-LEDs togglen } // Frequenzkorrektur für 36kHz (512-416 plus 3 Takte fürs Laden von TCNT2?) ISR (TIMER2_OVF_vect) { TCNT2 += 99; // += bewirkt, dass schon erfolgte Zähltakte nicht ignoriert werden! port_acs_36kHz &= ~pin_acs_36kHz; // bei Nulldurchgang soll die IR-LED aus sein! //port_acs_36kHz |= pin_acs_36kHz; // seltamerweise funktioniert das auch? if(count36kHz) count36kHz--; if(acs) acs--; } void Sleep(uint8_t pause) // 1/36000 Pause blockierend { count36kHz=pause; while(count36kHz); } void Msleep(uint16_t pause) // 1/1000 Pause blockierend { while(pause--) Sleep(36); } void ACSData(uint16_t *data) { OCR2=253; port_acs_led_l |= pin_acs_led_l; // ACS LED left on while((port_acs_tsop & pin_acs_tsop) && (OCR2 > 151)) { acs=8; // Impulse senden, acs wird in OVF-ISR runtergezählt while(acs); OCR2--; } port_acs_led_l &= ~pin_acs_led_l; // ACS LED left off data[0]=OCR2; while(!(port_acs_tsop & pin_acs_tsop)); // warten bis keine Echo mehr OCR2=253; port_acs_led_r |= pin_acs_led_r; // ACS LED right on while((port_acs_tsop & pin_acs_tsop) && (OCR2 > 151)) { acs=8; while(acs); OCR2--; } port_acs_led_r &= ~pin_acs_led_r; // ACS LED right off data[1]=OCR2; while(!(port_acs_tsop & pin_acs_tsop)); } void ACS_init(void) { // 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 Bottum! enable_interrupts(); ddr_acs_led_l |= pin_acs_led_l; // die Anoden der IR-LEDs port_acs_led_l &= ~pin_acs_led_l; ddr_acs_led_r |= pin_acs_led_r; port_acs_led_r &= ~pin_acs_led_r; ddr_acs_36kHz |= pin_acs_36kHz; // die Kathoden der IR-LEDs }
Bild hier
http://www.youtube.com/watch?v=TvZ_JJk_yJE
Ich werde wohl auf AAs umrüsten, dann habe ich weniger Druck auf dem TT-Ball.
Gruß
mic
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Hallo Pinsel!Zitat von pinsel120866
Dein "Bienchen" sieht wirklich Spitze aus!!! Da ich das genau so schön haben möchte, würde ich das gern nachbauen. Allerdings habe ich noch keinerlei Erfahrungen mit Servos - das soll sich jetzt ändern! Der von Dir verwendete Servo scheint ja sehr klein zu sein und sehr gut an die Stirnseite des NIBObee zu passen. Was ist das für ein Servo, wo hast Du den her? Hast noch ein paar Tips für den Aufbau? Könntest Du den Quellcode des im Video verwendete Programms hier veröffentlichen?
Danke!
Hallo Tuxi-Halle,
freut mich, dass dir meine Erweiterung so gut gefällt. Der Aufbau ist auch einfach, weil du fertige Bauteile verwenden kannst:
1. Servo: http://www.conrad.de/goto.php?artikel=230500 auf X3 stecken (ACHTUNG vorher Plus-Minus vertauschen bzw. auf Polung achten)
2.US-Modul SRF05: http://www.shop.robotikhardware.de/s...roducts_id=133 kommt auf X2 (Leitung vorher richtig anlöten, Bedienungsanleitung genau durchlesen)
3. Halterung: Hier muss du etwas basteln.
4. Testprogramm ist angehängt.
Lesezeichen