naja
es ist das beispielprogramm i2c_slave von der lib des rp6
und es ist das beispiel prgramm movement2 vom c controller
Movement:
sensorcheck:Code:/******************************************************************************* * RP6 C-Control PRO M128 Erweiterungsmodul * ---------------------------------------------------------------------------- * I2C Bus - Bewegung & Sensorik - Beispielprogramm * ---------------------------------------------------------------------------- * Ein weiteres einfaches Bewegungsprogramm, diesmal reagiert der RP6 * allerdings auf die Bumper. * Zunächst fährt der RP6 vorwärts in einer Kreisbahn. * Kollidiert er mit einem Hindernis, werden die Motoren gestoppt und * die LEDs fangen an zu blinken. * (man könnte natürlich auch anders auf die Kollision reagieren...) ******************************************************************************/ #include "../../RP6CCLib/RP6CCLib.cc" // ########################### #include "RP6MasterLib.cc" // ########################### #include "RP6_Sensorcheck.cc" /** * Dieser Thread wird ausgeführt sobald der Roboter mit einem * Hindernis kollidiert ist. */ void blink(void) { while(true) { setRP6LEDs(LED2 | LED3); setLEDs(LED3 | LED4 | LED5); // LEDs kurz aufblitzen lassen ... Thread_Delay(5); // ... setLEDs(0); // ... Thread_Delay(30); setRP6LEDs(LED5 | LED6); setLEDs(LED3 | LED4 | LED5); Thread_Delay(5); setLEDs(0); Thread_Delay(30); } } void main(void) { RP6_CCPRO_Init(); // Auf Startsignal warten! newline(); println(" ________________________"); println(" \\| RP6 ROBOT SYSTEM |/"); println(" \\_-_-_-_-_-_-_-_-_-_/ "); newline(); println(" RP6 Movement DEMO 2 "); newline(); beep(100, 200, 300); showScreenLCD("Movement", "DEMO Program 2"); AbsDelay(2000); clearLCD(); // ACS auf mittlere Sendeleistung stellen: RP6_writeCMD_1param(RP6_BASE_ADR, CMD_SET_ACS_POWER, ACS_PWR_MED); RP6_writeCMD_1param(RP6_BASE_ADR, CMD_SET_WDT, true); RP6_writeCMD_1param(RP6_BASE_ADR, CMD_SET_WDT_RQ, true); // Der Thread zur Überprüfung von Statusänderungen wird gestartet: Thread_Start(1,thread_checkINT0); // Vorwärts im Kreis fahren: changeDirection(FWD); moveAtSpeed(100,40); setCursorPosLCD(1,0); printLCD("Moving... :-)"); setRP6LEDs(LED1 | LED4); byte stopped; stopped = false; while(true) { if(!stopped) { // Es sollte nur einmal stop() und Thread_Start aufgerufen // werden, daher fragen wir hier ab, ob das bereits // geschehen ist. // Man muss die Bumper nicht in RP6_Sensorcheck.cc // auswerten. Man kann auch hier direkt die beiden Variablen // der Tastsensoren abfragen: if(bumperLeft || bumperRight) { stop(); // Roboter stoppen! Thread_Start(2,blink); // Blinken! stopped = true; // Roboter wurde angehalten! setCursorPosLCD(1,0); printLCD("Ouch! Crash! :-("); } } Thread_Delay(1); // Muss immer hier rein, sonst werden die anderen // Threads blockiert. } }
Code:/******************************************************************************* * RP6 C-Control PRO M128 Erweiterungsmodul * ---------------------------------------------------------------------------- * I2C Bus Beispielprogramm * ---------------------------------------------------------------------------- * In diese Datei wurde die Sensorauswertung ausgelagert. So bleibt * das Programm insgesamt übersichtlicher. * * Die Ausgaben des ACS wurden in diesem Beispiel entfernt! ******************************************************************************/ //------------------------------------------------------------------------------ // #ifndef __SENSORCHECK__ // Alles nur EINMAL einbinden! #define __SENSORCHECK__ // Diese zwei Zeilen und die letzte in dieser Datei sind wichtig, sonst // funktioniert das übersetzen nicht! Auch bei eigenen Erweiterungen MUSS das // am Anfang stehen! /** * Wenn sich der Zustand des ACS verändert hat, wird diese Funktion * aufgerufen. Was hier genau gemacht wird, hängt dann von der Anwendung ab. */ void handle_ACS(void) { } /** * Genauso wie bei der ACS Funktion, wird handle_Bumpers aufgerufen sobald * sich der Zustand der Tastsensoren vom RP6 geändert hat. */ void handle_Bumpers(void) { beep_t(100, 1, 1); if(bumperRight) { // Rechter Tastsensor setCursorPosLCD(0,14); printLCD("BR"); } else // Links nichts detektiert - also Text vom LCD löschen: clearPosLCD(0,14,2); if(bumperLeft) { // Linker Tastsensor setCursorPosLCD(0,0); printLCD("BL"); } else clearPosLCD(0,0,2); if(bumperLeft && bumperRight) { // Beide, also in der Mitte setCursorPosLCD(0,6); printLCD("MID"); } else clearPosLCD(0,6,3); } /** * Bei niedriger Akkuspannung wird diese Funktion aufgerufen */ void handle_BatLow(void) { print("BAT LOW:"); printInteger(adcBat); println(" "); } /** * Sobald Bewegungsabläufe abgeschlossen sind, oder bei einer * Fehlerabschaltung aufgrund blockierter Motoren wird diese Funktion * aufgerufen. */ void handle_DriveSystemChange(void) { print(" DRIVE:"); printInteger(movementComplete); printInteger(motorOvercurrent); println(" "); } /** * Der RP6 kann mit dem IR Empfänger vom ACS auch RC5 Codes von Fernbedienungen * empfangen. Sobald ein Tastencode empfangen wurde, wird diese Funktion * aufgerufen. */ void handle_RC5_reception(void) { beep_t((RC5_data+5)*15, 2, 2); print(" RC5: "); printInteger(RC5_toggle); // Togglebit (Taste gehalten print(":"); // oder mehrfach gedrückt?) printInteger(RC5_adr); // Adresse print(":"); printInteger(RC5_data); // Tastencode println(" "); } /** * Damit der Roboter nicht ausser Kontrolle gerät, wenn das CCPRO oder andere * Host Controller abstürzen (oder die Kommunikation aus sonstigen Gründen * gestört ist), kann ein Watchdog Timer aktiviert werden, der * alle 250ms eine Anfrage an den Host sendet. Antwortet dieser nicht innerhalb * von 3 Sekunden auf diese Anfrage, werden die Motoren gestoppt und der Roboter * muss zurückgesetzt werden bevor er weiterfahren kann. * * Man kann diese periodischen Anfragen auch gut verwenden um zu signalisieren * dass das Programm noch läuft, indem man eine LED blinken lässt, oder wie * in diesem Beispielprogramm ein Zeichen auf dem LC-Display ("Heartbeat"). */ byte heartbeat; void handle_WDT_RQ(void) { if(heartbeat) { clearPosLCD(0, 11, 1); heartbeat = false; } else { setCursorPosLCD(0,11); printLCD("*"); heartbeat = true; } } /** * Dies ist die etwas aufgeräumte Interrupt Behandlungsroutine. Die eigentliche * Auswertung der Daten erfolgt in den einzelnen Funktionen oben. Diese * werden hier bei Bedarf aufgerufen. */ void thread_checkINT0(void) { while(true) { if(Port_ReadBit(PORT_PE5_INT)) { // Hat der Controller auf dem Mainboard neue Daten? // Die drei Status Register auslesen: RP6_readRegisters(RP6_BASE_ADR, 0, messageBuf, 3); // Wir überprüfen, ob die Status Bits sich verändert haben, // also verknüpfen wir den alten und neuen Wert per Exclusiv Oder // um nur die geänderten Bits auswerten zu müssen. byte compare; compare = messageBuf[0] ^ interrupt_status; interrupt_status = messageBuf[0]; // ------------------------------------ // Zunächst prüfen wir ob sich die ACS Status Bits verändert haben. // Falls nicht, hat irgend etwas anderes den Interrupt ausgelöst und // wir können mit den anderen Abfragen weitermachen. if(compare & MASK_ACS) { // Die ACS Status Variablen setzen: obstacleLeft = messageBuf[0] & 0x20; obstacleRight = messageBuf[0] & 0x40; // ACS in getrennter Funktion weiterbehandeln: handle_ACS(); } // ------------------------------------ // Abfragen ob sich der Zustand der Bumper geändert hat, falls // ja, Text auf der seriellen Schnittstelle ausgeben: if(compare & MASK_BUMPER) { bumperLeft = messageBuf[0] & 0x2; bumperRight = messageBuf[0] & 0x4; handle_Bumpers(); } // ------------------------------------ // Überprüfen ob ein RC5 Datenpaket mit dem IRCOMM empfangen // worden ist - falls ja auf der seriellen ausgeben: if(interrupt_status & MASK_RC5) { RP6_readRegisters(RP6_BASE_ADR, I2C_REG_RC5_ADR, messageBuf, 2); RC5_toggle = messageBuf[0] >> 5; RC5_adr = messageBuf[0] & 0x1F; RC5_data = messageBuf[1]; handle_RC5_reception(); } // ------------------------------------ // Überprüfen ob die Batteriespannung zu niedrig ist: if(compare & MASK_BATLOW) { RP6_readRegisters(RP6_BASE_ADR, I2C_REG_ADC_UBAT_L, messageBuf, 2); adcBat = (messageBuf[1] << 8) | (messageBuf[0]); handle_BatLow(); } // ------------------------------------ // Bewegung fertig? Notabschaltung? if(compare & MASK_DRIVE) { movementComplete = messageBuf[2] & 1; motorOvercurrent = messageBuf[2] & 4; handle_DriveSystemChange(); } // ------------------------------------ // Auf Watchdog Requests prüfen: if(messageBuf[1] & MASK_WDT_RQ) { handle_WDT_RQ(); } } Thread_Delay(1); } } #endif







Zitieren
Lesezeichen