Contrôler votre iRobot Create avec un Palm Pilot (11 / 16 étapes)

Étape 11 : Le programme, partie 3

Il est maintenant temps pour le « noyau » du programme, le fichier « robot.c ».

Tout en haut du fichier « robot.c » nous avons besoin :

 #include "robot.h" #include "string_arrays.c" #include <PalmTypes.h> #include <PalmCompatibility.h> #include <System/SystemPublic.h> #include <UI/UIPublic.h> void SetField (UInt16 formID, UInt16 fieldID, MemPtr str); Int16 Connect(); Boolean Disconnect(); void DisplaySensors(); Boolean MenuHandler (EventPtr event); Boolean SelectFormHandler (EventPtr event); Int16 SendScript (char length); void Display (char length); Boolean ScriptFormHandler (EventPtr event); Boolean MainFormHandler (EventPtr event); Boolean AppHandleEvent (EventPtr event); void AppEventLoop(); void AppStart(); void AppStop(); UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags); // GlobalsUInt16 port = 0; char prog = 0; unsigned char script[30][2]; 

Ce cadre est de la bibliothèque générique de Palm OS. Je suis également déclarer toutes les fonctions que j’ai utilisé en haut, donc vous n’avez pas à vous soucier de toute commande spéciale lorsque vous modifiez le fichier robot.c. Au fond, j’ai aussi quelques variables globales que j’utilise à divers points dans le programme.

La fonction « PilotMain » est le point d’entrée au programme. Il y a plusieurs raisons pourquoi un programme pourrait être lancé sur un Palm Pilot, mais nous voulons seulement s’inquiéter environ un ; Si le programme a été lancé par l’utilisateur PilotMain() commencera le reste du programme.

 UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) { if (cmd == sysAppLaunchCmdNormalLaunch) { AppStart(); AppEventLoop(); AppStop(); } return 0; } 

Les fonctions AppStart() et AppStop() sont assez basique, AppStart() Assurez-vous que l’application démarre correctement, et AppStop() s’assure de l’application se ferme correctement.

 void AppStart() { FrmGotoForm(FormMain); } void AppStop() { Disconnect(); FrmCloseAllForms(); } 

