HX711, WeightSensor, LoadCell (old Title: Reading a 7-Segment Display with the Imp?!)

Hi Folks,

did anyone tried to read a 7-Segment Display with the eImp?

What IC did you use to connect all the input pins?

Chrischi

Read the display? What’s the display on, and how many digits? If it’s multiple digits it’s likely multiplexed which would make that harder.

yes, not reading… more like getting the high and low state of the segments and convert it back to a number. There are 4 digits and the display is on a cheap scale.
I was trying to amp the load-cell with a INA125P from TI but i never got the accuracy of the original scale (0,1g). So i was thinking about to get the original values from the
segment display and could also use the scale without the imp.

You’d be better off using a chip designed for reading load cells; Tom might remember what the one we have around the office is?

Reading the digits, which will certainly be multiplexed, will be hard.

I used this before… worked like a charm:

http://www.dfrobot.com/index.php?route=product/product&product_id=1031

@axisdev

how is/was the accuracy? With the INA from TI i have to do a lot of smoothing to get
constant values. I also think the Imp generates a lot of noise while measuring.
Next i will try to read while the WiFi is off.

@Hugo
Maybe you got a better setup to do stable 0.1g readings.

The chip sounds like that one (24 bit etc). 0.1g on what max scale? You also need to work out your temperature compensation for the load cell as that makes a significant difference.

For my project I was using an Arduino mega… though I also needed RFID, and found that when RFID was active I couldn’t get a solid reading from the load cell. I didn’t have to do any smoothing to get good readings out of that module.

@Hugo
max 1500g-2000g. After Tare 600g.

@axisdev
thx!

maybe i order a hx711 and try to port the Code to the eImp. I think it is some sort of pseudo I2C.

I believe the HX is basically bit-bangable clock+data. Pretty easy. If that’s the one we have, then Brandon here has got some code which would just need to find its way to github.

I always wanted a generic method to interface 7 segs display; This would open up interfacing to all sorts: scales, meters, medical equipt, anything with 7 seg display. Perhaps another approach is a simplified ocr system to decode the digits to give a serial data stream which u can hook up to an imp or whatever. No high res needed here, hacking an optical mouse (there is a low res camera in them) may be a possibility, just need some with the knowledge, skill and time to develop it. i will be tempted to buy one if there is one for sale!
Ken

Today i got a HX711. The one @axisdev posted before.

I tested the original Code with a Arduino to see if the LoadCell and the whole Setup are working. Got nice results.

So i ported the Arduino Code:

`
Hx711::Hx711(uint8_t pin_dout, uint8_t pin_slk) :
_pin_dout(pin_dout), _pin_slk(pin_slk)
{
pinMode(_pin_slk, OUTPUT);
pinMode(_pin_dout, INPUT);

digitalWrite(_pin_slk, HIGH);
delayMicroseconds(100);
digitalWrite(_pin_slk, LOW);

averageValue();
this->setOffset(averageValue());
this->setScale();

}

long Hx711::getValue()
{
byte data[3];

while (digitalRead(_pin_dout))
	;

for (byte j = 0; j < 3; j++)
{
	for (byte i = 0; i < 8; i++)
	{
		digitalWrite(_pin_slk, HIGH);
		bitWrite(data[2 - j], 7 - i, digitalRead(_pin_dout));
		digitalWrite(_pin_slk, LOW);
	}
}

digitalWrite(_pin_slk, HIGH);
digitalWrite(_pin_slk, LOW);

return ((long) data[2] << 16) | ((long) data[1] << 8) | (long) data[0];

}
`

Here is my “Test”- Code for the imp:

`
slk <- hardware.pin1;
slk.configure(DIGITAL_OUT);

dout <- hardware.pin5;
dout.configure(DIGITAL_IN);

function init() {
slk.write(1);
imp.sleep(0.0001);
slk.write(0);
imp.wakeup(5.0, getValue);
server.log(getValue());
}

function bitSet(value, bit) {
return ((value) | (1 << (bit)));
}

function bitClear(value, bit) {
return ((value) & ~(1 << (bit)))
}

function bitWrite(value, bit, bitvalue) {
return (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
}

function getValue()
{
data <- blob(3);

while (dout.read()) {
for (local j = 0; j < 3; j++)
{
for (local i = 0; i < 8; i++)
{
slk.write(1);
bitWrite(data[2 - j], 7 - i, dout.read());
slk.write(0);
}
}
}

slk.write(1);
slk.write(0);

return (data[2] << 16) | (data[1] << 8) | data[0];

}

init();
`

Unfortunately the Code doesnt work, it’s also the first time i tried to do bitbanging a device. Could someone take a look at my Code to see what’s wrong…

thx

First thing I see is that you do queue getValue() to be called 5 seconds after resetting the chip, but then try to log the value immediately. That’s not going to work :slight_smile:

Change the imp.wakeup to:

