# HELP:Convert 24bit from ADC to decimal

#### abicash

##### Member
Hello

The HX711 is a serial device which outputs 24 bits in form of bit banging.
The data is in 2's complements form.
Vref = 5v
Full scale differential
input voltage range V(inp)-V(inn) ±0.0039*VREF mV
Internal gain = 128
Output data coding 2’s complement 800000 to 7FFFFF HEX

My problem is understanding this format.
I have always known in my MCU that a 10-bit sends 0-1023 bits and i can easily scale for a 0-5v input.

In this particular setup i have a loadcell giving a 0-10mv (2mV/V @ 5v excitation for a 5kg weight)

After i get the data as 24 bits (shifted appropriately) i XOR it with 0x80000

Code:
weight_raw ^= 0x800000;
My question :
Since i am not interested in negative values, how do i scale this as normal decimal value for arithmetic calculations?

Best regards

#### Les Jones

##### Well-Known Member
Hi,
This is how I do it in my code for reading digital calipers. I think I found the basic method that this code uses somewhere on the web (I can't remember where.)
I use it on an ATtiny4313

.ORG 0x90

RBCD0: .BYTE 1 ;MSB These following variable must be in this sequence ( 7 bytes )
RBCD1: .BYTE 1
RBCD2: .BYTE 1
RBCD3: .BYTE 1 ;LSB

Rbin0: .BYTE 1 ;MSB
Rbin1: .BYTE 1
Rbin2: .BYTE 1 ;LSB

; ***************************************************************************************************************
; * See note at start of program about Variables used in this subroutine in SRM *
; * ;Using registers R16, R17, R18, R19, R28, R29 Some may need to save them on the stack *
; * *
; * BintoBCD *
; ***************************************************************************************************************

BintoBCD:
PUSH R28
PUSH R29
LDI R19,24 ; 24-Bits Use at counter

LDI R16,0x00 ; Clear result area
STS RBCD0,R16
STS RBCD1,R16
STS RBCD2,R16
STS RBCD3,R16
Loop:
LDI R28,LOW (RBCD0) ;Set Y register to point to RBCD0
LDI R29,0x00 ;Required for Attiny4313 Not required as Attiny2313 has less than 256 bytes of data space
LDI R18,4 ;use as counter

BintoBCD1:

LDI R16,0x33
ST Y,R17 ; I do not think I need to save it at this point
SBRC R17,3 ; top bit of low nibble ? (If the original nibble was 5 or greater then adding 3
; will cause the top bit of nibble to be set)
ANDI R16,0xF0 ;

SBRC R17,7 ; top bit of high nibble ? (If the original nibble was 5 or greater then adding 3
; will cause the top bit of nibble to be set
ANDI R16,0x0F
SUB R17,R16
ST Y+,R17 ;Store indirect and increment pointer
DEC R18 ;Decrement counter (Counts down from 4)
BRNE BintoBCD1
LDI R28,LOW (Rbin2 + 1) ;Set Y register to point to Rbin2 +1 as we are using pre decrement
LD R17,-Y ;Rbin LSB
ROL R17 ; Need to save back after rotate
ST Y,R17
LD R17,-Y
ROL R17
ST Y,R17
LD R17,-Y
ROL R17
ST Y,R17
LD R17,-Y
ROL R17
ST Y,R17
LD R17,-Y
ROL R17
ST Y,R17
LD R17,-Y
ROL R17
ST Y,R17
LD R17,-Y
ROL R17
ST Y,R17

DEC R19 ;Counts down from 24
BRNE Loop
POP R29
POP R28
RET

I also have code to deal with negative values if you find that you need it.

Les.

#### abicash

##### Member
Hi Les
Thanks for the post.
Unfortunately I don't understand assembly.
Can u explain as an algorithm?

Although I seem to have found an answer
In my OP I have explained the specs of the ADC.
The entire range is 23 bit since the 24th bit is sign bit.
Now since I don't require negative values, I simply check the sign bit and forcibly turn all negative values to 0.
For positive values I have a range of 22 bits, max being 0x7fffff

#### Les Jones

##### Well-Known Member
Hi,
I can't remember exactly how it works but I have found the information that the code was based on. It was based on code to run on a PIC chip dealing with 16 bit to BCD conversion. I even found the web page. http://www.piclist.com/techref/microchip/math/radix/bcd2bin16.htm
I must have managed to understand it at the time I modified it for 24 bit and to run on an Atmel ATtiny4313. As you do not use assembler I assume you are probably using "C" I would think there must be a way to deal with binary numbers as well as decimal in "C" I am very poor at "C" programming so I can't help you to do it with "C"

I have just tried Googling "binary to decimal in c language" and found many results.

Les.

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I don't quite follow the problem..

After the Result "weight_raw ^= 0x800000;" You should be left with a number between -8388608 and 8388607...
(make sure you use a signed long )

Just ADD 8388608 to the result and you will have 0 to 16777214.. Then 16777214 will represent 5v....

ADC * 5 / 16777213 = voltage to display...

#### abicash

##### Member
Ian
Thanks a lot.
5v is right.
But I don't understand one thing.
Since the entire -8388608 and 8388607 range is from -20mv to +20mv, what if a negative voltage is read?
Currently I ignore negative values so my range is reduced

#### Les Jones

##### Well-Known Member
Hi Ian,
I think "abicash" is just asking just wants to know how to convert a 24 bit binary number to decimal. What I don't understand is why he did not need to convert a 10 bit binary number to decimal in the past. (And just extend the technique used from 10 bits to 24 bits.)

Hi abicash,
If the output is a signed number then I would think positive numbers would indicate compression and negative numbers tension in the load cell. (Or the other way round.) Ignore this comment. I had not read your original post properly. I assumed the ADC was part of the load cell.
If the load cell only gives positive outputs then the ADC should only give positive readings. You may be better off forcing the reading to zero if the sign bit is set rather than just masking it off. If you mask it off then a reading of - 1 count would would be interpreted as a full scale positive reading.

Les.

Last edited:

#### abicash

##### Member
Actually the question is about eventual scaling for displaying.
If the value is known then it could be converted to any form.
Here I have trouble understanding the concept since I have never used a bipolar voltage range.

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I don't know that ADC... But!! 23bits is quite a good result... 0 to 8388607 is a reasonable resolution.... The output of the ADC is 2s comp so really we should be compensating for the 1 but at 23 bits there is no need!!

So make 0 = 0 and 8388607 = 5V

#### Les Jones

##### Well-Known Member
So 1 count will be about 0.6 uV With that sort of resolution you will need to take great care that thermoelectric effects do not change your readings significantly.

Les.

#### Les Jones

##### Well-Known Member
Actually the ADC input range with a 5 volt reference is +/- 20mV so one count will be 0.0024 uV
You would need to mount the ADC very close to the load cell and avoid any temperature differences between connections between the load cell and ADC.
What is the application of this equipment and is such extreme resolution or accuracy required.

Les.

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I read a slow moving loadcell ( In the pendant rope on a crane ) I use 10 bit and oversample by 24..
This yields 0 to 24576 bit count.... ( obviously with mapping this is far smaller ).. I have a "gloop" factor as a small delay in the ADC reading loop.... Primarily to smooth noise... On some cranes the noise is really bad!!

I then average 3 of these readings, after the averaging I get extremely good results..

After calculations I can monitor the display and factor the "gloop" to achieve the best I can get!

So! a 10 bit can give better than 100kg resolution on a 50te crane... 0.2%.... good enough!! The dynamics of the crane won't allow you to see this resolution...

What are you measuring to need 24bits anyway??

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
the chip costs less than a dollar.
So why not
Oh! So the resolution isn't a big thing???

I use a ina125p And I set the vref to 1.2v ( ish ) This gives a reading of @ 6448 to 24576 available for use ( 1.2v ~ 4.5v )
You can just divide the result down to 12 or 10bit.. Personally I would just map 0 to 0 and 8388607 to 5V as I said before... I take it you know how to map the output to a readout!!

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Les Jones

I never understood why people think binary isn't decimal on the humble micro... People confuse BCD with Decimal... As far as a micro is concerned, Decimal and Binary are one and the same, no conversion necessary...

I think it's because its decimal represented in base 2....