This is the first rev of HW3 for IDD
Dependencies: MMA8451Q USBDevice mbed nRF24L01P
main.cpp
00001 //NOTE: NORDIC BOARD ONLY WORKS W/ MBED 84! 00002 //Chose pin ordering from https://mbed.org/questions/1360/Using-nRF24L01-Module-with-FRDM-Board/ -- unused pins 00003 00004 #include "mbed.h" 00005 #include "nRF24L01P.h" // nordic library 00006 00007 #define DEBUG 0 // code debug mode 00008 #define BASE 0 // is base station 00009 00010 00011 #include "USBMouseKeyboard.h" // for the sword - mouse/keyboard combo 00012 #if(BASE == 1) 00013 USBMouseKeyboard MK; //Default is REL_MOUSE, bout could use ABS_MOUSE too 00014 #endif 00015 00016 #define SCALING 50 // factor to multiply the accelerometer reading by (usually it is in the scale of g's. Decides sensitivity of mouse. Keep it less 100 (mouse is assigned an int8) 00017 00018 // Accelerometer includes 00019 #include "MMA8451Q.h" 00020 #define MMA8451_I2C_ADDRESS (0x1d<<1) 00021 00022 // define I2C Pins and address for KL25Z. Taken from default sample code. 00023 PinName const SDA = PTE25; 00024 PinName const SCL = PTE24; 00025 00026 // Base station TX/RX 00027 #define RX_NRF24L01P_ADDRESS ((unsigned long long) 0xABABABABAB ) 00028 #define TX_NRF24L01P_ADDRESS ((unsigned long long) 0xCDCDCDCDCD ) 00029 00030 // The nRF24L01+ supports transfers from 1 to 32 bytes 00031 // To base station: roll | cycle 1 2 3 | space = jump | left click = attack | right click = defend | w | s | d | a | 8-bit Y mouse movement | 8-bit X mouse movement 00032 // WASD = forward, left, back, right 00033 // From PC, only need (zero padded) 1 bit flag indicating if hit 00034 #define TRANSFER_SIZE 4 00035 00036 Serial pc(USBTX, USBRX); // PC communication 00037 00038 PwmOut motor(D2); // Only specific pins have PWM capability 00039 00040 nRF24L01P nordic(PTD2, PTD3, PTC5, PTD0, PTD5, PTA13); // mosi, miso, sck, csn, ce, irq 00041 00042 DigitalIn modeSW(D15); // base station or sword mode can be selected w/ jumper 00043 00044 DigitalOut greenLED(LED_GREEN); 00045 00046 // Accelerometer 00047 MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); 00048 00049 void Calibrate(void); 00050 void Acc_GetXY(void); 00051 00052 int16_t x,y; // variables to hold acceleration data after call to Acc_Get_All 00053 float x_b, y_b; // acc bias 00054 00055 // Debug 00056 //DigitalOut greenLED(LED_GREEN); 00057 //DigitalOut redLED(LED_RED); 00058 00059 AnalogIn ATTACK(A0); // attack FSR 00060 AnalogIn SELECT(A1); // defense/mode FSR 00061 AnalogIn XJOY(A2); // joystick x axis 00062 AnalogIn YJOY(A3); // joystick y axis 00063 00064 DigitalIn JOYSEL(D3); 00065 00066 bool isBaseStation; 00067 bool motorOnFlag; 00068 int motorCycle = 0; 00069 00070 int main() { 00071 int8_t mouse_x, mouse_y; 00072 Calibrate(); // Calibrate accelerometer 00073 00074 modeSW.mode(PullUp); // Configure pull up to minimize wire on sword 00075 00076 isBaseStation = (bool) !modeSW; // Detect device via jumper connection 00077 00078 wait(5); 00079 00080 // Power up wireless 00081 nordic.powerUp(); 00082 00083 // Display + change the (default) setup of the nRF24L01+ chip 00084 00085 // Addresses 5 bytes long 00086 00087 if (isBaseStation){ 00088 nordic.setTxAddress(TX_NRF24L01P_ADDRESS ,5); 00089 nordic.setRxAddress(RX_NRF24L01P_ADDRESS ,5); 00090 } 00091 else{ 00092 nordic.setRxAddress(TX_NRF24L01P_ADDRESS ,5); 00093 nordic.setTxAddress(RX_NRF24L01P_ADDRESS ,5); 00094 } 00095 00096 pc.printf( "nRF24L01+ Frequency : %d MHz\r\n", nordic.getRfFrequency() ); 00097 pc.printf( "nRF24L01+ Output power : %d dBm\r\n", nordic.getRfOutputPower() ); 00098 pc.printf( "nRF24L01+ Data Rate : %d kbps\r\n", nordic.getAirDataRate() ); // 1Mbps 00099 pc.printf( "nRF24L01+ TX Address : 0x%010llX\r\n", nordic.getTxAddress() ); 00100 pc.printf( "nRF24L01+ RX Address : 0x%010llX\r\n", nordic.getRxAddress() ); 00101 00102 // Data packet length 00103 nordic.setTransferSize( TRANSFER_SIZE ); 00104 00105 nordic.setReceiveMode(); 00106 nordic.enable(); 00107 00108 // Set motor PWM period 00109 motor.period(0.001f); // 1ms period 00110 motor.write(0.0f); // initially not on 00111 00112 // Status flags 00113 bool motorON = false; 00114 bool mouse1 = false; 00115 bool mouse2 = false; 00116 bool mouse3 = false; 00117 bool mouse4 = false; 00118 bool mouse5 = false; 00119 bool attackflag = false; 00120 00121 int rxDataCnt = 0; 00122 00123 // counting the mode 00124 uint8_t mode_count = 0; 00125 00126 while (1) { 00127 // Only reads 1 byte from PC + sends to other mcu (pads w/ bytes) if base station 00128 if (isBaseStation){ 00129 00130 // If we've received anything over the host serial link... 00131 if ( pc.readable() ) { 00132 char txData[TRANSFER_SIZE]; 00133 // ...add it to the transmit buffer -- only care about first byte 00134 txData[0] = pc.getc(); 00135 txData[1] = 100; 00136 txData[2] = 100; 00137 txData[3] = '\n'; 00138 00139 // Send the transmitbuffer via the nRF24L01+ 00140 nordic.write( NRF24L01P_PIPE_P0, txData, TRANSFER_SIZE ); 00141 00142 // Toggle LED1 (to help debug Host -> nRF24L01+ communication) 00143 /*if (txData[0] == 66) 00144 greenLED = !greenLED;*/ 00145 } 00146 00147 // If we've received anything in the nRF24L01+... = sword 00148 if ( nordic.readable() ) { 00149 char rxData[TRANSFER_SIZE]; 00150 // ...read the data into the receive buffer 00151 rxDataCnt = nordic.read( NRF24L01P_PIPE_P0, rxData, TRANSFER_SIZE ); 00152 00153 //Get data and convert to mouse x,y and key entry 00154 // To base station: roll | cycle 1 2 3 | space = jump | left click = attack | right click = defend | w | s | d | a | 8-bit Y mouse movement | 8-bit X mouse movement 00155 00156 int8_t dx = rxData[0]; // change in x 00157 int8_t dy = rxData[1]; // change in y 00158 00159 bool mode_stat = (rxData[2] >> 7) & 1; // checking flag bits 00160 bool joy_but = (rxData[2] >> 6) & 1; 00161 bool def_stat = (rxData[2] >> 5) & 1; 00162 bool attack_stat = (rxData[2] >> 4) & 1; 00163 bool key_w = (rxData[2] >> 3) & 1; 00164 bool key_s = (rxData[2] >> 2) & 1; 00165 bool key_d = (rxData[2] >> 1) & 1; 00166 bool key_a = (rxData[2] >> 0) & 1; 00167 00168 bool roll = (rxData[3] >> 0) & 1; 00169 00170 #if(BASE == 1) // Only if base station 00171 MK.move(dy, dx); // move mouse relative 00172 00173 if(joy_but) // do keyboard events 00174 MK.putc(' '); 00175 00176 if(attack_stat) 00177 { 00178 MK.press(MOUSE_LEFT); 00179 mouse1 = true; 00180 } 00181 if(!attack_stat && mouse1) 00182 { 00183 MK.release(MOUSE_LEFT); 00184 mouse1 = false; 00185 } 00186 if(key_a) // move left 00187 { 00188 MK.press(MOUSE_RIGHT); 00189 mouse2 = true; 00190 } 00191 if(!key_a && mouse2) 00192 { 00193 MK.release(MOUSE_RIGHT); 00194 mouse2 = false; 00195 } 00196 if(key_d) // move right 00197 { 00198 MK.press(MOUSE_MIDDLE); 00199 mouse3 = true; 00200 } 00201 if(!key_d && mouse3) 00202 { 00203 MK.release(MOUSE_MIDDLE); 00204 mouse3 = false; 00205 } 00206 // mouse 4, 5 have issues on windows 00207 if(key_w) // move forward 00208 { 00209 //MK.press(16); // mouse5 00210 //mouse5 = true; 00211 MK.putc('w'); 00212 } 00213 /*if(!key_w && mouse5) 00214 { 00215 MK.release(16); 00216 mouse5 = false; 00217 }*/ 00218 if(key_s) // move backward 00219 { 00220 //MK.press(8); // mouse4 00221 //mouse4 = true; 00222 MK.putc('s'); 00223 } 00224 /*if(!key_s && mouse4) 00225 { 00226 MK.release(8); 00227 mouse4 = false; 00228 }*/ 00229 00230 // Single push commands 00231 if(def_stat) 00232 MK.putc('d'); 00233 00234 if(mode_stat) 00235 { 00236 MK.putc('1'+mode_count); 00237 mode_count = (mode_count+1)%3; 00238 } 00239 if(roll) 00240 MK.putc('r'); 00241 00242 #endif 00243 00244 //pc.printf("x: %d y: %d \r\n",dx,dy); 00245 00246 // Display the receive buffer contents via the host serial link 00247 /*for ( int i = 0; i < TRANSFER_SIZE; i++ ) { 00248 00249 pc.putc( rxData[i] ); 00250 }*/ 00251 } 00252 } 00253 00254 // sword 00255 else{ 00256 int ATTACKVAL = ATTACK.read_u16(); // attack FSR 00257 int SELECTVAL = SELECT.read_u16(); // mode/defense FSR 00258 int XJOYVAL = XJOY.read_u16(); // joystick x 00259 int YJOYVAL = YJOY.read_u16(); // joystick y 00260 int JOYSELVAL = (int) JOYSEL; // joystick select value 00261 00262 // if joystick push/pulled all the way on axis, do roll/move faster in direction 00263 //bool roll = ((XJOYVAL > 64000) || (XJOYVAL < 1000) || (YJOYVAL > 64000) || (YJOYVAL < 1000)) ? true: 0; 00264 // Disable backward roll due to lack of continuous MOUSE buttons 00265 bool roll = ((XJOYVAL > 64000) || (XJOYVAL < 1000) || (YJOYVAL > 64000)) ? true: 0; 00266 00267 // thresholding 00268 bool mode_stat = (SELECTVAL > 45000) ? true: 0; // 1, 2, 3 rotated (defense/mode FSR pressed all the way) 00269 bool joy_but = JOYSEL == 0? true: 0; 00270 bool def_stat = (SELECTVAL > 10000 && SELECTVAL < 45000) ? true: 0; // defend if defense/mode FSR slightly pressed 00271 bool attack_stat = ATTACKVAL > 10000? true: 0; // attack if attack FSR pressed 00272 bool key_d = XJOYVAL > 35000 ? true: 0; // if joystick moves in direction, direction key should be pressed 00273 bool key_a = XJOYVAL < 30000 ? true : 0; 00274 bool key_w = YJOYVAL > 35000 ? true: 0; 00275 bool key_s = YJOYVAL < 30000 ? true: 0; 00276 00277 // turn on motor at start of attack 00278 00279 if (attack_stat == true) 00280 attackflag = true; 00281 if (attackflag == true){ 00282 if (motorCycle < 250){ 00283 motorCycle++; 00284 motor.write(0.40f); // 40% duty cycle, relative to period 00285 00286 } 00287 else { 00288 motorCycle = 0; 00289 attackflag = false; 00290 motor.write(0.00f); 00291 } 00292 } 00293 00294 00295 00296 // make byte 2 of packet 00297 uint8_t key_stat = mode_stat<<7|joy_but<<6|def_stat<<5|attack_stat<<4|key_w<<3|key_s<<2|key_d<<1|key_a<<0; 00298 00299 //pc.printf("F1: %d \t F2: %d \t X: %d \t Y: %d \t SEL: %d \r\n", ATTACKVAL, SELECTVAL, XJOYVAL, YJOYVAL, JOYSELVAL); 00300 00301 // Let serial read catch up on base station/PC side 00302 wait_us(150); 00303 00304 char swordData[TRANSFER_SIZE]; 00305 00306 Acc_GetXY(); // Get X, Y acceleration 00307 00308 mouse_x = x; // x, y assigned in prev function 00309 mouse_y = y; 00310 00311 char lowX = char(mouse_x & 0x00FF); // only use lowest 8 bits of data 00312 char lowY = char(mouse_y & 0x00FF); 00313 00314 //pc.printf("x: %f \t y: %f \r\n", mouse_x,mouse_y); 00315 00316 // left A, right D, back S, up W 00317 00318 // MSB -- LSB send packet 00319 swordData[0] = lowX; 00320 swordData[1] = lowY; 00321 swordData[2] = char(key_stat); 00322 swordData[3] = char(roll); // cast bool into char 00323 00324 // Send the transmitbuffer via the nRF24L01+ 00325 nordic.write( NRF24L01P_PIPE_P0, swordData, TRANSFER_SIZE ); 00326 00327 // If we've received anything from base station 00328 if ( nordic.readable() ) { 00329 00330 greenLED = !greenLED; 00331 00332 char rxData[TRANSFER_SIZE]; 00333 // ...read the data into the receive buffer 00334 rxDataCnt = nordic.read( NRF24L01P_PIPE_P0, rxData, TRANSFER_SIZE ); 00335 00336 #if DEBUG == 1 00337 // Display the receive buffer contents via the host serial link 00338 for ( int i = 0; i < TRANSFER_SIZE; i++ ) { 00339 pc.putc( rxData[i] ); 00340 } 00341 #endif 00342 00343 // From PC, only need (zero padded) 1 bit flag indicating if hit 00344 // In first byte 00345 motorON = (rxData[0] >> 0) & 1; // Motor ON when sword contact made 00346 if (motorON) 00347 motorOnFlag = true; 00348 } 00349 00350 // if flag to turn motor on sent, run motor for a little while and then stop 00351 // period not extended if another motor on command sent in the middle of the count 00352 00353 } 00354 } 00355 } 00356 00357 // perform initial accelerometer calibration to zero stuff 00358 void Calibrate(void) 00359 { 00360 unsigned int count1; 00361 count1 = 0; 00362 float sstatex = 0; 00363 float sstatey = 0; 00364 00365 do{ 00366 sstatex += acc.getAccX(); // Accumulate Samples 00367 sstatey += acc.getAccY(); 00368 count1++; 00369 }while(count1!=0x0400); // 1024 times 00370 x_b = sstatex/1024.0; // division between 1024 00371 y_b = sstatey/1024.0; 00372 } 00373 00374 // remove offset from calibration + scale for sensitivity when getting accelerometer data 00375 void Acc_GetXY(void) 00376 { 00377 x = (int16_t)((acc.getAccX()- x_b)*SCALING); 00378 y = (int16_t)((acc.getAccY()- y_b)*SCALING); 00379 } 00380 00381 /* Processing code 00382 00383 //sikuli-java.jar needed to keep track of HP/score for rumble + serial RX/TX 00384 00385 import org.sikuli.script.*; 00386 import processing.serial.*; 00387 00388 Serial myPort; // Serial port 00389 int lastTime = 0; // Time counter 00390 00391 Region myHPReg = new Region(1,1,500,500); // HP watch regions x, y, w, h 00392 Region otherHPReg = new Region(500,500,500,500); 00393 00394 // Specify event handler for detecting changes 00395 class hpChangeClass implements SikuliEventObserver { 00396 @Override 00397 void targetChanged(SikuliEventChange evnt1) { 00398 println( "changed!" ); 00399 for (int i = 0; i <100; i++){ 00400 myPort.write(3); // Rumble motor (LSB high) 00401 } 00402 //lastTime++; 00403 } 00404 00405 void targetAppeared(SikuliEventAppear evnt2) { 00406 println("test"); 00407 } 00408 00409 void targetVanished(SikuliEventVanish evnt3) { 00410 println("test"); 00411 } 00412 00413 } 00414 00415 hpChangeClass regionChange = new hpChangeClass(); 00416 00417 void setup(){ 00418 size(1,1); // Don't care (out of focus) 00419 myPort = new Serial(this, "/dev/tty.usbmodem1422", 9600); // Serial setup 00420 myPort.clear(); 00421 //lastTime = millis(); 00422 myHPReg.highlight(5); // Show regions watched for 5 seconds 00423 otherHPReg.highlight(5); 00424 00425 myHPReg.onChange(10, regionChange); // num of pixels for change detection, event handler 00426 myHPReg.observeInBackground((int)Float.POSITIVE_INFINITY); // watch forever 00427 00428 otherHPReg.onChange(10, regionChange); // num of pixels for change detection, event handler 00429 otherHPReg.observeInBackground((int)Float.POSITIVE_INFINITY); // watch forever 00430 } 00431 00432 void draw() { 00433 00434 Wait 00435 if ( millis() - lastTime > 5000 ) { 00436 myPort.write(68); 00437 lastTime = millis(); 00438 } 00439 00440 } 00441 00442 */ 00443 00444
Generated on Thu Jul 14 2022 01:30:18 by 1.7.2