Raspberry Pi Smart Food Scale with Hexabitz Modules

In this tutorial we are building a Raspberry Pi smart food scale with Hexabitz modules

projectImage

Things used in this project

Hardware components

HARDWARE LIST
1 Raspberry Pi 3 Model B+
1 Hexabitz 4-Pin USB-Serial Prototype Cable
1 Hexabitz Raspberry Pi Interface Module (HF1R0x)
1 Hexabitz BitzClamp
1 Hexabitz Load Cell (Strain Gauge) Sensor Module (H26R00)
1 DFRobot 7'' HDMI Display with Capacitive Touchscreen

Software apps and online services

STMicroelectronics STM32CUBEPROG

Story

In this tutorial we are building a Raspberry Pi kitchen scale, whose precision is amazingly accurate. In addition, It can calculate energy in calories, display this info on the LCD, and you can transfer the weight information remotely.

 

Calories are essential for human health. The key is consuming the right amount thus, many weight loss programs center around reducing the intake of calories so counting calories is your first step to weight management.

projectImage

How I build it 🛠️

 

The most important thing to build your own scale is a “load cell”, which is a metal bar with a hole in the center. This is available for different weight classes (up to 1kg, up to 5kg, up to 50kg, etc.). Even though some have a different form, all are provided with four cables.

 

A load cell is a transducer which converts force into a measurable electrical output. Although there are many varieties of force sensors, strain gauge load cells are the most commonly used type.

 

A load cell consists of a metal core and a set of electrical resistances that transform when a force is applied to it. But after the force is removed, it returns to its original state. The reversibility of this material determines the quality and accuracy of the load cell. The equivalent electrical circuit of a load cell is as follows:

Our load cell has 4 wires:

 

🔴 Red for Excitation+

 

⚫ Black for Excitation-

 

🟡 Yellow for Output+

 

🟢 Green for Output-

 

projectImage

Be careful about the side of the load cell when you’re putting a weigh on it. Usually, there is an arrow on the module that shows the force direction. With the help of this arrow, you can place the weight and the load cell correctly.

projectImage

To read out the values, the weight sensor module is also required.

 

Load Cell Sensor (H26R0x) : H26R0x is a load cell (strain gauge) sensor interface module based on Avia Semiconductor HX711 Wheatstone bridge ADC and STM32F0 MCU. This module is a precision 24-bit analog-to-digital converter (ADC) designed for weigh scales and industrial control applications. It interfaces to load cells (strain gauges) in a Wheatstone bridge configuration. The module accepts a full bridge (5-pin connection) as well as a secondary sensor connection (2 pins).

projectImage
projectImage
projectImage
projectImage
projectImage
projectImage
projectImage
projectImage
projectImage

To use a load cell module, first you need to calibrate it. Then stream strain gauge channel (ch) in gram to a port in remote module (HF1R0 module) with specified period and timeout. To do this add the following APIs to your Hexabitz load cell module code.

Module_Status Calibration(uint16_t full_scale, float cell_output, float cell_drift)
//Set load cell calibration values (full scale, cell output, cell
drift)
Module_Status ZeroCal(uint8_t ch) // Perform zero weight calibration on the load cell
Module_Status StreamGramToPort(uint8_t ch,uint8_t port, uint8_t module, uint32_t period, uint32_t timeout);

projectImage

Raspberry Pi Interface (HF1R0x):HF1R0x Is Hexabitz Raspberry Pi interface module. It interfaces seamlessly to Raspberry Pi 3B/3B+/4B single-board computers and enables you to connect and control your favorite Hexabitz modules from the Raspberry Pi operating system and build your own Raspberry Pi Hat. You can use C++ Hexabitz Interface library on Raspbian, Ubuntu or other compatible Linux distributions from within your C++ or Python applications.

Notes:

 

Connect the H26R0 module to HF1R0 module.

 

Make sure to connect your Hexabitz module at the right spot or left spot then put the Jumper JP1 and JP2 at right position.

 

Be sure to download the firmware on the module before soldering.

 

https://hexabitz.com/docs/how-to/update-module-firmware/

 

Code Explanation 🖥️ 🧐 ⚖️

 

Python Tkinter

 

