I am a beginner and hope for guidance

Post here first, or if you can't find a relevant section!
Backflip
Posts: 28
Joined: Fri Nov 14, 2025 6:09 pm
Answers: 0

Re: I am a beginner and hope for guidance

Post by Backflip »

Thanks again.

I got an issue with my way to address the registers of the ADCs. When I try to read them, I get zero in the result. And it seems I cannot change anything there. I tried to change the clock pre scaler value, and it did not change the conversion time.

This is my code:

Code: Select all

/*
Tests with Nucleo-64 STM32G474RE summer 2026
Test of Analog input on  via Arduino Framework
Test of Digital input output via Arduino Framework
Test of Serial Monitor
*/

// the setup function runs once when you press reset or power the board

bool di= false;
int potmeter = 0;
uint32_t maskCommonCCRPresc = 0b00000000001111000000000000000000; //0b00000000 00111100 00000000 00000000
uint32_t presc256 = 0b00000000001011000000000000000000;
uint32_t presc4 = 0b00000000000010000000000000000000;
uint32_t adcClkFrq;
uint32_t ADCregister;

void setup() {
  // initialize pin inputs and outputs
  delay(8000);
  pinMode(A2, OUTPUT);              // External LED and in series with 180 ohm to GND
  pinMode(A5, INPUT);               // Switch is connected to VCC and recistor to GND.
  pinMode(A0, INPUT_ANALOG);  
  analogReadResolution(12); 
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  ADCregister = ADC12_COMMON->CCR;
  Serial.print("ADC12_CCR: ");
  Serial.println(ADCregister, BIN);
  ADC12_COMMON->CCR = (ADC12_COMMON->CCR & ~maskCommonCCRPresc) | presc256;
  ADCregister = ADC12_COMMON->CCR;
  Serial.print("ADC12_CCR after manipulation: ");
  Serial.println(ADCregister, BIN);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(A2, digitalRead(A5));  // turn the A2 output according to A5 input
  digitalWrite(LED_BUILTIN, HIGH);    // Takes about 210 ns or about 36 CPU clockcycles.
  potmeter = analogRead(A0);          // Inputs a 10 bit value from AD-converter even though it is a 12 bit ADC in MPU.
                                      // The reason is likely due to portability of software.
  digitalWrite(LED_BUILTIN, LOW);     // I measured the excecution time here by digital oscilloscope. It is 150 us !!!

  ADCregister = ADC12_COMMON->CCR;
  Serial.print("ADC12_CCR: ");
  Serial.println(ADCregister, BIN);
  ADCregister = ADC1->CR;
  Serial.print("ADC1_CR: ");
  Serial.println(ADCregister, BIN);
  ADCregister = ADC2->CR;
  Serial.print("ADC2_CR: ");
  Serial.println(ADCregister, BIN);

  Serial.print("Potvalue: ");
  Serial.println(potmeter);
  delay(2000);                      // wait for a 0.1 second
}
This is the first lines of output on the Serial Monitor:

ADC12_CCR: 0
ADC12_CCR after manipulation: 0
ADC12_CCR: 0
ADC1_CR: 0
ADC2_CR: 0
Potvalue: 885
ADC12_CCR: 0
ADC1_CR: 0
ADC2_CR: 0
Potvalue: 879
ADC12_CCR: 0
ADC1_CR: 0
ADC2_CR: 0
Potvalue: 885
ag123
Posts: 1987
Joined: Thu Dec 19, 2019 5:30 am
Answers: 33

Re: I am a beginner and hope for guidance

Post by ag123 »

I think there are quite a few things to use an ADC, among them to clock the ADC and to enable the ADC.
if you are not using one of the LLMs you could even use meta.ai if the rest aren't free, but that there are the likes of chatgpt, gemini, co-pilot in github which can propose some codes, there are actually many more LLMs these days including some local ones.
you could probably use stm32cube IDE to generate some codes for the ADC and review how it is done there, that is easier as Cube IDE has a graphical interface to guide configuring the ADC, after that start copying over some codes to work with the ADC.
there is also the plain 'old' web (e.g. google) search, you would find lots of examples for stm32, in particular if you search in github, there are lots of codes.

I think @fpiSTM has created an example here to use HAL for ADC
viewtopic.php?t=110

there are some other examples here but that these are for the 'internal channels'
https://github.com/stm32duino/STM32Exam ... annels.ino

do take note that in the (board) variant, there are clock setup codes in SystemClock_Config(void) e.g.
https://github.com/stm32duino/Arduino_C ... ic_clock.c
https://github.com/stm32duino/Arduino_C ... ic_clock.c
the ADC clocks are derived from the main system clock after setting up the system clock

some of the ADC handling codes in stm32duino (STM) core are here
https://github.com/stm32duino/Arduino_C ... analog.cpp
https://github.com/stm32duino/Arduino_C ... g_analog.c
that is the base from which you get analogRead() etc.
Backflip
Posts: 28
Joined: Fri Nov 14, 2025 6:09 pm
Answers: 0

Re: I am a beginner and hope for guidance

Post by Backflip »

I finally got the ADC to work with my code, so it will be possible for me to investigate it further.

You can use the Arduino Framework with analogRead, but it comes with a lot of limitations. The conversion time duration is very long and about 150 us. In the last part of analogRead, the AD-converter is set in Deep-power-down mode and the two clock signals to the ADC is removed in the RCC system. If you want to discover how analogRead uses the ADC, you cannot read the relevant registers afterword's to get information.

The ADCs use two different clock inputs, that can be switched on and off separately by the RCC controller. One input is for the digital interface, and the other is for the AD-conversion. But the clock for the AD-conversion can be made in more different ways and with different prescalers and switches needed to pass the clock signal. The clock configuration diagrams given seem misleading, and it is not always clear which of the two clock signals, that the functions address.

The Arduino Framework sets the Nucleo-STM32G474RE to use the HSE 24 MHz crystal clock input to control the PLL, so it provides a 170 MHz system clock. You might see the STM32CubeMX Clock Configuration diagram. It is not the default CubeMX setting, because it utilizes the HSI RC oscillator. Furthermore, the Arduino framework sets the divider before the PLLP output to 2. The ADCs are left in deep power down-mode with no clocks.

I have used AI for many questions. It is often helpful, but sometimes you get misleading answers. I had an issue with reading somewhat wrong levels. After some time, I found an error regarding a default channel setting of differential input, but I should set single ended channel setting. AI had proposed code without setting the hal data structure for single ended input. And when I asked about the wrong readings, the answer was that I did not calibrate the ADC as I should. I lost a lot of time here...

With an ADC clock of 42.5 MHz, I get a conversion time duration with HAL functions of about 3.3 us. If you disable the ADC after conversion the time increases to 5.64 us. With bare metal code using the registers as proposed by ag123, the time is reduced to 0.91 us.

I have not seen any significant reduction in the ADC noise by reducing the ADC clock below 42.5 MHz. I guess you should utilize other methods to reduce noise in the signal.

This is the code I used to also investigate the settings of the RCC clock and the ADC:

Code: Select all

/*
Tests with Nucleo-64 STM32G474RE summer 2026
Test of Analog input on  via HAL procedures
Test of Digital input output via Arduino Framework
Test of Serial Monitor
*/

// the setup function runs once when you press reset or power the board

const uint32_t mask_RCC_CCIPR_ASC12_Clksource =    0B00110000000000000000000000000000;
const uint32_t set_RCC_CCIPR_ADC12_Clksource_PLL = 0B00010000000000000000000000000000;
const uint32_t set_RCC_CCIPR_ADC12_Clksource_sys = 0B00100000000000000000000000000000;
//                                                   10987654321098765432109876543210
uint32_t RCCregister;
uint32_t ADCregister;
int potmeter = 0;
uint32_t adc_value;

