difficulty in conversion from int16_t to int

hi
i am mainly taking resistance from a pot, feeding it into a 16bit adc and then using the value. the problem is my adc0 value which has the digital data for resistance from pot is showing correct values, but my variable rer(of type int) is giving me a value zero most of the times or else values which shouldnt be coming logically.pls pls advice

p.s. i have added the necessary headers as well <wire.h> and <Adafruit_ADS1015.h>

void setup(void)
{
Serial.begin(57600);
ads1115.begin();
}
 
void loop(void)
{
int16_t adc0;
int rer; 
adc0 = ads1115.readADC_SingleEnded(0);  //reading value of resistance from pot at port A0 of adc and converting it to digital
rer=adc*10000/26365; //performing calibration

pls i need suggestions

This code will not even compile. YOu might be better off posting your actual code.

rer=adc*10000/26365; //performing calibration

variable "adc" is not defined anywhere in your snippet.

Also: assuming adc was meant to be adc0, what is the value returned by ads1115.readADC_SingleEnded(0)?

rer=adc*10000/26365; //performing calibration

could potentially wrap the (int) value of rer, and then divide it by 26365, giving you spurious values.

Welcome to the land of integer maths!

Mark

rer=adc*10000/26365; //performing calibration

Let's say your ADC gives you 1000. Already you have 1000 * 10000 which is 10000000 which is much more than will fit into an integer.

thank for the responses people

@nick
according to me since precedence of division is higher, so it would do 10000/26365 first and thn multiply it with adc0. So i dont think that we have a problem there. Moreover it would have given an overflow error for the same.

the problem still persists
also i dont understand that since in arduino uno even int is signed and of 2 bytes which is same as int16_t, so this problem shouldn't occur at all.

Really need help with this people..

according to me since precedence of division is higher, so it would do 10000/26365 first and thn multiply it with adc0.

The precedence of division and multiplication are equal. If they weren't, then 10000/26365 would be 0.

okay

can u suggest some solution for the problem??

Increase your resolution, do your calibration, reduce your resolution.

10000/26536 is clearly non-integer, so start with a data type that can handle that and work backwards.

@aarondc
i am new to programming, can u give me some idea as to how i am to increase the resolution??

can u give me some idea as to how i am to increase the resolution??

One way:
rer=adc*10000UL/26365UL; //performing calibration

and how exactly does this work??

It uses unsigned long registers to compute the result, so 1023 * 10000 will fit without rollover.

You could use
rer=adc*10000.0/26365.0; //performing calibration
to perform floating point arithmetic, instead, if the intended result is a float, rather than an int.

thanks a lot man!!!rlly!!

will try it and post the results here..thanks again!!!:slight_smile:

milano_new:
@nick
according to me since precedence of division is higher, so it would do 10000/26365 first and thn multiply it with adc0. So i dont think that we have a problem there. Moreover it would have given an overflow error for the same.

Division and multiplication are the same precedence and left-associative, so therefore the multiplication is done first.

What overflow error? You just get "bad" data.

solved the problem:

rer=float(adc0)*10000.0/26365.0;

actually 10000/26365 always comes out to be zero because both are integers and so final answer given as integer is zero.

Yes but this is in the context of the original multiplication:

int16_t adc0;
int rer; 
adc0 = ads1115.readADC_SingleEnded(0);  //reading value of resistance from pot at port A0 of adc and converting it to digital
rer = adc0 * 10000 / 26365; //performing calibration

So this is the sequence:

  • Find adc0 as an int (same as int16_t). Say it is 800.
  • Calculate: adc0 * 10000 (ie. 800 * 10000 = 80000000)
  • The above value is truncated to fit into an int. (80000000 = 0x7A1200, truncated to 16 bits = 0x1200, which is 4608)
  • Divide 4608 / 26365 giving 0.174777. Since this is an int this division gives 0.

So the issue is not so much that 10000 / 26365 is zero as an int (which it is) but that the previous multiplication did not fit into an int.

The earlier suggested solution of using longs instead of ints would work, because 80000000 fits into a long. Your other solution of using floats also works as they can handle fractional numbers.

solved it-

rer=float(adc0)*10000.0/26365.0;

or
rer=float(adc0)*float(10000/26365)

milano_new:
solved it-
...

or
rer=float(adc0)*float(10000/26365)

No, that won't work. You really have to read what has been posted above.

void setup ()
  {
  Serial.begin (115200);
  int adc0 = 800;
  int rer=float(adc0)*float(10000/26365);
  Serial.println (rer);
  }  // end of setup

void loop () { }

Output:

0

Not correct.

Depends what his definition of "solve" is, innit?

:fearful: