Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
vany5921
Published

M5Stack Smart Supermarket

Thanks for the source code and project information provided by @沧海

AdvancedFull instructions provided3 hours3,166
M5Stack Smart Supermarket

Things used in this project

Hardware components

ESP32 Basic Core IoT Development Kit
M5Stack ESP32 Basic Core IoT Development Kit
×1
Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
×1
Adafruit Mini Thermal Receipt Printer
×1
M5Stack Weight
×1
Pressure sensor
×1

Software apps and online services

UIFlow
VS Code
Microsoft VS Code
ArduinoJson
Adafruit thermal printer library

Story

Read more

Schematics

schematics

Physical connection

Code

M5Stack Basic Code

Python
First of all, the UI is designed to simulate the supermarket. It consists of three parts: title bar, content bar and control button.
Title Block: display M5 SIM supermarket
Content column: commodity name, weight, unit price and total price
Control bar: Apple button, walnut button and print button
Because it's a simulation supermarket, you can use the three buttons of m5stack basic to provide apple and walnut options. You can also use the M5 face kit or the newly produced card keyboard kit to expand your options.
In addition to the UI, console programming mainly includes several parts:
The first is the programming of the electronic scale. This part needs to realize the connection and debugging between the master control and the electronic scale. The wiring has been shown on the first floor. Note that VCC I choose 3.3V. The software part mainly relies on an hx711 library, and the detailed call mode. The player can refer to my electronic scale post. Here, the calibration coefficient is still saved in a TXT file and stored in the main control. Because uiflow can easily keep multiple function programs in the main control, I also upload the calibration program of the electronic scale to the main control. Players can use 100g / 200g weight to calibrate according to the temperature change (for example, the seasonal change has an impact on the deformation sensor). The calibration results are stored in the txt file, which is convenient to call.
The second is the programming of UART. We choose UART2 as the port of data delivery. Because we need to transfer four sets of data, such as goods, unit price, weight and total price, we use JSON format to transfer them.
The third is the programming of button trap, which is relatively simple. Respond to the trigger of three buttons, among which apple and walnut will update the product name and unit price, while print button will send the assembled JSON through UART2.
Here is the code of the console. The notes are clear. You can understand it with the first floor. The tool we use is the plug-in of vscode + m5stack, which is very convenient for debugging. When downloading the program, we use the wonderful little tool of upyloder.
# date 2019-09-25
##Uiflow design UI to realize electronic scale
# 0914 ----- Solved UART sending unit price + weighing data + total price + product name

# 0924 ----- The first joint commissioning with Arduino

# 0925 ----- Combined with Arduino Pro Mini 5V / 16m, the price roughly refers to the market price, apple 15 (Walnut 31 yuan) / kg finishing
 
from m5stack import *
from m5ui import *
from utime import sleep_us
from uiflow import *
from hx711 import HX711
global val_cort  #校正系数
global val,v_up,v_tp
v_up=0
v_tp=0
global s_json,v_comd #JSON string sent to UART

s_json=''
v_comd=''

#UART initialization, using UART2 to pass the data to be printed to arduin Pro Mini
 
uart = None
uart = machine.UART(2, tx=17, rx=16)
uart.init(9600, bits=8, parity=None, stop=1)
 
 
class Scales(HX711):
    def __init__(self, d_out, pd_sck):
        super(Scales, self).__init__(d_out, pd_sck)
        self.offset = 0
 
    def reset(self):
        self.power_off()
        self.power_on()
 
    def tare(self):
        self.offset = self.read()
 
    def raw_value(self):
        return self.read() - self.offset
 
    def stable_value(self, reads=10, delay_us=500):
        values = []
        for _ in range(reads):
            values.append(self.raw_value())
            sleep_us(delay_us)
        return self._stabilizer(values)
 
    @staticmethod
    def _stabilizer(values, deviation=10):
        weights = []
        for prev in values:
            weights.append(sum([1 for current in values if abs(prev - current) / (prev / 100) <= deviation]))
        return sorted(zip(values, weights), key=lambda x: x[1]).pop()[0]
 
#Create an instance
 
scales = Scales(d_out=5, pd_sck=2)
#Read out the pre stored correction coefficient
with open('cort.txt', 'r') as myfile:
        val_cort=float(myfile.read().replace('\n', ''))  #Read out the pre stored correction coefficient

