PIC10F2xx ADRES- what is it actually storing?

Thread Starter

jlawley1969

Joined Feb 22, 2021
97
this is a bit of a silly one. I am trying to use the PIC10F222 to produce a modified sine wave and I want to have feedback from a current sensor to change the duty cycle (and so in turn the RMS).

I have ADCON0 set up properly because I am able to input a voltage to GP0 and have an effect on the duty cycle. The thing that is driving me crazy is I do not know what is being stored when ADRES is read(called?). I know that it is a string but how do I scale the string to be basically a number(integer) I can use in formulas.
I made this work with arduino by
/////////////////////////
sensorValue = analogRead(A4);
voltage = sensorValue * (5/1023);
/////////////////////////

This gives me a value that makes sense and is scaled from 0-5, I assume I should be able to do something similar with the PIC10F222? I have been trying different things and searching forums all day and nothing has proven helpful.
I have a pickit3 and for some reason even though it says it is a debugger I am unable to use it as a debug header so I can't see what my variables are in MPLABx which is what is really killing me because I feel as though I am just coding in the dark.

I know this is a bit vague so let me know if there is any clarification I can give.
 

JohnInTX

Joined Jun 26, 2012
4,787
ADRES has a count proportional to the input voltage as a fraction of the reference voltage. For an 8 bit result, if Vref is 5V and the input voltage is 2.5V, the count will be (2.5V/5Vref) * 256 = 128 or 80h. From there you can scale the result to fit whatever range you want.

A more general way to think about it is that the ADC divides the reference voltage determined by VrefH - VrefL into 2^N bits and maps the input voltage over that range.
 
Last edited:

trebla

Joined Jun 29, 2019
542
The PIC10F222 has very small amount of memory avalilable, therefore i suggest using millivolts as units instead of volts. This makes calculations less extensive:

millivolts = (sensorValue * 5000) >>8

This divides sensorvalue*5000 by 256 instead of 255 but IMO gives quite accurate result (and saves lot of memory).
 

Thread Starter

jlawley1969

Joined Feb 22, 2021
97
The PIC10F222 has very small amount of memory avalilable, therefore i suggest using millivolts as units instead of volts. This makes calculations less extensive:

millivolts = (sensorValue * 5000) >>8

This divides sensorvalue*5000 by 256 instead of 255 but IMO gives quite accurate result (and saves lot of memory).
hey I am curious as to how that saves memory bc that may help me in other parts of the code. thanks
 

JohnInTX

Joined Jun 26, 2012
4,787
hey I am curious as to how that saves memory bc that may help me in other parts of the code. thanks
Integers take up less space and are easier to deal with (less code) than floating point or other fractional notations. @trebla is showing how to scale the value by 1.953125 (5000 / 256). Adjusting the scale factor to use powers of two in the denominator makes division a simple shift instead of a big divide routine. When the denominator is a byte value, i.e. 2^8, you don't even need to shift, just discard the lower byte. In assembler that's easy.

Also, it is a good idea to do a little off-line algebra to reduce the calculations to a minimum. Frequently there are several steps in a calculation with constant values that can be combined and pre-computed into one value. Don't re-calculate anything in the PIC that you don't have to.

FWIW, the divisor in the raw ADC calculations is 256, 1024 etc. i.e. 2^Number_Of_Bits., not 1023, 255 etc. Those values are the highest ADC reading in the range ( 0 <= count <= 2^N - 1) but not the number of steps in the ADC.

Have fun!
 

AlbertHall

Joined Jun 4, 2014
12,345
FWIW, the divisor in the raw ADC calculations is 256, 1024 etc. i.e. 2^Number_Of_Bits., not 1023, 255 etc. Those values are the highest ADC reading in the range ( 0 <= count <= 2^N - 1) but not the number of steps in the ADC.
An input of 5V into an ADC using a 5V reference will (should?) give a fullscale result - 1023, 255 etc.
Thus using the fullscale value as the divisor will give the correctly scaled result.
I would agree with post #4 that using the 2^n value gives only a small error and may be a worthwhile sacrifice for smaller, quicker code.
 
Top