How to measure/know precisely the ADC reference voltage on STM32L052K6T6? - stm32

I am currenctly working on STM32L052K6T6.
I would like to know if there is an appropriate way to measure precisely the voltage used by the adc.
I read through the documentation that this voltage was on adc_channel17 but i have no idea on how to get it.
I also read there was a calibration Variable called VREFINT_CAL but again i did'nt see the process to use it properly.
I know this voltage is for me around 1.8V. But i need to know it untill 1.80000 at least to calculate accurate values of my sensor.
To program my MUC i am using Atollic, i did the basic pins configuration using STM32CubeMX.

The internal reference voltage is not used by the ADC. It is only used to measure the actual Vref voltage. Vref voltage depending on the version of the chip can be Vref+ or Vdda.
How to measure the actual Vref?
You need to measure the Vrefint (which is about 1.2V) and then using the simple math calcultate the Vref
Vrefint = Vref * (RAW_ADC / 4096)
So Vref = Vrefint * 4096 / RAW_ADC
or if you want to use VREFINT_CAL : Vref = 3 V * VREFINT_CAL / RAD_ADC

You have to do a calibration before measuring good value of channel VREF_INT.
HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);

Related

STM32 generate 22Mhz clock on gpio out from SystemCoreClock 110Mhz

I want to generate clock for PCA9959 LED driver with my STM32L552. The LED driver needs an external clock at 20 MHz (+/- 15%). I'm trying to generate a 22 MHz clock on port PA8 on STM32L552. I managed to generate a PWM on port PA8, but I can't reach the frequency of ~22Mhz. I arrive at a maximum of 8Mhz.
Here are the PWM parameters:
I'm not sure I filled in the pwm parameters correctly. Normally with his settings I guess I should have a 22 MHz PWM with a 20% duty cycle.
PWM (MHz) = SystemCoreClock (MHz) / Prescaler => 22MhZ = 110MHz / 5
My clock configuration:
Thanks for your help.
The easiest way to output a high speed clock like this is with the MCO peripheral, rather than a timer. Fortunately for you the MCO pin is PA8. Perhaps the person who designed your board knew this and intended you to use MCO. Read the reference manual to see how.
If you do want to use a timer to do 22MHz, then as you have correctly identified you cannot get a 50% duty-cycle on your PWM. I would recommend starting with a 40% or 60%, with an output-compare value of 2-out-of-5 or 3-out-of-5, not 1 as you have above.
There is no detail in the PCA9959 datasheet about what the required mark-space ratio of the clock is, but I guess anything other than 50% could be a problem. You would be better to divide the clock by an even number. Either just divide 110MHz by 6 and output 18.33MHz, or else slow your core down a bit and divide by 4 (reduce the N parameter of your PLL).
Whether you use MCO or PWM don't forget to set the GPIO pin mode to the fastest slew rate available. Maybe the 8MHz you are measuring is the result of aliasing a faster clock that has been through the wrong GPIO mode. You could test this using a scope with at least 100MHz bandwidth.

Raspberry Pi - How to measure 2 resistor values with GPIO

Is it possible to measure 3 specific resistor values by using GPIO / Without using a full ADC setup?
I have an alarm sensor that I want to hook up to my GPIO. This sensor has 3 specific resistors value, based on it's state:
1) Normal - 4k7
2) Alarm - 9k3
3) Tamper - infinite.
Due to long lines, I would prefer 12V power on one side.
I would like to be able to detect these states by 2 normal GPIO input pins.
Is that even possible? What would be the schematic needed for this?
Or is the only solution to use (external) ADC's?
I am thinking about a voltage diver with resistors and a 1N4148 diode to clip it to 3v3. But so far my results are unfruitfull.
Thanks.
The problem here is you have three levels to measure. If we had two we could use a simple resistor divider setup to make (say) the 4k7 and 9k3 outputs on the sensor to logic 0 (<=0.8V) or logic 1 (>=1.3V) on a single GPIO pin. We could do this on two GPIO pins if we had two "independent samples" of the sensor output rather than one.
Given the above it is possible to design some simple logic network to do the comparisons but as the other comment mentions you're off into the realms of electronics.
ADC is the simplest way to go if you want to stay in the software domain. The are other SBC devices e.g. ESP8266 which have onboard ADC functionality and built-in Wifi https://esp8266-projects.org/2015/03/internal-adc-esp8266/ or you can hook up an add-on ADC to the Rpi for example https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters
Good luck

Time dependent resistance using SimScape Electrical foundation library in Matlab

I'm trying to model a large electrical network of resistors and capacitors in SimScape using Electrical foundation library blocks. One of the resistors needs to change its resistance as a function of time, say like this:
R=R0*(1-delR*(1-exp(-t))
where R is resistance, R0 is the initial resistance, delR is the factor by which I want the resistance to decrease and t is time. I can't figure out how to incorporate time variance at all in to the simscape model(as I can't seem to access a time variable). There is a variable resistance block available, but I'm facing the same problem there as well, as it seems to be built to vary with respect to voltage. I'm using Matlab 2016a.
You can either:
Use the variable resistance block in conjunction with the clock block to achieve this.
Build your own block (a good starting point is the source code for variable resistance). And use the time keyword:
https://www.mathworks.com/help/physmod/simscape/lang/time.html
Your equations could look something like:
let
R = R0 * (1 - delR * (1 - exp(time));
in
v == R * i;

Understanding some ADC instructions

I am trying to program an adc in stm32f4. I want to know what are the roles of these five instructions?
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right
ADC_Mode_Independent The ADC functions independently of others. Other modes allow two ADC to be read at exactly the same time (for power measurement) or interleaved (2 or 3 ADC cooperate to read the same channel more often)
ADC_Prescaler_Div2 - How fast the ADC works its SAR algorithm
ADC_DMAAccessMode_Disabled - DMA provides the ability to take a number of readings and have them automatically put into a table in memory
ADC_TwoSamplingDelay_5Cycles - There are two registers, this one one is a delay between successive readings, the other is the sampling time, the time taken to physically sense the voltage on the pin. You must have a low impedance source to use shorter sampling. explained in the manual. Some processors can read the same pin more than once before stepping to the next pin, hence the delay read the ADC accuracy appnotes.
ADC_DataAlign_Right

LM35 temp sesnor equation for arduino uno which connected to matlab GUI

Hi I'm new in matlab GUI
I am trying to create an axes plot the temperature which comes from LM35 through arduino uno to matlab
I used the following code to read the analog voltage, readVoltage(a,0)
I get a values about 0.28 - 0.30 but I don't know exactly what this values exactly means is it the the real temperature/100 or what? I know there is an ADC inside arduino converts the input voltage to another range (0-1023) when I use analogRead() on the arduino side. Does it also work here or not? I confused about this thing when I should assume it is 0-1023 or directly get the reading.
The arduino ADC reads a voltage and outputs a number according to
the reference voltage
the bit width of the ADC
in this case I suppose that you are using the 5V reference and 10 bit mode, so
Vmeasured = NumberFromADC * 5V / 1024
Now, according to the LM35 datasheet the output voltage is
Vout = 10mV/°C * T
inverting the equation:
T = Vout / (10mV/°C) = NumberFromADC * 5V / 1024 / (10mV/°C) = NumberFromADC * 500 / 1024
(of course expressed in °C)
BTW I suggest you to change the voltage reference to an internal one, since the 5V are not stable and precise enough to have a good measuring system. More info here.
And, of course, if you change the reference voltage you will need to change the equation since the reference itself will not be 5V anymore.