myfile.close()
scales.tare() #One peeling at initialization
 
 
#------------------UI 
setScreenColor(0x222222)
M5title = M5Title(title="M5 Sim Supermarket", x=3 , fgcolor=0xFFFFFF, bgcolor=0x0000FF)
label0 = M5TextBox(16, 49, "Commodity", lcd.FONT_Ubuntu,0xFFFFFF, rotate=0)
label1 = M5TextBox(16, 90, "Unit Price", lcd.FONT_Ubuntu,0xFFFFFF, rotate=0)
label2 = M5TextBox(16, 127, "Weight", lcd.FONT_Ubuntu,0xFFFFFF, rotate=0)
label3 = M5TextBox(17, 164, "Total Price", lcd.FONT_Ubuntu,0xFFFFFF, rotate=0)
rectangle0 = M5Rect(34, 203, 60, 20, 0xf80d0d, 0xfcfbfb)
rectangle1 = M5Rect(127, 203, 60, 20, 0x55e10c, 0xf8f4f4)
rectangle2 = M5Rect(222, 203, 60, 20, 0x528be5, 0xFFFFFF)
label4 = M5TextBox(42, 205, "Apple", lcd.FONT_Default,0xFFFFFF, rotate=0)
label5 = M5TextBox(134, 207, "Walnut", lcd.FONT_Default,0xfaf9fa, rotate=0)
label6 = M5TextBox(237, 207, "Print", lcd.FONT_Default,0xFFFFFF, rotate=0)
text_comd = M5TextBox(135, 47, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)
text_up = M5TextBox(134, 93, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)
text_weig = M5TextBox(134, 130, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)
text_tp = M5TextBox(134, 164, "Text_tp", lcd.FONT_Default,0xFFFFFF, rotate=0)
 
 
while True:
    val = val_cort*scales.stable_value() #Calculation with conversion compensation coefficient, such as -0.00051235

    val1=("%.2f" % val) #Format the weighing data with 2 decimal places
    text_weig.setText(str(val1)) #Display update weighing data
    v_tp=val*v_up/1000 #Price converted to kilogram due to weighing
    
    v_tp=("%.2f" % v_tp)
    text_tp.setText(str(v_tp)) #Update total price data
    sleep_us(200000)
    if btnA.wasPressed():
        # global params
        v_comd='Apple'
        text_comd.setText(v_comd)
        text_up.setText('15.0')
        v_up=15
        pass
 
    if btnB.wasPressed():
        # global params
        v_comd='Walnut'
        text_comd.setText(v_comd)
        text_up.setText('31.0')
        v_up=31
        pass
 
    if btnC.wasPressed():
        s_json="{\"up\":\""+str(v_up)+"\",\"tp\":\""+str(v_tp)+"\",\"commodity\":\""+v_comd+"\",\"weigh\":\""+str(val1)+"\"}"
        uart.write(s_json+"\r\n")
        pass

Arduino pro mini Code

Arduino
The code of the controller consists of two parts:
One is to define two soft serial ports, one for receiving the product information in JSON format from m5stack. The second is used to issue printing instructions to the thermal printer. It is necessary to switch Listening between two soft serial ports. I also used special notes on the first floor. Otherwise, it will not work normally.
Second, we need to analyze the JSON format data from m5stack. We use the famous arduinojson library. The current version is 6.12. Please go to arduinojson.org for details. Because this time we only need to parse four data, so we use a layer of JSON format. Arduinojson.org provides a JSON assistant, which is very convenient for you to design JSON strings and related code, memory allocation and other auxiliary work.
//-------date:2019-09-24
//-------Simulation supermarket printer control terminal program
//-------Main functions: 1. Analyze data from (m5stack) softserial
//                       2. Test the output of thermal printer
//                       3. Docking with m5stack basic

//                          
/*
Data format sent by m5stack: up --- unit price; TP --- total price, commodity --- product name, weight --- weight

{
  "up": "7",
  "tp": "840",
  "commodity": "apple",
  "weigh": "120"
}
*/
 
//------------ArduinoJson
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
SoftwareSerial swSer1(10,11); //UNO-10-RX;UNO-11-TX
//------------Thermal printer
#include "Adafruit_Thermal.h"
SoftwareSerial mySerial(5, 6); // UNO-5-RX;UNO-6-TX
Adafruit_Thermal printer(&mySerial);     // Pass addr to printer constructor
 
void setup() {
  // Initialize serial port
Serial.begin(9600);
swSer1.begin(9600);
mySerial.begin(9600);
printer.begin();        // Init printer 
 
}
 
void loop() {
 
//DynamicJsonDocument doc(152);
//Monitor the soft serial port from m5stack
  swSer1.listen();
while (!swSer1.available())
delay(100);
 
  // Deserialize the JSON document
const size_t capacity = JSON_OBJECT_SIZE(4) + 50;//Define helper generation from arduinojson.org

DynamicJsonDocument doc(capacity);
 
  DeserializationError error = deserializeJson(doc, swSer1); //Reading data without soft serial port

  // Test if parsing succeeds.
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }
 
//仅供调试
String s_commodity=doc["commodity"];
String s_weigh=doc["weigh"];
String s_up=doc["up"];
String s_tp=doc["tp"];
Serial.print(s_commodity);
Serial.print("-----");
Serial.print(s_weigh);
Serial.print("-----");
Serial.print(s_up);
Serial.print("-----");
Serial.println(s_tp);
 
ToPrint(s_commodity,s_weigh,s_up,s_tp); //Call print module
 
}
 
 
void ToPrint( String t_comm , String t_weig  , String t_up , String t_tp){
 
        //Monitor No.2 soft serial port

        mySerial.listen();
        printer.begin();        // Init printer 
        // caption
        printer.inverseOn();
        printer.println(F(" M5 Sim SuperMarket "));
        printer.inverseOff();
        //print
        printer.println("--------------------------");
        printer.boldOn();
        printer.print(F("Commodity:"));
        printer.boldOff();
        printer.println(t_comm);
 
        printer.boldOn();
        printer.print(F("Weigh(g):"));
        printer.boldOff();
 
        printer.println(t_weig);
        printer.boldOn();
        printer.print(F("Unit Price:"));
        printer.boldOff();
 
        printer.println( t_up);
 
        printer.boldOn();
        printer.print(F("Total Price:"));
        printer.boldOff();
        printer.println(t_tp);
        printer.println("--------------------------");
        printer.feed(2);
 
        printer.setDefault(); // Restore printer to defaults
}

Credits

CangHai

Posted by vany5921

Comments