Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2019
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.26 KB | None | 0 0
  1. /*
  2. * MSP432 Signal Pass-through with triple buffering
  3. *
  4. * Copyright (c) Dr. Xinrong Li @ UNT
  5. * All rights reserved.
  6. */
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdbool.h>
  11. #include <stdint.h> //Exact-width integer types
  12. #include <ti\devices\msp432p4xx\driverlib\driverlib.h> //Driver library
  13.  
  14. #define CHANNEL1 0
  15. #define CHANNEL2 1
  16. #define CHANNEL3 2
  17. #define CHANNEL4 3
  18.  
  19. #define THROTTLE 3
  20. #define ROLL 2
  21. #define PITCH 1
  22. #define YAW 0
  23.  
  24. #define PI 3.14159265358979323846
  25.  
  26. #define X 0 // X axis
  27. #define Y 1 // Y axis
  28. #define Z 2 // Z axis
  29. #define FREQ 250 // Sampling frequency
  30. #define DCO_FREQ 48e6
  31. #define SSF_GYRO 65.5 // Sensitivity Scale Factor of the gyro from datasheet
  32.  
  33.  
  34. int initialized = 0;
  35. int gyro_raw[3] = {0,0,0};
  36. long gyro_offset[3] = {0,0,0};
  37. float gyro_angle[3] = {0,0,0};
  38.  
  39. int acc_raw[3] = {0,0,0};
  40. float acc_angle[3] = {0,0,0};
  41. long acc_total_vector;//total 3D acceleration vector
  42.  
  43. float errors[3]; // Measured errors (compared to instructions) : [Yaw, Pitch, Roll]
  44. float error_sum[3] = {0, 0, 0}; // Error sums (used for integral component) : [Yaw, Pitch, Roll]
  45. float previous_error[3] = {0, 0, 0}; // Last errors (used for derivative component) : [Yaw, Pitch, Roll]
  46.  
  47. unsigned long pulse_length_esc1 = 1000;
  48. unsigned long pulse_length_esc2 = 1000;
  49. unsigned long pulse_length_esc3 = 1000;
  50. unsigned long pulse_length_esc4 = 1000;
  51.  
  52. float measures [3] = {0,0,0,};
  53. float instruction[4];
  54.  
  55. void initDevice(void);
  56. void calculateAngles(void);
  57. void calculateGyroAngles(void);
  58. void calculateAccelerometerAngles(void);
  59. void resetGyroAngles(void);
  60. void getFlightInstruction(void);
  61. void calculateErrors(void);
  62. void pidController(void);
  63. void initGPIO(void);
  64. void initUART(void);
  65.  
  66. uint8_t BlueTooth = 0;
  67. uint8_t Temp;
  68. uint8_t PWM;
  69.  
  70. void main(void)
  71. {
  72. // 1. First, read raw values from IMU
  73. //read and store the values to
  74. //accelRaw=[x,y,z]
  75. //gyroRaw=[x,y,z]
  76. // 2. Calculate angles from gyro & accelerometer's values
  77. calculateAngles();
  78.  
  79. // 3. takes user input map it in the throttle range of 1ms-2ms
  80. getFlightInstruction();
  81. // 4. takes the difference between the user input and measured valued
  82. calculateErrors();
  83. // 5. Calculate motors speed with PID controller
  84. pidController();
  85. // 6. Apply motors speed to PCA pwm board
  86. }
  87.  
  88. void calculateAngles(void)
  89. {
  90. calculateGyroAngles();
  91. calculateAccelerometerAngles();
  92.  
  93. if (initialized==1)
  94. {
  95. // Correct the drift of the gyro with the accelerometer
  96. gyro_angle[X] = gyro_angle[X] * 0.9996 + acc_angle[X] * 0.0004;
  97. gyro_angle[Y] = gyro_angle[Y] * 0.9996 + acc_angle[Y] * 0.0004;
  98. }
  99. else
  100. {
  101. // At very first start, init gyro angles with accelerometer angles
  102. resetGyroAngles();
  103. initialized = 1;
  104. }
  105.  
  106. // To dampen the pitch and roll angles a complementary filter is used
  107. measures[ROLL] = measures[ROLL] * 0.9 + gyro_angle[X] * 0.1;
  108. measures[PITCH] = measures[PITCH] * 0.9 + gyro_angle[Y] * 0.1;
  109. measures[YAW] = -gyro_raw[Z] / SSF_GYRO; // Store the angular motion for this axis
  110. }
  111.  
  112. void calculateGyroAngles(void)
  113. {
  114. // Subtract offsets
  115. gyro_raw[X] -= gyro_offset[X];
  116. gyro_raw[Y] -= gyro_offset[Y];
  117. gyro_raw[Z] -= gyro_offset[Z];
  118.  
  119. // Angle calculation using integration
  120. gyro_angle[X] += (gyro_raw[X] / (FREQ * SSF_GYRO));
  121. gyro_angle[Y] += (-gyro_raw[Y] / (FREQ * SSF_GYRO)); // Change sign to match the accelerometer's one
  122.  
  123. // Transfer roll to pitch if IMU has yawed
  124. gyro_angle[Y] += gyro_angle[X] * sin(gyro_raw[Z] * (PI / (FREQ * SSF_GYRO * 180)));
  125. gyro_angle[X] -= gyro_angle[Y] * sin(gyro_raw[Z] * (PI / (FREQ * SSF_GYRO * 180)));
  126. }
  127.  
  128. void calculateAccelerometerAngles(void)
  129. {
  130. // Calculate total 3D acceleration vector : sqrt(X² + Y² + Z²)
  131. acc_total_vector = sqrt(pow(acc_raw[X], 2) + pow(acc_raw[Y], 2) + pow(acc_raw[Z], 2));
  132.  
  133. // To prevent asin to produce a NaN, make sure the input value is within [-1;+1]
  134. if (abs(acc_raw[X]) < acc_total_vector)
  135. {
  136. acc_angle[X] = asin((float)acc_raw[Y] / acc_total_vector) * (180 / PI); // asin gives angle in radian. Convert to degree multiplying by 180/pi
  137. }
  138.  
  139. if (abs(acc_raw[Y]) < acc_total_vector)
  140. {
  141. acc_angle[Y] = asin((float)acc_raw[X] / acc_total_vector) * (180 / PI);
  142. }
  143. }
  144.  
  145. void resetGyroAngles(void)
  146. {
  147. gyro_angle[X] = acc_angle[X];
  148. gyro_angle[Y] = acc_angle[Y];
  149. }
  150. void getFlightInstruction(void)
  151. {
  152. // * - Roll : from -33° to 33°
  153. //* - Pitch : from -33° to 33°
  154. //* - Yaw : from -180°/sec to 180°/sec
  155. //* - Throttle : from 1000µs to 1800µs
  156.  
  157. instruction[YAW] =0;
  158. instruction[PITCH] =0;
  159. instruction[ROLL] =0;
  160. //need to translate no input user input into pulse length
  161. if(BlueTooth==127)
  162. {
  163. instruction[THROTTLE]= PWM+50;//throttle
  164. if(instruction[THROTTLE]<=1000)
  165. {
  166. instruction[THROTTLE]=1000;
  167. }
  168. }
  169. if(BlueTooth==120)
  170. {
  171. instruction[THROTTLE] = PWM-50;//throttle
  172. if(instruction[THROTTLE]>=1800)
  173. {
  174. instruction[THROTTLE]=1800;
  175. }
  176. }
  177. BlueTooth=0;
  178.  
  179. };
  180.  
  181. void calculateErrors(void)
  182. {
  183. errors[YAW] = instruction[YAW] - measures[YAW];
  184. errors[PITCH] = instruction[PITCH] - measures[PITCH];
  185. errors[ROLL] = instruction[ROLL] - measures[ROLL];
  186. }
  187.  
  188. void pidController(void)
  189. {
  190. float Kp[3] = {4.0, 1.3, 1.3}; // P coefficients in that order : Yaw, Pitch, Roll
  191. float Ki[3] = {0.02, 0.04, 0.04}; // I coefficients in that order : Yaw, Pitch, Roll
  192. float Kd[3] = {0, 18, 18}; // D coefficients in that order : Yaw, Pitch, Roll
  193. float delta_err[3] = {0, 0, 0}; // Error deltas in that order : Yaw, Pitch, Roll
  194. float yaw_pid = 0;
  195. float pitch_pid = 0;
  196. float roll_pid = 0;
  197.  
  198. // Initialize motor commands with throttle
  199. pulse_length_esc1 = instruction[THROTTLE];
  200. pulse_length_esc2 = instruction[THROTTLE];
  201. pulse_length_esc3 = instruction[THROTTLE];
  202. pulse_length_esc4 = instruction[THROTTLE];
  203.  
  204. // Do not calculate anything if throttle is 0
  205. if (instruction[THROTTLE] >= 1012) {
  206. // Calculate sum of errors : Integral coefficients
  207. error_sum[YAW] += errors[YAW];
  208. error_sum[PITCH] += errors[PITCH];
  209. error_sum[ROLL] += errors[ROLL];
  210.  
  211. // Calculate error delta : Derivative coefficients
  212. delta_err[YAW] = errors[YAW] - previous_error[YAW];
  213. delta_err[PITCH] = errors[PITCH] - previous_error[PITCH];
  214. delta_err[ROLL] = errors[ROLL] - previous_error[ROLL];
  215.  
  216. // Save current error as previous_error for next time
  217. previous_error[YAW] = errors[YAW];
  218. previous_error[PITCH] = errors[PITCH];
  219. previous_error[ROLL] = errors[ROLL];
  220.  
  221. // PID = e.Kp + (integral)e.Ki + (delta)e.Kd
  222. yaw_pid = (errors[YAW] * Kp[YAW]) + (error_sum[YAW] * Ki[YAW]) + (delta_err[YAW] * Kd[YAW]);
  223. pitch_pid = (errors[PITCH] * Kp[PITCH]) + (error_sum[PITCH] * Ki[PITCH]) + (delta_err[PITCH] * Kd[PITCH]);
  224. roll_pid = (errors[ROLL] * Kp[ROLL]) + (error_sum[ROLL] * Ki[ROLL]) + (delta_err[ROLL] * Kd[ROLL]);
  225.  
  226. // Calculate pulse duration for each ESC
  227. pulse_length_esc1 = instruction[THROTTLE] + roll_pid + pitch_pid - yaw_pid;
  228. pulse_length_esc2 = instruction[THROTTLE] - roll_pid + pitch_pid + yaw_pid;
  229. pulse_length_esc3 = instruction[THROTTLE] + roll_pid - pitch_pid + yaw_pid;
  230. pulse_length_esc4 = instruction[THROTTLE] - roll_pid - pitch_pid - yaw_pid;
  231. }
  232.  
  233. //sets the minimum and maximum throttle values
  234. //keeps pwms within esc operating range
  235. if (pulse_length_esc1 <= 1100)
  236. {
  237. pulse_length_esc1 =1100;
  238. }
  239. else
  240. {
  241. pulse_length_esc1 =2000;
  242. }
  243. if (pulse_length_esc2 <= 1100)
  244. {
  245. pulse_length_esc2 =1100;
  246. }
  247. else
  248. {
  249. pulse_length_esc2 =2000;
  250. }
  251. if (pulse_length_esc3 <= 1100)
  252. {
  253. pulse_length_esc3 =1100;
  254. }
  255. else
  256. {
  257. pulse_length_esc3 =2000;
  258. }
  259. if (pulse_length_esc4 <= 1100)
  260. {
  261. pulse_length_esc4 =1100;
  262. }
  263. else
  264. {
  265. pulse_length_esc4 =2000;
  266. }
  267. }
  268.  
  269. void initDevice(void)
  270. {
  271. WDT_A_holdTimer(); //stop Watchdog timer
  272.  
  273. //Change VCORE to 1 to support a frequency higher than 24MHz.
  274. //See data sheet for Flash wait-state requirement for a given frequency.
  275. PCM_setPowerState(PCM_AM_LDO_VCORE1);
  276. FlashCtl_setWaitState(FLASH_BANK0, 1);
  277. FlashCtl_setWaitState(FLASH_BANK1, 1);
  278.  
  279. //Enable FPU for DCO Frequency calculation.
  280. FPU_enableModule();
  281. FPU_enableLazyStacking(); // Required to use FPU within ISR.
  282.  
  283. //Only use DCO nominal frequencies: 1.5, 3, 6, 12, 24, 48MHz.
  284. CS_setDCOFrequency(DCO_FREQ);
  285.  
  286. //Divider: 1, 2, 4, 8, 16, 32, 64, or 128.
  287. //SMCLK used by UART and ADC14.
  288.  
  289. CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_16);
  290.  
  291. }
  292.  
  293. void initGPIO(void)
  294. {
  295. // - P3.2: IN ( UART: UCA2RXD ).
  296. // - P3.3: OUT ( UART: UCA2TXD ).
  297. // P3->SEL0 |= ( BIT2 | BIT3 );
  298. GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
  299. // P3->SEL1 &= ~( BIT2 | BIT3 );
  300. GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
  301. }
  302.  
  303. void initUART(void)
  304. {
  305. EUSCI_A2->CTLW0 |= EUSCI_A_CTLW0_SWRST;
  306. //Configuration for 3MHz SMCLK, 9600 baud rate.
  307. //Calculated using the online calculator that TI provides at:
  308. //http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
  309.  
  310. const eUSCI_UART_Config config2 =
  311. {
  312. EUSCI_A_UART_CLOCKSOURCE_SMCLK, //SMCLK Clock Source
  313. 19, //BRDIV = 19
  314. 9, //UCxBRF = 8
  315. 85, //UCxBRS = 0
  316. EUSCI_A_UART_NO_PARITY, //No Parity
  317. EUSCI_A_UART_LSB_FIRST, //MSB First
  318. EUSCI_A_UART_ONE_STOP_BIT, //One stop bit
  319. EUSCI_A_UART_MODE, //UART mode
  320. EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION //Oversampling
  321. };
  322.  
  323. // Configure GPIO pins for UART. RX: P1.2, TX:P1.3.
  324. GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2|GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
  325.  
  326. UART_initModule(EUSCI_A2_BASE, &config2);
  327. UART_enableModule(EUSCI_A2_BASE); // Initialize eUSCI
  328.  
  329. //EUSCI_A2->IFG &= ~EUSCI_A_IFG_RXIFG; //EUSCI_A_IFG_RXIFG=1 Clear eUSCI RX interrupt flag
  330. UART_clearInterruptFlag(EUSCI_A2_BASE,~EUSCI_A_IFG_RXIFG);
  331.  
  332. //EUSCI_A2->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A2 RX interrupt
  333. UART_enableInterrupt(EUSCI_A2_BASE,EUSCI_A_IE_RXIE);
  334.  
  335. //see website fore more explanation on NVIC: https://www.keil.com/pack/doc/CMSIS/Core/html/group__NVIC__gr.html#ga5bb7f43ad92937c039dee3d36c3c2798
  336. NVIC_EnableIRQ ( EUSCIA2_IRQn ); //for cortex-M based device
  337. NVIC_SetPriority ( EUSCIA2_IRQn, 16 );//for cortex-M based device
  338. }
  339.  
  340. void EUSCIA2_IRQHandler (void)
  341. {
  342. uint8_t Mask = 0x7f;
  343. //Bluetooth transmits a packet that can be set to 9 bits that is read LSB first.
  344. //check to see if setting UART to LSB manipulates the Data to become MSB or manipulation is required
  345. //Check to see the default HC-06 packet size setting packets vary from 5-9 bits and register is 8 bits
  346. // UART_clearInterruptFlag(EUSCI_A2_BASE,~EUSCI_A_IFG_RXIFG);
  347.  
  348. if (EUSCI_A2->IFG & EUSCI_A_IFG_RXIFG)
  349. {
  350.  
  351. Temp = UART_receiveData(EUSCI_A2_BASE);
  352. BlueTooth = (Temp & Mask);
  353. //BlueTooth = EUSCI_A2->RXBUF;
  354. UART_clearInterruptFlag(EUSCI_A2_BASE,~EUSCI_A_IFG_RXIFG);
  355.  
  356. }
  357. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement