Python Forum
Normalizing a value from HX711
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Normalizing a value from HX711
#1
I have a scale project that is used to determine the quantity of beer in a keg. Since not all beers weigh the same, the full weight of the keg is inconsistent. I'd like to find a way to "normalize" the range of variables used for the varied weights. When I run the following code, it starts out with getting a "zero" reference then I place the full keg on. With a full keg, I get values between 500000 and 515000. How do I convert the larger number to a simple "100" so that I could use percentage of range (0-100) instead of 0-inconsistent number.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Scale project that uses a scale to determine the volume of beer in the keg.
# A row of LEDs indicates the state of the program and the volume of the keg.
# A requests post initiates a push notification to my phone when the weight of the keg changes.
 
import time
import sys
import requests
from gpiozero import LED
 
 
#Define LED indicators - these are GPIO numbers
LED1 = LED(21) #Blue
LED2 = LED(26) #Red
LED3 = LED(20) #Amber
LED4 = LED(19) #Green
LED5 = LED(16) #Green
LED6 = LED(13) #Green
LED7 = LED(6) #Green
LED8 = LED(12) #Green
LED9 = LED(5) #Pink
 
EMULATE_HX711=False
 
referenceUnit = 1
 
if not EMULATE_HX711:
    import RPi.GPIO as GPIO
    from hx711 import HX711
else:
    from emulated_hx711 import HX711
 
def moving_average(prev_average, new_value, num_steps = 5.0):
   return (prev_average * (num_steps - 1) + new_value) / num_steps
 
average = weight = 400000  #just a value close to what a newly deployed keg would be
w_threshold = 2000  #approximate value of 3-4 fluid ounces of the beer
 
def cleanandexit():
    print("Cleaning...")
    if not EMULATE_HX711:
        GPIO.cleanup()       
    print("Bye!")
    sys.exit()
 
hx = HX711(27, 22)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(1)
hx.reset()
hx.tare()
 