// Initialization data structures for HAL functions
GPIO_InitTypeDef GPIO_InitStruct;
ADC_ChannelConfTypeDef sConfig;
ADC_HandleTypeDef hadc1{};
ADC_HandleTypeDef hadc2{};
ADC_HandleTypeDef hadc3{};
ADC_HandleTypeDef hadc4{};
ADC_HandleTypeDef hadc5{};

// Function to read out a 32bit hardware registers for me to analyze
void println32bin(uint32_t i) {
  if (i<2147483648) Serial.print("0"); //32 bits
  if (i<1073741824) Serial.print("0");
  if (i<536870912) Serial.print("0");
  if (i<268435456) Serial.print("0");
  if (i<134217728) Serial.print("0"); //28 bits
  if (i<67108864) Serial.print("0");
  if (i<33554432) Serial.print("0");
  if (i<16777216) Serial.print("0");
  if (i<8388608) Serial.print("0"); //24 bits
  if (i<4194304) Serial.print("0");
  if (i<2097152) Serial.print("0");
  if (i<1048576) Serial.print("0");
  if (i<524288) Serial.print("0");
  if (i<262144) Serial.print("0");
  if (i<131072) Serial.print("0");
  if (i<65536) Serial.print("0");
  if (i<32768) Serial.print("0"); //16 bits
  if (i<16384) Serial.print("0");
  if (i<8192) Serial.print("0");
  if (i<4096) Serial.print("0");
  if (i<2048) Serial.print("0");
  if (i<1024) Serial.print("0");
  if (i<512) Serial.print("0");
  if (i<256) Serial.print("0");
  if (i<128) Serial.print("0");
  if (i<64) Serial.print("0");
  if (i<32) Serial.print("0");
  if (i<16) Serial.print("0");
  if (i<8) Serial.print("0");
  if (i<4) Serial.print("0");
  if (i<2) Serial.print("0");
  Serial.println(i,BIN);
  Serial.println("10987654321098765432109876543210");
  };

