/* * File: sheila_final.c * Author: Sheila Balu * Target PIC: PIC32MX250F128B */ #include "config.h" // clock AND protoThreads configure! #include "pt_cornell_1_2_1.h" // threading library // graphics libraries #include "tft_gfx.h" #include "tft_master.h" #include #include #include "i2c_helper.h" //PORT A #define EnablePullDownA(bits) CNPUACLR=bits; CNPDASET=bits; //PORT B #define EnablePullDownB(bits) CNPUBCLR=bits; CNPDBSET=bits; // === thread structures ============================================ // thread control structs static struct pt pt_serial, pt_time, pt_DMA_output; int sys_time_seconds = 0; // system 1 second interval tick int flap_up = 0; // increase flap int flap_down = 0; // decrease flap int kill_switch = 0; // kill switch int adc_throttle = 0; // throttle int adc_rudder = 0; // rudder value int pause = 0; // 1 if paused, 0 otherwise int landing_gear = 0; // 1 if gear extended, 0 if retracted int brake_left = 0; // 1 if left brake is on int brake_right = 0; // 1 if right brake is on char buffer[1000]; // printing buffer int x1 =0, x2 = 0, x3 = 0, x4 = 0; // used to average values int y1 =0, y2 = 0, y3 = 0, y4 = 0; // used to average values static volatile float tilt1 = 0, tilt2 = 0; // === One second Thread ====================================================== static PT_THREAD (protothread_time(struct pt *pt)) { PT_BEGIN(pt); while(1) { PT_YIELD_TIME_msec(1000) ; // yield time 1 second sys_time_seconds++ ; // draw sys_time tft_fillRoundRect(0,10, 200, 14, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 10); tft_setTextColor(ILI9340_YELLOW); tft_setTextSize(2); sprintf(buffer,"Time: %d", sys_time_seconds); tft_writeString(buffer); } // END WHILE(1) PT_END(pt); } // timer thread // === Thread 1 (ECE4760 UART) ====================================== static PT_THREAD (protothread_serial(struct pt *pt)) { PT_BEGIN(pt); while(1) { PT_YIELD_TIME_msec(32); // read status of buttons, switches, and potentiometers flap_up = mPORTAReadBits(BIT_4)!=0; flap_down = mPORTAReadBits(BIT_3)!=0; kill_switch = mPORTAReadBits(BIT_2)!=0; pause = mPORTBReadBits(BIT_5)!=0; landing_gear = mPORTBReadBits(BIT_4)!=0; adc_throttle = ReadADC10(0)/10; // RB13 adc_rudder = ReadADC10(1)-850; // RB3 brake_left = mPORTBReadBits(BIT_7)!=0; brake_right = mPORTBReadBits(BIT_15)!=0; float values[6]; readImuValues(values); // Parse the IMU data float xAccel = values[0]; float yAccel = values[1]; float zAccel = values[2]; // fuse the data from the IMU using trigonometry float accTilt1 = atan2f(yAccel, zAccel)*180/M_PI; // Tilt angle from accelerometer (in degrees) float accTilt2 = atan2f(xAccel, zAccel)*180/M_PI; // Tilt angle from accelerometer (in degrees) // x4 = x3; x3 = x2; x2 = x1; x1 = accTilt1; float x_avg = (x4+x3+x2+x1)/4; // y4 = y3; y3 = y2; y2 = y1; y1 = accTilt2; float y_avg = (y4+y3+y2+y1)/4; // serial communication sprintf(PT_send_buffer, "%d %d %d %d %d %d %d %.0f %.0f %d %d %d\r\n", 0, flap_up, flap_down, kill_switch, pause, landing_gear, adc_throttle, x_avg, y_avg, adc_rudder, brake_left, brake_right); PT_SPAWN(pt, &pt_DMA_output, PT_DMA_PutSerialBuffer(&pt_DMA_output)); } // END WHILE(1) PT_END(pt); } void my_adc_setup() { CloseADC10(); // ensure the ADC is off before setting the configuration // define setup parameters for OpenADC10 // Turn module on | ouput in integer | trigger mode auto | enable autosample // ADC_CLK_AUTO -- Internal counter ends sampling and starts conversion (Auto convert) // ADC_AUTO_SAMPLING_ON -- // ADC_AUTO_SAMPLING_OFF -- Sampling begins with AcquireADC10(); #define PARAM1 ADC_FORMAT_INTG16 | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON //Sampling begins immediately after last conversion completes; SAMP bit is automatically set // define setup parameters for OpenADC10 // ADC ref external | disable offset test | disable scan mode | do 2 sample | use single buf | alternate mode on #define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_2 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_ON // // Define setup parameters for OpenADC10 // use peripherial bus clock | set sample time | set ADC clock divider // ADC_CONV_CLK_Tcy2 means divide CLK_PB by 2 (max speed) // ADC_SAMPLE_TIME_5 seems to work with a source resistance < 1kohm // SLOW it down a little #define PARAM3 ADC_CONV_CLK_PB | ADC_SAMPLE_TIME_15 | ADC_CONV_CLK_Tcy //ADC_SAMPLE_TIME_15| ADC_CONV_CLK_Tcy2 // define setup parameters for OpenADC10 // set AN11 and as analog inputs // AN11 is RB13, AN5 is RB3 #define PARAM4 ENABLE_AN11_ANA | ENABLE_AN5_ANA // define setup parameters for OpenADC10 // do not assign channels to scan #define PARAM5 SKIP_SCAN_ALL //|SKIP_SCAN_AN5 //SKIP_SCAN_AN11 |SKIP_SCAN_AN5 //SKIP_SCAN_ALL // use ground as neg ref for A | use AN11 for input A // // configure to sample AN5 and AN11 // AN5 = RB3 SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | ADC_CH0_POS_SAMPLEA_AN11 | ADC_CH0_NEG_SAMPLEB_NVREF | ADC_CH0_POS_SAMPLEB_AN5 ); OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using the parameters defined above EnableADC10(); // Enable the ADC } void my_tft_setup() { // init the display tft_init_hw(); // 240x320 vertical display tft_begin(); tft_fillScreen(ILI9340_BLACK); tft_setRotation(0); // Use tft_setRotation(1) for 320x240 } void my_button_setup() { // init flap_up button to RA3 mPORTASetPinsDigitalIn(BIT_4); EnablePullDownA(BIT_4); // init flap_down button to RA4 mPORTASetPinsDigitalIn(BIT_3); EnablePullDownA(BIT_3); // init kill_switch button to RA2 mPORTASetPinsDigitalIn(BIT_2); EnablePullDownA(BIT_2); // init pause button to RB5 mPORTBSetPinsDigitalIn(BIT_5); EnablePullDownB(BIT_5); // init landing gear button to RB11 mPORTBSetPinsDigitalIn(BIT_4); EnablePullDownB(BIT_4); // init brake left button to RB7 mPORTBSetPinsDigitalIn(BIT_7); EnablePullDownB(BIT_7); // init brake right button to RB15 mPORTBSetPinsDigitalIn(BIT_15); EnablePullDownB(BIT_15); } void my_imu_setup() { // == IMU i2c communication setup ======================== //Enable channel //BRG computed value for the baud rate generator. The value is // calculated as follows: BRG = (Fpb / 2 / baudrate) - 2. OpenI2C1( I2C_ON, 0x2C ); // Take the MPU 6050 out of sleep mode char data[] = {0}; i2c_write(0x6b, data, 1); // Set the gyro sensitivity to 131 lsb/(degrees/second)) i2c_write(0x1b, data, 1); // Calibrate the gyroscopes (robot must be stable on flat surface) calibrateGyros(); } // === Main ====================================================== void main(void) { PT_setup(); INTEnableSystemMultiVectoredInt(); // setup system wide interrupts // init the threads PT_INIT(&pt_time); PT_INIT(&pt_serial); my_adc_setup(); my_tft_setup(); my_button_setup(); my_imu_setup(); // round-robin scheduler for threads while (1) { PT_SCHEDULE(protothread_time(&pt_time)); PT_SCHEDULE(protothread_serial(&pt_serial)); } } // main // === end ======================================================