【教程】基于M5Stack的两种玩法的HX711厨房电子秤-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 6117|回复: 0

【教程】基于M5Stack的两种玩法的HX711厨房电子秤

[复制链接]
发表于 2021-5-12 18:20 | 显示全部楼层 |阅读模式
本帖最后由 沧海笑1122 于 2021-5-12 18:23 编辑

                      基于M5Stack的两种玩法的HX711厨房电子秤
【背景故事】
    电子秤我前后做过6个版本:
第一版是2014年完成的,基于arduinonano+LCD 5110+hx711,这一版也是一个实用器,使用了将近五六年,主要是用作厨房秤,这些年烘培出无数美味面包,这一版电子秤功不可没。
第二版是基于m5stack basic+hx711,因此还写过一个帖子《129行代码的M5Stack(coreEsp32)电子秤(micropython)》。
第三版是基于M5StickC+Unit(HX711)电子秤,用UIFlow写的,全部代码只有25行,得益于UIFlow对hx711的良好封装。
第四版就是在第三版基础上,使用app inventor 2.0写了一个手机APP,通过手机ble与m5atom的ble进行通信,将称重数据上送至手机APP,从而实现一个手机电子秤。
第五版就是使用blynk+m5stickc,实现的基于物联网的电子秤,也是在手机上显示电子秤称重结果,但使用的技术有所不同。
第六版是基于raspberry pico+LCD1602实现的,基本上是一个原型搭建,会在专门的帖子里介绍,本文不展开。
今天的文章重点写第4、5版,他们的共同点是使用一个通用的秤盘,他们的不同点就是分别使用了esp32,esp32+手机,esp32+blynk(当然也离不开一部手机)来实现一个带有去皮功能的厨房秤。
主要知识点包括uiflow使用、esp32与手机ble通信、blynk编程。就实用而言,第三版已经足矣,而趣味性则各有千秋。

【一、软硬件准备】
  
电子秤版本
  
主要硬件
软件
秤盘+形变传感器
  
V4
  
M5stackAtom(esp32)+ Unit(HX711)+安卓手机
App Inventor 2.0(手机APP)
  
Arduino IDE 1.8.13
  
V5
  
M5StickC(esp32)+ Unit(HX711)+安卓手机
Blynk (手机app)
  
UIFLOW 1.7.6
备注:
这是一个计重 Unit。集成专为高精度电子秤而设计的24位A/D转换器芯片HX711。输入选择开关可任意选取通道A 或通道B,与其内部的低噪声可编程放大器(PGA)相连.通道A 的可编程增益为128 或64,对应的满额度差分输入信号幅值分别为±20mV或±40mV.通道B 则为固定的32 增益,所有控制信号由管脚驱动,无需对芯片内部的寄存器编程。
2、秤盘+形变传感器
(1)形变传感器:形变传感器,顾名思义根据物体重量不同,称重时作用于两个支点的形变传感器,从而产生物理形变,发出电信号,经过A/D转换后提供给单片机进行处理、展示。形变传感器来自网购。请注意量程,我用于厨房秤用途,所以选用1000g。
(2)秤盘:小盒一只,乐高积木两片,热熔胶枪一把。
首先我们看一下工作情况:
  • V4电子秤工作情况:
v4_atom1_b.jpg

  • V5电子秤工作情况
v5_pic1.jpg

注:v5用的秤盘是第一版使用的秤盘,原理完全一致,外形有所不同。
【二、秤盘+形变传感器制作过程】
详见我以前的帖子:

  • 调试并计算折算系数
     (1)使用100g砝码一只,观察称重数据为-829;200g砝码一只,观察称重数据为-1660,因此得到称重折算系数为:-1660/200=-829/100=8.3
     每个形变传感器的参数略有不同,所以用砝码校正折算系数是必要的。
     (2)联调后,顺利得到正确称重数据。
形变传感器接unit时,需要把引线重新焊一下,并且热缩处理。

【四、原理框图】
1、V4 M5StickC+BLE+手机APP(ai2)电子秤(以下简称V5电子秤)
(1)app inventor 2.0部分

这是电子秤APP的UI部分:
v4_pic1_c.png
  