void setup() {
  // initialize digital pin LED_BUILTIN as an output. Prøver nu i stedet A2.
  delay(8000);
  pinMode(A2, OUTPUT);              // External LED and in series with 180 ohm to GND. It is PA4
  pinMode(A5, INPUT);               // Switch is connected to VCC and recistor to GND. It is PC0
  pinMode(LED_BUILTIN, OUTPUT);     // LD2 on board. It is PA5

  Serial.begin(115200);
    // Checks some settings
      // 1. Specify which ADC to initialize
   
  // 2. Configure ADC Parameters
  //hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;  //SYNC clock do work, but ASYNX clock don't
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.GainCompensation = 0;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.SamplingMode = LL_ADC_REG_SAMPLING_MODE_NORMAL;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;

  hadc2 = hadc1;
  hadc3 = hadc1;
  hadc4 = hadc1;
  hadc5 = hadc1;
  hadc1.Instance = ADC1; 
  hadc2.Instance = ADC2; 
  hadc3.Instance = ADC3; 
  hadc4.Instance = ADC4; 
  hadc5.Instance = ADC5; 

  // Use of Arduino framework to input analog isgnal
  pinMode(PA0, INPUT_ANALOG);
  analogReadResolution(12);

  potmeter = analogRead(A0);  //After this reading, the ADC enters Deep Power Down mode and all RCC clocks for ADC are removed.
  Serial.println("Potvalue from analogRead: ");
  Serial.println(potmeter);

  //HAL code for setting input analog pin
  GPIO_InitStruct.Pin = GPIO_PIN_0;           // Change to your specific pin
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  __HAL_RCC_ADC12_CLK_ENABLE();  //changes bit 13 in RCC_AHB2ENR to 1 to enable the ADC12 digital interface clock
  __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_ADCCLK); //should activate output PLLP. Division should already be 2 from Arduino setting
                                              //it do set bit 17 in RCC_PLLCFGR

  //Here you set the AD-conversion clock source to ADC12.
  //LL_RCC_SetADCClockSource(LL_RCC_ADC12_CLKSOURCE_PLL); //seting bits 28,29 in RCC_CCIPR. Function seems not declared in Arduino framework
  //Then this is used instead:
  RCC->CCIPR = (RCC->CCIPR & ~mask_RCC_CCIPR_ASC12_Clksource) | set_RCC_CCIPR_ADC12_Clksource_PLL; //sets ADC12 clock source

  //Some status output for checks
  RCCregister = RCC->AHB2ENR;
  Serial.println("RCC_AHB2ENR: ");
  println32bin(RCCregister);
  ADCregister = ADC12_COMMON->CCR;
  Serial.println("ADC12_CCR: ");
  println32bin(ADCregister);
  ADCregister = ADC1->CR;   //At this point the ADC1 is in Deep-power-down (default reset state)
  Serial.println("ADC1_CR: ");
  println32bin(ADCregister);

  // Now other HAL initialization

   // 1. Stop current ADC conversion
  if (HAL_ADC_Stop(&hadc1) == HAL_OK )
    Serial.println("ADC1 stopped OK");
  else
    Serial.println("ADC1 error in stop");
  if (HAL_ADC_Stop(&hadc2) == HAL_OK ) 
    Serial.println("ADC2 stopped OK"); 
  else
    Serial.println("ADC2 error in stop");

  // 2. Configure the new channel (e.g., ADC_CHANNEL_1)
  
  sConfig.Channel = ADC_CHANNEL_1;      // Target new ADC Channel
  sConfig.Rank = ADC_REGULAR_RANK_1;    // Set as first rank in sequence
  //sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; // Adjust as needed
  sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED; // Very important initialization not documented everywhere
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  //sConfig.Offset = 1000;
  //sConfig.OffsetSign = ADC_OFFSET_SIGN_NEGATIVE;
  //sConfig.OffsetSaturation = DISABLE;
  
  switch (HAL_ADC_ConfigChannel(&hadc1, &sConfig)) {
  case HAL_OK:
    Serial.println("ADC1 Channel Config HAL_OK");
    break;
  case HAL_ERROR: 
  Serial.println("ADC1 Channel Config HAL_ERROR");
    break;
  case HAL_BUSY:
    Serial.println("ADC1 Channel Config HAL_BUSY");
    break;
  case HAL_TIMEOUT:  
    Serial.println("ADC1 Channel Config HAL_TIMEOUT");
    break;
  default:
    Serial.println("ADC1 Channel Config HAL_Otherwise");
    break;
  };
  
  
  // Initialization of ADC1 from HAL ADC data structure
  switch (HAL_ADC_Init(&hadc1)) {
    case HAL_OK:
      Serial.println("ADC1 Init HAL_OK");
      break;
    case HAL_ERROR: 
      Serial.println("ADC1 Init HAL_ERROR");
      break;
    case HAL_BUSY:
      Serial.println("ADC1 Init HAL_BUSY");
      break;
    case HAL_TIMEOUT:  
      Serial.println("ADC1 Init HAL_TIMEOUT");
      break;
    default:
      Serial.println("ADC1 Init HAL_Otherwise");
      break;
    };

  delay(10);

  //Prints some status regarding registers of ADC and RCC
  ADCregister = ADC12_COMMON->CCR;
  Serial.println("ADC12_CCR: ");
  println32bin(ADCregister);
  ADCregister = ADC1->CR;
  Serial.println("ADC1_CR: ");
  println32bin(ADCregister);

  //Dump of important RCC registers
  RCCregister = RCC->CR;
  Serial.println("RCC_CR: ");
  println32bin(RCCregister);
  RCCregister = RCC->CFGR;
  Serial.println("RCC_CFGR: ");
  println32bin(RCCregister);
  RCCregister = RCC->PLLCFGR;
  Serial.println("RCC_PLLCFGR: ");
  println32bin(RCCregister);
  RCCregister = RCC->AHB2RSTR;
  Serial.println("RCC_AHB2RSTR: ");
  println32bin(RCCregister);
  RCCregister = RCC->APB1RSTR1;
  Serial.println("RCC_APB1RSTR1: ");
  println32bin(RCCregister);
  RCCregister = RCC->APB1RSTR2;
  Serial.println("RCC_APB1RSTR2: ");
  println32bin(RCCregister);
  RCCregister = RCC->AHB2ENR;
  Serial.println("RCC_AHB2ENR: ");
  println32bin(RCCregister);
  RCCregister = RCC->APB1ENR1;
  Serial.println("RCC_APB1ENR1: ");
  println32bin(RCCregister);
  RCCregister = RCC->APB2ENR;
  Serial.println("RCC_APB2ENR: ");
  println32bin(RCCregister);
  RCCregister = RCC->AHB2SMENR;
  Serial.println("RCC_AHB2SMENR: ");
  println32bin(RCCregister);
  RCCregister = RCC->CCIPR;
  Serial.println("RCC_CCIPR: ");
  println32bin(RCCregister);

  HAL_ADC_Start(&hadc1);               //Start AD-conversion by ADC1
  //LL_ADC_Enable(ADC1);               //Alternative start command
  //LL_ADC_REG_StartConversion(ADC1);  //Alternative start command

  //Print some ADC status just after start of conversion
  ADCregister = ADC1->CR;
  Serial.println("ADC1_CR when started: ");
  println32bin(ADCregister);
  ADCregister = ADC12_COMMON->CCR;
  Serial.println("ADC12_CCR: ");
  println32bin(ADCregister);

  //Awaits ADC to finish conversion
  switch (HAL_ADC_PollForConversion(&hadc1, 100)) {
    case HAL_OK:
      Serial.println("ADC1 Conversion HAL_OK");
      break;
    case HAL_ERROR: 
      Serial.println("ADC1 Conversion HAL_ERROR");
      break;
    case HAL_BUSY:
      Serial.println("ADC1 Conversion HAL_BUSY");
      break;
    case HAL_TIMEOUT:  
      Serial.println("ADC1 Conversion HAL_TIMEOUT");
      break;
    default:
      Serial.println("ADC1 Conversion HAL_Otherwise");
      break;
    };

  adc_value = HAL_ADC_GetValue(&hadc1);
  potmeter = adc_value;
  Serial.print("Potvalue: ");
  Serial.println(potmeter);

  ADCregister = ADC1->CR;
  Serial.println("ADC1_CR: ");
  println32bin(ADCregister);
  ADCregister = ADC12_COMMON->CCR;
  Serial.println("ADC12_CCR: ");
  println32bin(ADCregister);
  };

