Continue to Site

Help me with ADC calculation and voltage conversion

Status
Not open for further replies.

Maverickmax

Hi

I have been doing a small experiment as I get the reading such as 920 from ADC channel when the input voltage is 680V. Then I get the value - 82 when the voltage is 0V.

920 - 680V
82 - 0V

How to convert between 920 and 82 into 680V and 0V respectively for my code?

So far I have done a little calculation:

680/920 = 0.739

so 0.739*920 will yields 680V

but when I try to calculate 0.739 * 82 and I would expect OV but I get 60.6V

So I have done summat wrong with my calculation. Any help would be appreicated

Maverickmax

echo47

volts = (ADC - 82) * 680V / (920 - 82)

banh

Maverickmax said:
Hi

I have been doing a small experiment as I get the reading such as 920 from ADC channel when the input voltage is 680V. Then I get the value - 82 when the voltage is 0V.

920 - 680V
82 - 0V

How to convert between 920 and 82 into 680V and 0V respectively for my code?

So far I have done a little calculation:

680/920 = 0.739

so 0.739*920 will yields 680V

but when I try to calculate 0.739 * 82 and I would expect OV but I get 60.6V

So I have done summat wrong with my calculation. Any help would be appreicated

Maverickmax

you can use interpolation, as the relationship (between voltage and adc value) is linear

VVV

You first need to subtract the offset (82) from the reading and then divide by the slope of the characteristic.

Maverickmax

Hi

When I applied the equation in my codes and tested it and the most of time
I only get the 0V when I adjust variable resistor forth and back but sometime
I get 680V but I don't get any reading when I adjusted the votlage between
0V and 680V.

I exclude 680* from Temp = (adc_result[6]-82)/(920-82) and I found out that
I only get most of the 0 and 1 only.

Is there anything that I maybe overlook or is it summat wrong with my function prototype?

Code:
int Voltage_measurement(void)
{
int Temp;
return Temp;
}

Maverickmax

I still could not get any reading between 680V and 0V as I only get 0V and few 680V when I turn the variable resistor to full.

Is it do with my code?

Maverick max

Let assume that adc_result[6] would be 920, the temp would return 680 which is fine. However the value less that 920 down to 1 which yields 0V. Why is that?

Maverick Max

VVV

The formula is correct. Are you sure that adc_result[6] is the correct value upon entry?
To test, why not modify your code to simply return that value and see if it is changing linearly from 82 to 920 as you vary the voltage.

return Temp

This should return 82~920, depending on voltage.
If it doesn't, then you need to check the acquisition routine, hardware, etc.

Maverickmax

Hi

In regard to your question, I have checked it many times as I get getting the reading from 82 to 920.

I have another simple test by applying 920 in the equation instead of using adc_result[6] is 920 and change my code to test my calculation:

Code:
 int Temp;
Temp = 680*((920-82)/(920-82));
return Temp;

Result: 680

Result: 0

result:0

result:0

result:0

result:0

I realise it must be do with codes and I don't know why I get 0...

You can try the code and you would probably get the same result like mine

I changed from int to unsigned int, no effect then changed it to float - still same result

Strange innit?

Maverickmax

silvio

Why don't you try this way:

Code:
int Voltage_measurement(void)
{
int Temp;
return Temp;
}

The results of (adc_result[6]-82)/(920-82); will be zero regardless the type of Temp for value of adc_results[6] bellow 920, just because the results will always be less than 1.

Funny enough the results will become even negative for value of adc_results[6] bellow 82.

If you follow the echo47's advice then according with C precedence operators the binary operators found on the same level of precedence will be evaluated from left to right. Thus first () then * then /

Thus Temp = 680*(adc_result[6]-82)/(920-82); will be evaluated this way:

2nd. (920-82)
3rd. 680 * results of 1st evaluation
4th. results of 3rd evaluation divided by results of 2nd evaluation

According to the above equation, always all it's on the right of the * sign will be solved before the multiplication.
((adc_result[6]-82)/(920-82)) will always be less than 1 (0,99.......) for values of adc_results less than 920. That's why you get always zero !

Hope it's clear why I removed the two ().

Maverickmax

Hi Silivo

I have tested the equation: Temp = 680*(N-82)/(920-82);

where N is 920, 900, 500 etc

The result is not what I have been looking for.

It doesn't solve my problem.... :-(

silvio

Maverickmax said:
I have tested the equation: Temp = 680*(N-82)/(920-82);

where N is 920, 900, 500 etc

The result is not what I have been looking for.

It doesn't solve my problem.... :-(

