Page 1 of 1

internal ADC channels ?

Posted: Tue Jul 16, 2024 2:28 pm
by STM32ardui
Hello,

I want to try out the ADC internal channels example on a STM32G0B1CBT6

In example are some definitions:

Code: Select all

/* Values available in datasheet */
#if defined(STM32C0xx)
#define CALX_TEMP 30
#else
#define CALX_TEMP 25
#endif

#if defined(STM32C0xx)
#define VTEMP      760
#define AVG_SLOPE 2530
#define VREFINT   1212
#elif defined(STM32F1xx)
#define VTEMP     1430
#define AVG_SLOPE 4300
#define VREFINT   1200
#elif defined(STM32F2xx) || defined(STM32F4xx)
#define VTEMP      760			
#define AVG_SLOPE 2500			
#define VREFINT   1210			
#endif
In datasheet I found chapters:
5.3.4 Embedded voltage reference
5.3.21 Temperature sensor characteristics
5.3.22 VBAT monitoring characteristics

So:
a) VTEMP is "voltage at 30°C" - for this MCU 0,76 V?
b) AVG_SLOPE 2500 means 2,5 mV/°C?
c) VREFINT is the typical "internal reference voltage" - for this MCU 1,212 V

But there is no CALX_TEMP in datasheet.
Is is simply the temperature, for which VTEMP is valid - so 25°C or 30°C


BTW: I know from reference manual RM0444 chapter 15.10 Battery voltage monitoring there is a voltage divider. For STM32G0B1CBT6 it is Vbat/3. And I think some MCU have a divider by 4 - that's nothing I have to setup for my MCU?

Re: internal ADC channels ?

Posted: Tue Jul 16, 2024 3:07 pm
by fpiSTM
Did you test default example ? Did it work?

Re: internal ADC channels ?

Posted: Tue Jul 16, 2024 4:33 pm
by ag123
I tend to 1st look in the datasheet
https://www.st.com/en/microcontrollers- ... 0b1cb.html
5.3.21 Temperature sensor characteristics (pg. 113)
  • TL (1) VTS linearity with temperature - ±1 ±2 °C
  • Avg_Slope(2) Average slope min 2.3 typ 2.5 max 2.7 mV/°C
  • V30 Voltage at 30°C (±5 °C)(3) min 0.742 typ 0.76 max 0.785 V
  • tSTART(TS_BUF)(1) Sensor Buffer Start-up time in continuous mode(4) - 8 15 µs
  • tSTART(1) Start-up time when entering in continuous mode(4) - 70 120 µs
  • tS_temp(1) ADC sampling time when reading the temperature 5 - - µs
  • IDD(TS)(1) Temperature sensor consumption from VDD, when selected by ADC - 4.7 7 µA
then in the ref manual
https://www.st.com/resource/en/referenc ... ronics.pdf
15.9 Temperature sensor and internal reference voltage (pg 376)
the formula and procedure is given there, take note those steps about enabling the temperature sensor etc.
oh and I tend to set a long sample time for the ADC just so that it won't be reading that V_sensor too abruptly

but I tend to take the short cut

Code: Select all

Vadc = AdcValue / 4096 * 3.3;
Temp (deg C) = (Vadc - V30 ) * avg_slope  + 30 deg C
Vadc may be made more accurate e.g. spec sheet
5.3.19 Voltage reference buffer characteristics
Vrefbuf = 2.042 v

Vref_Value / 2.042 = 4096 / V_fullrange; // 4096 ~ 12 bits
V_fullrange = 4096 * 2.042 / Vref_Value
then plug
Vadc = AdcValue / 4096 * V_fullrange;

This is a bit speculative, and normally I tend to be lazy and simply plug 4096 ~ 3.3v :D
The projection based on Vrefbuf makes an assumption that V_fullrange may not be 3.3v, e.g. a bit lesser, but that I think such linear projection may given oddball V_fullrange value which may 'exceed' 3.3v, possibly due to linearity issues etc.
I've seen wildly wrong temperatures from 'board to board', my guess is some of those in the 'flea market' may have bad chips.
Normally, when the formula 'works' e.g. give a value pretty close to room temperature, I'd simply make do and leave that formula as is.

a main use of that temp sensor is when I try to put that pill board in an enclosed enclosure, just to check that it isn't running too 'hot' (I've seen like 40 deg C quite warm), I also tend to be lazy and would put a big battery rather than try to 'save power' :D

Re: internal ADC channels ?