// the loop function runs over and over again forever
void loop() {
  digitalWrite(A2, digitalRead(A5));  // turn the A2 output according to A5 input

  LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5);

  /*
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 100);
  adc_value = HAL_ADC_GetValue(&hadc1);
  potmeter = adc_value;
  */
  //HAL_ADC_Stop(&hadc1);        // increases time from 3.3 us to 5.65 us. So 2.35 us longer to disable ADC between measurements this way.
  //

  //ADC using direct register manipulation below.
  //The duration is 0.91 us with ADC clock of 42.5 MHz (or T=23.53 ns)
  //Changing the ADC clock to 16 times slower makes T=376.6 ns and the conversion time 11.6 us. 
  //It means that a time difference of 30 ADC clock cycles. The Channel configuration of 12.5 ADC clock cycles sample time is likely
  //somehow excecuted by the ADC hardware. Otherwise 30 ADC clock cycles don't make sense. Yes. This is confirmed by changing 
  //the channel configuration to 6.5 ADC clock cycles, and it reduces time from 11.6 us to 9.4 us.
  //By the way. The slow ADC clock cause a significant change in the measured potvalue from about 1150 to 1350. This needs investigation.
  //The input is very sensitive. Just putting a 10x oscilloprobe on makes a change from 1150 to 1230.
  //Adding a 100 nF capacitor to GND changed reading to about 1350. Oscillocope confirm no shift in value by this decoupling. It is there
  //with no capacitor. And with slow clock the voltage somehow recover with no capacitor. The capacitor do not reduce the 
  //noise seen in the measured value. Neither do the slow clock.
  //
  // 1. Clear previous conversion flags (flags are cleared by writing 1)
  ADC1->ISR = ADC_ISR_EOC | ADC_ISR_EOS | ADC_ISR_OVR;

  // 2. Start regular conversion
  ADC1->CR |= ADC_CR_ADSTART;

  // 3. Wait for conversion complete
  while ((ADC1->ISR & ADC_ISR_EOC) == 0U) {
    // wait
    };

  // 4. Read converted data
  potmeter = (uint16_t)ADC1->DR;

  LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_5);
  
  Serial.print("Potvalue: ");
  Serial.println(potmeter);
  delay(1000);                      // wait for a 1 second
  };