print("The scale is ready"
print("put the keg on...")
 
LED9.blink(.2,3# indication that the scale is running - not blinking means program crash
start = time.time()
 
while True:
    try:       
        keg1 = hx.get_weight(5)
        weight = keg1
        keg1 = round(keg1,3)
        start_weight = keg1
        print(keg1, average)
        if time.time() - start > 5:
            weight = keg1
            lost_weight = average - keg1
            lost_weight = round(lost_weight,3)
            if lost_weight > w_threshold:
               #r = requests.post("https://bit.ly/editedforprivacy")  #Join URL that triggers push notification to my phone
               print("You got served")
               average = keg1  #resets average to new keg1 value for faster recovery
            print(lost_weight)  #visual indication of how much was poured - one pint is about 8400
            average = moving_average(average, weight)
            average = round(average,3)
            start = time.time()
 
 
        if 8000 >= keg1 <= 507001: #keg is outside of usable range - flashes when keg is missing (indicating tare is complete at startup)
            LED1.blink(.2,.2)
        else:
            LED1.off()
 
        if 109800 >= keg1 >= 80000: #Red less than 5% - DANGER
            LED2.blink(.5,.5)
        else:
            LED2.off()
             
        if 130600 >= keg1 >= 109799: #Amber less than 10% - Warning
            LED3.on()
        else:
            LED3.off()
             
        if 507000 >= keg1 >= 130599: #  Green 10-20% - Caution
            LED4.on()
        else:
            LED4.off()
             
        if 507000 >= keg1 >= 172199: #Green2 20-40%
            LED5.on()
        else:
            LED5.off()
             
        if 507000 >= keg1 >= 255400: #Green3 40-60%
            LED6.on()
        else:
            LED6.off()
             
        if 507000 >= keg1 >= 338600: #Green4 60-80%
            LED7.on()
        else:
            LED7.off()
             
        if 507000 >= keg1 >= 421800: #Green5 80-100%
            LED8.on()
        else:
            LED8.off()
 
 
        hx.power_down()
        hx.power_up()
        time.sleep(1)
 
 
    except (KeyboardInterrupt, SystemExit):
 
        cleanandexit()
Keep in mind that this code's values are based on a full keg being about 507000 and an empty keg being about 89000. This works out to a net weight of about 418000, which is the weight of the beer.

I have found that I can get inconsistent "full" values using the same keg. Running this 4 times this morning, I got the following values for full: 507000, 511000, 509000, and 516000.
Reply
#2
scale = 100 / (full - empty)
percent_full = (weight - empty) * scale

Empty is the weight of an empty keg. Hopefully this is consistent enough to be a constant. full is the weight of a full keg and would be taken just before entering the loop. It will be different for each keg.
Reply
#3
That seems easy enough. So what I need to do now is to tell the program when to capture the "full" value. Plobby do that with a button push, kind of like a reset function. I will see what I can do with this. Thanks for the idea.
Reply
#4
So I added a few things, haven't been able to test it yet. Let me know if this is what you were talking about. I only changed the part where these maths control the lights, not much else. I also added the reset button on GPIO4, expecting a push of that button will reset the "full" value to the currently observed "keg1" value that the HX711 is reporting. On paper, this looks like what I am after.

Behold the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Scale project that uses a scale to determine the volume of beer in the keg.
# A row of LEDs indicates the state of the program and the volume of the keg.
# A requests post initiates a push notification to my phone when the weight of the keg changes.
  
import time
import sys
import requests
from gpiozero import LED
  
  
#Define LED indicators - these are GPIO numbers
LED1 = LED(21) #Blue
LED2 = LED(26) #Red
LED3 = LED(20) #Amber
LED4 = LED(19) #Green
LED5 = LED(16) #Green
LED6 = LED(13) #Green
LED7 = LED(6) #Green
LED8 = LED(12) #Green
LED9 = LED(5) #Pink
Reset = Button(4) #Button to reset the variable "full" to the current scale value
 
 
EMULATE_HX711=False
  
referenceUnit = 1
  
if not EMULATE_HX711:
    import RPi.GPIO as GPIO
    from hx711 import HX711
else:
    from emulated_hx711 import HX711
  
def moving_average(prev_average, new_value, num_steps = 5.0):
   return (prev_average * (num_steps - 1) + new_value) / num_steps
 
def reset_full():
    full = keg1
     
average = weight = 400000  #just a value close to what a newly deployed keg would be
w_threshold = 2000  #approximate value of 3-4 fluid ounces of the beer
  
def cleanandexit():
    print("Cleaning...")
    if not EMULATE_HX711:
        GPIO.cleanup()       
    print("Bye!")
    sys.exit()
  
hx = HX711(27, 22)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(1)
hx.reset()
hx.tare()
  
print("The scale is ready"
print("put the keg on...")
  
LED9.blink(.2,3# indication that the scale is running - not blinking means program crash
start = time.time()
  
while True:
    try:       
        keg1 = hx.get_weight(5)
        weight = keg1
        keg1 = round(keg1,3)
        start_weight = keg1
         
        print(keg1, average)
        if time.time() - start > 5:
            weight = keg1
            lost_weight = average - keg1
            lost_weight = round(lost_weight,3)
            if lost_weight > w_threshold:
               #r = requests.post("https://bit.ly/editedforprivacy")  #Join URL that triggers push notification to my phone
               print("You got served")
               average = keg1  #resets average to new keg1 value for faster recovery
            print(lost_weight)  #visual indication of how much was poured - one pint is about 8400
            average = moving_average(average, weight)
            average = round(average,3)
            start = time.time()
            Reset.when_pressed = reset_full
 
            full = keg1
            empty = 89000
            scale = 100 / (full - empty)
            percent_full = (weight - empty) * scale
 
  
        if 1 >= percent_full <= 102: #keg is outside of usable range - flashes when keg is missing (indicating tare is complete at startup)
            LED1.blink(.2,.2)
        else:
            LED1.off()
  
        if 1.1 >= percent_full >= 5: #Red less than 5% - DANGER
            LED2.blink(.5,.5)
        else:
            LED2.off()
              
        if 100 >= percent_full >= 10: #Amber less than 10% - Warning
            LED3.on()
        else:
            LED3.off()
              
        if 100 >= percent_full >= 20: #  Green 10-20% - Caution
            LED4.on()
        else:
            LED4.off()
              
        if 100 >= percent_full >= 40: #Green2 20-40%
            LED5.on()
        else:
            LED5.off()
              
        if 100 >= percent_full >= 60: #Green3 40-60%
            LED6.on()
        else:
            LED6.off()
              
        if 100 >= percent_full >= 80: #Green4 60-80%
            LED7.on()
        else:
            LED7.off()
              
        if 100 >= keg1 >= 80.1: #Green5 80-100%
            LED8.on()
        else:
            LED8.off()
  
  
        hx.power_down()
        hx.power_up()
        time.sleep(1)
  
  
    except (KeyboardInterrupt, SystemExit):
  
        cleanandexit()
Reply
#5
The percent_full equation converts the keg weight to a number in the range 0 to 100. This is the number you should use for calculating average and turning LED's on and off. It should be calculated each time you weigh the keg.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Issue with HX711 reading duckredbeard 0 2,817 Aug-28-2020, 10:00 AM
Last Post: duckredbeard
  HX711&matplotlib problems olego 0 2,403 Jul-12-2019, 12:22 PM
Last Post: olego
  Guizero HX711 Load Cell and python3 stdout? Tesla 1 4,328 Jan-16-2019, 01:15 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020