Tkinter is the standard GUI library for Python. Python when combined with Tkinter provides a fast and easy way to create GUI applications. Tkinter provides a powerful object-oriented interface to the Tk GUI toolkit. Creating a GUI application using Tkinter is an easy task.

 

projectImage

All you need to do is perform the following steps :

 

-Import the Tkinter module.

 

-Create the GUI application main window.

 

-Add one or more of the above-mentioned widgets to the GUI application.

 

-Enter the main event loop to take action against each event triggered by the user.

 

· You can start Python3 from the command line (with python3) then

import tkinter

· If you get an error message, then exit out of Python3 and call this command to install it.

sudo apt-get install python3-tk

"master" represents the parent window, where the entry widget should be placed. Like other widgets, it's possible to further influence the rendering of the widget by using options. The comma separated list of options can be empty.

 

The Button widget is a standard Tkinter widget, which is used for various kinds of buttons. A button is a widget which is designed for the user to interact with, i.e. if the button is pressed by mouse click some action might be started. They can also contain text and images like labels.

 

Python pyserial

 

This module encapsulates the access for the serial port. It provides backends for Python running on Windows, OSX, Linux, BSD (possibly any POSIX compliant system) and IronPython. The module named “serial” automatically selects the appropriate backend.

projectImage

Depending on the version of python, there are several commands to install the package pyserial.

 

sudo apt-get install python-serial python3-serial

Note :

 

There are several ways to determine the USB port to which the device is connected. The fastest is to connect the unit to the USB port then to immediately run the command dmesg -s 1024.

 

You’ll get directly the tty port on which it is connected.

 

Python code to read the serial port:

 

This section of code primarily instantiates the serial class, setting it up with all the various bits of information that it needs to make the connection with.

 

port – This defines the serial port that the object should try and do read and writes over.

 

baudrate – This is the rate at which information is transferred over a communication channel.

 

parity – Sets whether we should be doing parity checking, this is for ensuring accurate data transmission between nodes during communication.

 

stopbits – This is the pattern of bits to expect which indicates the end of a character or the data transmission.

 

bytesize – This is the number of data bits.

 

timeout – This is the amount of time that serial commands should wait for before timing out.

 

import serial
ser = serial.Serial(        
               port='/dev/ttyUSB0',
               baudrate = 921600,
               parity=serial.PARITY_NONE,
               stopbits=serial.STOPBITS_ONE,
               bytesize=serial.EIGHTBITS,
               timeout=1
           )

 

struct Module

 

This module performs conversions between Python values and C structs represented as Python bytes objects. This can be used in handling binary data stored in files or from network connections, among other sources. It uses Format Strings as compact descriptions of the layout of the C structs and the intended conversion to/from Python values.

projectImage
projectImage
projectImage

We’ll kick off with learning the functions used in this project:

 

Byte to float function:

projectImage

