2024-02-08 04:40 PM - edited 2024-02-08 05:01 PM
Hello, reaching out to see if anyone can provide some thoughts on a project I'm working on. The project works but though I'm a longtime Arduino developer this is my first STM32 project - so not 100% sure of some of the parameters I've chosen are the best or most efficient.
The project is simple, custom board implementing a remote control that will eventually transmit using BLE. The remote control design is straightforward and similar to a XBox style controller. It has two joysticks, two toggle switches, two potentiometers (dials), four push buttons and a battery monitor (voltage divider). Here is an image from my HW design software if that helps:
All of the circuitry works except RF, which I haven't tested yet, and I've written the code in STM32CubeIDE to read the inputs. Here are the specifics along with something I'm not sure about:
Questions:
Coming from the Arduino world all of the ADC conversion stuff is new to me, so learning it as I go. There are a lot of options to choose (trigger conversion edge, sampling time, offset number, overrun behaviour, end of sequence selection, etc.) and it's hard to tell from the documentation what they do and how they all work together. This all works so I'm really curious if someone with more experience has any ideas on if it could be better, more efficient, etc.
Here is my ADC setup
There isn't a lot of custom code, most is IDE generated HAL stuff, so below are the relevant sections
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
// Continuous ADC conversion of Analog inputs is complete and stored in the data structure to be used later.
data.j1PotX = (uint8_t) MAP(AD_RES_BUFFER[0], 0, 4096, 0, 256);
data.j1PotY= (uint8_t) MAP(AD_RES_BUFFER[1], 0, 4096, 0, 256);
data.j2PotX = (uint8_t) MAP(AD_RES_BUFFER[2], 0, 4096, 0, 256);
data.j2PotY = (uint8_t) MAP(AD_RES_BUFFER[3], 0, 4096, 0, 256);
data.pot1 = (uint8_t) MAP(AD_RES_BUFFER[4], 0, 4096, 0, 256);
data.pot2 = (uint8_t) MAP(AD_RES_BUFFER[5], 0, 4096, 0, 256);
data.BatteryVoltage = AD_RES_BUFFER[6];
// For convenience, read digital pins here
data.j1Button = HAL_GPIO_ReadPin(j1Button_GPIO_Port, j1Button_Pin);
data.j2Button = HAL_GPIO_ReadPin(j2Button_GPIO_Port, j2Button_Pin);
data.tSwitch1 = HAL_GPIO_ReadPin(tSwitch1_GPIO_Port, tSwitch1_Pin);
data.tSwitch2 = HAL_GPIO_ReadPin(tSwitch2_GPIO_Port, tSwitch2_Pin);
data.button1 = HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin);
data.button2 = HAL_GPIO_ReadPin(Button2_GPIO_Port, Button2_Pin);
data.button3 = HAL_GPIO_ReadPin(Button3_GPIO_Port, Button3_Pin);
data.button4 = HAL_GPIO_ReadPin(Button4_BOOT0_GPIO_Port, Button4_BOOT0_Pin);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
uint16_t MAP(uint16_t au16_IN, uint16_t au16_INmin, uint16_t au16_INmax, uint16_t au16_OUTmin, uint16_t au16_OUTmax)
{
return ((((au16_IN - au16_INmin)*(au16_OUTmax - au16_OUTmin))/(au16_INmax - au16_INmin)) + au16_OUTmin);
}
Here is main, just some extra initialization and then printing out to the USB for now
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Config code for STM32_WPAN (HSE Tuning must be done before system clock configuration) */
MX_APPE_Config();
/* USER CODE BEGIN Init */
//LL_HSEM_1StepLock( HSEM, 5 ); // CES: Forum has this as a fix for USB+BLE
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* IPCC initialisation */
MX_IPCC_Init();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_Device_Init();
MX_RTC_Init();
MX_ADC1_Init();
MX_TIM2_Init();
MX_RF_Init();
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
// Turn on Blue LED, indicating that we're NOT in boot mode and all initializations are complete
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
HAL_TIM_Base_Start(&htim2);
HAL_ADC_Start_DMA(&hadc1, (uint32_t *) AD_RES_BUFFER, 7);
/* Init code for STM32_WPAN */
MX_APPE_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// Read a value then delay for 1 second
//HAL_GPIO_ReadPin(GPIOx, GPIO_Pin)
//data.tSwitch1 = HAL_GPIO_ReadPin(tSwitch1_GPIO_Port, tSwitch1_Pin);
//data.j1PotX = analogRead(&hadc1, J1POTX_ADC_CHANNEL);
//data.j1PotY = analogRead(&hadc1, J1POTY_ADC_CHANNEL);
//data.j2PotY = analogRead(&hadc1, J2POTY_ADC_CHANNEL);
bufLen = snprintf(txBuf, 256,
"J1PotX: %u\t"
"J1PotY: %u\t"
"J1Button: %u\t"
"J2PotX: %u\t"
"J2PotY: %u\t"
"J2Button: %u\t"
"pot1: %u\t"
"pot2: %u\t"
"Button1: %u\t"
"Button2: %u\t"
"Button3: %u\t"
"Button4: %u\t"
"Battery: %u\r\n",
data.j1PotX, data.j1PotY, data.j1Button, data.j2PotX, data.j2PotY, data.j2Button, data.pot1, data.pot2,
data.button1, data.button2, data.button3, data.button4, data.BatteryVoltage);
CDC_Transmit_FS((uint8_t *) txBuf, bufLen);
HAL_Delay(1000);
MX_APPE_Process();
}
}