AppEventLoop() est au cœur du programme. Chaque fois que quelque chose se passe AppEventLoop() récupérera le « événement » et essayez de le manipuler. Tout d’abord, il envoie l’événement à quelques fonctions intégrées pour essayer de laisser le système gérer l’événement. Si le système ne gère entièrement l’événement AppEventLoop(), puis transmet l’événement à nos propres fonctions pour tenter de le manipuler. FrmDispatchEvent() est la fonction de gestionnaire d’événements que nous avons attribué à gérer les événements de formulaire actif.

 void AppEventLoop() { EventType event; short error; do { EvtGetEvent (&event, 50); // Wait 100 ticks before sending a nilEvent // Allow the system to attemt to handle events before trying ourself if (SysHandleEvent(&event)) continue; if (MenuHandleEvent((void*)0, &event, &error)) continue; if (AppHandleEvent(&event)) continue; if (MenuHandler(&event)) continue; // Send the event to the form event handler FrmDispatchEvent(&event); } while (event.eType != appStopEvent); } 

AppHandleEvent() est la première fonction non-système AppEventLoop() envoie des événements. Il vérifie pour voir si l’événement signifie le chargement de l’une des formes. Dans l’affirmative il met en place le formulaire et assigne un gestionnaire d’événements par défaut (pour FrmDispatchEvent()).

 Boolean AppHandleEvent (EventPtr event) { FormPtr frm; Int frmID; Boolean handled = false; char str[255]; str[0] = '\0'; if (event->eType == frmLoadEvent) { frmID = event->data.frmLoad.formID; frm = FrmInitForm(frmID); FrmSetActiveForm(frm); switch (frmID) { case FormMain: FrmSetEventHandler(frm, MainFormHandler); FrmDrawForm(frm); StrCat(str, PROGRAM[prog]); SetField(frmID, FldProg, str); handled = true; break; case FormSelect: FrmSetEventHandler(frm, SelectFormHandler); FrmDrawForm(frm); StrCat (str, DISCRIPIONS[prog]); SetField (frmID, FldDescription, str); handled = true; break; case FormMacro: FrmSetEventHandler(frm, ScriptFormHandler); FrmDrawForm(frm); handled = true; break; } } return handled; } 

MenuHandler() est la fonction suivante sur la liste de AppEventLoop (). Si l’utilisateur fait un menu de sélection MenuHandler() Il gérera.

 Boolean MenuHandler (EventPtr event) { Boolean handled = false; Err err; // The command that runs the demo program that corosponds to 'prog' char data[] = {128, 136, prog}; // Handle the menu button's if (event->eType == menuEvent) { MenuEraseStatus(NULL); switch (event->data.menu.itemID) { // Go to the verious forms case MnuStatus: FrmGotoForm(FormMain); handled = true; break; case MnuScript: FrmGotoForm(FormSelect); handled = true; break; case MnuMacro: FrmGotoForm(FormMacro); handled = true; break; // Open the serial connection case MnuConnect: Connect(); handled = true; break; // Close the serial connection case MnuDisconnect: Disconnect(); handled = true; break; // Start/Stop the currently selected program or macro case MnuRun: if (!Connect()) break; // Send the command to the iRobot SrmSend(port, data, 3, &err); SrmSendFlush(port); handled = true; break; case MnuStop: // Replace the 'prog' byte with -1 (255) to stop the currently running program data[2] = 255; // Send the command to the iRobot if (!Connect()) break; SrmSend(port, data, 3, &err); SrmSendFlush(port); handled = true; break; case MnuAbout: FrmAlert(AboutAlert); handled = true; break; } } return handled; } 

Connect() et Disconnect() servent à ouvrir et fermer le port série de la Palm Pilot. Météo ou pas le robot est branché à la Palm Pilot et activée lorsque ces fonctions sont utilisées n’est pas trop important. Dur, si le robot ne reçoit pas au moins une fois la commande « Start » (il est envoyé lorsque la fonction Connect() est appelée) vous pourriez avoir quelques problèmes pour exécuter vos propres scripts.

 Int16 Connect() { Err err; char data = 128; // Open the serial port if (!port) SrmOpen(serPortCradlePort, 57600, &port); // Send the "Start" command to make sure the Create comes out of "Off" mode SrmSend(port, &data, 1, &err); SrmSendFlush(port); return port; } Boolean Disconnect() { // Close the serial port if (port && !SrmClose(port)) { port = 0; return true; } else return false; } 

SetFiled() est utilisé par diverses fonctions pour afficher des données dans les champs de texte définis dans le fichier « robot.rcp ».

 void SetField (UInt16 formID, UInt16 fieldID, MemPtr str){ FormPtr frm; FieldPtr fld; UInt16 obj; CharPtr p; VoidHand h; frm = FrmGetFormPtr(formID); obj = FrmGetObjectIndex(frm, fieldID); fld = (FieldPtr)FrmGetObjectPtr(frm, obj); h = (VoidHand)FldGetTextHandle(fld); if (h == NULL) { h = MemHandleNew (FldGetMaxChars(fld)+1); ErrFatalDisplayIf(!h, "No Memory"); } p = (CharPtr)MemHandleLock(h); StrCopy(p, str); MemHandleUnlock(h); FldSetTextHandle(fld, (Handle)h); FldDrawField(fld); } 

DisplaySensors() est utilisé par le formulaire principal (la forme de « Status ») pour récupérer les info capteur du robot et ensuite l’afficher à l’utilisateur. Tout d’abord, il envoie la commande « List Query » au robot avec une liste de capteurs qui nous intéresse. DisplaySensors() alors analyser la réponse du robot et mettre à jour l’affichage en conséquence.

 void DisplaySensors() { // The data packet sent to the create that requests the sensor data char data[] = {128, 149, 8, 8, 7, 9, 10, 11, 12, 22, 21}; // The byte array that holds the sensor data retrived by the create char inData[9]; char str[20]; UInt16 tmp, *volt; Err err; VoidHand bitmapHandle; BitmapPtr bitmap; Boolean wheall = false, whealr = false; str[0] = '\0'; if (port) { // Only perform this loop if the serial connection is open FrmDrawForm(FrmGetActiveForm()); // Re-draw the form, to clear the old data // Send the request to the create for the sensor data, and put the reply in 'inData' SrmReceiveFlush(port, 0); SrmSend(port, data, 11, &err); SrmSendFlush(port); SrmReceive(port, inData, 9, 20, &err); // The wall sensor if (inData[0]) { bitmapHandle = DmGetResource('Tbmp', PicWall); bitmap = MemHandleLock(bitmapHandle); WinDrawBitmap(bitmap, 110, 25); MemHandleUnlock(bitmapHandle); } // The bumper's and wheal drop sensors tmp = (int)inData[1]; if (tmp >= 16) tmp=tmp-16; // Caster wheal if (tmp >= 8) { // Left wheal wheall = true; tmp = tmp - 8; } if (tmp >= 4) { // Right wheal whealr = true; tmp = tmp - 4; } if (tmp >= 2) { // Left wheal bitmapHandle = DmGetResource('Tbmp', PicBumpL); bitmap = MemHandleLock(bitmapHandle); WinDrawBitmap(bitmap, 25, 30); MemHandleUnlock(bitmapHandle); tmp = tmp - 2; } if (tmp == 1) { // Right wheal bitmapHandle = DmGetResource('Tbmp', PicBumpR); bitmap = MemHandleLock(bitmapHandle); WinDrawBitmap(bitmap, 60, 30); MemHandleUnlock(bitmapHandle); } // We draw the wheal's after drawing the bumpers, so the // pictures overlap properly if (wheall) { bitmapHandle = DmGetResource('Tbmp', PicWhealL); bitmap = MemHandleLock(bitmapHandle); WinDrawBitmap(bitmap, 37, 52); MemHandleUnlock(bitmapHandle); } if (whealr) { bitmapHandle = DmGetResource('Tbmp', PicWhealR); bitmap = MemHandleLock(bitmapHandle); WinDrawBitmap(bitmap, 71, 52); MemHandleUnlock(bitmapHandle); } // The 4 clif sensors if (inData[2]+inData[3]+inData[4]+inData[5] > 0) { bitmapHandle = DmGetResource('Tbmp', PicCliff); bitmap = MemHandleLock(bitmapHandle); if (inData[2] > 0) WinDrawBitmap(bitmap, 21, 35); // Left if (inData[3] > 0) WinDrawBitmap(bitmap, 31, 25); // Top left if (inData[4] > 0) WinDrawBitmap(bitmap, 80, 25); // Top Right if (inData[5] > 0) WinDrawBitmap(bitmap, 90, 35); // Right MemHandleUnlock(bitmapHandle); } // The raw battery voltage volt = (UInt16*)(inData + 6); StrIToA(str, *volt); StrCat(str, " mV"); if (inData[8] > 0 && inData[8] <= 3) StrCat(str, " (crg)"); SetField(FormMain, FldVoltage, str); } } 

MainFormHandler() est la fonction attribuée à l’écran principale (statut). Il est conçu pour gérer les événements spécifiques à votre situation. Le gestionnaire formulaire individuel surtout juste gérer les événements causés par l’utilisateur, mais le gestionnaire de formulaire principal sera également répondre aux nillEvent qui sont générés chaque 50 « ticks » (une graduation est une mesure du temps qui utilise Palm OS) de AppEventLoop().

 Boolean MainFormHandler (EventPtr event) { Boolean handled = false; switch (event->eType) { // Every 50 ticks we check the create's sensors (pending a serial connection) case nilEvent: DisplaySensors(); handled = true; break; case ctlSelectEvent: if (event->data.ctlSelect.controlID == BtnDisconnect) { Disconnect(); handled = true; } break; } return handled; } 

SelectFormHandler() gère les événements du formulaire select.

 Boolean SelectFormHandler (EventPtr event) { Boolean handled = false; char str[255]; str[0] = '\0'; switch (event->eType) { case lstSelectEvent: prog = event->data.lstSelect.selection; StrCat (str, DISCRIPIONS[prog]); SetField (FormSelect, FldDescription, str); handled = true; break; } return handled; } 

ScriptFormHandler() gère les événements pour la forme de scripts. Une grande partie des ScriptFormHandler() est une distinction entre les différents boutons de programmation. Parce que le bouton de programmation ID sont des numéros consécutifs, au lieu de chercher des événements de bouton spécifique nous pouvons chercher des gammes de bouton.

 Boolean ScriptFormHandler (EventPtr event) { const char MAX_SCRIPT = 8; static char length = 0; Boolean handled = false; UInt16 id; Int16 x; FieldPtr fld; FormPtr frm; switch (event->eType) { case frmOpenEvent: Display(length); handled=true; break; // Handle the various buttons case ctlSelectEvent: id = event->data.ctlSelect.controlID; switch (id) { case BtnSend: SendScript(length); handled = true; break; case BtnClear: length = 0; Display(length); handled = true; break; case BtnDel: length--; if (length < 0) length = 0; Display(length); handled = true; break; } // The script action buttons if (id >= BtnUp && id <= BtnPause) { if (length < MAX_SCRIPT) { script[length][0] = id-3100; script[length][1] = 1; length++; } Display(length); handled = true; } // The script time buttons if (id >= BtnP1 && id <= BtnP16) { x = script[length-1][1]; script[length-1][1] = (x+(id-3200) <= 25) ? x+(id-3200) : x; Display(length); handled = true; } break; // The scroll bar case sclRepeatEvent: x = event->data.sclRepeat.newValue - event->data.sclRepeat.value; frm = FrmGetActiveForm(); fld = (FieldPtr)FrmGetObjectPtr (frm, FrmGetObjectIndex(frm, FldScript)); if (x >= 0) FldScrollField (fld, x, winDown); else FldScrollField (fld, x*-1, winUp); break; } return handled; } 

La fonction de Display() traduit les données dans le tableau de scripts dans une chaîne lisible par un humain et l’affiche dans un champ de texte que l’utilisateur peut voir.

 void Display (char length) { char str[1000]; char x; char tmp[10]; str[0] = '\0'; // Turn the script array into a string and display it for (x = 0; x < length; x++) { StrCat (str, COMMANDS[script[x][0]]); StrCat (str, " for \0"); StrIToA (tmp, script[x][1]); StrCat (str, tmp); StrCat (str, " Seconds\n\0"); } SetField (FormMacro, FldScript, str); } 

Enfin la fonction SendScript() prend la variable de script et traduire en commandes que l’iRobot Create peut comprendre et ensuite envoyer le résultat à votre robot. Il est appelé par la fonction ScriptFormHandler().

 Int16 SendScript (char length) { char safe[] = {128, 131}; char data[150]; char i; char x = 0; char y; char cmds = 0; Err err; data[x] = 131; data[++x] = 152; y = ++x; for (i = 0; i < length; i++) { switch (script[i][0]) { case 0: data[++x] = 137; data[++x] = 0; data[++x] = 150; data[++x] = 128; data[++x] = 0; data[++x] = 155; data[++x] = script[i][1]*10; data[++x] = 137; data[++x] = 0; data[++x] = 0; data[++x] = 128; data[++x] = 0; cmds += 3; break; case 1: data[++x] = 137; data[++x] = 255; data[++x] = 106; data[++x] = 128; data[++x] = 0; data[++x] = 155; data[++x] = script[i][1]*10; data[++x] = 137; data[++x] = 0; data[++x] = 0; data[++x] = 128; data[++x] = 0; cmds += 3; break; case 2: data[++x] = 137; data[++x] = 0; data[++x] = 150; data[++x] = 1; data[++x] = 44; data[++x] = 155; data[++x] = script[i][1]*10; data[++x] = 137; data[++x] = 0; data[++x] = 0; data[++x] = 128; data[++x] = 0; cmds += 3; break; case 3: data[++x] = 137; data[++x] = 0; data[++x] = 150; data[++x] = 254; data[++x] = 212; data[++x] = 155; data[++x] = script[i][1]*10; data[++x] = 137; data[++x] = 0; data[++x] = 0; data[++x] = 128; data[++x] = 0; cmds += 3; break; case 4: data[++x] = 137; data[++x] = 0; data[++x] = 125; data[++x] = 0; data[++x] = 1; data[++x] = 155; data[++x] = script[i][1]*10; data[++x] = 137; data[++x] = 0; data[++x] = 0; data[++x] = 128; data[++x] = 0; cmds += 3; break; case 5: data[++x] = 137; data[++x] = 0; data[++x] = 125; data[++x] = 255; data[++x] = 255; data[++x] = 155; data[++x] = script[i][1]*10; data[++x] = 137; data[++x] = 0; data[++x] = 0; data[++x] = 128; data[++x] = 0; cmds += 3; break; case 6: data[++x] = 155; data[++x] = script[i][1]*10; cmds += 1; break; } } data[y] = x+1; Connect(); // Send the script SrmSend(port, data, x+1, &err); SrmSendWait(port); SrmSendFlush(port); return err; } 

Articles Liés

Contrôler votre appareil android avec une télécommande wii

Contrôler votre appareil android avec une télécommande wii

Hé les gars pour mon troisième instructable je vais vous montrer comment contrôler votre appareil android avec une Wiimotevous aurez besoin est1 x: télécommande wii1 x: appareil androidÉtape 1: Téléchargement de l'app tout d'abord, vous devez aller à
Contrôler votre avion RC avec avait votre téléphone

Contrôler votre avion RC avec avait votre téléphone

Avez-vous jamais voulu contrôler votre avion de RC au moyen de l'inclinaison d'un objet ? J'ai toujours eu l'idée à l'arrière de ma tête mais j'ai jamais poursuivi jusqu'à ce que cette semaine dernière. Mes premières pensées ont été d'utiliser un tri
Contrôler votre chambre lumineuse avec votre téléphone portable

Contrôler votre chambre lumineuse avec votre téléphone portable

Cette instructable vous montrera comment connecter votre ampoule sur votre téléphone mobile et il commande par capteur IR.Vous pouvez contrôler quelque chose électrique à votre domicile après cette instructable, si vous comprenez les concepts princip
Contrôler votre arduino depuis votre PC avec le Qt Gui

Contrôler votre arduino depuis votre PC avec le Qt Gui

pour mon premier instructable je vais vous montrer comment utiliser Qt pour faire des interfaces graphiques pour votre arduino (ou n'importe quel appareil rs232)Donc, si vous souhaitez créer vos propres interfaces graphiques, vous souhaitez contrôler
Contrôler votre ordinateur avec une manette PS3 avec rumble - SixAxis ou DualShock

Contrôler votre ordinateur avec une manette PS3 avec rumble - SixAxis ou DualShock

le titre est assez explicite. Vous allez installer une manette PS3 sur votre ordinateur et même l'utiliser pour lutter contre elle. J'ai testé avec les deux types de contrôleurs. Cela fonctionne.Avant de commencer, vous allez vouloir les éléments sui
Contrôler votre ordinateur avec votre voix

Contrôler votre ordinateur avec votre voix

ce n'est pas un code très grand et vous pouvezcommander votre ordinateur avec votre voixen 10 minutes environÉtape 1: Ce que vous aurez besoinvous aurez besoin :n'importe quel logiciel de programmation pour ceci que je suis en utilisant notepad ++Éta
Contrôler votre musique sans fil avec une souris Logitech

Contrôler votre musique sans fil avec une souris Logitech

avez-vous jamais eu besoin de contrôler votre musique sans fil ? Avec un peu de logiciel et d'une souris Logitech, c'est facile. Nous irons sur la façon de mettre en place votre souris afin que vous pouvez mettre en pause, sauter et rejouer jusqu'à c
Comment contrôler votre (mode graphique) Raspberry Pi 2 avec Ethernet du PC Windows

Comment contrôler votre (mode graphique) Raspberry Pi 2 avec Ethernet du PC Windows

Salut les garsJe suis Pushkar Jog de Goa, en Inde et je vais vous montrer les gars comment faire pour contrôler votre ordinateur puissant taille peu les cartes de crédit, Raspberry Pi sans utiliser la souris, clavier et moniteur supplémentaire mais j
Contrôler votre discours avec arduino

Contrôler votre discours avec arduino

Contrôler votre app keynote de mac avec un arduino.Étape 1: Choses nécessaires :Arduino (j'utilise uno, mais tous doivent faire).Câble USB pour l'arduino.IR recevoir diode.Télécommande universelle IR.câbles de démarrage pour le décodeur IR.Etape 2: C
Contrôler votre Arduino depuis un PC avec un câble Usb

Contrôler votre Arduino depuis un PC avec un câble Usb

si vous voulez savoir comment tou peut contrôler votre Arduino avec votre PC ou laissez votre Arduino à afficher les données sur votre PC, puis suivez mes pas. Pour ce faire, vous aurez besoin du logiciel pour créer des interfaces. Avec WD Interface
Meilleure façon de contrôler votre Arduino avec un appareil Mobile !

Meilleure façon de contrôler votre Arduino avec un appareil Mobile !

De nombreux projets tels que celui-ci impliquent nécessitant un bouclier WiFi ou un Bluetooth Module. Cependant, grâce à Billy, comme c'est encore possible, il n'est plus nécessaire. Ce tutoriel vous expliquera en profondeur sur la façon de contrôler
Contrôler votre ordinateur en l’air comme Tony Stark ! (Créez votre propre application de Motion Leap)

Contrôler votre ordinateur en l’air comme Tony Stark ! (Créez votre propre application de Motion Leap)

Bonjour à tous,Je suis Geeve George un amour de Maker.I 15 an, Vision par ordinateur, développement Android et algorithme Design.I suis actuellement en 11e année et également un étudiant de Collaboration de recherche avec le MIT Media Lab Inde initia
Comment contrôler une imprimante 3D avec un téléphone via AstroBox bricolage

Comment contrôler une imprimante 3D avec un téléphone via AstroBox bricolage

Cet Instructable va vous montrer comment configurer un serveur d'impression basée sur Raspberry Pi, vous pouvez contrôler et surveiller votre imprimante 3D à distance (y compris de tranchage distant) d'un téléphone, tablette ou ordinateur.Impression
Contrôler votre chat

Contrôler votre chat

votre chat fait garder sauter sur la table de salle à manger ? Peut-être il va ronger sur vos mains et les chevilles ? Apprenez à contrôler votre chat dans ce Instructable.Étape 1: Les bases Cette astuce fonctionne sur presque tous les chats. Si votr