I have tried to make an enlarged clock diagram from page 597 in RM440 with focus on the ADC clock. But it is no official understanding of the design – only my beginner sketch. It is made after my faulty trials to make changes to the ADC clock frequency, so perhaps others might find this usefull. I cannot see a way to upload a picture here, so I make a link to the ST Community:
https://community.st.com/stm32-mcus-pro ... cus-167393
Backflip
Posts: 28
Joined: Fri Nov 14, 2025 6:09 pm
Answers: 0

Re: I am a beginner and hope for guidance

Post by Backflip »

Composite wrote: Sun Nov 30, 2025 2:25 am
Find this file somewhere in Arduino directory: stm32g4xx_hal_conf_default.h
make this changes:

Code: Select all

#include "stm32yyxx_hal_conf.h"

// 09-06-2020
#define HAL_OPAMP_MODULE_ENABLED
// 18-06-2020
#define HAL_HRTIM_MODULE_ENABLED
// 20-06-2020
#define HAL_CORDIC_MODULE_ENABLED
// 09-06-2022
#define HAL_COMP_MODULE_ENABLED
// 10-05-2023
#define HAL_I2C_MODULE_ENABLED
// 16-11-2023
#define HAL_DAC_MODULE_ENABLED


#if 0
like I did to activate peripheral needed.

[/code]
[/quote]

Thank you for this comment @Composite

I had problems with some HAL-functions for OPAMPS not being defined. Perhaps after an update, but I just started to use OPAMPS now. This trick helped to make it work with the Nucleo STM32G474RE board.
ag123
Posts: 1987
Joined: Thu Dec 19, 2019 5:30 am
Answers: 33

Re: I am a beginner and hope for guidance

Post by ag123 »

Code: Select all

I have not seen any significant reduction in the ADC noise by reducing the ADC clock below 42.5 MHz. I guess you should utilize other methods to reduce noise in the signal.
those are not 'noise' those are radio waves, stm32 adc is so sensitive that it can pick up radio waves from the air, especially if your wire input to ADC is sufficiently long, it becomes an antenna to receive the radio waves.
temperature and light logging
temperature and light logging
lighttemp260811.png (70.33 KiB) Viewed 164 times
you can probably add an RC filter to temper that somewhat if your signal variations is low enough
https://en.wikipedia.org/wiki/Low-pass_filter
otherwise, it'd take shielding to prevent picking up the radio waves.

that in a different sense makes the simple ADC an SDR (software defined radio)
Backflip
Posts: 28
Joined: Fri Nov 14, 2025 6:09 pm
Answers: 0

Re: I am a beginner and hope for guidance

Post by Backflip »

@ag123 Thanks for the advise, that the seen noise could also be received radio signals.