imp.wakeup(5.0, function() { server.log(getValue()); });

The other issue is that you have misread this arduino code:

while (digitalRead(_pin_dout)) ;

…which is a loop waiting for the pin to go low. It should just be:

while(dout.read());

(though, this is a busy spin which isn’t advisable; I’m assuming it never spins for long)

Here’s the complete code, with a bit of optimization on the bitset/clear stuff; I think your code looked right it was just a lot of hoops to set a bit. I also reversed the order of the loop as it was a bit more elegant. Obviously, this is untested…

`slk <- hardware.pin1;
slk.configure(DIGITAL_OUT);

dout <- hardware.pin5;
dout.configure(DIGITAL_IN);

function init() {
slk.write(1);
imp.sleep(0.0001);
slk.write(0);
}

function getValue()
{
// blobs are pre-initialized to zero
data <- blob(3);

// wait for ready
while (dout.read());

for (local j = 2; j >=0; j–) {
for (local i = 7; i >=0 ; i–) {
slk.write(1);
if (dout.read()) data[j] |= (1<<i);
slk.write(0);
}
}

slk.write(1);
slk.write(0);

return (data[2] << 16) | (data[1] << 8) | data[0];
}

// Initialize, read value after 5 seconds
init();
imp.wakeup(5, function() {
server.log(getValue());
});
`

thx @Hugo

i tried the Code and got a compile error “Expression expected” for this:

if (dout.read()) data[j] |= (1<<i);

i think you mean this?
if (dout.read()) data[j] = data[j] | (1<<i);

and i get this:
[Device] 16777215

After all i got it not working…

I would like to get this thing running and see it at the e-Imp GitHub repo.

i tried a lot more and ported the whole Code but i can not get any values from
the HX711, power_down and power_up are working. Could you or someone please take a closer look:

`sck <- hardware.pin1;
sck.configure(DIGITAL_OUT); // DIGITAL??? ANALOG??

dout <- hardware.pin5;
dout.configure(DIGITAL_IN); // DIGITAL??? ANALOG??

HIGH <- 1;
LOW <- 0;

function is_ready() {
return dout.read() == LOW;
}

function set_gain(gain) {
switch (gain) {
case 128: // channel A, gain factor 128
GAIN <- 1;
break;
case 64: // channel A, gain factor 64
GAIN <- 3;
break;
case 32: // channel B, gain factor 32
GAIN <- 2;
break;
}
sck.write(LOW);
read();
}

function bitSet(value, bit) {
return ((value) | (1 << (bit)));
}

function bitClear(value, bit) {
return ((value) & ~(1 << (bit)))
}

function bitWrite(value, bit, bitvalue) {
return (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
}

function read() {
data <- blob(3);

// wait for the chip to become ready
while (!is_ready());

// pulse the clock pin 24 times to read the data
for (local j = 2; j >=0; j–) {
for (local i = 7; i >=0; i–) {
sck.write(HIGH);
if (dout.read()) data[j] = data[j] | (1<<i);
sck.write(LOW);
}
}

for (local i = 0; i < GAIN; i++) {
sck.write(HIGH);
sck.write(LOW);

}

data[2] ^ 0x80;

return (data[2] << 16) | (data[1] << 8) | data[0];
}

function read_average(times) {
local sum = 0;
for (local i = 0; i < times; i++) {
sum += read();
}
return sum / times;
}

function get_value(times) {
return read_average(times) - OFFSET;
}

function get_units(times) {
return get_value(times) / SCALE;
}

function tare(times) {
local sum = read_average(times);
set_offset(sum);
}

function set_scale(scale) {
SCALE <- scale;
}

function set_offset(offset) {
OFFSET <- offset;
}

function power_down() {
sck.write(LOW);
sck.write(HIGH);
}

function power_up() {
sck.write(LOW);
}

function reset() {
sck.write(HIGH);
imp.sleep(0.000100);
sck.write(LOW);
}

function init() {
reset();
imp.sleep(0.5);
set_gain(128);
imp.sleep(0.5);
loop();
}

function loop() {
server.log(read());
imp.wakeup(1, loop);
}

init();`

Brandon is shortly posting a tutorial on the HX711, so that will likely answer your question more fully. As I said, I wrote the code blind and didn’t test it so I don’t really know why you’re seeing strange numbers.

big thanks! Hugo and Co.

The blog post should be up later today - just finalizing some graphics for it :slight_smile:

In the meantime, here’s a sneak peak at the code he wrote: https://gist.github.com/bbharris/53f4351af704867b4df0

Note - that code does some temperature compensation - which you may need to tweak / remove?

Nice!!! as i see, i was very wrong with my code… :wink:

The readings are very accurate. I like it!

@brandon thx for doing an sharing this.

By the way - the blog post is up now - it has lots of pretty graphs :slight_smile:

https://community.electricimp.com/blog/imp-load-cells/