HX711 and Load Cell Library or Code Samples for Stamp?
VivaCaffeina Posts: 1
in BASIC Stamp
I'd like to experiment with a load cell and HX711. Yah, yah, I could do it with an Arduino but I have an existing setup I'd like to just add to. I've done some searching and haven't found any HX711 code. Any hint/tips/leads? Thanks!
You won't be able to bit bang a hx711 with pbasic. OTOH doing it with P1 is trivial.
All of the Basic stamps are 16-bit and are rather slow at user code, being interpreted out of EEPROM. To read a HX711 you must issue 25 to 27 clock pulses, after each of which you can read one of the 24 data bits from the data pin. The total number of clock pulses must be 25, 26, or 27, as this determines the channel and speed for the next HX711 conversion. The maximum width of a pulse is 50 usec, which is achievable with PULSOUT, but dealing with the 24 bit signed 2's complement return data will be very awkward on a stamp, as will scaling the return value to generate a meaningful weight. The usual method is to
receive each bit, shift an initially blank result variable one bit to the left, then OR the incoming data bit into bit 0 of the result.. Problem is you will run out of bits at 16. To avoid this you need to take the bit shifted out of your low result and shift it into a high result, and working with wider data on a stamp is at best very awkward, and if you don't at least send the HX711 10 more pulses it will error out instead of doing another conversion.
Thank you for the concise answer; appreciate it.
Now, how would doing it with a P1 be trivial?
P1 is a 32-bit processor, so it can deal with the 24-bit HX711 data without the awkwardness. Also the code is already written in Spin although the object in the old OBEX doesn't properly handle negative or overflow values, fixing that isn't hard.
SHIFTIN should work; no need to bit-bang. Two SHIFTINs in a row to get the 25 to 27 bits. The vanilla STAMP clocks the data at about 17 kHz, but the actual clock pulses are short, less than 50µs I think.
Looks like that might work. You would need to use two SHIFTINs, presumably an 8 bit followed by a 16 or vice-versa, then PULSOUT the trailing clocks which do not return data but set the mode for the next conversion. You still have the problem that you got 24 bits of data on a 16 bit system without much in the way of tools for scaling it down.
I was going to say that Mohamed Refky posted quite a bit about using the AD7760 with the BASIC Stamp, for interface to a weighing scale. But most of those links are too old, page not found. I wonder if those are archived somewhere?
@localroger, I found this thread,
where you commented "HX711 as it's considered kind of a low-rent device in my corner of the high-performance weighing world". I guess so. The HX711 interface is quite peculiar, it's performance too maybe. Be that as it may, there are tricks that can extend BASIC Stamp math to higher resolution.
I've worked a bit more with the HX711 since I made that comment. The main problem with it, other than its wonky interface, is that it doesn't support sense leads so it can't compensate for the voltage drop in a long cable. I'm not sure whether it would be temperature stable enough to NTEP certification for legal for trade applications. But it should be fine for its original intended use, as an easy to use load cell interface for tabletop scales.
When working with integer math I generally look for a 32-bit constant which, when multiplied by the ADC count generates a 64-bit result with the high 32 bits (the ** operator gives this in Spin) which is the number of divisions (for example, a scale weighing 100 x 0.02 lb would have a capacity of 5000 divisions and to display weight you would multiply by 2 and insert a decimal point). In order to perform a calibration, to determine this scaling constant from a weight test, you need to be able to do a 64 by 32 bit division. Fortunately there is a Propeller math library for that. You don't need that ability at runtime, or if you can take the test results and do the calculation manually off-device.
"I've worked a bit more with the HX711 since I made that comment. The main problem with it, other than its wonky interface, is that it doesn't support sense leads so it can't compensate for the voltage drop in a long cable."
Although the datasheets for the HX711 are less than adequate, you can actually compensate for voltage drop over a long cable with a 6-wire (7 shield) load sensor.
If you look on page 1 and find where R1 connects to the Collector, disconnect that at R1. Then from the load cell, use the +Sense to connect to R1 instead.
With a 6-wire load cell you will have something like ... (Excite+ , Excite-, Signal+, Signal-, Sense+, and Sense- (and a Shield) ) ...
Excite+ , Excite-, Signal+, Signal- are your standard 4-wire signals Sense+, and Sense- are used for doing exactly what you are wanting. However we have an implementation that uses the Sense- to detect any tampering of the load cells and just use the Sense+ to regulate voltage directly at the load cell.
There is an interesting filter I have been using with the HX711 that you might also be interested in that I have implemented in PIC Assembly language.
In the image the Blue line is the raw data from the HX711
The red line is a standard positive peak detector with a decay of 1
The green line is a negative peak detector with a decay of 1
The orange line is the data that I am using which is simply an average of the peak detector positive and the peak detector negative
Yes you can use the sense leads to regulate the excitation voltage but that's not how it's done in any industrial quality scale. They all have sense inputs for the ADC which regulate the gain of the ADC. This allows you to compensate for larger changes in the excitation, as well as using an external excitation supply. I have seen 10 volt excitation supplies dropped to less than 5 in real world situations (e.g. a truck scale with 12 load cells and 100 foot home run cable). This may have been the idea behind the HX711's low-gain B channel but you'd have to do the scaling to compensate for sense input changes in your software along with calibration.
That's an interesting filter result for something so computationally simple. I think in practice you'd need a threshold to disable it in case of a large step weight change, otherwise one of the peak detectors will have to decay to the new weight value. I've used exponentially weighted moving averages a lot, but those depend on a multiply operation each cycle. Your peak method only needs divide by 2, which you can do with shift right.
In our application we needed something with a fast response to any immediate change. That filter is used as an absolute detector in an industrial application where the weight may vary from 50 pounds to 2000 pounds. I tried several different averaging techniques but all of them were slow to respond and/or full of noise. (more filtering = less noise and slower response ; less filtering = more noise and faster response) The method described above is by far the most preferred method for our application. The Decay can be set to be more aggressive, but with the sampling time within the PIC (operating at 64MHz) , even a decay of 1 is acceptably responsive to quick settle times. The data is 'normalized' so that resting is at mid scale ( 8388608 ) of a 24-Bit returned value.
I haven’t looked inside, but I’ll hazard a guess that my cheap but slick bathroom scale uses a commodity chip like the HX711, if not that one exactly, not industrial by any means. The processor lives on top of the load cell, so barely needs sense wires. Ugh, The zero offset is terribly sensitive to bending caused by shifting its position on a tile floor. As a result it can have me (or my wife) losing or gaining pounds in the course of an hour. It seems to run a zeroing algorithm after stepping off, so a second try is more accurate, so long as the scale stays put.
That’s a very interesting filter Beau. I’m thinking a statistician (which I’m not) would have fun with it. When you say “decay of 1”, am I right to see that as linear; subtract (add) 1 (out of 2^24) at each sample interval, until the filtered max (min) again is below (above) the current value. What is the time scale in the graph?
"When you say “decay of 1”, am I right to see that as linear; subtract (add) 1 (out of 2^24) at each sample interval, until the filtered max (min) again is below (above) the current value." - Yes, that is correct
"What is the time scale in the graph?" -it was only a couple of seconds. Since it wasn't a merit I was trying to quantify other that what was an acceptable perception of a real time response I honestly didn't measure the time interval.
The nature of a load cell reading is notoriously noisy and takes time to settle anyway, so time usually doesn't matter because you can just throw a bunch of averaging at it and increase your signal to noise ratio by "ensemble averaging". In our case it is used in an anti theft attempt where an immediate response is more important than a slow average. (<--Think museum: swapping the real deal for a fake if you know the approximate weight of the item you are trying to swap) Normal averaging techniques suppress sudden changes and delay the response time.