I only got previous experience with the older AtMega328p processer, and it came into production in 2008. It do have successive approximation ADC with a resistor network, and the manufacturer recommend to keep the ADC-clock below 200 kHz for max performance and below 1 MHz for derated performance. The STM32G4xx processors entered the marked in 2019 - 11 years later. I was just surprised to notice, that the datasheet for the G4 processors stated, that max ADC performance could be expected up to a 60 MHz. So in 11 years you can see a speed increase of 300 times with higher accuracy. The new ADCs are also successive approximation ADC, but with switched capacitor technique.

Therefore I have been a bit stunned about the increased speed performance and liked to verify just a little.

I have tried to look at the performance of a AtMega328p ADC when I increased the ADC clock frequency from 125 kHz to 1 and 2 MHz. You can see the result here:
https://forum.arduino.cc/t/arduino-nano ... or/1204040.

At 2 MHz clock frequency, you see, that most input analog values are converted OK, but a few analog values cause significant conversion errors. In this way it becomes misleading to characterize the effect of higher ADC-clock frequency as just an increase in "random noise" in the resulting output value.

I have not analyzed the STM32G4xx processors much, but I have noticed on my Nucleo board, that close capacitive decoupling at inputs cause a significant reduction in the seen noise. Furthermore the use of differential mode ADC input with no close decoupling can also cause a significant reduction. This observation I reported here: https://community.st.com/stm32-mcus-pro ... bad-167443.
ag123
Posts: 1987
Joined: Thu Dec 19, 2019 5:30 am
Answers: 33

Re: I am a beginner and hope for guidance

Post by ag123 »

@Backflip the 'proof' of receiving radio waves is indicated in the irradiance chart I presented earlier, notice that in the early morning hours, there are hardly any 'spikes', that is correct as it is after all dark.
but the circled area at night shows a lot of spikes and it is dark, the difference being that I operated my computer and the photodiode (an bpw34 photodiode) is about a meter away from the computer.
the wires are about 15-20 cm long hence this shows that it (the wire) is picking up the EMI emissions.
I could have added a 10 uF capacitor to suppress (filter) it, but I did not.

I'm not too sure about radio tech, but that I'd guess if one build an LC tank with the antenna (the wire) thereby suppressing the untuned frequencies, and that one samples that LC tank as input, one could literally operate it as an AM or SW radio, the antenna (wire) and the LC tuning is key as otherwise I'd guess normal radio waves are too low to be detectable.
to make things 'easier' would be to simply operate it literally through a diode and rc cap, thereby making it a diode detector, then the AM / SW output is simply audio, well within ADC sampling rates. a silicon diode detector needs like 0.7v, if a radio can operate with that, the amplification created by the antenna and LC tank is probably it, pushing the voltages well above diode voltages to be detectable.

removing that 'noise' I'd guess depends on the context, if the signal frequency is well lower than the 'noise' then an RC filter does it well.
viewtopic.php?p=8486#p8486
otherwise I'd guess it'd take shielding etc to prevent the ADC from picking up the signals. of course there could be other noise sources, accordingly cosmic background radiation (beta particles) could occasionally cause a tick, but I'd guess it is 'rare', then thermal noise etc.
but for the most common 'modern' source, it is probably radio waves (EMI).

on a side note, I wanted to build an fm radio but is noob about RF and radio, I need to make a VCO (I'm thinking if a stm32 could literally provide the 'LO' at 100 mhz! a trouble is this needs to be tuned) and a mixer stage, unfortunately the venerable SA602 is no longer produced
https://www.nxp.com/docs/en/data-sheet/SA602A.pdf
https://www.digikey.com/en/products/bas ... 602/143073
it kinds of leave me scrambling to find an equivalent.
that mixes FM broadcast frequencies the VCO + RF to produce 10.7 mhz IF
and I'd need a bandpass to get that output
if all these can be pieced together, the theory goes that if one samples this 10.7 mhz IF, does an FFT, one literally demodulate the FM and built a digital FM receiver !
I'm still lacking the skills in putting these together.
Post Reply

Return to “General discussion”