Gyroscope LED Controller STM32F407 Discovery
Gyroscope LED Controller STM32F407 Discovery
MES Project
Gyroscope LED Controller
Andrei George-Andrei
ACES Master Program
2021
1
Contents
1. Project description………………………………………………………………………….……3
2. Hardware description………………………………………………………………………….…3
3. Developing tools used……………………………………………………………………….…...5
4. Software description……………………………………………………………………….…….8
5. Conclusions ……………………………………………………………………………………...9
6. Source code………………………………………………………………………………………9
2
1. Project description
Using a gyroscope, the MCU will control the 4 LEDs (disposed in a cross formation around the
sensor) that are available on the developing board. The light intensity of each LED will be
depending on the tilt measurement from the inertial sensor.
For example:
If the board is a little inclined to the south side, the led from that side will light up. The bigger
the tilt angle, the more the light intensity will rise. If the sensor will be tilted both south and
west, two LEDs will start lightning the same way described above.
2. Hardware description
For the project a STM32F407 Discovery board (fig. 2.1) was used. It has an on board soldered
LIS3DSH ST MEMS 3-axis accelerometer (fig. 2.2), 4 LEDs (fig. 2.2).
The accelerometer has an SPI communication interface. Fig. 2.3 describes the circuit schematic of
the tilt device.
3
Fig. 2.1 Discovery board
4
3. Developing tools used
For the project development several software tools were used. The pin allocation (fig. 3.1) and
peripheral configuration (fig. 3.2) was done by STM32CubeMX. It can also ease the clock
configuration (fig. 3.3) and generate code.
The main program was written and debugged in STM32CubeIDE and the data was visualized in
real time with STM Studio app (fig. 3.4).
5
Fig. 3.2 STM32CubeMX SPI configuration
6
Fig. 3.3 STM32CubeMX clock configuration
7
Fig. 3.4 STM Studio live data visualization
4. Software description
The code logic is described in fig. 4.1
8
5. Conclusions
In conclusion, we can state that STM32F407 Discovery board is a resourceful device, maybe
overpowered for our project. The multitude of peripherals and the high performance ARM Cortex-M4
microcontroller make the discovery board a great choise for our project and for all sorts of demanding
projects.
The four LEDs light up as we planned: if we tilt the board on one side, the LED on that side will get
brighter and brighter accordingly to the inclination angle.
6. Source code
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
******************************************************************************
* @attention
* the "License"; You may not use this file except in compliance with the
* opensource.org/licenses/BSD-3-Clause
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
9
/* USER CODE END Includes */
SPI_HandleTypeDef hspi1;
TIM_HandleTypeDef htim4;
uint8_t spiTxBuf[2];
uint8_t spiRxBuf[2];
int8_t x_data;
int8_t y_data;
//int8_t dutyCycleCH1 = 0;
//int8_t dutyCycleCH2 = 0;
10
//int8_t dutyCycleCH3 = 0;
//int8_t dutyCycleCH4 = 0;
void SystemClock_Config(void);
/**
* @retval int
*/
int main(void)
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
11
/* USER CODE BEGIN Init */
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_TIM4_Init();
spiTxBuf[0] = 0x20;
// acc CTRL_REG4 address
spiTxBuf[1] = 0x13;
// (0x10 - speed) + (0x03 - Xen, Yen)
// spiTxBuf[0] = 0x23;
// spiTxBuf[1] = 0xC8;
12
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
HAL_Delay(2000);
/* Infinite loop */
while (1)
x_data = spiRxBuf[0];
// store X axis data
htim4.Instance->CCR1 = 0; // CCRx -
PWM value %
htim4.Instance->CCR3 = 0;
htim4.Instance->CCR1 = -(x_data);
htim4.Instance->CCR3 = 0;
13
{
htim4.Instance->CCR3 = x_data;
htim4.Instance->CCR1 = 0;
y_data = spiRxBuf[0];
htim4.Instance->CCR2 = 0;
htim4.Instance->CCR4 = 0;
htim4.Instance->CCR4 = -(y_data);
htim4.Instance->CCR2 = 0;
htim4.Instance->CCR2 = y_data;
htim4.Instance->CCR4 = 0;
// htim4.Instance->CCR1 = -(x_data);
// htim4.Instance->CCR2 = y_data;
// htim4.Instance->CCR3 = x_data;
14
// htim4.Instance->CCR4 = -(y_data);
HAL_Delay(5);
/**
* @retval None
*/
void SystemClock_Config(void)
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
Error_Handler();
15
/** 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_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
Error_Handler();
/**
* @param None
* @retval None
*/
hspi1.Instance = SPI1;
16
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_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
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();
/**
* @param None
* @retval None
*/
17
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
htim4.Instance = TIM4;
htim4.Init.Prescaler = 16;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 100;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
Error_Handler();
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
Error_Handler();
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
Error_Handler();
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
Error_Handler();
18
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 50;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
Error_Handler();
Error_Handler();
Error_Handler();
Error_Handler();
HAL_TIM_MspPostInit(&htim4);
/**
* @param None
* @retval None
19
*/
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
20
/* USER CODE BEGIN 4 */
/**
* @retval None
*/
void Error_Handler(void)
/* User can add his own implementation to report the HAL error return state */
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* @retval None
*/
/* User can add his own implementation to report the file name and line number,
#endif /* USE_FULL_ASSERT */
21