Page 1 of 1
Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Mon Aug 17, 2020 3:50 am
by zapta
Hi all,
[using bluepill, STM32F103C8, using vscode/platform.io with Arduino framework and stlink v2 uploading/debugging]
My questions to you are:
1. Does the bluepill has a single or double ADCs? (I mean real two ADCs that can convert in parallel).
2. Is there an asynchronous API for the ADCs?
Background: I am migrating a program from teensy to bluepill to redcue cost and have a question about the usage of the ADC(s). The program sets a timer to generate 100Khz interrupts and on each interrupt handler call it does the following:
Code: Select all
interrupt routine {
I1 = read_adc1 result;
I2 = read_adc2 result;
start adc1; // for reading in next interrupt
start adc2;
process results I1, I2; // processing is significant, decoding position/speed of a stepper motor.
}
I managed to setup a timer that invokes the interrupt routine but am not sure how to setup the ADC(s) or do asynchronous start/read. All I see is the arduino blocking analog read.
Thanks.
Re: Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Mon Aug 17, 2020 9:43 am
by fpiSTM
You will have to implement yourself the ADC read using the HAL/LL layer.
I've provide an example of a converted STM32Cube project here:
viewtopic.php?f=41&t=110&p=669
For question 1:
https://www.st.com/en/microcontrollers- ... 103c8.html
2 x 12-bit, 1 μs A/D converters (up to 16 channels)
Conversion range: 0 to 3.6 V
Dual-sample and hold capability
Temperature sensor
Re: Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Mon Aug 17, 2020 2:21 pm
by zapta
> I've provide an example of a converted STM32Cube project here: viewtopic.php?f=41&t=110&p=669
Thanks fpiSTM. I will go through the example and try to understand.
Will this involve just adding .h and .c file to my stm32duino project directory or will it also require to modify/add/replace lower level library files that come with the stm32duino environment?
Also, if anybody has an example of asynchronous ADC in a stm32duino project, please let me know.
Re: Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Mon Aug 17, 2020 2:30 pm
by fpiSTM
Just add to tour sketch file or new file. No need to modify the core.
Re: Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Mon Aug 17, 2020 10:24 pm
by zapta
Thanks fpiSTM that's very useful. I collected commands and came with the program below which seems to measure A0 using ADC1 inside the main loop (no sampling from interrupts yet), so that's a progress.
A few question for you if you don't mind:
1. Does this program look reasonable so far?
2. How do I select a different input (other than A0)?
3. Are all the selectable analog inputs the same or are some more preferred than others?
4. The conversion takes about 10usec. Any way to speed it up? (e.g. sub 5usec)
5. I want to add a second channel ADC2 with same time sampling. Should I just treat it as a separate channel with its own Start/Read or does the chip has a simultaneous two channel operation? (how?).
EDIT: it seems that HAL_ADC_Start(&hadc1) alone takes ~8usec and looking at its code it seems to be logic heaver. I guess I need to trigger the conversion in a different way, mayby directly from the timer and run my signal processing at the ADC completion interrupt?
Thanks,
Z.
Code: Select all
// stm32duino core API here https://github.com/stm32duino/wiki/wiki/API
#include <Arduino.h>
ADC_HandleTypeDef hadc1;
HardwareTimer *AdcTimer = new HardwareTimer(TIM1);
// Updated by an interrupt routine. Protect as needed.
static int counter = 0;
void adc_setup(ADC_HandleTypeDef* adc_handle, ADC_TypeDef *adc) {
adc_handle->Instance = adc;
adc_handle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
adc_handle->Init.ScanConvMode = ADC_SCAN_DISABLE;
adc_handle->Init.ContinuousConvMode = DISABLE;
adc_handle->Init.NbrOfConversion = 1;
adc_handle->Init.DiscontinuousConvMode = DISABLE;
adc_handle->Init.NbrOfDiscConversion = 1;
adc_handle->Init.ExternalTrigConv = ADC_SOFTWARE_START;
HAL_StatusTypeDef status = HAL_ADC_Init(adc_handle);
if (status != HAL_OK ) {
for(;;) {
Serial.printf("ADC setup error: %d", status);
delay(1000);
}
}
}
void adc_loop() {
auto start = micros();
HAL_ADC_Start(&hadc1);
HAL_StatusTypeDef status = HAL_ADC_PollForConversion(&hadc1, 100);
if (status != HAL_OK ) {
for(;;) {
Serial.printf("ADC read error: %d", status);
delay(1000);
}
}
int value = HAL_ADC_GetValue(&hadc1);
auto end = micros();
Serial.printf("Adc: %d (%d usec)\n", value, end - start);
}
// Timer interrupt routing.
void Timer_callback(void) { counter++; }
// Arduino's one time setup.
void setup() {
// Should be done first, to print setup errors.
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
adc_setup(&hadc1, ADC1);
AdcTimer->pause();
AdcTimer->setOverflow(100000, HERTZ_FORMAT); // 10 Hz
AdcTimer->attachInterrupt(Timer_callback);
AdcTimer->resume();
}
// Arduino's main loop handler.
void loop() {
adc_loop();
digitalWrite(LED_BUILTIN, LOW); // LED on
delay(50);
digitalWrite(LED_BUILTIN, HIGH); // LED off.
delay(950);
}
Re: Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Tue Sep 01, 2020 3:31 pm
by zapta
A quick update, everything is working now. I am using Timer1 to generate output pulses for reference and internal triggers to ADC1 that acts as a master to ADC2 and IRQ handling on ADC1 completion. I first had it working with the CUBE IDE and then ported to the arduino framework.
Re: Asynchronous ADC start/read on bluepill STM32F103C8?
Posted: Tue Sep 01, 2020 4:01 pm
by stevestrong
Can you share a working example?