diff --git a/STM32F405RGTx/.settings/language.settings.xml b/STM32F405RGTx/.settings/language.settings.xml
new file mode 100644
index 0000000..3178ba2
--- /dev/null
+++ b/STM32F405RGTx/.settings/language.settings.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/STM32F405RGTx/.settings/stm32cubeide.project.prefs b/STM32F405RGTx/.settings/stm32cubeide.project.prefs
new file mode 100644
index 0000000..b52fae9
--- /dev/null
+++ b/STM32F405RGTx/.settings/stm32cubeide.project.prefs
@@ -0,0 +1,2 @@
+DC22A860405A8BF2F2C095E5B6529F12=A7382F0030CE3C7B1E2E6100CFC7BE85
+eclipse.preferences.version=1
diff --git a/STM32F405RGTx/Core/Inc/.lut 2.hpp.icloud b/STM32F405RGTx/Core/Inc/.lut 2.hpp.icloud
new file mode 100644
index 0000000..170ed11
Binary files /dev/null and b/STM32F405RGTx/Core/Inc/.lut 2.hpp.icloud differ
diff --git a/STM32F405RGTx/Core/Inc/accelerometer.hpp b/STM32F405RGTx/Core/Inc/accelerometer.hpp
new file mode 100644
index 0000000..e662936
--- /dev/null
+++ b/STM32F405RGTx/Core/Inc/accelerometer.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include "main.h"
+
+#define IMU_ADDR 0x19<<1 //| Use 8-bit address
+#define REG_CTRL_1 0x20 //| Control Register-1
+#define REG_CTRL_4 0x23 //| Control Register-4
+#define REG_X_L 0x28 //| X-Axis LSB
+#define REG_X_H 0x29 //| X-Axis MSB
+#define REG_Y_L 0x2A //| Y-Axis LSB
+#define REG_Y_H 0x2B //| Y-Axis MSB
+#define REG_Z_L 0x2C //| Z-Axis LSB
+#define REG_Z_H 0x2D //| Z-Axis MSB
+
+//Constants used to convert raw acceleration based on range
+#define ACC_RANGE_2G 16384
+#define ACC_RANGE_4G 8192
+#define ACC_RANGE_8G 4096
+#define ACC_RANGE_16G 2048
+
+//Control register 4 values to change acceleration range
+#define CTRL_REG_4_ACCL_RANGE_16G 0x30 // Full scale +/-16g
+#define CTRL_REG_4_ACCL_RANGE_8G 0x20 // Full scale +/-8g
+#define CTRL_REG_4_ACCL_RANGE_4G 0x10 // Full scale +/-4g
+#define CTRL_REG_4_ACCL_RANGE_2G 0x00 //Full scale = +/-2g
+
+//Selected acceleration range
+#define SELECTED_ACC_RANGE ACC_RANGE_2G
+#define SELECTED_CTRL_REG_4_ACCL_RANGE CTRL_REG_4_ACCL_RANGE_2G
+
+#define GRAVITATIONAL_CONSTANT 9.8
+
+enum axis{
+ x_axis,
+ y_axis,
+ z_axis};
+
+class Accelerometer{
+ public:
+ float getAcceleration(axis accelerationAxis);
+ float getSpeed(axis speedAxis);
+ float getPos(axis accelerationAxis);
+ float getTimeDiff();
+ uint8_t getRawAccelerationLow(axis accelerationAxis);
+ uint8_t getRawAccelerationHigh(axis accelerationAxis);
+ void update();
+ Accelerometer(I2C_HandleTypeDef *I2CConnection_);
+
+ private:
+ void convertRawAcceleration();
+ void readRawAcceleration();
+ void updatePos();
+ void updateSpeed();
+ void getTimeValues();
+
+ float ACC[3] = {0,0,0};
+ float POS[3] = {0,0,0};
+ float SPEED[3] = {0,0,0};
+
+ uint8_t RAW_ACC_L[3] = {0,0,0};
+ uint8_t RAW_ACC_H[3] = {0,0,0};
+
+ int PREVIOUS_TIME = 0;
+ int CURRENT_TIME = 0;
+ float TIME_DIFF = 0;
+
+ I2C_HandleTypeDef *I2CConnection;
+
+};
+
+
diff --git a/STM32F405RGTx/Core/Inc/accelerometer_thread.hpp b/STM32F405RGTx/Core/Inc/accelerometer_thread.hpp
new file mode 100644
index 0000000..d1a833f
--- /dev/null
+++ b/STM32F405RGTx/Core/Inc/accelerometer_thread.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "main.h"
+#include "accelerometer.hpp"
+
+class AccelerometerThread{
+ public:
+ static void initialize();
+ static void update();
+ static I2C_HandleTypeDef *I2CConncetion;
+ static Accelerometer accelerometer;
+ static osThreadId_t getThreadId();
+ static void stopMeasurements();
+ static void resumeMeasurements();
+ private:
+ static RTOSThread thread;
+};
+
diff --git a/STM32F405RGTx/Core/Inc/threads.hpp b/STM32F405RGTx/Core/Inc/threads.hpp
index 1a6753c..3bd8e46 100644
--- a/STM32F405RGTx/Core/Inc/threads.hpp
+++ b/STM32F405RGTx/Core/Inc/threads.hpp
@@ -7,11 +7,15 @@
#include "LED_thread.hpp"
#include "svpwm_thread.hpp"
#include "vhz_thread.hpp"
+#include "accelerometer_thread.hpp"
// Thread Periodicities (ms)
#define MEASUREMENTS_THREAD_PERIODICITY 100
#define MEASUREMENTS_THREAD_PRIORITY osPriorityRealtime7
+#define ACCELEROMETER_THREAD_PERIODICITY 100
+#define ACCELEROMETER_THREAD_PRIORITY osPriorityRealtime4
+
#define STATE_MACHINE_THREAD_PERIODICITY 150
#define STATE_MACHINE_THREAD_PRIORITY osPriorityRealtime6
diff --git a/STM32F405RGTx/Core/Src/accelerometer.cpp b/STM32F405RGTx/Core/Src/accelerometer.cpp
new file mode 100644
index 0000000..09d7d51
--- /dev/null
+++ b/STM32F405RGTx/Core/Src/accelerometer.cpp
@@ -0,0 +1,72 @@
+#include "accelerometer.hpp"
+
+Accelerometer::Accelerometer(I2C_HandleTypeDef *I2CConnection_){
+ I2CConnection = I2CConnection_;
+}
+float Acceleromter::getAcceleration(axis accelerationAxis){
+ return ACC[accelerationAxis];
+}
+float Acceleromter::getSpeed(axis speedAxis){
+ return SPEED[speedAxis];
+}
+float Acceleromter::getPos(axis positionAxis){
+ return POS[positionAxis];
+}
+float Acceleromter::getTimeDiff(){
+ return timeDiff;
+}
+uint8_t Acceleromter::getRawAccelerationLow(axis accelerationAxis){
+ return RAW_ACC_L[accelerationAxis];
+}
+uint8_t Acceleromter::getRawAccelerationHigh(axis accelerationAxis){
+ return RAW_ACC_H[accelerationAxis];
+}
+void Acceleromter::update(){
+ readRawAccleration();
+ convertRawAcceleration();
+ getTimeValues();
+ updatePos();
+ updateSpeed();
+ PREVIOUS_TIME = CURRENT_TIME;
+}
+
+
+void Acceleromter::convertRawAcceleration(){
+ for(int i =0 ; i<3; i++)
+ {
+
+ int16_t RAW_ACC = RAW_ACC_H[i];
+ RAW_ACC <<= 8;
+ RAW_ACC |= RAW_ACC_L[i];
+ ACC[i] = ((float)RAW_ACC / (float)SELECTED_ACC_RANGE)*GRAVITATIONAL_CONSTANT;
+ }
+}
+void Acceleromter::readRawAcceleration(){
+ // Get acceleration in X-AXIS
+ HAL_I2C_Mem_Read(&hi2c1, IMU_ADDR, REG_X_H, I2C_MEMADD_SIZE_8BIT, RAW_ACC_H[x_axis], 1, 1000);
+ HAL_I2C_Mem_Read(&hi2c1, IMU_ADDR, REG_X_L, I2C_MEMADD_SIZE_8BIT, RAW_ACC_L[x_axis], 1, 1000);
+
+
+ // Get acceleration in Y-AXIS
+ HAL_I2C_Mem_Read(&hi2c1, IMU_ADDR, REG_Y_H, I2C_MEMADD_SIZE_8BIT, RAW_ACC_H[y_axis], 1000);
+ HAL_I2C_Mem_Read(&hi2c1, IMU_ADDR, REG_Y_L, I2C_MEMADD_SIZE_8BIT, RAW_ACC_L[y_axis], 1, 1000);
+
+
+ // Get acceleration in Z-AXIS
+ HAL_I2C_Mem_Read(&hi2c1, IMU_ADDR, REG_Z_H, I2C_MEMADD_SIZE_8BIT, RAW_ACC_H[z_axis], 1, 1000);
+ HAL_I2C_Mem_Read(&hi2c1, IMU_ADDR, REG_Z_L, I2C_MEMADD_SIZE_8BIT, RAW_ACC_L[z_axis], 1, 1000);
+}
+void Acceleromter::updatePos(){
+ for(int i =0; i<3; i++){
+ POS[i] += SPEED[i]*TIME_DIFF+0.5*ACC[i]*TIME_DIFF*TIME_DIFF;
+ }
+}
+void Acceleromter::updateSpeed(){
+ for(int i =0; i<3; i++){
+ SPEED[i] += ACC[i]*TIME_DIFF;
+ }
+}
+void Acceleromter::getTimeValues(){
+ CURRENT_TIME = HAL_GetTick();
+ TIME_DIFF = ((float)CURRENT_TIME-(float)PREVIOUS_TIME)/1000;
+}
diff --git a/STM32F405RGTx/Core/Src/lut/.ADC_TO_TEMP_LUT 2.c.icloud b/STM32F405RGTx/Core/Src/lut/.ADC_TO_TEMP_LUT 2.c.icloud
new file mode 100644
index 0000000..002d9d8
Binary files /dev/null and b/STM32F405RGTx/Core/Src/lut/.ADC_TO_TEMP_LUT 2.c.icloud differ
diff --git a/STM32F405RGTx/Core/Src/main.c b/STM32F405RGTx/Core/Src/main.c
new file mode 100644
index 0000000..8715e68
--- /dev/null
+++ b/STM32F405RGTx/Core/Src/main.c
@@ -0,0 +1,832 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file : main.c
+ * @brief : Main program body
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2022 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "cmsis_os.h"
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN PTD */
+
+/* USER CODE END PTD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+ADC_HandleTypeDef hadc1;
+DMA_HandleTypeDef hdma_adc1;
+
+CAN_HandleTypeDef hcan1;
+
+I2C_HandleTypeDef hi2c1;
+DMA_HandleTypeDef hdma_i2c1_rx;
+DMA_HandleTypeDef hdma_i2c1_tx;
+
+SPI_HandleTypeDef hspi1;
+
+TIM_HandleTypeDef htim1;
+TIM_HandleTypeDef htim3;
+TIM_HandleTypeDef htim9;
+
+UART_HandleTypeDef huart4;
+
+/* Definitions for defaultTask */
+osThreadId_t defaultTaskHandle;
+const osThreadAttr_t defaultTask_attributes = {
+ .name = "defaultTask",
+ .stack_size = 128 * 4,
+ .priority = (osPriority_t) osPriorityNormal,
+};
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+void SystemClock_Config(void);
+static void MX_GPIO_Init(void);
+static void MX_TIM1_Init(void);
+static void MX_TIM9_Init(void);
+static void MX_CAN1_Init(void);
+static void MX_I2C1_Init(void);
+static void MX_SPI1_Init(void);
+static void MX_UART4_Init(void);
+static void MX_ADC1_Init(void);
+static void MX_DMA_Init(void);
+static void MX_TIM3_Init(void);
+void StartDefaultTask(void *argument);
+
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/**
+ * @brief The application entry point.
+ * @retval int
+ */
+int main(void)
+{
+ /* USER CODE BEGIN 1 */
+
+ /* USER CODE END 1 */
+
+ /* MCU Configuration--------------------------------------------------------*/
+
+ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
+ HAL_Init();
+
+ /* USER CODE BEGIN Init */
+
+ /* USER CODE END Init */
+
+ /* Configure the system clock */
+ SystemClock_Config();
+
+ /* USER CODE BEGIN SysInit */
+
+ /* USER CODE END SysInit */
+
+ /* Initialize all configured peripherals */
+ MX_GPIO_Init();
+ MX_TIM1_Init();
+ MX_TIM9_Init();
+ MX_CAN1_Init();
+ MX_I2C1_Init();
+ MX_SPI1_Init();
+ MX_UART4_Init();
+ MX_ADC1_Init();
+ MX_DMA_Init();
+ MX_TIM3_Init();
+ /* USER CODE BEGIN 2 */
+
+ /* USER CODE END 2 */
+
+ /* Init scheduler */
+ osKernelInitialize();
+
+ /* USER CODE BEGIN RTOS_MUTEX */
+ /* add mutexes, ... */
+ /* USER CODE END RTOS_MUTEX */
+
+ /* USER CODE BEGIN RTOS_SEMAPHORES */
+ /* add semaphores, ... */
+ /* USER CODE END RTOS_SEMAPHORES */
+
+ /* USER CODE BEGIN RTOS_TIMERS */
+ /* start timers, add new ones, ... */
+ /* USER CODE END RTOS_TIMERS */
+
+ /* USER CODE BEGIN RTOS_QUEUES */
+ /* add queues, ... */
+ /* USER CODE END RTOS_QUEUES */
+
+ /* Create the thread(s) */
+ /* creation of defaultTask */
+ defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
+
+ /* USER CODE BEGIN RTOS_THREADS */
+ /* add threads, ... */
+ /* USER CODE END RTOS_THREADS */
+
+ /* USER CODE BEGIN RTOS_EVENTS */
+ /* add events, ... */
+ /* USER CODE END RTOS_EVENTS */
+
+ /* Start scheduler */
+ osKernelStart();
+
+ /* We should never get here as control is now taken by the scheduler */
+ /* Infinite loop */
+ /* USER CODE BEGIN WHILE */
+ while (1)
+ {
+ /* USER CODE END WHILE */
+
+ /* USER CODE BEGIN 3 */
+ }
+ /* USER CODE END 3 */
+}
+
+/**
+ * @brief System Clock Configuration
+ * @retval None
+ */
+void SystemClock_Config(void)
+{
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+
+ /** Configure the main internal regulator output voltage
+ */
+ __HAL_RCC_PWR_CLK_ENABLE();
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+ /** Initializes the RCC Oscillators according to the specified parameters
+ * in the RCC_OscInitTypeDef structure.
+ */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLM = 8;
+ RCC_OscInitStruct.PLL.PLLN = 160;
+ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
+ RCC_OscInitStruct.PLL.PLLQ = 4;
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Initializes the CPU, AHB and APB buses clocks
+ */
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
+ |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+
+ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
+ {
+ Error_Handler();
+ }
+}
+
+/**
+ * @brief ADC1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_ADC1_Init(void)
+{
+
+ /* USER CODE BEGIN ADC1_Init 0 */
+
+ /* USER CODE END ADC1_Init 0 */
+
+ ADC_ChannelConfTypeDef sConfig = {0};
+
+ /* USER CODE BEGIN ADC1_Init 1 */
+
+ /* USER CODE END ADC1_Init 1 */
+ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
+ */
+ hadc1.Instance = ADC1;
+ hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
+ hadc1.Init.Resolution = ADC_RESOLUTION_12B;
+ hadc1.Init.ScanConvMode = ENABLE;
+ hadc1.Init.ContinuousConvMode = ENABLE;
+ hadc1.Init.DiscontinuousConvMode = DISABLE;
+ hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
+ hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
+ hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
+ hadc1.Init.NbrOfConversion = 11;
+ hadc1.Init.DMAContinuousRequests = DISABLE;
+ hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
+ if (HAL_ADC_Init(&hadc1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_3;
+ sConfig.Rank = 1;
+ sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_2;
+ sConfig.Rank = 2;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_1;
+ sConfig.Rank = 3;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_0;
+ sConfig.Rank = 4;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_4;
+ sConfig.Rank = 5;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_5;
+ sConfig.Rank = 6;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_6;
+ sConfig.Rank = 7;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_9;
+ sConfig.Rank = 8;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_8;
+ sConfig.Rank = 9;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_15;
+ sConfig.Rank = 10;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
+ */
+ sConfig.Channel = ADC_CHANNEL_14;
+ sConfig.Rank = 11;
+ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN ADC1_Init 2 */
+
+ /* USER CODE END ADC1_Init 2 */
+
+}
+
+/**
+ * @brief CAN1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_CAN1_Init(void)
+{
+
+ /* USER CODE BEGIN CAN1_Init 0 */
+
+ /* USER CODE END CAN1_Init 0 */
+
+ /* USER CODE BEGIN CAN1_Init 1 */
+
+ /* USER CODE END CAN1_Init 1 */
+ hcan1.Instance = CAN1;
+ hcan1.Init.Prescaler = 16;
+ hcan1.Init.Mode = CAN_MODE_NORMAL;
+ hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
+ hcan1.Init.TimeSeg1 = CAN_BS1_1TQ;
+ hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
+ hcan1.Init.TimeTriggeredMode = DISABLE;
+ hcan1.Init.AutoBusOff = DISABLE;
+ hcan1.Init.AutoWakeUp = DISABLE;
+ hcan1.Init.AutoRetransmission = DISABLE;
+ hcan1.Init.ReceiveFifoLocked = DISABLE;
+ hcan1.Init.TransmitFifoPriority = DISABLE;
+ if (HAL_CAN_Init(&hcan1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN CAN1_Init 2 */
+
+ /* USER CODE END CAN1_Init 2 */
+
+}
+
+/**
+ * @brief I2C1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_I2C1_Init(void)
+{
+
+ /* USER CODE BEGIN I2C1_Init 0 */
+
+ /* USER CODE END I2C1_Init 0 */
+
+ /* USER CODE BEGIN I2C1_Init 1 */
+
+ /* USER CODE END I2C1_Init 1 */
+ hi2c1.Instance = I2C1;
+ hi2c1.Init.ClockSpeed = 100000;
+ hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
+ hi2c1.Init.OwnAddress1 = 0;
+ hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ hi2c1.Init.OwnAddress2 = 0;
+ hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ if (HAL_I2C_Init(&hi2c1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN I2C1_Init 2 */
+
+ /* USER CODE END I2C1_Init 2 */
+
+}
+
+/**
+ * @brief SPI1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_SPI1_Init(void)
+{
+
+ /* USER CODE BEGIN SPI1_Init 0 */
+
+ /* USER CODE END SPI1_Init 0 */
+
+ /* USER CODE BEGIN SPI1_Init 1 */
+
+ /* USER CODE END SPI1_Init 1 */
+ /* SPI1 parameter configuration*/
+ hspi1.Instance = SPI1;
+ hspi1.Init.Mode = SPI_MODE_MASTER;
+ hspi1.Init.Direction = SPI_DIRECTION_2LINES;
+ hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
+ hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
+ hspi1.Init.NSS = SPI_NSS_SOFT;
+ hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
+ hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
+ hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ hspi1.Init.CRCPolynomial = 10;
+ if (HAL_SPI_Init(&hspi1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN SPI1_Init 2 */
+
+ /* USER CODE END SPI1_Init 2 */
+
+}
+
+/**
+ * @brief TIM1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_TIM1_Init(void)
+{
+
+ /* USER CODE BEGIN TIM1_Init 0 */
+
+ /* USER CODE END TIM1_Init 0 */
+
+ TIM_MasterConfigTypeDef sMasterConfig = {0};
+ TIM_OC_InitTypeDef sConfigOC = {0};
+ TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
+
+ /* USER CODE BEGIN TIM1_Init 1 */
+
+ /* USER CODE END TIM1_Init 1 */
+ htim1.Instance = TIM1;
+ htim1.Init.Prescaler = 0;
+ htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
+ htim1.Init.Period = 65535;
+ htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+ htim1.Init.RepetitionCounter = 0;
+ htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+ if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
+ sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+ if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfigOC.OCMode = TIM_OCMODE_PWM1;
+ sConfigOC.Pulse = 0;
+ sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
+ sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+ sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
+ sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
+ sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+ if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfigOC.OCMode = TIM_OCMODE_TIMING;
+ if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfigOC.OCMode = TIM_OCMODE_PWM1;
+ if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
+ sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
+ sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
+ sBreakDeadTimeConfig.DeadTime = 0;
+ sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
+ sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
+ sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
+ if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN TIM1_Init 2 */
+
+ /* USER CODE END TIM1_Init 2 */
+ HAL_TIM_MspPostInit(&htim1);
+
+}
+
+/**
+ * @brief TIM3 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_TIM3_Init(void)
+{
+
+ /* USER CODE BEGIN TIM3_Init 0 */
+
+ /* USER CODE END TIM3_Init 0 */
+
+ TIM_MasterConfigTypeDef sMasterConfig = {0};
+ TIM_OC_InitTypeDef sConfigOC = {0};
+
+ /* USER CODE BEGIN TIM3_Init 1 */
+
+ /* USER CODE END TIM3_Init 1 */
+ htim3.Instance = TIM3;
+ htim3.Init.Prescaler = 0;
+ htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
+ htim3.Init.Period = 65535;
+ htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+ htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+ if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
+ sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+ if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sConfigOC.OCMode = TIM_OCMODE_PWM1;
+ sConfigOC.Pulse = 0;
+ sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
+ sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
+ if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN TIM3_Init 2 */
+
+ /* USER CODE END TIM3_Init 2 */
+ HAL_TIM_MspPostInit(&htim3);
+
+}
+
+/**
+ * @brief TIM9 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_TIM9_Init(void)
+{
+
+ /* USER CODE BEGIN TIM9_Init 0 */
+
+ /* USER CODE END TIM9_Init 0 */
+
+ TIM_SlaveConfigTypeDef sSlaveConfig = {0};
+
+ /* USER CODE BEGIN TIM9_Init 1 */
+
+ /* USER CODE END TIM9_Init 1 */
+ htim9.Instance = TIM9;
+ htim9.Init.Prescaler = 0;
+ htim9.Init.CounterMode = TIM_COUNTERMODE_UP;
+ htim9.Init.Period = 65535;
+ htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+ htim9.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+ if (HAL_TIM_Base_Init(&htim9) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
+ sSlaveConfig.InputTrigger = TIM_TS_ITR0;
+ if (HAL_TIM_SlaveConfigSynchro(&htim9, &sSlaveConfig) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN TIM9_Init 2 */
+
+ /* USER CODE END TIM9_Init 2 */
+
+}
+
+/**
+ * @brief UART4 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_UART4_Init(void)
+{
+
+ /* USER CODE BEGIN UART4_Init 0 */
+
+ /* USER CODE END UART4_Init 0 */
+
+ /* USER CODE BEGIN UART4_Init 1 */
+
+ /* USER CODE END UART4_Init 1 */
+ huart4.Instance = UART4;
+ huart4.Init.BaudRate = 115200;
+ huart4.Init.WordLength = UART_WORDLENGTH_8B;
+ huart4.Init.StopBits = UART_STOPBITS_1;
+ huart4.Init.Parity = UART_PARITY_NONE;
+ huart4.Init.Mode = UART_MODE_TX_RX;
+ huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart4.Init.OverSampling = UART_OVERSAMPLING_16;
+ if (HAL_UART_Init(&huart4) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN UART4_Init 2 */
+
+ /* USER CODE END UART4_Init 2 */
+
+}
+
+/**
+ * Enable DMA controller clock
+ */
+static void MX_DMA_Init(void)
+{
+
+ /* DMA controller clock enable */
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ __HAL_RCC_DMA1_CLK_ENABLE();
+
+ /* DMA interrupt init */
+ /* DMA1_Stream0_IRQn interrupt configuration */
+ HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
+ /* DMA1_Stream6_IRQn interrupt configuration */
+ HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
+ /* DMA2_Stream0_IRQn interrupt configuration */
+ HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
+
+}
+
+/**
+ * @brief GPIO Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_GPIO_Init(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+ /* GPIO Ports Clock Enable */
+ __HAL_RCC_GPIOH_CLK_ENABLE();
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_RESET);
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(GPIOB, NFAULT_Pin|EN_DRIVER_Pin, GPIO_PIN_RESET);
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(TERM_GPIO_Port, TERM_Pin, GPIO_PIN_RESET);
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(CS_DRIVER_GPIO_Port, CS_DRIVER_Pin, GPIO_PIN_RESET);
+
+ /*Configure GPIO pins : PC0 PC1 PC2 */
+ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+ /*Configure GPIO pin : USER_BUTTON_Pin */
+ GPIO_InitStruct.Pin = USER_BUTTON_Pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(USER_BUTTON_GPIO_Port, &GPIO_InitStruct);
+
+ /*Configure GPIO pins : NFAULT_Pin EN_DRIVER_Pin */
+ GPIO_InitStruct.Pin = NFAULT_Pin|EN_DRIVER_Pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ /*Configure GPIO pin : TERM_Pin */
+ GPIO_InitStruct.Pin = TERM_Pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(TERM_GPIO_Port, &GPIO_InitStruct);
+
+ /*Configure GPIO pin : CS_DRIVER_Pin */
+ GPIO_InitStruct.Pin = CS_DRIVER_Pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(CS_DRIVER_GPIO_Port, &GPIO_InitStruct);
+
+}
+
+/* USER CODE BEGIN 4 */
+
+/* USER CODE END 4 */
+
+/* USER CODE BEGIN Header_StartDefaultTask */
+/**
+ * @brief Function implementing the defaultTask thread.
+ * @param argument: Not used
+ * @retval None
+ */
+/* USER CODE END Header_StartDefaultTask */
+void StartDefaultTask(void *argument)
+{
+ /* USER CODE BEGIN 5 */
+ /* Infinite loop */
+ for(;;)
+ {
+ osDelay(1);
+ }
+ /* USER CODE END 5 */
+}
+
+/**
+ * @brief Period elapsed callback in non blocking mode
+ * @note This function is called when TIM2 interrupt took place, inside
+ * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
+ * a global variable "uwTick" used as application time base.
+ * @param htim : TIM handle
+ * @retval None
+ */
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+{
+ /* USER CODE BEGIN Callback 0 */
+
+ /* USER CODE END Callback 0 */
+ if (htim->Instance == TIM2) {
+ HAL_IncTick();
+ }
+ /* USER CODE BEGIN Callback 1 */
+
+ /* USER CODE END Callback 1 */
+}
+
+/**
+ * @brief This function is executed in case of error occurrence.
+ * @retval None
+ */
+void Error_Handler(void)
+{
+ /* USER CODE BEGIN Error_Handler_Debug */
+ /* User can add his own implementation to report the HAL error return state */
+ __disable_irq();
+ while (1)
+ {
+ }
+ /* USER CODE END Error_Handler_Debug */
+}
+
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief Reports the name of the source file and the source line number
+ * where the assert_param error has occurred.
+ * @param file: pointer to the source file name
+ * @param line: assert_param error line source number
+ * @retval None
+ */
+void assert_failed(uint8_t *file, uint32_t line)
+{
+ /* USER CODE BEGIN 6 */
+ /* User can add his own implementation to report the file name and line number,
+ ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+ /* USER CODE END 6 */
+}
+#endif /* USE_FULL_ASSERT */
+
diff --git a/STM32F405RGTx/Core/Src/rtos_threads/accelerometer_thread.cpp b/STM32F405RGTx/Core/Src/rtos_threads/accelerometer_thread.cpp
new file mode 100644
index 0000000..b8738ea
--- /dev/null
+++ b/STM32F405RGTx/Core/Src/rtos_threads/accelerometer_thread.cpp
@@ -0,0 +1,32 @@
+#include "main.h"
+#include "threads.hpp"
+
+void AccelerometerThread::initialize(){
+ accelerometer = Accelerometer(I2CConnection);
+ thread = RTOSThread(
+ "accelerometer_thread",
+ 1024*5,
+ ACCELEROMETER_THREAD_PRIORITY,
+ update
+ );
+}
+
+void AccelerometerThread::update(void* args) {
+ while (1) {
+ accelerometer.update();
+ osThreadFlagsWait(0x00000001U, osFlagsWaitAll, 0U);
+ osDelay(MEASUREMENTS_THREAD_PERIODICITY);
+ }
+}
+
+void AccelerometerThread::stopMeasurements() {
+ osThreadSuspend(thread.getThreadId());
+}
+
+void AccelerometerThread::resumeMeasurements() {
+ osThreadResume(thread.getThreadId());
+}
+
+osThreadId_t AccelerometerThread::getThreadId() {
+ return thread.getThreadId();
+}
diff --git a/WLoopCAN b/WLoopCAN
index c2e6e14..a7194fa 160000
--- a/WLoopCAN
+++ b/WLoopCAN
@@ -1 +1 @@
-Subproject commit c2e6e147ea696810f0d990ae5a5c92e03f272f2e
+Subproject commit a7194faf71b923351f31030b4a72ae00557c511d
diff --git a/WLoopUtil b/WLoopUtil
index fb7f781..61d1bae 160000
--- a/WLoopUtil
+++ b/WLoopUtil
@@ -1 +1 @@
-Subproject commit fb7f78112385e09242a7c314be93c145391f2cdc
+Subproject commit 61d1bae8a3c23922c637b7e9943deaecfa66dc8a
diff --git a/scripts/.generate_lut 2.py.icloud b/scripts/.generate_lut 2.py.icloud
new file mode 100644
index 0000000..654e878
Binary files /dev/null and b/scripts/.generate_lut 2.py.icloud differ