序号
  
内容
备注
  
1
  
Scan BLE :搜索周边的BLE设备

  
2
  
Select&connect Atom:在设备列表中,选择并且连接标记为M5stackAtom的BLE设备(M5Atom  esp32 core)
选择连接后,标记为4的按钮会显示:Now  Connected
  
3
  
Get scale Data: 触发一个定时器,每隔1秒读取一次Atom送来的称重数据

  
4
  
连接按钮,建立连接后,字体会变为黑色
未连接则为灰色
  
5
  
数据区,显示一个小数点保留一位的称重数据
单位是克
v4_pic2_d.png
这是逻辑设计部分,也都比较直观:
  
序号
  
内容
备注
  
1
  
触发计时器后的动作,调用一个readstrings事件,读取相应的seriveUuid和characteristicUuid的数据

  
2
  
这就是UI中get scale  data按钮对应的逻辑,触发一个计数器

  
3
  
Scan ble被点击后,调用的搜索ble设备功能,同时对连接按钮的属性进行赋值

  
4
  
Ble连接建立后,连接按钮会显示:Now  Connected

  
5
  
选择周边ble设备的功能,选中后,会传递mac_device地址

  
6
  
这是一个收取ble数据的事件,将读到的stringvalues数据赋值给label的文本,够直观吧,令人想到了uiflow这样的做法。
由于读到的是一个列表,所以数据会带一对括号,简单用一个文本替换做处理。也许你会有更好的办法,我是懒了一下

(2)我们来看一下arduino侧的做法(M5Atom esp32)
v4_atom1_a.jpg
2、V5 M5StickC+blynk(手机物联网APP)电子秤(以下简称V5电子秤)
(1)M5StickC部分,我们仍然使用uiflow
v5_pic1_f.png
  
序号
  
内容
备注
  
1
  
UI设计,由于我们不需要在C上显示,仅仅是一个参考,所以留一个称重数据即可
仅作参考,你也可以选择Atom,就不需要设计UI
  
2
  
连接wifi需要的ssid以及password

  
3
  
检查连接wifi状态,并且连接blynk  server,需要输入你从blynk获取的该项目的令牌
我们使用裘师兄提供的mixly的服务器,20万能量值
  
4
  
LCD电压2.7V,原理同上

  
5
  
设置px折算系数,原理同上

  
6
  
主循环:在C上显示称重数据
仅作参考,你也可以选择Atom,就不需要设计UI
  
7
  
去皮按钮,同上
这是C上的实体去皮按钮
  
8
  
这是一个blynk write去皮按钮的回调函数,在手机app上触发去皮按钮,会把状态传送给v2(虚拟pin2),从而实现去皮
Blynk 去皮按钮
  
9
  
这是一个blynk的read函数,以v1(虚拟pin1)向blynk  server传送称重数据,将在手机app上进行读取、显示



(2)blynk部分

