HX711 ADC interfacing with PIC16F887A

Thread Starter

PasanJay

Joined Mar 19, 2021
13
Hello guy, I'm trying to interface hx711 adc with pi16f877a.. I've found the reference C program in the datasheet for hx711.. from that i was able to get raw readings from the hx711, i am using mikroC complier. my question is how can i get this readings to represent a weight.. is there any formula..? and i guess the initial raw reading under no load is the OFFSET value which you subtract from next readings to balance the zero position.. but when i do that the readings fluctuate here and there and will not zero the readings.. but when i connect the same setup to arduino.. readings are normal and most importantly the no load value stays at zero without fluctuating... what am i missing?

C:
#define LOW  0
#define HIGH 1

#define INPUT  1
#define OUTPUT 0


sbit HX711_SCLK at RB5_bit;
sbit HX711_DOUT at RB4_bit;

sbit HX711_SCLK_Direction at TRISB5_bit;
sbit HX711_DOUT_Direction at TRISB4_bit;

sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;

char txt[10];
float read1 = 0;
float offset = 0;
float gram = 0;
float val1;
float val2;
int k;

unsigned long Read_HX711() {
    unsigned long count = 0;
    unsigned char i; //, highest = 0, higher = 0, hi = 0, lo = 0;

    HX711_DOUT_Direction = OUTPUT;
    HX711_SCLK_Direction = OUTPUT;

    HX711_DOUT = 1;
    HX711_SCLK = 0;

    HX711_DOUT_Direction = INPUT;

    while(HX711_DOUT);

    for(i = 0; i < 24; i++) { // gain 128
        HX711_SCLK = 1;
        count <<= 1;
        HX711_SCLK = 0;

        if(HX711_DOUT)count++;
    }

    HX711_SCLK = 1;
    count ^= 0x800000;
    HX711_SCLK = 0;

    return(count);
}
unsigned long readAverage(void) {
  double sum = 0;
  for (k = 0; k < 10; k++) {
    sum = sum + Read_HX711();
  }
  sum = sum /10;
  return sum;
}
void main(void) {

    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);


offset = readAverage();

        while (1) {
    read1 = readAverage(); // this is my try for the initial readings to stay at zero
    if (offset >= read1) {
      val1 = (offset - read1);
      gram = val1;
    } else {
      val2 = (read1 - offset);
      gram = val2;

    }//////////////////////////////////////////////////////////////////////////////
     floatToStr_FixLen(gram, txt,6);
     LCD_Out(1,4,txt);
    //gram value is fluctuating
  }

}
 

ericgibbs

Joined Jan 29, 2010
18,766
hi PJ,
This is an Arduino sketch similar to C++, it may help, you need to calibrate the scale.
E
C++:
#include "HX711.h"

HX711 scale;

void setup() {
  Serial.begin(38400);
  Serial.println("HX711 80 sam/sec Demo");

  Serial.println("Initializing the scale");
  // parameter "gain" is ommited; the default value 128 is used by the library
  // HX711.DOUT    - pin #A1
  // HX711.PD_SCK    - pin #A0

  scale.begin(A1, A0);
  Serial.println("Uncalibrated Data");
  Serial.print("Raw Data: \t\t");
  Serial.println(scale.read());            // print a raw reading from the ADC

  Serial.print("read average: \t\t");
  Serial.println(scale.read_average(80));      // print the average of 80 readings from the ADC

  Serial.print("Read value: \t\t");
  Serial.println(scale.get_value(5));        // print the average of 5 readings from the ADC minus the tare weight (not set yet)

  Serial.print("Read units: \t\t");
  Serial.println(scale.get_units(5), 1);    // print the average of 5 readings from the ADC minus tare weight (not set) divided
    // by the SCALE parameter (not set yet)

  // 2280 this value is obtained by calibrating the scale with known weights; see the README for details
  scale.set_scale(98.f);    // mytest 30kG L/C resolution 1gm                

  // reset the scale to 0////
  scale.tare();                      

  Serial.println("After setting up the scale:");

  Serial.print("read: \t\t");
  Serial.println(scale.read());                 // print a raw reading from the ADC

  Serial.print("read average: \t\t");
  Serial.println(scale.read_average(80));       // print the average of 20 readings from the ADC

  Serial.print("get value: \t\t");
  // print the average of 85 readings from the ADC minus the tare weight, set with tare()
  Serial.println(scale.get_value(8));      

  Serial.print("get units: \t\t");

   // print the average of 8 readings from the ADC minus tare weight, divided
   // by the SCALE parameter set with set_scale
  Serial.println(scale.get_units(8), 1);      
                   
  Serial.println("Readings:");
}

