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