diff --git a/Firmware/carteHRI.uvoptx b/Firmware/carteHRI.uvoptx index ccc8985..8f2521d 100644 --- a/Firmware/carteHRI.uvoptx +++ b/Firmware/carteHRI.uvoptx @@ -1,775 +1,814 @@ 1.0
### uVision Project, (C) Keil Software
*.c *.s*; *.src; *.a* *.obj *.lib *.txt; *.h; *.inc *.plm *.cpp 0 0 0 Target 1 0x4 ARM-ADS 168000000 1 1 0 1 0 1 65535 0 0 0 79 66 8 .\lst\ 1 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 1 1 1 0 0 1 0 1 18 0 User Manual (MCBSTM32F400) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\Keil\MCBSTM32F400\Documentation\mcbstm32f200.chm 1 Schematics (MCBSTM32F400) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\Keil\MCBSTM32F400\Documentation\mcbstm32f400-schematics.pdf 2 Getting Started (STM32F4-Discovery) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\ST\STM32F4-Discovery\Documentation\DM00037368.pdf 3 User Manual (STM32F4-Discovery) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\ST\STM32F4-Discovery\Documentation\DM00039084.pdf 4 Bill of Materials (STM32F4-Discovery) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\ST\STM32F4-Discovery\Documentation\stm32f4discovery_bom.zip 5 Gerber Files (STM32F4-Discovery) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\ST\STM32F4-Discovery\Documentation\stm32f4discovery_gerber.zip 6 Schematics (STM32F4-Discovery) C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.5.0\MDK\Boards\ST\STM32F4-Discovery\Documentation\stm32f4discovery_sch.zip 7 MCBSTM32F400 Evaluation Board Web Page (MCBSTM32F400) http://www.keil.com/mcbstm32f400/ 8 STM32F4-Discovery Web Page (STM32F4-Discovery) http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1199/PF252419 0 1 1 1 1 1 1 1 1 1 0 1 1 1 0 1 1 1 1 0 0 11 STLink\ST-LINKIII-KEIL_SWO.dll 0 ARMRTXEVENTFLAGS -L50 -Z18 -C0 -M0 -T0 0 DLGDARM (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) 0 DLGTARM (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) 0 ARMDBGFLAGS -T0 0 DLGUARM (105=-1,-1,-1,-1,0) 0 ST-LINKIII-KEIL_SWO -U303030303030303030303031 -O8398 -S1 -C0 -A0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO19 -TC168000000 -TP21 -TDS8053 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F407VG$CMSIS\Flash\STM32F4xx_1024.FLM) 0 UL2CM3 UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407VG$Flash\STM32F4xx_1024.FLM)) 0 1 uart_txBuffer[0] 1 1 uart_txBuffer[1] 2 1 demoSineOutput 3 1 ctrl_motorPosHall 4 1 ctrl_timestamp 0 2 motorCurrentDebug 1 2 motorTargetCurrentDebug 2 2 ctrl_motorTorque_mNm_c 3 2 motorTorque_mNm_dbg 4 2 motorTorque_mNm 5 2 nCycles 6 2 motorPosCod,0x0A 7 2 CurrentSensOffset,0x0A 8 2 motorCurrent_mA_mean 9 2 motorCurrent_mA 10 2 ADCValuesBuffer,0x0A 11 2 motorCurrent_mA 12 2 motorCurrentSum 13 2 debugVar01,0x0A 14 2 adcValues1,0x0A 15 2 motorCurrent_mA 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 STM32_files 1 0 0 0 1 1 1 0 0 0 0 .\src\system_stm32f4xx.c system_stm32f4xx.c 0 0 1 2 2 0 0 0 0 .\startup_stm32f4xx.s startup_stm32f4xx.s 0 0 SRC 1 0 0 0 2 3 1 0 0 0 0 .\src\main.c main.c 0 0 2 4 1 0 0 0 0 .\src\communication.c communication.c 0 0 2 5 1 0 0 0 0 .\src\controller.c controller.c 0 0 STM32_libs 1 0 0 0 3 6 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_gpio.c stm32f4xx_gpio.c 0 0 3 7 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rcc.c stm32f4xx_rcc.c 0 0 3 8 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_tim.c stm32f4xx_tim.c 0 0 3 9 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\misc.c misc.c 0 0 3 10 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_exti.c stm32f4xx_exti.c 0 0 3 11 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_syscfg.c stm32f4xx_syscfg.c 0 0 3 12 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_adc.c stm32f4xx_adc.c 0 0 3 13 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dac.c stm32f4xx_dac.c 0 0 3 14 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dma.c stm32f4xx_dma.c 0 0 3 15 1 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_usart.c stm32f4xx_usart.c 0 0 3 16 4 0 0 0 0 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\CMSIS\Lib\ARM\arm_cortexM4lf_math.lib arm_cortexM4lf_math.lib 0 0 + + 3 + 17 + 1 + 0 + 0 + 0 + 0 + C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_i2c.c + stm32f4xx_i2c.c + 0 + 0 + SRC_drivers 1 0 0 0 4 - 17 + 18 1 0 0 0 0 .\src\drivers\adc.c adc.c 0 0 4 - 18 + 19 1 0 0 0 0 .\src\drivers\callback_timers.c callback_timers.c 0 0 4 - 19 + 20 1 0 0 0 0 .\src\drivers\dac.c dac.c 0 0 4 - 20 + 21 1 0 0 0 0 .\src\drivers\h_bridge.c h_bridge.c 0 0 4 - 21 + 22 1 0 0 0 0 .\src\drivers\incr_encoder.c incr_encoder.c 0 0 4 - 22 + 23 1 0 0 0 0 .\src\drivers\uart.c uart.c 0 0 4 - 23 + 24 1 0 0 0 0 .\src\drivers\hall.c hall.c 0 0 4 - 24 + 25 1 0 0 0 0 .\src\drivers\led.c led.c 0 0 4 - 25 + 26 1 0 0 0 0 .\src\drivers\debug_gpio.c debug_gpio.c 0 0 4 - 26 + 27 1 0 0 0 0 .\src\drivers\button.c button.c 0 0 + + 4 + 28 + 1 + 0 + 0 + 0 + 0 + .\src\drivers\i2c.c + i2c.c + 0 + 0 + + + 4 + 29 + 1 + 0 + 0 + 0 + 0 + .\src\drivers\mpu_6050.c + mpu_6050.c + 0 + 0 + SRC_lib 1 0 0 0 5 - 27 + 30 1 0 0 0 0 .\src\lib\basic_filter.c basic_filter.c 0 0 5 - 28 + 31 1 0 0 0 0 .\src\lib\pid.c pid.c 0 0 5 - 29 + 32 1 0 0 0 0 .\src\lib\utils.c utils.c 0 0 5 - 30 + 33 1 0 0 0 0 .\src\lib\circular_buffer.c circular_buffer.c 0 0
diff --git a/Firmware/carteHRI.uvprojx b/Firmware/carteHRI.uvprojx index 2a6b74b..43e992c 100644 --- a/Firmware/carteHRI.uvprojx +++ b/Firmware/carteHRI.uvprojx @@ -1,591 +1,606 @@ 2.1
### uVision Project, (C) Keil Software
Target 1 0x4 ARM-ADS STM32F407VG STMicroelectronics Keil.STM32F4xx_DFP.2.5.0 http://www.keil.com/pack IROM(0x08000000,0x100000) IRAM(0x20000000,0x20000) IRAM2(0x10000000,0x10000) CPUTYPE("Cortex-M4") FPU2 CLOCK(168000000) ELITTLE UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32F407VG$Flash\STM32F4xx_1024.FLM)) 6103 $$Device:STM32F407VG$Device\Include\stm32f4xx.h $$Device:STM32F407VG$SVD\STM32F40x.svd 0 0 0 0 0 0 1 .\output\ motorControl 1 0 1 1 1 .\lst\ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 3 1 SARMCM3.DLL -REMAP -MPU DCM.DLL -pCM4 SARMCM3.DLL -REMAP -MPU TCM.DLL -pCM4 1 0 0 0 16 0 1 1 1 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 11 STLink\ST-LINKIII-KEIL_SWO.dll 1 0 0 1 1 4096 1 BIN\UL2CM3.DLL "" () 0 0 1 1 1 1 1 1 1 0 1 1 0 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 "Cortex-M4" 0 0 0 1 1 0 0 2 1 0 8 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0x0 0x0 0 0x0 0x0 0 0x0 0x0 0 0x0 0x0 0 0x0 0x0 0 0x0 0x0 0 0x20000000 0x20000 1 0x8000000 0x100000 0 0x0 0x0 1 0x0 0x0 1 0x0 0x0 1 0x0 0x0 1 0x8000000 0x100000 1 0x0 0x0 0 0x0 0x0 0 0x0 0x0 0 0x0 0x0 0 0x20000000 0x20000 0 0x10000000 0x10000 1 - 4 + 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 USE_STDPERIPH_DRIVER STM32F4XX ARM_MATH_CM4 ..\CodeUC;.\inc;.\src;C:\STM32F4-Discovery_FW_V1.1.0\Libraries\CMSIS\ST\STM32F4xx\Include;C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\inc;C:\STM32F4-Discovery_FW_V1.1.0\Utilities\STM32F4-Discovery;C:\STM32F4-Discovery_FW_V1.1.0\Libraries\CMSIS\Include 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0x08000000 0x20000000 STM32_files system_stm32f4xx.c 1 .\src\system_stm32f4xx.c startup_stm32f4xx.s 2 .\startup_stm32f4xx.s SRC main.c 1 .\src\main.c communication.c 1 .\src\communication.c controller.c 1 .\src\controller.c STM32_libs stm32f4xx_gpio.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_gpio.c stm32f4xx_rcc.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rcc.c stm32f4xx_tim.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_tim.c misc.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\misc.c stm32f4xx_exti.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_exti.c stm32f4xx_syscfg.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_syscfg.c stm32f4xx_adc.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_adc.c stm32f4xx_dac.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dac.c stm32f4xx_dma.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dma.c stm32f4xx_usart.c 1 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_usart.c arm_cortexM4lf_math.lib 4 C:\STM32F4-Discovery_FW_V1.1.0\Libraries\CMSIS\Lib\ARM\arm_cortexM4lf_math.lib + + stm32f4xx_i2c.c + 1 + C:\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_i2c.c + SRC_drivers adc.c 1 .\src\drivers\adc.c callback_timers.c 1 .\src\drivers\callback_timers.c dac.c 1 .\src\drivers\dac.c h_bridge.c 1 .\src\drivers\h_bridge.c incr_encoder.c 1 .\src\drivers\incr_encoder.c uart.c 1 .\src\drivers\uart.c hall.c 1 .\src\drivers\hall.c led.c 1 .\src\drivers\led.c debug_gpio.c 1 .\src\drivers\debug_gpio.c button.c 1 .\src\drivers\button.c + + i2c.c + 1 + .\src\drivers\i2c.c + + + mpu_6050.c + 1 + .\src\drivers\mpu_6050.c + SRC_lib basic_filter.c 1 .\src\lib\basic_filter.c pid.c 1 .\src\lib\pid.c utils.c 1 .\src\lib\utils.c circular_buffer.c 1 .\src\lib\circular_buffer.c
diff --git a/Firmware/src/drivers/i2c.c b/Firmware/src/drivers/i2c.c new file mode 100644 index 0000000..4c4df61 --- /dev/null +++ b/Firmware/src/drivers/i2c.c @@ -0,0 +1,246 @@ +#include "i2c.h" + +#include "stm32f4xx_i2c.h" + +#include "../lib/utils.h" + +const uint32_t TIMEOUT = 3200; ///< Approximate maximum time for a I2C operation to complete (approx. 100us). + +/** + * @brief Repeats until the expression returns false, or the timeout is reached. + */ +#define WAIT_WITH_TIMEOUT(x) \ +do \ +{ \ + uint32_t duration = 0;\ + while((x)) \ + { \ + if(duration++ > TIMEOUT) \ + { \ + i2c_Reset(); \ + if(ok != NULL) \ + *ok = false; \ + return; \ + } \ + } \ +} while(0) + +/** + * @brief Initializes the I2C bus. + */ +void i2c_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct; + I2C_InitTypeDef I2C_InitStruct; + + // Enable the peripheral clock. + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); + + // Setup the pins as I2C SDA/SCL. + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + + GPIO_InitStruct.GPIO_Pin = I2C_SDA_Pin; + GPIO_Init(I2C_SDA_Port, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Pin = I2C_SCL_Pin; + GPIO_Init(I2C_SCL_Port, &GPIO_InitStruct); + + GPIO_PinAFConfig(I2C_SDA_Port, I2C_SDA_PinSource, I2C_GPIO_AF); + GPIO_PinAFConfig(I2C_SCL_Port, I2C_SCL_PinSource, I2C_GPIO_AF); + + // Setup the I2C peripheral. + I2C_InitStruct.I2C_ClockSpeed = 100000; // [Hz]. + I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; + I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; + I2C_InitStruct.I2C_OwnAddress1 = 0x00; + I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; + I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; + + I2C_DeInit(I2C_PERIPH); + I2C_Init(I2C_PERIPH, &I2C_InitStruct); + I2C_Cmd(I2C_PERIPH, ENABLE); + + // + utils_DelayUs(50); + I2C_GenerateSTART(I2C_PERIPH, ENABLE); + utils_DelayUs(50); + I2C_GenerateSTART(I2C_PERIPH, DISABLE); + utils_DelayUs(50); + + I2C_GenerateSTOP(I2C_PERIPH, ENABLE); + utils_DelayUs(50); + I2C_GenerateSTOP(I2C_PERIPH, DISABLE); + utils_DelayUs(50); +} + +/** + * @brief Performs a stop condition, to abort the current transaction. + */ +void i2c_Reset(void) +{ + I2C_GenerateSTOP(I2C_PERIPH, ENABLE); + utils_DelayUs(50); + I2C_GenerateSTOP(I2C_PERIPH, DISABLE); + utils_DelayUs(50); +} + +/** + * @brief Writes a 8-bit value to a register. + * @param slaveAddress 7-bit I2C slave address. + * @param registerAddress 8-bit register address. + * @param registerValue value to write to the 8-bit register. + * @param ok the value pointed will be set to true if the operation completed + * successfully, or to false if an error occured. If a NULL pointer is given, + * then it is ignored. + */ +void i2c_WriteRegister(uint8_t slaveAddress, uint8_t registerAddress, + uint8_t registerValue, bool *ok) +{ + i2c_WriteMultiBytesRegister(slaveAddress, registerAddress, + ®isterValue, 1, ok); +} + +/** + * @brief Writes several bytes to a register. + * @param slaveAddress 7-bit I2C slave address. + * @param registerAddress 8-bit register address. + * @param registerValue values array to write to the 8-bit register. + * @param registerSize number of bytes to write. + * @param ok the value pointed will be set to true if the operation completed + * successfully, or to false if an error occured. If a NULL pointer is given, + * then it is ignored. + */ +void i2c_WriteMultiBytesRegister(uint8_t slaveAddress, uint8_t registerAddress, + uint8_t const *registerValue, + uint8_t registerSize, bool *ok) +{ + int i; + + // Wait until the I2C peripheral is ready. + WAIT_WITH_TIMEOUT(I2C_GetFlagStatus(I2C_PERIPH, I2C_FLAG_BUSY)); + + // Send a start condition, and wait until the slave has acknowledged. + I2C_GenerateSTART(I2C_PERIPH, ENABLE); + WAIT_WITH_TIMEOUT(!I2C_CheckEvent(I2C_PERIPH, I2C_EVENT_MASTER_MODE_SELECT)); + + // Send slave address and write mode, and wait until the slave has + // acknowledged. + I2C_Send7bitAddress(I2C_PERIPH, slaveAddress<<1, I2C_Direction_Transmitter); + WAIT_WITH_TIMEOUT(!I2C_CheckEvent(I2C_PERIPH, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); + + // Write the register address. + I2C_SendData(I2C_PERIPH, registerAddress); + WAIT_WITH_TIMEOUT(!I2C_CheckEvent(I2C_PERIPH, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); + + // Write the register content. + for(i=0; i + +#include "i2c.h" +#include "../lib/utils.h" + +#define GRAVITY_INTENSITY 9.81f +#define SINT16_MAX_F ((float)USHRT_MAX) + +#define SLAVE_ADDRESS 0x68 ///< 0x68 if the AD0 pin is low, 0x69 otherwise. + +#define REG_CONFIG 0x1A ///< Configuration register. +#define REG_GYRO_CONFIG 0x1B ///< Gyroscope configuration register. +#define REG_ACCEL_CONFIG 0x1C ///< Accelerometer configuration register. +#define REG_SMPLRT_DIV 0x19 ///< Sample rate divider register. +#define REG_ACCEL_VALUES 0x3b ///< Accelerometer measurements register. +#define REG_TEMP_VALUES 0x41 ///< Temperature measurements register. +#define REG_GYRO_VALUES 0x43 ///< Gyroscope measurements register. +#define REG_SIG_PATH_RST 0x68 ///< Signal path reset register. +#define REG_USER_CTRL 0x6A ///< User control register. +#define REG_POWER_MGMT_1 0x6B ///< Power management 1 register. +#define REG_WHO_AM_I 0x75 ///< Who am I register. + +#define WHO_AM_I_VAL 0x68 ///< Expected value of the REG_WHO_AM_I register. + +/// Gets the actual range value from a mpu_AccelRange enum value. +const float MPU_ACCEL_RANGE_REG_TO_CONV_FACTOR[] = +{ + 2.0f / SINT16_MAX_F * GRAVITY_INTENSITY, + 4.0f / SINT16_MAX_F * GRAVITY_INTENSITY, + 8.0f / SINT16_MAX_F * GRAVITY_INTENSITY, + 16.0f / SINT16_MAX_F * GRAVITY_INTENSITY +}; + +/// Gets the actual range value from a mpu_GyroRange enum value. +const float MPU_GYRO_RANGE_REG_TO_CONV_FACTOR[] = +{ + 250.0f / SINT16_MAX_F, + 500.0f / SINT16_MAX_F, + 1000.0f / SINT16_MAX_F, + 2000.0f / SINT16_MAX_F +}; + +bool mpu_initialized = false; ///< True if the MPU-6050 is initialized, false otherwise. + +float accelFactor, ///< Converts a raw 16-bit integer value to an acceleration [m/s^2]. + gyroFactor; ///< Converts a raw 16-bit integer value to an angular speed [deg/s]. + +/** + * @brief Initializes the MPU-6050 device. + * @param accelRange accelerometer range. + * @param gyroRange gyroscope range. + * @param bandwidth bandwith of the accelerometer and gyroscope. + * @return true if the initialization was successful, false otherwise. + */ +bool mpu_Init(mpu_AccelRange accelRange, mpu_GyroRange gyroRange, + mpu_Bandwidth bandwidth) +{ + uint16_t id; + + // + accelFactor = MPU_ACCEL_RANGE_REG_TO_CONV_FACTOR[accelRange]; + gyroFactor = MPU_GYRO_RANGE_REG_TO_CONV_FACTOR[gyroRange]; + + // Reset the MPU-6050. + i2c_WriteRegister(SLAVE_ADDRESS, REG_POWER_MGMT_1, (1<<7)|(1<<6), NULL); // Device reset. + utils_DelayMs(100); + + // Test the communication with the chip. + id = i2c_ReadRegister(SLAVE_ADDRESS, REG_WHO_AM_I, NULL); + + if(id != WHO_AM_I_VAL) // Error. + return false; + + // Reset the MPU-6050 again. + i2c_WriteRegister(SLAVE_ADDRESS, REG_POWER_MGMT_1, + (1<<7)|(1<<6), NULL); // Device reset. + utils_DelayMs(100); + + i2c_WriteRegister(SLAVE_ADDRESS, REG_SIG_PATH_RST, + (1<<2)|(1<<1)|(1<<0), NULL); // Signal path reset. + utils_DelayMs(100); + + // Setup the MPU-60X0 registers. + i2c_WriteRegister(SLAVE_ADDRESS, REG_USER_CTRL, + (0<<6) | // Disable FIFO. + (0<<5) | // Disable master mode for the external I2C sensor. + (0<<4) | // Do not disable the I2C slave interface (mandatory for the MPU-6050). + (0<<2) | // Do not reset the FIFO. + (0<<1) | // Do not reset the I2C. + (0<<0), // Do not reset the signal paths for the sensors. + NULL); + + i2c_WriteRegister(SLAVE_ADDRESS, REG_POWER_MGMT_1, + (0<<7) | // Do not reset the device. + (0<<6) | // Disable sleep. + (0<<5) | // Disable the "cycle" mode. + (0<<3) | // Do not disable the temperature sensor. + (3<<0), // PLL with Z axis gyro ref. + NULL); + + i2c_WriteRegister(SLAVE_ADDRESS, REG_GYRO_CONFIG, + (0<<7) | // Do not perform self-test for axis X. + (0<<6) | // Do not perform self-test for axis Y. + (0<<5) | // Do not perform self-test for axis Z. + (gyroRange<<3), // Gyroscope range. + NULL); + + i2c_WriteRegister(SLAVE_ADDRESS, REG_ACCEL_CONFIG, + (0<<7) | // Do not perform self-test for axis X. + (0<<6) | // Do not perform self-test for axis Y. + (0<<5) | // Do not perform self-test for axis Z. + (accelRange<<3), // Accelerometer range. + NULL); + + i2c_WriteRegister(SLAVE_ADDRESS, REG_CONFIG, + (0<<3) | // Disable synchronisation with FSYNC pin. + (bandwidth<<0), // Accelerometer and gyroscope bandwidth. + NULL); + + if(bandwidth == MPU_DLPF_BW_256HZ) + i2c_WriteRegister(SLAVE_ADDRESS, REG_SMPLRT_DIV, 7, NULL); + else + i2c_WriteRegister(SLAVE_ADDRESS, REG_SMPLRT_DIV, 0, NULL); + + // + mpu_initialized = true; + + return true; +} + +/** + * @brief Acquires the acceleration from the IMU. + * @param ax variable to write the X-axis acceleration on [m/s^2]. + * @param ay variable to write the Y-axis acceleration on [m/s^2]. + * @param az variable to write the Z-axis acceleration on [m/s^2]. + * @remark ax, ay, and az pointer must be valid (they can't be NULL). + * @remark if the MPU-6050 is not initialized (mpu_Init() was not called + * successfully), then this function does nothing. + * @remark If the operation failed, then *ax, *ay and *az are not modified. + */ +void mpu_GetAcceleration(float *ax, float *ay, float *az) +{ + bool ok; + uint8_t accelData[6]; + + if(!mpu_initialized) + return; + + i2c_ReadMultiBytesRegister(SLAVE_ADDRESS, REG_ACCEL_VALUES, + &accelData[0], 6, &ok); + + if(!ok) + return; + + *ax = ((float)(int16_t)((accelData[0]<<8) | accelData[1])) * accelFactor; + *ay = ((float)(int16_t)((accelData[2]<<8) | accelData[3])) * accelFactor; + *az = ((float)(int16_t)((accelData[4]<<8) | accelData[5])) * accelFactor; +} + +/** + * @brief Acquires the angular speed from the IMU. + * @param gx variable to write the X-axis angular speed on [deg/s]. + * @param gy variable to write the Y-axis angular speed on [deg/s]. + * @param gz variable to write the Z-axis angular speed on [deg/s]. + * @remark gx, gy, and gz pointer must be valid (they can't be NULL). + * @remark if the MPU-6050 is not initialized (mpu_Init() was not called + * successfully), then this function does nothing. + * @remark If the operation failed, then *ax, *ay and *az are not modified. + */ +void mpu_GetAngularSpeed(float *gx, float *gy, float *gz) +{ + bool ok; + uint8_t gyroData[6]; + + if(!mpu_initialized) + return; + + i2c_ReadMultiBytesRegister(SLAVE_ADDRESS, REG_GYRO_VALUES, + &gyroData[0], 6, &ok); + + if(!ok) + return; + + *gx = ((float)(int16_t)((gyroData[0]<<8) | gyroData[1])) * gyroFactor; + *gy = ((float)(int16_t)((gyroData[2]<<8) | gyroData[3])) * gyroFactor; + *gz = ((float)(int16_t)((gyroData[4]<<8) | gyroData[5])) * gyroFactor; +} + +/** + * @brief Acquires the temperature from the IMU. + * @return the measured temperature [°C], or 0 if the operation failed. + * @remark if the MPU-6050 is not initialized (mpu_Init() was not called + * successfully), then this function does nothing. + */ +float mpu_GetTemperature(void) +{ + bool ok; + uint8_t tempData[2]; + + if(!mpu_initialized) + return 0.0f; + + i2c_ReadMultiBytesRegister(SLAVE_ADDRESS, REG_TEMP_VALUES, + &tempData[0], 2, &ok); + + if(!ok) + return 0.0f; + + return ((float)(int16_t)((tempData[0]<<8) | tempData[1])) / 340.0f + 36.53f; // Coefs from the registers map spec. +} diff --git a/Firmware/src/drivers/mpu_6050.h b/Firmware/src/drivers/mpu_6050.h new file mode 100644 index 0000000..b2f2c91 --- /dev/null +++ b/Firmware/src/drivers/mpu_6050.h @@ -0,0 +1,67 @@ +#ifndef __MPU_6050_H +#define __MPU_6050_H + +#include "../main.h" + +/** @defgroup MPU-6050 Driver / MPU-6050 + * @brief Driver for the MPU-6050, a 6-axis IMU from Invensense. + * + * This driver uses the I2C bus of the digital extension connector. + * + * Call mpu_Init() first in the initialization code. Then, call mpu_Get() to + * get the accelerations and angular speeds. + * + * @note This driver setup the MPU-6050 sampling rate to 1 kHz. Calling + * mpu_Get() more often will return the same values. + * + * @addtogroup MPU-6050 + * @{ + */ + +/** + * @brief Enumeration of the possible accelerometer ranges. + */ +typedef enum +{ + MPU_ACCEL_RANGE_2G = 0, ///< +-2 G (+-19.62 m/s^2). + MPU_ACCEL_RANGE_4G = 1, ///< +-4 G (+-39.24 m/s^2). + MPU_ACCEL_RANGE_8G = 2, ///< +-8 G (+-78.48 m/s^2). + MPU_ACCEL_RANGE_16G = 3 ///< +-16 G (+-156.96 m/s^2). +} mpu_AccelRange; + +/** + * @brief Enumeration of the possible gyrometer ranges. + */ +typedef enum +{ + MPU_GYRO_RANGE_250DPS = 0, ///< +- 250 deg/s. + MPU_GYRO_RANGE_500DPS = 1, ///< +- 500 deg/s. + MPU_GYRO_RANGE_1000DPS = 2, ///< +- 1000 deg/s. + MPU_GYRO_RANGE_2000DPS = 3 ///< +- 2000 deg/s. +} mpu_GyroRange; + +/** + * @brief Enumeration of the possible bandwiths. + */ +typedef enum +{ + MPU_DLPF_BW_256HZ = 0, ///< Cut-off freq: 256 Hz. IMU sampling freq: 8kHz. + MPU_DLPF_BW_188HZ = 1, ///< Cut-off freq: 188 Hz. IMU sampling freq: 1kHz. + MPU_DLPF_BW_98HZ = 2, ///< Cut-off freq: 98 Hz. IMU sampling freq: 1kHz. + MPU_DLPF_BW_42HZ = 3, ///< Cut-off freq: 42 Hz. IMU sampling freq: 1kHz. + MPU_DLPF_BW_20HZ = 4, ///< Cut-off freq: 20 Hz. IMU sampling freq: 1kHz. + MPU_DLPF_BW_10HZ = 5, ///< Cut-off freq: 10 Hz. IMU sampling freq: 1kHz. + MPU_DLPF_BW_5HZ = 6 ///< Cut-off freq: 5 Hz. IMU sampling freq: 1kHz. +} mpu_Bandwidth; + +bool mpu_Init(mpu_AccelRange accelRange, mpu_GyroRange gyroRange, + mpu_Bandwidth bandwidth); +void mpu_GetAcceleration(float *ax, float *ay, float *az); +void mpu_GetAngularSpeed(float *gx, float *gy, float *gz); +float mpu_GetTemperature(void); + +/** + * @} + */ + +#endif