void loop() {
  scale.begin(A1, A0);
  Serial.print("A=:");
  Serial.print(scale.get_units(), 1);
  Serial.print(" Avg=");
   Serial.println(scale.get_units(10), 0);

  // scale.begin(A1, A0);
// Serial.print("  B=:");
// Serial.println(scale.get_units(), 1);

// Serial.print("Bvg=");
// Serial.println(scale.get_units(8), 1);

// scale.power_down();                    // put the ADC in sleep mode
  // delay(5000);
  // scale.power_up();
}
 

Thread Starter

PasanJay

Joined Mar 19, 2021
13
i guess calibration wont be an issue... issue is the values are fluctuating under no load i want the value to be zero under no load.. i guess it is called zero balancing(correct me if i'm wrong)
 

ericgibbs

Joined Jan 29, 2010
18,766
hi,
Thats where the Tare correction is applied.
// reset the scale to 0////
scale.tare();


Get 80 raw readings, then when you want to zero the weight, subtract that Tare weight.
Sum of say 80 raw readings divided by 80=== the required subtract weight. [save in EEPROM]

E
Serial.print("Read and Average 20, No Load, Zero Offset Counts: =");
Serial.println(scale.read_average(20)); // Display the average of 20 readings from the ADC for Zero Tare
 

ericgibbs

Joined Jan 29, 2010
18,766
hi,
The last work I did on a PIC was 5 years ago, 18F4520, using Oshonsoft Basic. [ attached a file]

I expect you have read the HX711 datasheet, the Read function is about 23 bits serial.
The Basic and the image I prepared may help.
E
 

Attachments

Thread Starter

PasanJay

Joined Mar 19, 2021
13
thank you very much eric... i'll look into it... is there an offset in the hx711 module itself (without connecting a load cell)?
 

ericgibbs

Joined Jan 29, 2010
18,766
hi,
Without a load cell connected the readings will be meaningless.

They will drift around.You can make a dummy bridge for testing, by connecting two 1k's in series across the Vext pads, connect the junction of the two resistors to one of the input pins,

Using a 2k 20 turn trim pot, connect the two outer pins across the Vext pins [ in parallel with the two 1ks.
Then connect the wiper of the trim pot to the other input pin.

Use a DVM and adjust the pot so the voltage across the two input pins is zero.

Then by turning the trim pot you can simulate load cell voltages.
It is a very coarse way of making a resistor bridge.!

Ask if you need a sketch.

E
This image is like the type I used.
A L/C is much better,
 

Attachments

Last edited:

Thread Starter

PasanJay

Joined Mar 19, 2021
13
thank you for your reply.. i tried several times and came up to some extend... ok this is the new issue...when there is no load applied on the LC, the raw readings are between 836900 - 837000. then i took 80 readings and got the average reading.. this new average reading is my offset? am i right? so if i substract the new offset value from the next raw reading, i should get a 0 (zero)? but instead i am getting 4.2964... something... how to get this thing to start reading values from zero?

C:
 offset = read_average(); // setting offset by reading the average of 80 readings
        while (1) {

     weight = (Read_HX711()- offset); // subtracting the offset from new raw readings
      if (weight<0){                    // sometimes the readings goes negative.. so assigned all negatives values as zero
      weight = 0;
      Lcd_Out(1,3,"               ");}
      
     floatToStr_FixLen(weight, txt,7);
     LCD_Out(1,4,txt);
     delay_ms(100);
  }
 

ericgibbs

Joined Jan 29, 2010
18,766
hi PJ,
Your Offset [Tare] is typical of what is used for setting the Zero, by subtracting the Offset count.

I am of the same opinion as Ian. those individual values are very High.???

E
 

Ian Rogers

Joined Dec 12, 2012
1,136
One thing I did notice.... 24 bit resolution.... If you just read 16 bit it will still be very accurate and a lot more stable..
 

Thread Starter

PasanJay

Joined Mar 19, 2021
13
thank you Ian and Eric.... the individual values are raw readings straight from the hx711... and i took the average by utilizing a for loop.. as they done in hx711 master arduino library.. anyway i have the same feeling that the 24 resolution make things more unstable... i'll try 16bit.. when we using hx711 with arduino, what is the default resolution?
 

ericgibbs

Joined Jan 29, 2010
18,766
Hi PJ,
I have finally located all the bits for that earlier HX711 project, using an Arduino, with a 2kG load cell.
If you get stuck let me know and I will rebuild the project.

Which load cell are you using.?
E
 

Thread Starter

PasanJay

Joined Mar 19, 2021
13
Thank you eric.. thats very kind of you... i did several projects using hx711 with Atmega238p... but i had never encountered this issue.. when using tare function in arduino(in hx711 library) , the scale reads would easily starts from zero... in my MikroC I'm using the gain as 128... what is the default gain in hx711 library in arduino...?
 

ericgibbs

Joined Jan 29, 2010
18,766
hi PJ<
I have set it up, bit of a birds nest, but it shows the performance.
Used two HX711, with and without JP2 .
These are the results with this program.
E
C++:
// 010521_ PJ AAC  Test EG57
// 5kG L/C Arduino Nano
// Test weight 2kG Calibrated Mass
#include <HX711.h>

HX711 scale;

void setup() {
  Serial.begin(38400);
  Serial.println("HX711 PJ Demo");

  Serial.println("Initializing the scale");
  // parameter "gain" is ommited; the default value 128 is used by the library
  // HX711.DOUT    - pin #A1
  // HX711.PD_SCK    - pin #A0
  scale.begin(A1, A0);

  Serial.println("Before setting up the scale:");
  Serial.print("read: \t\t");
  Serial.println(scale.read());            // print a raw reading from the ADC

  Serial.print("read average: \t\t");
  Serial.println(scale.read_average(20));      // print the average of 20 readings from the ADC

  Serial.print("get value: \t\t");
  Serial.println(scale.get_value(5));        // print the average of 5 readings from the ADC minus the tare weight (not set yet)

  Serial.print("get units: \t\t");
  Serial.println(scale.get_units(5), 1);    // print the average of 5 readings from the ADC minus tare weight (not set) divided
// by the SCALE parameter (not set yet)
// this value is obtained by calibrating the scale with known weights;
  scale.set_scale(90.f);
  scale.tare();// reset the scale to 0

  Serial.println("After setting up the scale:");

  Serial.print("read: \t\t");
  Serial.println(scale.read());                 // print a raw reading from the ADC

  Serial.print("read average: \t\t");
  Serial.println(scale.read_average(20));       // print the average of 20 readings from the ADC

  Serial.print("get value: \t\t");
  Serial.println(scale.get_value(5));        // print the average of 5 readings from the ADC minus the tare weight, set with tare()

  Serial.print("get units: \t\t");
  Serial.println(scale.get_units(5), 1);        // print the average of 5 readings from the ADC minus tare weight, divided
                        // by the SCALE parameter set with set_scale

  Serial.println("Readings:");
}

void loop() {
  Serial.print("A= ");
  Serial.print(scale.get_units(), 1);
  Serial.print("  Avg= ");
  Serial.println(scale.get_units(10), 1);

 // scale.power_down();                    // put the ADC in sleep mode
  delay(1000);
 // scale.power_up();
}
 

Attachments

Ian Rogers

Joined Dec 12, 2012
1,136
thank you Ian and Eric.... the individual values are raw readings straight from the hx711... and i took the average by utilizing a for loop.. as they done in hx711 master arduino library.. anyway i have the same feeling that the 24 resolution make things more unstable... i'll try 16bit.. when we using hx711 with arduino, what is the default resolution?
24 bits... But read it the same way and divide the reading by 256 ( >>= 8 )... Tada 16 bits..
 
Top