Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 #include "mbed.h" 00002 #include "usbhid.h" 00003 00004 00005 /* RC_Simulator.....By Jafar Qutteineh*/ 00006 /* This program takes the PPM Singal(Pulse Position Modulation) from your RC transmitter 00007 and emulate it as a USB HID Joystick. 00008 Currently, program configured to accept Throttle, Rudder, Elevator, Ailerons and 00009 2 buttons. It can be adjusted easily to read other channels as well. 00010 The current state of code is just a proof of concept. It's rough and not clean, 00011 once you understand how it work, customize to your like*/ 00012 00013 /*Credit goes to Phil Wright for USB HID code and to Shinichiro Oba Joystiq work*/ 00014 00015 /*Setup: Just connect the GND and PPM singal of your transmitter to the GND and P5 respectivly.*/ 00016 00017 /*How it works: 00018 -P5 is configured as InturreptIn pin. whenever the PPM signal goes down Inturrept SignalFall() is fired. 00019 -SignalFall keep track of timing: 00020 a) If Pulse width is <300 uS it's most probably a glitch. 00021 b) If pulse width is >300 uS but less than < 2000 uS this is a correct channel. Read it and wait for next channel 00022 c) If Pulse width is >8000 uS this is a new frame, start again. 00023 d) Timing will be different from transmitter to another, you may want to play a little bit here 00024 -Once a complete frame is read the values are feedback to our USB HID Joysick class. 00025 */ 00026 00027 00028 00029 InterruptIn PPMsignal(p5); // connect PPM signal to this, you can change to anyother pin 00030 Serial PC(USBTX,USBRX); // I used this for debuging 00031 USBJoystick joystick; /* This is basicly Shinichiro joystiq, I've only adjusted the Report descriptor to my needs. 00032 for more help on this check: 00033 -http://frank.circleofcurrent.com/cache/hid_tutorial_1.htm 00034 -http://helmpcb.com/electronics/usb-joystick */ 00035 00036 00037 int TimeElapsed =0; //Keeps track of time between inturrepts 00038 Timer timer; 00039 unsigned char CurChannel=0; //This will point to the current channel in PPM frame. My PPM signal looks like 10 channels and 1 start frame 00040 // yours could be different 00041 unsigned char Channels[11]={0,0,0,0,0,0,0,0,0,0,0}; //This where channels value is stored until frame is complete. 00042 unsigned short Times[11]={0,0,0,0,0,0,0,0,0,0,0}; //This where channels value is stored until frame is complete. 00043 bool CanUpdate=false; // Once PPM frame is complete this will be true 00044 00045 //Raise_Error is just a function that helped me in development process. You can ignore it all togather. 00046 void Raise_Error (unsigned char Err_Code, int info) { 00047 switch (Err_Code) { 00048 case 0: 00049 PC.printf ("%i\n",info); 00050 break; 00051 case 1: 00052 PC.printf ("Broke@ %i\n",info); 00053 break; 00054 case 2: 00055 PC.printf ("Set ok\n"); 00056 break; 00057 case 3: 00058 PC.printf ("%i\n",info); 00059 break; 00060 case 255: 00061 PC.printf("Initalized sucessfully \n"); 00062 break; 00063 default: 00064 PC.printf("I shouldn't be here \n"); 00065 } 00066 00067 } 00068 00069 //Here were all the work takeplace 00070 void SignalFall() { 00071 TimeElapsed = timer.read_us(); 00072 if (TimeElapsed <300) { 00073 //Raise_Error(0,TimeElapsed); 00074 return; //ignore, it's a glitch. Dont move to the next channel 00075 } 00076 __disable_irq(); 00077 timer.reset(); 00078 //Raise_Error(0,TimeElapsed); 00079 if ((TimeElapsed > 8000 ) && (CurChannel != 0)) { //somehow before reaching the end of PPM frame you read "New" frame signal??? 00080 //Ok, it happens. Just ignore this frame and start a new one 00081 //Raise_Error (1,CurChannel); //incomplete channels set 00082 CurChannel=0; 00083 } 00084 if ((TimeElapsed < 8000 ) && (CurChannel == 0)) { 00085 //Raise_Error (1,CurChannel); //incomplete channels set 00086 __enable_irq(); // This is good. You've received "New" frame signal as expected 00087 return; 00088 } 00089 00090 // Process current channel. This is a correct channel in a correct frame so far 00091 //if (CurChannel==4) Raise_Error(3,TimeElapsed); 00092 Channels[CurChannel]= (TimeElapsed-1000)*255/1000; // Normalize reading (Min: 900us Max: 1900 us). This is my readings, yours can be different 00093 Times[CurChannel] = TimeElapsed; 00094 CurChannel++; 00095 00096 if (CurChannel==9 ) { // great!, you've a complete correct frame. Update Joystick and star a new frame 00097 CurChannel=0; 00098 //Raise_Error(3,0); 00099 CanUpdate= true; 00100 } 00101 __enable_irq(); 00102 } 00103 00104 void Initalize () { 00105 __disable_irq(); 00106 PC.baud(115200); // set baude rate 00107 PPMsignal.mode (PullUp); 00108 PPMsignal.fall(&SignalFall); //Attach SignalFall routine to handle PPMsignal fall 00109 timer.start(); 00110 Raise_Error(255,0); // return successful 00111 timer.reset(); 00112 __enable_irq(); 00113 00114 } 00115 00116 int main() { 00117 //unsigned short *pOut = Times; 00118 unsigned char *pOut = Channels; 00119 00120 Initalize(); 00121 //wait(5); 00122 00123 00124 while (1) { 00125 if (CanUpdate) { // update joystick here 00126 CanUpdate=false; 00127 joystick.joystick(Channels[1],Channels[4],Channels[3],Channels[2],Channels[7],Channels[8]); //update joystick state (Throttle, Rudder, X,Y, Button 1, Button 2) 00128 PC.printf("% 4d,% 4d,% 4d,% 4d\r",pOut[1],pOut[2],pOut[3],pOut[4]); // Raise_Error(3,Channels[1]); 00129 //Channel 5 : PIT 00130 //Channel 6: PLT 00131 } 00132 } 00133 00134 } 00135
Generated on Tue Jul 12 2022 20:25:32 by
1.7.2