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


#1

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


#2

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.


#3

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.


#4

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.


#5

I used this before… worked like a charm:

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


#6

@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.


#7

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.


#8

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.


#9

@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.


#10

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.


#11

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


#12

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


#13

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());
});
`


#14

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.


#15

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();`


#16

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.


#17

big thanks! Hugo and Co.


#18

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?


#19

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.


#20

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/