You want to say that Temp variable is still zero ?

Maverickmax said:
How to convert between 920 and 82 into 680V and 0V respectively for my code?
it's not been solved by the equation proposed by echo47 ?

Maverickmax said:
I have been doing a small experiment as I get the reading such as 920 from ADC channel when the input voltage is 680V. Then I get the value - 82 when the voltage is 0V.

You mean "- 82" or "82" as a result for 0v ?

What kind of ADC you use ?

Just because you can use the differential mode operation of the A/D by biasing the A / D Vin(-) input and adjust the zero offset in order to get a code of 000000.... for 0v input. Then you can adjust the span to accomodate with the input range.

Maverickmax

On my inital request, I need get the reading from ADC ranging from 920 to 82 so I need to convert 920 and 82 into 680V to 0V

So

I followed echo47's equation such as temp=680*((adc_result[6]-82)/(920-82)); and I only get 680 when the adc_result is 920 but number below 920 down to 83, give 0. This is not what I really expect as I need the reading when any value between 919 to 83. So far I could not manage to iron the problem out yet

MaverickMax

silvio

Which compiler you use for which micro ?

Try this way:

Code:
int Voltage_measurement(void)
{
int Temp;
return Temp;
}

If in doubt cast.

Can you tell me now the value of "Temp" for let's say adc_results[6] = 460

Maverickmax

Im using Keil and the microcontroller is XC161

As I have modified my code as you requested.

According to my calculator, the result would be approximately 307 but unfortunately the result from codes yields -6

MaverickMax

silvio

OK change to unsigned int

Code:
unsigned int Voltage_measurement(void)
{
unsigned int Temp;
return Temp;
}

artem

What is the int length of your compiler ?

Just to ensure that even compiler bug does not affect compile code as

volatile long int temp; // (32 bits calculation is a must as result can exceed 0xffff)

temp = temp/ (920-82);

and you can scale the divisor part to get unrounded result and keep source out of floating math to achieve necessary precision for your task.

What compiler do you use and its version number?

silvio

artem said:
(32 bits calculation is a must as result can exceed 0xffff)

YES, my apologize, I didn't think about that

Maverickmax

I have attached my code for you...

the complier - Keil uVision4 IDE

Maverickmax

Maverickmax

Bascially I have not optimized the codes and I followed your instruction.....

Nothing changed

Maverick Max

artem

for me it seems that something wrong with your input from adc . Check it first .

Code:
C:\Borland\projects\test2>bcc32 -IC:\Borland\BCC55\Include\  -LC:\Borland\BCC55\Lib test.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test.c:

C:\Borland\projects\test2>test
sizeof int 4
sizeof long int 4
size of short int 2
test with 32 bit integer
result is 0
result is 16
result is 32
result is 48
result is 64
result is 81
result is 97
result is 113
result is 129
result is 146
result is 162
result is 178
result is 194
result is 210
result is 227
result is 243
result is 259
result is 275
result is 292
result is 308
result is 324
result is 340
result is 357
result is 373
result is 389
result is 405
result is 421
result is 438
result is 454
result is 470
result is 486
result is 503
result is 519
result is 535
result is 551
result is 568
result is 584
result is 600
result is 616
result is 632
result is 649
result is 665
test with 16 bit integer
result is 0
result is 16
result is 32
result is 48
result is 64
result is 2
result is 19
result is 35
result is 51
result is 67
result is 5
result is 22
result is 38
result is 54
result is 70
result is 8
result is 25
result is 41
result is 57
result is 73
result is 11
result is 27
result is 44
result is 60
result is 76
result is 14
result is 30
result is 47
result is 63
result is 1
result is 17
result is 33
result is 50
result is 66
result is 4
result is 20
result is 36
result is 53
result is 69
result is 7
result is 23
result is 39

C:\Borland\projects\test2>type test.c
#include <stdio.h>

void main(void)
{
volatile unsigned long int temp;
volatile unsigned short int temp1;

int tint;

printf("sizeof int %d\n",sizeof(int));
printf("sizeof long int %d\n", sizeof(long int));
printf("size of short int %d\n",sizeof(short int));

puts("test with 32 bit integer");

for(tint=82; tint < 920;tint += 20)
{
temp= 680 * (tint-82);
temp = temp/(920-82);

printf("result is %d\n", temp);
}

puts("test with 16 bit integer");

for(tint=82; tint < 920;tint += 20)
{
temp1= 680 * (tint-82);
temp1 = temp1/(920-82);

printf("result is %d\n", temp1);
}

}

Status
Not open for further replies.