Robot
The embedded systems for UTRA's autonomous humanoid soccer-playing robot
freertos.cpp
1 
49 /* Includes ------------------------------------------------------------------*/
50 #include "FreeRTOS.h"
51 #include "task.h"
52 #include "cmsis_os.h"
53 
54 /* USER CODE BEGIN Includes */
66 #include <stdint.h>
67 #include <stdbool.h>
68 #include <math.h>
69 #include "Notification.h"
70 #include "SystemConf.h"
71 #include "usart.h"
72 #include "gpio.h"
73 #include "i2c.h"
74 #include "MPU6050.h"
75 #include "MPUFilter.h"
76 #include "UART_Handler.h"
77 #include "DynamixelProtocolV1.h"
78 #include "Communication.h"
79 #include "rx_helper.h"
80 #include "tx_helper.h"
81 /* USER CODE END Includes */
82 
83 /* Variables -----------------------------------------------------------------*/
84 osThreadId defaultTaskHandle;
85 uint32_t defaultTaskBuffer[ 128 ];
86 osStaticThreadDef_t defaultTaskControlBlock;
87 osThreadId UART1TaskHandle;
88 uint32_t UART1TaskBuffer[ 128 ];
89 osStaticThreadDef_t UART1TaskControlBlock;
90 osThreadId UART2TaskHandle;
91 uint32_t UART2TaskBuffer[ 128 ];
92 osStaticThreadDef_t UART2TaskControlBlock;
93 osThreadId UART3TaskHandle;
94 uint32_t UART3TaskBuffer[ 128 ];
95 osStaticThreadDef_t UART3TaskControlBlock;
96 osThreadId UART4TaskHandle;
97 uint32_t UART4TaskBuffer[ 128 ];
98 osStaticThreadDef_t UART4TaskControlBlock;
99 osThreadId UART6TaskHandle;
100 uint32_t UART6TaskBuffer[ 128 ];
101 osStaticThreadDef_t UART6TaskControlBlock;
102 osThreadId IMUTaskHandle;
103 uint32_t IMUTaskBuffer[ 128 ];
104 osStaticThreadDef_t IMUTaskControlBlock;
105 osThreadId CommandTaskHandle;
106 uint32_t CommandTaskBuffer[ 512 ];
107 osStaticThreadDef_t CommandTaskControlBlock;
108 osThreadId RxTaskHandle;
109 uint32_t RxTaskBuffer[ 512 ];
110 osStaticThreadDef_t RxTaskControlBlock;
111 osThreadId TxTaskHandle;
112 uint32_t TxTaskBuffer[ 512 ];
113 osStaticThreadDef_t TxTaskControlBlock;
114 osMessageQId UART1_reqHandle;
115 uint8_t UART1_reqBuffer[ 16 * sizeof( UARTcmd_t ) ];
116 osStaticMessageQDef_t UART1_reqControlBlock;
117 osMessageQId UART2_reqHandle;
118 uint8_t UART2_reqBuffer[ 16 * sizeof( UARTcmd_t ) ];
119 osStaticMessageQDef_t UART2_reqControlBlock;
120 osMessageQId UART3_reqHandle;
121 uint8_t UART3_reqBuffer[ 16 * sizeof( UARTcmd_t ) ];
122 osStaticMessageQDef_t UART3_reqControlBlock;
123 osMessageQId UART4_reqHandle;
124 uint8_t UART4_reqBuffer[ 16 * sizeof( UARTcmd_t ) ];
125 osStaticMessageQDef_t UART4_reqControlBlock;
126 osMessageQId UART6_reqHandle;
127 uint8_t UART6_reqBuffer[ 16 * sizeof( UARTcmd_t ) ];
128 osStaticMessageQDef_t UART6_reqControlBlock;
129 osMessageQId TXQueueHandle;
130 uint8_t TXQueueBuffer[ 32 * sizeof( TXData_t ) ];
131 osStaticMessageQDef_t TXQueueControlBlock;
132 osMutexId PCUARTHandle;
133 osStaticMutexDef_t PCUARTControlBlock;
134 
135 /* USER CODE BEGIN Variables */
136 enum motorNames {MOTOR1, MOTOR2, MOTOR3, MOTOR4, MOTOR5,
137  MOTOR6, MOTOR7, MOTOR8, MOTOR9, MOTOR10,
138  MOTOR11, MOTOR12, MOTOR13, MOTOR14, MOTOR15,
139  MOTOR16, MOTOR17, MOTOR18
140 };
141 
142 Dynamixel_HandleTypeDef Motor1, Motor2, Motor3 ,Motor4, Motor5,
143  Motor6, Motor7, Motor8, Motor9, Motor10,
144  Motor11, Motor12, Motor13, Motor14, Motor15,
145  Motor16, Motor17, Motor18;
146 
147 IMUnamespace::MPU6050 IMUdata (1, &hi2c1);
148 
149 bool setupIsDone = false;
150 static volatile uint32_t error;
151 /* USER CODE END Variables */
152 
153 /* Function prototypes -------------------------------------------------------*/
154 void StartDefaultTask(void const * argument);
155 extern void StartUART1Task(void const * argument);
156 extern void StartUART2Task(void const * argument);
157 extern void StartUART3Task(void const * argument);
158 extern void StartUART4Task(void const * argument);
159 extern void StartUART6Task(void const * argument);
160 extern void StartIMUTask(void const * argument);
161 extern void StartCommandTask(void const * argument);
162 extern void StartRxTask(void const * argument);
163 extern void StartTxTask(void const * argument);
164 
165 void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
166 
167 /* USER CODE BEGIN FunctionPrototypes */
168 // For vApplicationGetIdleTaskMemory
169 #ifdef __cplusplus
170 extern "C" {
171 #endif
172 /* USER CODE END FunctionPrototypes */
173 
174 /* GetIdleTaskMemory prototype (linked to static allocation support) */
175 void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
176 
177 /* Hook prototypes */
178 
179 /* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
180 // For vApplicationGetIdleTaskMemory
181 #ifdef __cplusplus
182 }
183 #endif
184 
185 static StaticTask_t xIdleTaskTCBBuffer;
186 static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
187 
188 void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
189 {
190  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
191  *ppxIdleTaskStackBuffer = &xIdleStack[0];
192  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
193  /* place for user code */
194 }
195 /* USER CODE END GET_IDLE_TASK_MEMORY */
196 
197 /* Init FreeRTOS */
198 
199 void MX_FREERTOS_Init(void) {
200  /* USER CODE BEGIN Init */
201 
202  /* USER CODE END Init */
203 
204  /* Create the mutex(es) */
205  /* definition and creation of PCUART */
206  osMutexStaticDef(PCUART, &PCUARTControlBlock);
207  PCUARTHandle = osMutexCreate(osMutex(PCUART));
208 
209  /* USER CODE BEGIN RTOS_MUTEX */
210  /* add mutexes, ... */
211  /* USER CODE END RTOS_MUTEX */
212 
213  /* USER CODE BEGIN RTOS_SEMAPHORES */
214  /* add semaphores, ... */
215  /* USER CODE END RTOS_SEMAPHORES */
216 
217  /* USER CODE BEGIN RTOS_TIMERS */
218  /* start timers, add new ones, ... */
219  /* USER CODE END RTOS_TIMERS */
220 
221  /* Create the thread(s) */
222  /* definition and creation of defaultTask */
223  osThreadStaticDef(defaultTask, StartDefaultTask, osPriorityIdle, 0, 128, defaultTaskBuffer, &defaultTaskControlBlock);
224  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
225 
226  /* definition and creation of UART1Task */
227  osThreadStaticDef(UART1Task, StartUART1Task, osPriorityNormal, 0, 128, UART1TaskBuffer, &UART1TaskControlBlock);
228  UART1TaskHandle = osThreadCreate(osThread(UART1Task), NULL);
229 
230  /* definition and creation of UART2Task */
231  osThreadStaticDef(UART2Task, StartUART2Task, osPriorityNormal, 0, 128, UART2TaskBuffer, &UART2TaskControlBlock);
232  UART2TaskHandle = osThreadCreate(osThread(UART2Task), NULL);
233 
234  /* definition and creation of UART3Task */
235  osThreadStaticDef(UART3Task, StartUART3Task, osPriorityNormal, 0, 128, UART3TaskBuffer, &UART3TaskControlBlock);
236  UART3TaskHandle = osThreadCreate(osThread(UART3Task), NULL);
237 
238  /* definition and creation of UART4Task */
239  osThreadStaticDef(UART4Task, StartUART4Task, osPriorityNormal, 0, 128, UART4TaskBuffer, &UART4TaskControlBlock);
240  UART4TaskHandle = osThreadCreate(osThread(UART4Task), NULL);
241 
242  /* definition and creation of UART6Task */
243  osThreadStaticDef(UART6Task, StartUART6Task, osPriorityNormal, 0, 128, UART6TaskBuffer, &UART6TaskControlBlock);
244  UART6TaskHandle = osThreadCreate(osThread(UART6Task), NULL);
245 
246  /* definition and creation of IMUTask */
247  osThreadStaticDef(IMUTask, StartIMUTask, osPriorityNormal, 0, 128, IMUTaskBuffer, &IMUTaskControlBlock);
248  IMUTaskHandle = osThreadCreate(osThread(IMUTask), NULL);
249 
250  /* definition and creation of CommandTask */
251  osThreadStaticDef(CommandTask, StartCommandTask, osPriorityBelowNormal, 0, 512, CommandTaskBuffer, &CommandTaskControlBlock);
252  CommandTaskHandle = osThreadCreate(osThread(CommandTask), NULL);
253 
254  /* definition and creation of RxTask */
255  osThreadStaticDef(RxTask, StartRxTask, osPriorityRealtime, 0, 512, RxTaskBuffer, &RxTaskControlBlock);
256  RxTaskHandle = osThreadCreate(osThread(RxTask), NULL);
257 
258  /* definition and creation of TxTask */
259  osThreadStaticDef(TxTask, StartTxTask, osPriorityHigh, 0, 512, TxTaskBuffer, &TxTaskControlBlock);
260  TxTaskHandle = osThreadCreate(osThread(TxTask), NULL);
261 
262  /* USER CODE BEGIN RTOS_THREADS */
263  /* add threads, ... */
264  /* USER CODE END RTOS_THREADS */
265 
266  /* Create the queue(s) */
267  /* definition and creation of UART1_req */
268  osMessageQStaticDef(UART1_req, 16, UARTcmd_t, UART1_reqBuffer, &UART1_reqControlBlock);
269  UART1_reqHandle = osMessageCreate(osMessageQ(UART1_req), NULL);
270 
271  /* definition and creation of UART2_req */
272  osMessageQStaticDef(UART2_req, 16, UARTcmd_t, UART2_reqBuffer, &UART2_reqControlBlock);
273  UART2_reqHandle = osMessageCreate(osMessageQ(UART2_req), NULL);
274 
275  /* definition and creation of UART3_req */
276  osMessageQStaticDef(UART3_req, 16, UARTcmd_t, UART3_reqBuffer, &UART3_reqControlBlock);
277  UART3_reqHandle = osMessageCreate(osMessageQ(UART3_req), NULL);
278 
279  /* definition and creation of UART4_req */
280  osMessageQStaticDef(UART4_req, 16, UARTcmd_t, UART4_reqBuffer, &UART4_reqControlBlock);
281  UART4_reqHandle = osMessageCreate(osMessageQ(UART4_req), NULL);
282 
283  /* definition and creation of UART6_req */
284  osMessageQStaticDef(UART6_req, 16, UARTcmd_t, UART6_reqBuffer, &UART6_reqControlBlock);
285  UART6_reqHandle = osMessageCreate(osMessageQ(UART6_req), NULL);
286 
287  /* definition and creation of TXQueue */
288  osMessageQStaticDef(TXQueue, 32, TXData_t, TXQueueBuffer, &TXQueueControlBlock);
289  TXQueueHandle = osMessageCreate(osMessageQ(TXQueue), NULL);
290 
291  /* USER CODE BEGIN RTOS_QUEUES */
292  /* add queues, ... */
293  /* USER CODE END RTOS_QUEUES */
294 }
295 
296 /* StartDefaultTask function */
297 void StartDefaultTask(void const * argument)
298 {
299 
300  /* USER CODE BEGIN StartDefaultTask */
301  /* Infinite loop */
302  for(;;)
303  {
304  osDelay(1);
305  }
306  /* USER CODE END StartDefaultTask */
307 }
308 
309 /* USER CODE BEGIN Application */
328 void StartCommandTask(void const * argument)
329 {
330  Dynamixel_SetIOType(IO_POLL); // Configure IO
331 
332  Dynamixel_Init(&Motor12, 12, &huart6, GPIOC, GPIO_PIN_8, MX28TYPE);
333  Dynamixel_Init(&Motor11, 11, &huart6, GPIOC, GPIO_PIN_8, MX28TYPE);
334  Dynamixel_Init(&Motor10, 10, &huart6, GPIOC, GPIO_PIN_8, MX28TYPE);
335  Dynamixel_Init(&Motor9, 9, &huart1, GPIOA, GPIO_PIN_8, MX28TYPE);
336  Dynamixel_Init(&Motor8, 8, &huart1, GPIOA, GPIO_PIN_8, MX28TYPE);
337  Dynamixel_Init(&Motor7, 7, &huart1, GPIOA, GPIO_PIN_8, MX28TYPE);
338  Dynamixel_Init(&Motor6, 6, &huart4, GPIOC, GPIO_PIN_3, MX28TYPE);
339  Dynamixel_Init(&Motor5, 5, &huart4, GPIOC, GPIO_PIN_3, MX28TYPE);
340  Dynamixel_Init(&Motor4, 4, &huart4, GPIOC, GPIO_PIN_3, MX28TYPE);
341  Dynamixel_Init(&Motor3, 3, &huart2, GPIOA, GPIO_PIN_4, MX28TYPE);
342  Dynamixel_Init(&Motor2, 2, &huart2, GPIOA, GPIO_PIN_4, MX28TYPE);
343  Dynamixel_Init(&Motor1, 1, &huart2, GPIOA, GPIO_PIN_4, MX28TYPE);
344  Dynamixel_Init(&Motor13, 13, &huart3, GPIOB, GPIO_PIN_2, AX12ATYPE);
345  Dynamixel_Init(&Motor14, 14, &huart3, GPIOB, GPIO_PIN_2, AX12ATYPE);
346  Dynamixel_Init(&Motor15, 15, &huart3, GPIOB, GPIO_PIN_2, AX12ATYPE);
347  Dynamixel_Init(&Motor16, 16, &huart3, GPIOB, GPIO_PIN_2, AX12ATYPE);
348  Dynamixel_Init(&Motor17, 17, &huart3, GPIOB, GPIO_PIN_2, AX12ATYPE);
349  Dynamixel_Init(&Motor18, 18, &huart3, GPIOB, GPIO_PIN_2, AX12ATYPE);
350 
351 
352  Dynamixel_HandleTypeDef* arrDynamixel[18] = {&Motor1,&Motor2,&Motor3,&Motor4,
353  &Motor5,&Motor6,&Motor7,&Motor8,&Motor9,&Motor10,&Motor11,&Motor12,
354  &Motor13,&Motor14,&Motor15,&Motor16,&Motor17,&Motor18};
355 
356  UARTcmd_t Motorcmd[18];
357  for(uint8_t i = MOTOR1; i <= MOTOR18; i++) {
358  // Configure motor to return status packets only for read commands
359  Dynamixel_SetStatusReturnLevel(arrDynamixel[i], 1);
360 
361  // Configure motor to return status packets with minimal latency
362  Dynamixel_SetReturnDelayTime(arrDynamixel[i], 100);
363 
364  // Enable motor torque
365  Dynamixel_TorqueEnable(arrDynamixel[i], 1);
366 
367  // Settings for torque near goal position, and acceptable error (AX12A only)
368  if(arrDynamixel[i]->_motorType == AX12ATYPE){
369  AX12A_SetComplianceSlope(arrDynamixel[i], 5); // 4 vibrates; 7 is too loose
370  AX12A_SetComplianceMargin(arrDynamixel[i], 1);
371  }
372 
373  (Motorcmd[i]).motorHandle = arrDynamixel[i];
374  (Motorcmd[i]).type = cmdWritePosition;
375  }
376 
377  (Motorcmd[MOTOR1]).qHandle = UART2_reqHandle;
378  (Motorcmd[MOTOR2]).qHandle = UART2_reqHandle;
379  (Motorcmd[MOTOR3]).qHandle = UART2_reqHandle;
380  (Motorcmd[MOTOR4]).qHandle = UART4_reqHandle;
381  (Motorcmd[MOTOR5]).qHandle = UART4_reqHandle;
382  (Motorcmd[MOTOR6]).qHandle = UART4_reqHandle;
383  (Motorcmd[MOTOR7]).qHandle = UART1_reqHandle;
384  (Motorcmd[MOTOR8]).qHandle = UART1_reqHandle;
385  (Motorcmd[MOTOR9]).qHandle = UART1_reqHandle;
386  (Motorcmd[MOTOR10]).qHandle = UART6_reqHandle;
387  (Motorcmd[MOTOR11]).qHandle = UART6_reqHandle;
388  (Motorcmd[MOTOR12]).qHandle = UART6_reqHandle;
389  (Motorcmd[MOTOR13]).qHandle = UART3_reqHandle;
390  (Motorcmd[MOTOR14]).qHandle = UART3_reqHandle;
391  (Motorcmd[MOTOR15]).qHandle = UART3_reqHandle;
392  (Motorcmd[MOTOR16]).qHandle = UART3_reqHandle;
393  (Motorcmd[MOTOR17]).qHandle = UART3_reqHandle;
394  (Motorcmd[MOTOR18]).qHandle = UART3_reqHandle;
395 
396  Dynamixel_SetIOType(IO_DMA); // Configure IO to use DMA
397 
398  IMUdata.init(6);// 5 Hz bandwidth
399 
400  // Set setupIsDone and unblock the higher-priority tasks
401  setupIsDone = true;
402  xTaskNotify(RxTaskHandle, 1UL, eNoAction);
403  xTaskNotify(TxTaskHandle, 1UL, eNoAction);
404  xTaskNotify(UART1TaskHandle, 1UL, eNoAction);
405  xTaskNotify(UART2TaskHandle, 1UL, eNoAction);
406  xTaskNotify(UART3TaskHandle, 1UL, eNoAction);
407  xTaskNotify(UART4TaskHandle, 1UL, eNoAction);
408  xTaskNotify(UART6TaskHandle, 1UL, eNoAction);
409  xTaskNotify(IMUTaskHandle, 1UL, eNoAction);
410 
411  uint32_t numIterations = 0;
412  uint8_t i;
413  float positions[18];
414  while(1){
415  xTaskNotifyWait(0, NOTIFIED_FROM_TASK, NULL, portMAX_DELAY);
416 
417  // Convert raw bytes from robotGoal received from PC into floats
418  for(uint8_t i = 0; i < 18; i++){
419  uint8_t* ptr = (uint8_t*)&positions[i];
420  for(uint8_t j = 0; j < 4; j++){
421  *ptr = robotGoal.msg[i * 4 + j];
422  ptr++;
423  }
424  }
425 
426  if(numIterations % 100 == 0){
427  // Every 100 iterations, assert torque enable
428  for(uint8_t i = MOTOR1; i <= MOTOR18; i++){
429  Motorcmd[i].type = cmdWriteTorque;
430  Motorcmd[i].value = 1; // Enable
431  xQueueSend(Motorcmd[i].qHandle, &Motorcmd[i], 0);
432  }
433  }
434 
435  // Send each goal position to the queue, where the UART handler
436  // thread that's listening will receive it and send it to the motor
437  for(i = MOTOR1; i <= MOTOR18; i++){ // NB: i begins at 0 (i.e. Motor1 corresponds to i = 0)
438  switch(i){
439  case MOTOR1: Motorcmd[i].value = positions[i]*180/M_PI + 150;
440  break;
441  case MOTOR2: Motorcmd[i].value = positions[i]*180/M_PI + 150;
442  break;
443  case MOTOR3: Motorcmd[i].value = positions[i]*180/M_PI + 150;
444  break;
445  case MOTOR4: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
446  break;
447  case MOTOR5: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
448  break;
449  case MOTOR6: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
450  break;
451  case MOTOR7: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
452  break;
453  case MOTOR8: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
454  break;
455  case MOTOR9: Motorcmd[i].value = positions[i]*180/M_PI + 150;
456  break;
457  case MOTOR10: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
458  break;
459  case MOTOR11: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150;
460  break;
461  case MOTOR12: Motorcmd[i].value = positions[i]*180/M_PI + 150;
462  break;
463  case MOTOR13: Motorcmd[i].value = positions[i]*180/M_PI + 150; // Left shoulder
464  break;
465  case MOTOR14: Motorcmd[i].value = positions[i]*180/M_PI + 60; // Left elbow
466  break;
467  case MOTOR15: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150; // Right shoulder
468  break;
469  case MOTOR16: Motorcmd[i].value = -1*positions[i]*180/M_PI + 240; // Right elbow
470  break;
471  case MOTOR17: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150; // Neck pan
472  break;
473  case MOTOR18: Motorcmd[i].value = -1*positions[i]*180/M_PI + 150; // Neck tilt
474  break;
475  default:
476  break;
477  }
478 
479  Motorcmd[i].type = cmdWritePosition;
480  xQueueSend(Motorcmd[i].qHandle, &Motorcmd[i], 0);
481 
482  // Only read from legs
483  if(i <= MOTOR12){
484  Motorcmd[i].type = cmdReadPosition;
485  xQueueSend(Motorcmd[i].qHandle, &Motorcmd[i], 0);
486  }
487  }
488 
489  numIterations++;
490  }
491 }
492 
506 void StartUART1Task(void const * argument)
507 {
508  // Here, we use task notifications to block this task from running until a notification
509  // is received. This allows one-time setup to complete in a low-priority task.
510  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
511 
512  UARTcmd_t cmdMessage;
513  TXData_t dataToSend;
514  dataToSend.eDataType = eMotorData;
515 
516  for(;;)
517  {
518  while(xQueueReceive(UART1_reqHandle, &cmdMessage, portMAX_DELAY) != pdTRUE);
519  UART_ProcessEvent(&cmdMessage, &dataToSend);
520  }
521 }
522 
536 void StartUART2Task(void const * argument)
537 {
538  // Here, we use task notifications to block this task from running until a notification
539  // is received. This allows one-time setup to complete in a low-priority task.
540  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
541 
542  UARTcmd_t cmdMessage;
543  TXData_t dataToSend;
544  dataToSend.eDataType = eMotorData;
545 
546  for(;;)
547  {
548  while(xQueueReceive(UART2_reqHandle, &cmdMessage, portMAX_DELAY) != pdTRUE);
549  UART_ProcessEvent(&cmdMessage, &dataToSend);
550  }
551 }
552 
566 void StartUART3Task(void const * argument)
567 {
568  // Here, we use task notifications to block this task from running until a notification
569  // is received. This allows one-time setup to complete in a low-priority task.
570  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
571 
572  UARTcmd_t cmdMessage;
573  TXData_t dataToSend;
574  dataToSend.eDataType = eMotorData;
575 
576  for(;;)
577  {
578  while(xQueueReceive(UART3_reqHandle, &cmdMessage, portMAX_DELAY) != pdTRUE);
579  UART_ProcessEvent(&cmdMessage, &dataToSend);
580  }
581 }
582 
596 void StartUART4Task(void const * argument)
597 {
598  // Here, we use task notifications to block this task from running until a notification
599  // is received. This allows one-time setup to complete in a low-priority task.
600  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
601 
602  UARTcmd_t cmdMessage;
603  TXData_t dataToSend;
604  dataToSend.eDataType = eMotorData;
605 
606  for(;;)
607  {
608  while(xQueueReceive(UART4_reqHandle, &cmdMessage, portMAX_DELAY) != pdTRUE);
609  UART_ProcessEvent(&cmdMessage, &dataToSend);
610  }
611 }
612 
626 void StartUART6Task(void const * argument)
627 {
628  // Here, we use task notifications to block this task from running until a notification
629  // is received. This allows one-time setup to complete in a low-priority task.
630  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
631 
632  /* Infinite loop */
633  UARTcmd_t cmdMessage;
634  TXData_t dataToSend;
635  dataToSend.eDataType = eMotorData;
636 
637  for(;;)
638  {
639  while(xQueueReceive(UART6_reqHandle, &cmdMessage, portMAX_DELAY) != pdTRUE);
640  UART_ProcessEvent(&cmdMessage, &dataToSend);
641  }
642 }
643 
655 void StartIMUTask(void const * argument)
656 {
657  /* USER CODE BEGIN StartIMUTask */
658  // Here, we use task notifications to block this task from running until a notification
659  // is received. This allows one-time setup to complete in a low-priority task.
660  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
661 
662  TXData_t dataToSend;
663  dataToSend.eDataType = eIMUData;
664 
665  TickType_t xLastWakeTime;
666  xLastWakeTime = xTaskGetTickCount();
667 
668  const TickType_t IMU_CYCLE_TIME_MS = 2;
669  uint8_t i = 0;
671 
673 
674  for(;;)
675  {
676  // Service this thread every 2 ms for a 500 Hz sample rate
677  vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(IMU_CYCLE_TIME_MS));
678 
679  IMUdata.Read_Accelerometer_Withoffset_IT(); // Also updates pitch and roll
680 
681  // Gyroscope data is much more volatile/sensitive to changes than
682  // acceleration data. To compensate, we feed in samples to the filter
683  // slower. Good DSP practise? Not sure. To compensate for the high
684  // delays, we also use a filter with fewer taps than the acceleration
685  // filters. Ideally: we would sample faster to reduce aliasing, then
686  // use a filter with a smaller cutoff frequency. However, the filter
687  // designer we are using does not allow us to generate such filters in
688  // the free version, so this is the best we can do unless we use other
689  // software.
690  if (i % 16 == 0) {
692 // TODO: convert the MPUFilter_FilterAngularVelocity function
693  //MPUFilter_FilterAngularVelocity();
694  }
695  i++;
696  IMUdata.Fill_Struct(&IMUStruct);
697  dataToSend.pData = &IMUStruct;
698  xQueueSend(TXQueueHandle, &dataToSend, 0);
699  }
700  /* USER CODE END StartIMUTask */
701 }
702 
713 void StartRxTask(void const * argument)
714 {
715  initializeVars();
716  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
718 
719  for (;;) {
723  }
724 }
725 
738 void StartTxTask(void const * argument)
739 {
740  xTaskNotifyWait(UINT32_MAX, UINT32_MAX, NULL, portMAX_DELAY);
742 
743  for(;;)
744  {
748  }
749 }
750 
772 void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
773 {
774  // This callback runs after the interrupt data transfer from the sensor to the mcu is finished
775  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
776  xTaskNotifyFromISR(IMUTaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
777  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
778 }
779 
793 void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart){
794  if(setupIsDone){
795  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
796  if(huart == &huart5){
797  xTaskNotifyFromISR(TxTaskHandle, NOTIFIED_FROM_TX_ISR, eSetBits, &xHigherPriorityTaskWoken);
798  }
799  if(huart == &huart1){
800  xTaskNotifyFromISR(UART1TaskHandle, NOTIFIED_FROM_TX_ISR, eSetBits, &xHigherPriorityTaskWoken);
801  }
802  else if(huart == &huart2){
803  xTaskNotifyFromISR(UART2TaskHandle, NOTIFIED_FROM_TX_ISR, eSetBits, &xHigherPriorityTaskWoken);
804  }
805  else if(huart == &huart3){
806  xTaskNotifyFromISR(UART3TaskHandle, NOTIFIED_FROM_TX_ISR, eSetBits, &xHigherPriorityTaskWoken);
807  }
808  else if(huart == &huart4){
809  xTaskNotifyFromISR(UART4TaskHandle, NOTIFIED_FROM_TX_ISR, eSetBits, &xHigherPriorityTaskWoken);
810  }
811  else if(huart == &huart6){
812  xTaskNotifyFromISR(UART6TaskHandle, NOTIFIED_FROM_TX_ISR, eSetBits, &xHigherPriorityTaskWoken);
813  }
814  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
815  }
816 }
817 
831 void HAL_UART_RxCpltCallback(UART_HandleTypeDef * huart) {
832  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
833  if (huart == &huart5) {
834  xTaskNotifyFromISR(RxTaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
835  }
836  if(huart == &huart1){
837  xTaskNotifyFromISR(UART1TaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
838  }
839  else if(huart == &huart2){
840  xTaskNotifyFromISR(UART2TaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
841  }
842  else if(huart == &huart3){
843  xTaskNotifyFromISR(UART3TaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
844  }
845  else if(huart == &huart4){
846  xTaskNotifyFromISR(UART4TaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
847  }
848  else if(huart == &huart6){
849  xTaskNotifyFromISR(UART6TaskHandle, NOTIFIED_FROM_RX_ISR, eSetBits, &xHigherPriorityTaskWoken);
850  }
851  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
852 }
853 
866 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
867 {
868  error = HAL_UART_GetError(huart);
869 }
870 /* USER CODE END Application */
871 
872 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
void AX12A_SetComplianceMargin(Dynamixel_HandleTypeDef *hdynamixel, uint8_t complianceMargin)
Sets both the CW and CCW compliance margin.
Definition: AX12A.c:260
This file defines resources used throughout various parts of the system that engage in non-blocking I...
void waitForNotificationRX(void)
Waits until notified from ISR.
Definition: rx_helper.cpp:95
float value
Definition: UART_Handler.h:60
void AX12A_SetComplianceSlope(Dynamixel_HandleTypeDef *hdynamixel, uint8_t complianceSlope)
Sets both the CW and CCW compliance slope.
Definition: AX12A.c:243
Organizes all the information relevant to a motor.
void Fill_Struct(IMUStruct *myStruct)
Fills an IMUStruct.
Definition: MPU6050.cpp:302
This is the data structure copied into the sensor queue, and read by the thread that sends data to th...
Definition: UART_Handler.h:103
void initializeVars(void)
Initializes the private variables for StartRxTask.
Definition: rx_helper.cpp:65
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
This function is called whenever a transmission from a UART module is completed. For this program...
Definition: freertos.cpp:793
void Read_Gyroscope_Withoffset_IT()
Reads the gyroscope with interrupts and offsets.
Definition: MPU6050.cpp:232
osMessageQId TXQueueHandle
Definition: freertos.cpp:129
Header for the helper file used to aid StartTxTask() in freertos.cpp.
void StartTxTask(void const *argument)
This function is executed in the context of the TxTask thread. This thread is blocked until all senso...
Definition: freertos.cpp:738
The data structure which represents the data of the IMU, which is sent in queues between tasks...
Definition: UART_Handler.h:83
void shiftNotificationMask(void)
Shifts bits of NOTIFICATION_MASK.
Definition: tx_helper.cpp:59
void transmitStatusFromPC(void)
Makes calls to the UART module responsible for PC communication atomic.
Definition: tx_helper.cpp:123
void * pData
Definition: UART_Handler.h:105
RobotGoal robotGoal
Definition: Communication.c:30
void Dynamixel_Init(Dynamixel_HandleTypeDef *hdynamixel, uint8_t ID, UART_HandleTypeDef *UART_Handle, GPIO_TypeDef *DataDirPort, uint16_t DataDirPinNum, enum motorTypes_e motorType)
Initializes a motor handle.
void initiateDMATransfer(void)
Initiates DMA receive transfer using DMA.
Definition: rx_helper.cpp:82
void init(uint8_t lpf)
This function is used to initialize all aspects of the IMU which require I/O.
Definition: MPU6050.cpp:209
Header code for IMU filtering.
char msg[80]
Definition: robotGoal.h:27
void Dynamixel_SetReturnDelayTime(Dynamixel_HandleTypeDef *hdynamixel, uint16_t microSec)
Sets the time, in microseconds, that the motor should wait before returning a status packet...
void StartCommandTask(void const *argument)
This function is executed in the context of the commandTask thread. It initializes all data structure...
Definition: freertos.cpp:328
void StartUART3Task(void const *argument)
This function is executed in the context of the UART3_ thread. It processes all commands for the moto...
Definition: freertos.cpp:566
#define NOTIFIED_FROM_TX_ISR
Definition: Notification.h:35
void updateStatusToPC(void)
Makes calls to the UART module responsible for PC communication atomic.
Definition: rx_helper.cpp:112
void StartUART2Task(void const *argument)
This function is executed in the context of the UART2_ thread. It processes all commands for the moto...
Definition: freertos.cpp:536
#define NOTIFIED_FROM_RX_ISR
Definition: Notification.h:36
void MPUFilter_InitAllFilters()
Initialize acceleration and angular velocity FIR filters for IMU data.
Definition: MPUFilter.cpp:173
void StartIMUTask(void const *argument)
This function is executed in the context of the IMUTask thread. During each control cycle...
Definition: freertos.cpp:655
void StartRxTask(void const *argument)
This function is executed in the context of the RxTask thread. It initiates DMA-based receptions of R...
Definition: freertos.cpp:713
Header for top-level communication module.
void StartUART1Task(void const *argument)
This function is executed in the context of the UART1_ thread. It processes all commands for the moto...
Definition: freertos.cpp:506
void receiveDataBuffer(void)
Reads the received data buffer.
Definition: rx_helper.cpp:129
eUARTcmd_t type
Definition: UART_Handler.h:56
void Dynamixel_TorqueEnable(Dynamixel_HandleTypeDef *hdynamixel, uint8_t isEnabled)
Enables or disables torque for current motor.
void StartUART6Task(void const *argument)
This function is executed in the context of the UART6_ thread. It processes all commands for the moto...
Definition: freertos.cpp:626
void copySensorDataToSend(void)
Validates and copies sensor data to transmit.
Definition: tx_helper.cpp:72
Header file for the UART event processor, which is called whenever there are commands that need to be...
eTXData_t eDataType
Definition: UART_Handler.h:104
#define NOTIFIED_FROM_TASK
Definition: Notification.h:37
void StartUART4Task(void const *argument)
This function is executed in the context of the UART4_ thread. It processes all commands for the moto...
Definition: freertos.cpp:596
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
This function is called whenever an error is encountered in association with a UART module...
Definition: freertos.cpp:866
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
This function is called whenever a reception from a UART module is completed. For this program...
Definition: freertos.cpp:831
void Dynamixel_SetStatusReturnLevel(Dynamixel_HandleTypeDef *hdynamixel, uint8_t status_data)
Sets the conditions under which a status packet will be returned.
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
This function is called whenever a memory read from a I2C device is completed. For this program...
Definition: freertos.cpp:772
Header for the helper file used to aid StartRXTask() in freertos.cpp.
void UART_ProcessEvent(UARTcmd_t *cmdPtr, TXData_t *DataToSend)
The UART event processor calls the low-level libraries to execute reads and writes for motors...
Definition: UART_Handler.c:43
void Dynamixel_SetIOType(enum IO_FLAGS type)
Sets the I/O type used by the library.
Header code for the MPU6050 class.
void waitForNotificationTX(void)
Waits until notified from ISR.
Definition: tx_helper.cpp:139
Common header code for the AX12A library and MX28 library. It is generic in that any Dynamixel actuat...
The container type for motor commands. The control thread sends these to the various UART handlers th...
Definition: UART_Handler.h:55
void Read_Accelerometer_Withoffset_IT()
Reads the accelerometer with interrupts and offsets.
Definition: MPU6050.cpp:274