Posted: Wed Jul 17, 2024 10:22 am
by STM32ardui
I simply asked, if I understand the values correctly ...

fpiSTM wrote: Tue Jul 16, 2024 3:07 pm Did you test default example ? Did it work?
I can compile and upload, but it doesn't work.
The output is:

Code: Select all

12:12:58.278 ->  ----- internal ADC channels ----- 
12:12:58.342 -> �
The first line is from an additional Serial.printf(), I placed in setup().

And if I add some output at beginning of loop()

Code: Select all

void loop() {
  Serial.println("inside loop() ...");
#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED)
  bool icache_enabled = false;
I get this:

Code: Select all

12:15:08.358 ->  ----- internal ADC channels ----- 
12:15:08.403 -> i�
one time!
So it doesn't look like loop() is working like a loop.

----------------------------------------------------------------------------------

I moved setup() in front of loop() and add some global variables:

Code: Select all

int32_t   VRef;
int32_t   temp;
int32_t   vbat;


void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  delay(2000);
  Serial.printf("\n\n ----- internal ADC channels ----- \n");
  analogReadResolution(12);

  VRef = readVref();
  temp = readTempSensor(VRef);
  vbat = readVoltage(VRef, AVBAT);
  Serial.printf("VRef = %imV  temp = %i°C  Vbat = %imV   ", VRef, temp, vbat);
}
Now I get this output:

Code: Select all

12:35:17.469 ->  ----- internal ADC channels ----- 
12:35:17.502 -> VRef = 3281mV  temp = 29°C  Vbat = 1090mV   inside loop() ...
12:35:17.569 -> VRef(mv)= 3281�
Value of VBAT is wrong!
I connected a mignon cell between VB-pin and GND-pin of board. It should be the VBAT-pin. Even without a cell in battery holder, sketch returns 1,09 V.

This is the part of schematic:
RTC circuit.png
RTC circuit.png (46.1 KiB) Viewed 3827 times
So measuring of VBAT is useless.
But sketch should show VCC.
Is there a bug not taking care about voltage divider? 1,09 * 3 would make sense ..


--------------------------------------------------------------------------------------

I throw away all content from loop() and moved 4 last lines from setup() there.
I placed something out of cooler on chip and temperature is going down.

Code: Select all

12:48:54.207 -> VRef = 3279mV  temp = 30°C  Vbat = 1090mV   
12:48:59.198 -> VRef = 3283mV  temp = 30°C  Vbat = 1091mV   
12:49:04.212 -> VRef = 3283mV  temp = 30°C  Vbat = 1091mV   
12:49:09.186 -> VRef = 3279mV  temp = 29°C  Vbat = 1088mV   
12:49:14.180 -> VRef = 3281mV  temp = 30°C  Vbat = 1090mV   
12:49:19.198 -> VRef = 3283mV  temp = 30°C  Vbat = 1091mV   
12:49:24.169 -> VRef = 3279mV  temp = 30°C  Vbat = 1089mV   
12:49:29.172 -> VRef = 3283mV  temp = 24°C  Vbat = 1091mV   
12:49:34.159 -> VRef = 3281mV  temp = 23°C  Vbat = 1089mV   
12:49:39.178 -> VRef = 3281mV  temp = 23°C  Vbat = 1089mV   
12:49:44.149 -> VRef = 3281mV  temp = 22°C  Vbat = 1091mV   
12:49:49.159 -> VRef = 3283mV  temp = 22°C  Vbat = 1091mV   
12:49:54.145 -> VRef = 3281mV  temp = 21°C  Vbat = 1091mV   

A last remark: example calls two times Error_Handler();
I placed a Serial.println(...) before and forget semicolon at the end. Compiler doesn't complain. So I guess that preprocessor removes those parts.

Re: internal ADC channels ?

Posted: Wed Jul 17, 2024 12:19 pm
by fpiSTM
Testing the default example on a Nucleo G0B1RB I have no issue (A0 connected to 3.3V):

Code: Select all

VRef(mv)= 3310	Temp(°C)= 28	Vbat(mv)= 1110	A0(mv)= 3310
VRef(mv)= 3312	Temp(°C)= 29	Vbat(mv)= 1111	A0(mv)= 3312
VRef(mv)= 3308	Temp(°C)= 28	Vbat(mv)= 1108	A0(mv)= 3304
VRef(mv)= 3308	Temp(°C)= 28	Vbat(mv)= 1109	A0(mv)= 3308
VRef(mv)= 3308	Temp(°C)= 28	Vbat(mv)= 1110	A0(mv)= 3299