STM32 Timer-based ADC sampling at a specific rate, with debug output

  Рет қаралды 19,811

Random Rick

Random Rick

Күн бұрын

How to set up an STM32 to sample an ADC input at a specific rate, with a timer generating "events" that automatically perform the next ADC acquisition. You'll see in the code that there's no timer ISR used to kick off each conversion - it's all automatic until the DMA buffer is full.

Пікірлер: 43
@icollided
@icollided 3 ай бұрын
Thanks for making this video. I have to go back to it every time I migrate my project to a different chip and set everything up all over again. It would be nice if STM32cubeIDE would just let you select a different chip, and highlight issues that need to be solved manually.
@tshepomaredi_
@tshepomaredi_ 2 жыл бұрын
Didn't go through the DMA configuration.
@tomvogel2301
@tomvogel2301 2 жыл бұрын
Thanks Rick, very helpful.
@jiryongcho7710
@jiryongcho7710 Жыл бұрын
Clear and easy! Very helpful!
@rich2956
@rich2956 2 жыл бұрын
Well done! Very helpful.
@joerit633
@joerit633 2 жыл бұрын
Great video! Thank you Rick!!!
@robc3863
@robc3863 Жыл бұрын
Nice presentation! Your code only works on an 32F407VG if I enable DMA Continuous, which in the manual says "Bit 9 DDS: DMA disable selection (for single ADC mode) 1: DMA requests are issued as long as data are converted and DMA=1". Without that it just does one set of samples. I can see the timer3 OC toggle at the right frequency, so not sure why it doesn´t work without.
@ishuvarshney9162
@ishuvarshney9162 11 ай бұрын
I want to read 1 khz analog waveform after 50 microsecond of rising edge on adc which method of adc should i use for this
@hsenaed6894
@hsenaed6894 3 жыл бұрын
Please.Can you help me explain how to activate a XOR mode
@L2.Lagrange
@L2.Lagrange 2 ай бұрын
This is very interesting. Thank you
@merveozdas1193
@merveozdas1193 Жыл бұрын
Can you take a video about the outputs, I could not get an output
@merveozdas1193
@merveozdas1193 Жыл бұрын
Hi your video is really good, but I need to write these results by using usart but I don't know in which function can I write, I an writing in convcallback function,I could not see any output, I write in while it has no output also, what can I do to make it write by usart?
@m1geo
@m1geo Жыл бұрын
Really useful, thanks! 👌
@rick_er2481
@rick_er2481 2 жыл бұрын
Thanks Rick good video (Y)
@brahimmazighi2116
@brahimmazighi2116 Жыл бұрын
Thank you , it worked for me , the only issue is the adc is giving wrong reading in the buffer for indexes 1, 3,5...... when i use this method and the error is fixed where i get 2920 instead of 3520 for all of them ( im using a fixed dc signal just to test which corresponds to 3520) , but when i use the normal case without timers i dont get that error , so for indexes 0,2,4.... i get correct values 3520 . any idea why this is happening ?
@randomrickUK
@randomrickUK Жыл бұрын
No, sorry, I don't have an immediate idea of what's happening here. It doesn't make sense to me that only certain ADC acquisitions would give the wrong ADC reading. I'd really have to see both the code and the circuit to help further with this issue. I hope you manage to find an answer.
@gundaharishkumar6856
@gundaharishkumar6856 2 жыл бұрын
In your case whether configuring dma is not required?
@Brono25
@Brono25 2 жыл бұрын
I think it should be
@johansvensson6542
@johansvensson6542 Жыл бұрын
Hi I'm quite new at this and I got stuck and need some help. Creating the tx buffer gives me a compiler failure, did I forget to include something?
@randomrickUK
@randomrickUK Жыл бұрын
Hi Johan. First thing to check is the automatically generated code. Near the beginning of main() in main.c you will find the calls to the initialisation functions. Check that the call to MX_DMA_Init() comes BEFORE the call to MX_ADC_Init(). Sometimes CubeIDE gets this wrong, and you have to manually edit it. Though of course if you re-run the code generator, it will overwrite your change and you'll have to re-apply it.
@johansvensson6542
@johansvensson6542 Жыл бұрын
@@randomrickUK Hi I got everything working except the dma buffer variables, the compiler just wont accept these ones: uint16_t dmaBuffer[DMABUFLEN]; char txBuf[TXBUFLEN]; So could you please help me out with those aswell?
@randomrickUK
@randomrickUK Жыл бұрын
@@johansvensson6542 Do you mean the compiler complains about the 2 lines of code you showed me? Or their use somewhere else? It looks to me like one buffer is for ADC and the other is for UART but I don't know if you're using DMA for both or just for the ADC. Have you declared (#define) DMABUFLEN and TXBUFLEN? If so, tell me what the error message is that you're getting from the compiler, and then maybe I can help. Or do you mean that it compiles OK but just doesn't work when you run your code?
@roopesh668
@roopesh668 Жыл бұрын
Hi! What is the use of sampling?
@randomrickUK
@randomrickUK Жыл бұрын
"sampling" is just another way of saying "take ADC readings".
@Alan96555
@Alan96555 Жыл бұрын
how can i change the samplig rate in the while?
@Alan96555
@Alan96555 Жыл бұрын
and also, why you dont show the dma settings?
@mlorand6968
@mlorand6968 2 жыл бұрын
If you set dma to circular mode then you don't have to start dma again in interrupt
@aliismail2357
@aliismail2357 Жыл бұрын
That didnt work, the conversion complete callback was called once and stopped. Did you change anything in the ADC configuration so it doesn't stop?
@merveozdas1193
@merveozdas1193 Жыл бұрын
I could not understnd exactly, I need to sample my signal at 1000 Hz, what can I change from your code?
@randomrickUK
@randomrickUK Жыл бұрын
You need to change the settings of the timer (i.e. not the ADC). You need to set both the Prescaler (the PSC register) and the Counter Period (the ARR register) so that together they slow down the system clock to your 1000Hz (or 1 millisecond). This doesn't slow down the whole device - it just affects that timer, which is what we want. Although one part is called a prescaler and the other is called a counter, they both have the same effect of dividing down the main clock for your timer. So the timer runs at "system clock / prescaler / counter". Remember to reduce the value of both parameters by 1 due to the way the timer circuit works. For example, if you want the prescaler to be 50, then the value in the register should be 49. There is often more than one combination of Prescaler/Counter values that will give the same result. But for 1000Hz, it should be pretty easy unless you have a strange main system clock like 12.321 MHz, but you probably haven't. Let's say your system clock is 8MHz. That needs dividing (slowing) down by 8000 to get to your target of 1000Hz. Here are a couple of combinations that could do that: Prescaler 8000, Counter 1 (but that would be 7999 and 0 in the registers) Prescaler 1000, Counter 8 (999 and 7 in the registers) Be careful not to choose values that are too big for the registers! On some parts and in some timers, the Prescaler is only 16 bit, so you can't choose numbers bigger than the maximum for 16 bits. If you want to get a 1Hz pulse, you can't just put 8000000 in to the Prescaler because that number is too big.
@merveozdas1193
@merveozdas1193 Жыл бұрын
Thank you so much, for example if I choose 10 MHz and I did not divide it(so I chose divider 0), I arranged the ARR to 999, is this divider calculation true?but I have another question, I am getting EEG signals, do not I need to use Contunious Conversion instead of single conversion?
@joshuachettiar86
@joshuachettiar86 2 жыл бұрын
I'm facing a bug if i follow the video exactly only the first element of the array is getting updated and the other 9 are still at 0 Update: it got fixed after using HAL_TIM_PWM... instead of HAL_TIM_Base..
@randomrickUK
@randomrickUK 2 жыл бұрын
I'm glad to hear you got it fixed.
@joshuachettiar86
@joshuachettiar86 2 жыл бұрын
@@randomrickUK well apparently even if my ADC can run at 2.4 msps it will not get triggered with the timer from 1-2.4msps but will works very well from below 1msps
@roopesh668
@roopesh668 Жыл бұрын
what is the length of dma buffer
@randomrickUK
@randomrickUK Жыл бұрын
The DMA buffer can be any size you want, as long as you have enough spare RAM for it. You then pass that size to the HAL_ADC_Start_DMA() call when beginning the conversion.
@windigzweimal1414
@windigzweimal1414 Жыл бұрын
@@randomrickUK Sir, maybe Roopesh means max of dma buffer, I try STM32H743(RM0433 page.622) max of dma buffer is 65535. Other series of stm need to check the manual.
@joshuachettiar86
@joshuachettiar86 2 жыл бұрын
Will this work for highers speeds?
@randomrickUK
@randomrickUK 2 жыл бұрын
Hi - yes, it'll potentially work at higher speeds, but of course as the speeds go up, you need to consider the sample time setup of your adc - the more cycles, the more time each conversion will take. So you have to make sure that the conversion time is not longer than the (time) spacing of the ADC acquistions you want. Also remember that there's a certain number of (ADC clock) cycles over the number you choose in setting up the ADC - maybe they're all 12.5 cycles, or maybe that's just the last device I checked! So if you select "1.5 cycles" as your acquisition time, it's really 1.5 + 12.5 = 14 cycles of your ADC clock per ADC reading.
@joshuachettiar86
@joshuachettiar86 2 жыл бұрын
@@randomrickUK in the black pill it takes 15 ADC clock cycles for 1 sample, so suppose I set up a DMA for 100 samples and I set the Timer such that the time between edges is 15 ADC clock cycles. According to the video the DMA is ready untill all the buffer is filled right so i thought is it possible to vary sampling rate from max sampling rate to a very low sampling rate(32bit timer), also do we need to consider the time the DMA will take to send the sample from ADC to memory?
@randomrickUK
@randomrickUK 2 жыл бұрын
@@joshuachettiar86 If you set the timer to 15 ADC clock cycles, you're not achieving much - you may as well just set up the ADC to Continuous mode, which means "don't wait to be told to start the next ADC conversion - do it immediately". Using the timer is to achieve precise timing at a rate you want that's slower than the maximum possible (that being Continous Mode). Yes, the DMA Conversion Complete callback happens when the buffer is full. You can also have a callback for when the buffer is half full too. If you gate each separate conversion into the DMA buffer on the timer, I see no reason why you can't vary that timer as you wish, and of course the callback will simply happen when that buffer is full. I don't know the exact number of cycles the DMA takes to put each ADC value into each element of the DMA buffer, but it puts each sample in as it comes, so it's very quick - it doesn't wait until the end and then fill it up. What CAN take time is your callback at the end of the DMA buffer. What you do in your callback is unknown, of course, but keep in mind that if you want to immediately start the next DMA buffer fill (so you've configured your DMA as a circular buffer), you won't have a lot of time to process the current buffer contents before the start of it begins to be filled again. It's for this reason that we can use the half-buffer method. Say you want to add up all the ADC readings once the DMA buffer is full: it may take more time to do that than is available before the ADC starts to fill up the buffer over again. In this case, add up the first half of the buffer half way through and then complete it at the end of the DMA at which point you've already added up the first half so it doesn't matter if the ADC overwites the last values.
@joshuachettiar86
@joshuachettiar86 2 жыл бұрын
@@randomrickUK thanks!!! so i will just configure the code such that when i want the MAX sampling the ADC will switch to continuous conversion and when i want to lower it i will switch it such that the timer triggers it. thank you alot!!!! for the explanation i will test it and get back
@wolpumba4099
@wolpumba4099 20 күн бұрын
*Summary* *Goal:* (Starts at 0:00) * Sample an ADC input at a specific rate (40kHz in the example) using an STM32F303K8 microcontroller. * Use timer events to automatically trigger ADC conversions, eliminating the need for software-triggered conversions. * Provide a debug output signal synchronized with the ADC sampling rate. *ADC Setup:* (Starts at 1:16) * *Disable Scan Conversion Mode:* Ensures that only a single ADC channel is sampled. * *Disable Continuous Conversion Mode:* Prevents continuous ADC conversions; conversions will be triggered by the timer. * *Set External Trigger Conversion Source:* Select the timer output event that will trigger the ADC conversions (Timer 1 Trigger Out Event in this case). * *Configure Trigger Polarity:* Choose whether the ADC conversion should be triggered on the rising edge, falling edge, or both edges of the timer output. *Timer Setup:* (Starts at 3:05) * *Select Internal Clock Source:* Use the internal clock to drive the timer. * *Configure Timer Period (ARR Register):* Set the timer period to achieve the desired ADC sampling rate. The example uses a period of 1000 clock cycles for a 40kHz sampling rate with a 40MHz clock. * *Enable Update Event Generation:* This event is triggered when the timer counter resets, which will be used to trigger the ADC conversions. * *Configure Output Compare Channel (Optional):* This can be used to generate a debug output signal synchronized with the ADC sampling rate. The example configures Output Compare Channel 1 to toggle on every timer counter reset, generating a square wave at the sampling frequency. *Software Implementation:* (Starts at ~5:22 - not explicitly stated but code walkthrough begins) * *Initialize Timer and ADC:* Set up the timer and ADC peripherals with the desired configurations. * *Start Timer and Output Compare (if used):* Enable the timer and output compare channel to begin generating trigger events and debug output. * *Start ADC DMA:* Configure and enable DMA to transfer ADC conversion data to a memory buffer. * *Handle DMA Conversion Complete Callback:* This callback function is called when the DMA buffer is full. It can be used to process the acquired ADC data and restart the DMA transfer for the next buffer. *Key Points:* * The code leverages hardware features (timers and DMA) to automate the ADC sampling process, minimizing software overhead. * No interrupt service routines are required for ADC conversions. * A debug output signal allows for visual verification of the sampling rate. i used gemini 1.5 pro to summarize the transcript.
STM32 PWM basics
18:31
Random Rick
Рет қаралды 19 М.
HAL #13: ADC with DMA
10:15
Web learning
Рет қаралды 40 М.
Самый Молодой Актёр Без Оскара 😂
00:13
Глеб Рандалайнен
Рет қаралды 6 МЛН
ОСКАР vs БАДАБУМЧИК БОЙ!  УВЕЗЛИ на СКОРОЙ!
13:45
Бадабумчик
Рет қаралды 6 МЛН
Red❤️+Green💚=
00:38
ISSEI / いっせい
Рет қаралды 76 МЛН
Workings of ADC with HAL | VIDEO 24
48:39
Matej Blagšič
Рет қаралды 3,4 М.
Tutorial STM32 DAC Timer Triggered DMA
34:08
PR TechTalk
Рет қаралды 2,9 М.
rust runs on EVERYTHING (no operating system, just Rust)
18:10
Low Level Learning
Рет қаралды 350 М.
STM32CubeIDE basics - 10 ADC DMA TIM HAL lab
31:32
STMicroelectronics
Рет қаралды 58 М.
Fixing The STM32 CubeMX Bug When Using The I2S With The DMA
17:43
Tripplikit Electronics
Рет қаралды 6 М.
Stable Diffusion in Code (AI Image Generation) - Computerphile
16:56
Computerphile
Рет қаралды 288 М.
STM32 Multi ADC DMA method
29:42
PR TechTalk
Рет қаралды 4,7 М.
I Melted Wood With Friction
8:44
The Action Lab
Рет қаралды 843 М.
SMT32 ADC Interrupts with STM32CubeIDE
9:49
Random Rick
Рет қаралды 11 М.
ADC in STM32 || Single Channel || Keil
16:08
ControllersTech
Рет қаралды 33 М.
САМЫЙ ДОРОГОЙ ЧЕХОЛ! В стиле Mac Pro
0:35
Romancev768
Рет қаралды 146 М.
Смартфон УЛУЧШАЕТ ЗРЕНИЕ!?
0:41
ÉЖИ АКСЁНОВ
Рет қаралды 1,1 МЛН
Как распознать поддельный iPhone
0:44
PEREKUPILO
Рет қаралды 2 МЛН
Копия iPhone с WildBerries
1:00
Wylsacom
Рет қаралды 1,1 МЛН
Собери ПК и Получи 10,000₽
1:00
build monsters
Рет қаралды 2,8 МЛН