import serial
import struct
ser = serial.Serial(port='/dev/ttyS0',baudrate = 921600,parity=serial.PARITY_NONE,
                   stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
print(ser.name)

def byte_to_float(b):
    x = struct.unpack('f', b)
    return x
def stream():
    global w
    s = ser.read(4)
    print(s)
    [w,] = byte_to_float(s)
    w = int(w)
    print(w)
    return w

 

In our main program we define the tk window with the Tk() as the root variable. Then we create the title of the window.

 

from tkinter import *

root=Tk()

root.title("Hexabitz Scale")

projectImage
projectImage
projectImage

The stop button:

 

button=Button(root,text='Stop',bg ='orange',width=50,command=root.destroy)

button.pack()

projectImage
projectImage

You can use food calorie calculator to know the values for our GUI code.

projectImage
projectImage
projectImage

The sample button:

 

def start():

  global w

  w = stream()

  print(w)

  lable= Label (root,width=24,fg="yellow",bg="black")

  lable.config(font=("Courier",20))

  lable.config(text=str(w)+ ' g')

  lable.pack()

  

Bsample=Button(root,text='Sample weight(g)', bg ='gold',width=50,command=start)

Bsample.pack()

 

FoodName label and option menu:

 

🍏🍎🍌🍐🍊🍋🍆🍒🫑🥥🍍🍪🍬🍞🌽🥕

 

OPTIONS = [

"Apples", "Pears" ,"Raspberries","Bread","Sugar"] #etc

L1 = Label(root, text = "Food Name")

L1.pack()

variable = StringVar(root)

variable.set(OPTIONS[0]) # default value

w = OptionMenu(root, variable, *OPTIONS)

w.pack()

 

The calculationbutton:

 

def Calculate_calories():

    q =variable.get()

    w1 = int(w)

    if (q == "Apples"):

        x= 0.48

        z = x*w1

        print(z)

    elif(q == "Pears"):

        x= 0.57

        z = x*w1

        print(z)

    elif(q == "Bread"):

        x= 3.8

        z = x*w1

        print(z)

    elif(q == "Sugar"):

        x= 5.8

        z = x*w1

        print(z)

    else:

        x= 0.85

        z = x*w1

        print(z)

    lable= Label (root,width=24,fg="yellow",bg="black")

    lable.config(font=("Courier",20))

    lable.config(text = str(z) + " calories")

    lable.pack()

buttonc=Button(root,text='Calculate calories', bg ='light green',width=50,command=Calculate_calories)

buttonc.pack()

We end by a root.mainloop() function to keep events on the main window active and all other widgets interactive.

 

root.mainloop()

 

Test the System 😃 ⚖️ 🍏

projectImage
projectImage
projectImage

Schematics

 

Raspberry Pi Weight Scale Schematic

projectImage

CODE

CODE
# -*- coding: utf-8 -*-
"""
Created on Fri Sep  3 19:44:22 2021

@author: Aula_J
"""

from tkinter import *
import time
#import numpy as np
import serial
import struct
ser = serial.Serial(        
               port='/dev/ttyS0',
               baudrate = 921600,
               parity=serial.PARITY_NONE,
               stopbits=serial.STOPBITS_ONE,
               bytesize=serial.EIGHTBITS,
               timeout=1
           )
print(ser.name)
def byte_to_float(b):
    x = struct.unpack('f', b)
    return x
def stream():
    global w
    s = ser.read(4) #4byte
    print(s)
    [w,] = byte_to_float(s)
    w = int(w)
    print(w)
    return w
    

root=Tk()
root.title("Hexabitz Scale")
OPTIONS = [
"Apples", "Pears" ,"Raspberries",
"Bread",
"Sugar"
] #etc

def start():
  global w
  w = stream()
  print(w)
  lable= Label (root,width=24,fg="yellow",bg="black")
  lable.config(font=("Courier",20))
  lable.config(text=str(w)+ ' g')
  lable.pack()

button=Button(root,text='Stop',bg ='orange',width=50,command=root.destroy)
button.pack()
Bsample=Button(root,text='Sample weight(g)', bg ='gold',width=50,command=start)
Bsample.pack()
L1 = Label(root, text = " Food Name")
L1.pack()
variable = StringVar(root)
variable.set(OPTIONS[0]) # default value
w = OptionMenu(root, variable, *OPTIONS)
w.pack()
def Calculate_calories():
    q =variable.get()
    global w
    #w = stream()
    w1 =int(w)
    if (q == "Apples"):
        x= 0.48
        z = x*w1
        print(z)
    elif(q == "Pears"):
        x= 0.57
        z = x*w1
        print(z)
    elif(q == "Bread"):
        x= 3.8
        z = x*w1
        print(z)
    elif(q == "Sugar"):
        x= 5.8
        z = x*w1
        print(z)
    else:
        x= 0.85
        z = x*w1
        print(z)
    lable= Label (root,width=24,fg="yellow",bg="black")
    lable.config(font=("Courier",20))
    lable.config(text = str(z) + " calories")
    lable.pack()
buttonc=Button(root,text='Calculate calories', bg ='light green',width=50,command=Calculate_calories)
buttonc.pack()
root.mainloop()
icon H26R0x-Firmware-master.zip 2.5MB Download(0)

HF1R0x-Firmware 0.2.0

https://github.com/HexabitzPlatform/HF1R0x-Firmware/tree/0.2.0

The article was first published in hackster, September 5, 2021

cr: https://www.hackster.io/aula-jazmati/raspberry-pi-smart-food-scale-with-hexabitz-modules-e6cbaf

author: Aula Jazmati, Najib Kassab

License
All Rights
Reserved
licensBg
0