Blynk侧就两个组件,一个是用仪表盘显示称重数据,定义为v1(数据获取方式设为1秒获取一次;,第二个就是去皮按钮(定义为v2);开发板选用esp32 wifi连接方式。
v5_blynk1_a.jpg
v5_blynk1_c.jpg v5_blynk1_b.jpg v5_blynk1_d.jpg
【五、代码】
1、V4电子秤代码(atom侧,arduino)
  1. /*
  2.   2021-04-24
  3.    IT works
  4. */
  5. // BLE init
  6. #include <BLEDevice.h>
  7. #include <BLEServer.h>
  8. #include <BLEUtils.h>
  9. #include <BLE2902.h>

  10. BLEServer* pServer = NULL;
  11. BLECharacteristic* pCharacteristic = NULL;
  12. bool deviceConnected = false;
  13. bool oldDeviceConnected = false;

  14. // See the following for generating UUIDs:
  15. // https://www.uuidgenerator.net/
  16. #define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
  17. #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


  18. // HX711 INIT
  19. #include "HX711.h"
  20. // HX711 circuit wiring
  21. const int LOADCELL_DOUT_PIN = 32; //hx711接线
  22. const int LOADCELL_SCK_PIN = 26; //hx711接线
  23. HX711 scale;

  24. //uint32_t value = 0;
  25. float v_scale=0;   //float type in hx711.cpp

  26. #include "M5Atom.h"
  27. //闪动效果,在发送数据时,闪动一下全彩led
  28. uint8_t DisBuff[2 + 5 * 5 * 3];
  29. void setBuff(uint8_t Rdata, uint8_t Gdata, uint8_t Bdata)
  30. {
  31.     DisBuff[0] = 0x05;
  32.     DisBuff[1] = 0x05;
  33.     for (int i = 0; i < 25; i++)
  34.     {
  35.         DisBuff[2 + i * 3 + 0] = Rdata;
  36.         DisBuff[2 + i * 3 + 1] = Gdata;
  37.         DisBuff[2 + i * 3 + 2] = Bdata;
  38.     }
  39. }
  40. class MyServerCallbacks: public BLEServerCallbacks {
  41.     void onConnect(BLEServer* pServer) {
  42.       deviceConnected = true;
  43.     };

  44.     void onDisconnect(BLEServer* pServer) {
  45.       deviceConnected = false;
  46.     }
  47. };
  48. void setup() {
  49.   M5.begin(true, false, true);
  50.   Serial.begin(115200);
  51. // Start up the library
  52.   // Create the BLE Device
  53.   BLEDevice::init("M5StackAtom");

  54.   // Create the BLE Server
  55.   pServer = BLEDevice::createServer();
  56.   pServer->setCallbacks(new MyServerCallbacks());

  57.   // Create the BLE Service
  58.   BLEService *pService = pServer->createService(SERVICE_UUID);

  59.   // Create a BLE Characteristic
  60.   pCharacteristic = pService->createCharacteristic(
  61.                       CHARACTERISTIC_UUID,
  62.                       BLECharacteristic::PROPERTY_READ   |
  63.                       BLECharacteristic::PROPERTY_WRITE  |
  64.                       BLECharacteristic::PROPERTY_NOTIFY |
  65.                       BLECharacteristic::PROPERTY_INDICATE
  66.                     );

  67.   // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  68.   // Create a BLE Descriptor
  69.   pCharacteristic->addDescriptor(new BLE2902());

  70.   // Start the service
  71.   pService->start();

  72.   // Start advertising
  73.   BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  74.   pAdvertising->addServiceUUID(SERVICE_UUID);
  75.   pAdvertising->setScanResponse(false);
  76.   pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  77.   BLEDevice::startAdvertising();
  78.   Serial.println("initializing the scale");
  79.   delay(10);
  80.   scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  81.   scale.set_scale(-2070.98238269795);  //(raw_100-raw_0)/100 
  82.   // this value is obtained by calibrating the scale with known weights; see the README for details
  83.   scale.tare();   
  84.   Serial.println("Waiting a client connection to notify...");
  85.    
  86. }

  87. void loop() {
  88.     if (M5.Btn.wasPressed())
  89.       {

  90.         Serial.println("button is pressed,scale.tare()");
  91.         scale.tare();               // reset the scale to 0
  92.       }
  93.    
  94.     // notify changed value
  95.     if (deviceConnected)
  96.     {
  97.        v_scale = scale.get_units(20);
  98.        char txString[8]; // make sure this is big enuffz
  99.        dtostrf(v_scale, 1, 2, txString); // float to char ,for send
  100.        pCharacteristic->setValue(txString);
  101.        //m5atom led blink
  102.        setBuff(0x00, 0x40, 0x00);//green,绿色led
  103.        M5.dis.displaybuff(DisBuff);
  104.        delay(10);
  105.        setBuff(0x00, 0x00, 0x00); //black ,熄灭
  106.        M5.dis.displaybuff(DisBuff);
  107.        pCharacteristic->notify();
  108.        Serial.print("Value of scale = ");
  109.        Serial.println(txString);
  110.     }
  111.            
  112.         delay(90); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
  113.    
  114.     // disconnecting
  115.     if (!deviceConnected && oldDeviceConnected) {
  116.         delay(500); // give the bluetooth stack the chance to get things ready
  117.         pServer->startAdvertising(); // restart advertising
  118.         Serial.println("start advertising");
  119.         oldDeviceConnected = deviceConnected;
  120.     }
  121.     // connecting
  122.     if (deviceConnected && !oldDeviceConnected) {
  123.         // do stuff here on connecting
  124.         oldDeviceConnected = deviceConnected;
  125.     }
  126.   

  127.     delay(50);
  128.     M5.update();

  129. }
复制代码
2、V5电子秤
M5StackC侧代码(由Uiflow生成)


  1. from m5stack import *
  2. from m5ui import *
  3. from uiflow import *
  4. from IoTcloud import blynk
  5. import time
  6. import wifiCfg
  7. import unit

  8. setScreenColor(0x111111)
  9. weigh2 = unit.get(unit.WEIGHT, unit.PORTA)

  10. scale_pin = None
  11. scale = None
  12. butn_state = None
  13. butn = None
  14. Px = None

  15. wifiCfg.doConnect('your ssid', 'your pass')
  16. label0 = M5TextBox(47, 9, "HX711   LcdV=", lcd.FONT_Default, 0xFFFFFF, rotate=90)
  17. label1 = M5TextBox(47, 123, "0.0", lcd.FONT_Default, 0xFFFFFF, rotate=90)
  18. def blynk_read_v1(v_pin):
  19.   global scale_pin, scale, butn_state, butn, Px
  20.   scale_pin = v_pin
  21.   scale = "%.1f"%(((weigh2.weight) / Px))
  22.   blynk1.virtual_write(scale_pin, scale)
  23.   pass

  24. def blynk_write_v2(v_pin, value):
  25.   global scale_pin, scale, butn_state, butn, Px
  26.   butn_state = v_pin
  27.   butn = value
  28.   if butn[0] == '1':
  29.     weigh2.zero()
  30.   pass

  31. def buttonA_wasPressed():
  32.   global scale_pin, scale, butn_state, butn, Px
  33.   wait(0.1)
  34.   weigh2.zero()
  35.   pass
  36. btnA.wasPressed(buttonA_wasPressed)

  37. if wifiCfg.wlan_sta.isconnected():
  38.   label0.setColor(0x33ff33)
  39.   blynk1 = blynk.Blynk(server='blynk.mixly.org', port=8080, token='your token', heartbeat=1)
  40.   blynk1.handle_event('read v1', blynk_read_v1)
  41.   blynk1.handle_event('write v2', blynk_write_v2)
  42. else:
  43.   label0.setColor(0xffffff)
  44. scale = ''
  45. axp.setLDO2Volt(2.7)
  46. #Px = -8.24
  47. Px=-7.8 #self hx711
  48. while True:
  49.   label1.setText(str("%.1f"%((axp.getBatVoltage()))))
  50.   #label3.setText(str("%.1f"%(((weigh2.weight) / Px))))
  51.   #label2.setText('g')
  52.   wait(0.1)
  53.   blynk1.run()
  54.   wait_ms(2)
复制代码
【两版电子秤的对比小结】
  
电子秤版本
  
主要特点
单独显示屏
手机APP
趣味性及知识性
难度
  
V4
  
App inventor 2.0是非常优秀的便于上手的app制作工具,将手机Ble与esp32的ble连接后,便产生了丰富的拓展可能性。
★★★
★★
  
V5
  
Blynk是多年沉淀的物联网应用开源系统,难得可贵的是这个系统的坚守、开源和包容。esp32可以通过Ble、wifi、usb以及以太网等多种方式与其接入,从而产生丰富的创意
★★★
上述两个版本都属于比较容易上手的入门级小软件,又是实用的厨房秤,希望大家玩得开心。
感谢arduino.cn提供交流平台,感谢M5Stack生产优秀的极客玩具(同时也为工业物联网提供了丰富的扩展空间)
感谢M5论坛各位师兄指导,感谢裘炯涛师兄提供blynk.mixly.org服务器。
沧海抱拳。

v4/v5版的代码以及ai2文件打包附上,与各位分享。
v4v5code.zip (234.66 KB, 下载次数: 7)
v3_pic1.png
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-1 01:23 , Processed in 0.077920 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表