【西南交大电子实习】用ESP32和HX711实现的称重计/电子秤的Arduino代码

参考🔗:https://randomnerdtutorials.com/esp32-load-cell-hx711/

7月12日 Update:

  • 修改为克g盎司oz克拉ct之间的切换
  • 增加计数功能版本代码

需要安装的arduino库

  • Adafruit SSD1306
  • Adafruit GFX 库
  • HX711库
  • PushButton库

后面两个库是用户贡献库,需要注意作者名称,如下图

HX711库

按钮库

获取校准因子

#include <Arduino.h>
#include "soc/rtc.h"
#include "HX711.h"

// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 4; //HX711的DT引脚
const int LOADCELL_SCK_PIN = 16; //HX711的SCK引脚

HX711 scale;

void setup() {
  Serial.begin(115200); //波特率设置为115200
  // rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
  setCpuFrequencyMhz(RTC_CPU_FREQ_80M);

  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop() {

  if (scale.is_ready()) {
    scale.set_scale();    
    Serial.println("Tare... remove any weights from the scale.");
    delay(3000);
    scale.tare();
    Serial.println("Tare done...");
    Serial.print("Place a known weight on the scale...");
    delay(3000);
    long reading = scale.get_units(10);
    Serial.print("Result: ");
    Serial.println(reading);
  } 
  else {
    Serial.println("HX711 not found.");
  }
  delay(1000);
}

使用以下公式计算校准系数:

calibration factor = (reading)/(known weight)

每个设备的这个参数不同,需要自己测量

显示“Place a known weight on the scale”后再把物品放上去,tare是“去皮”的意思

校准称重传感器 Arduino IDE 串行监视器(波特率为115200

在我们的例子中,读数是 -141449。放置到压力传感器上的物体已知重量为 300g,因此我们的校准因子将为:-141449/300 = -471.497
参数获取

calibration factor = -141449/300 = -471.497

称重计代码

已更新成克,盎司,克拉之间的切换,自测可行,注意自调引脚


#include <Arduino.h>
#include "HX711.h"
#include "soc/rtc.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Pushbutton.h>
#include <esp32-hal-cpu.h>

// 需要自行更改的引脚有以下4个:
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16; //HX711的DT
const int LOADCELL_SCK_PIN = 4; //HX711的SCK

//Button
#define Tare_BUTTON_PIN 14    //去皮按键
#define Switch_BUTTON_PIN 12  //切换单位按键

#define CALIBRATION_FACTOR 465.344 //校准因子

HX711 scale;
float reading ;
float lastReading ;

//OLED Display
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 32  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1  // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



Pushbutton Tare_Button(Tare_BUTTON_PIN);
Pushbutton Switch_Button(Switch_BUTTON_PIN);

int per_unit = 0; //g, oz, ct。单位切换,默认为g,依次为克、盎司、克拉

void displayWeight(float weight) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Weight:");
  display.display();
  display.setCursor(0, 15);
  display.setTextSize(2);
  // display.print(weight);
  
  char weightStr[10];
  if(per_unit == 1){
    weight = 0.0353 * weight;
  }
  else if (per_unit == 2){
    weight = 5 * weight;
  }
  dtostrf(weight, 5, 1, weightStr); //通过函数将float数转换成表示一位小数的字符串
  display.print(weightStr);
  display.print(" ");
  if(per_unit == 0){
    display.print("g");
  }
  else if(per_unit == 1){
    display.print("oz"); //盎司
  }
  else if(per_unit == 2){
    display.print("ct"); //克拉
  }
  display.display();
}

void setup() {
  Serial.begin(115200);
  // rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
  setCpuFrequencyMhz(100);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
    
      ;
  }
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);

  Serial.println("Initializing the scale");
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);

  scale.set_scale(CALIBRATION_FACTOR);  // this value is obtained by calibrating the scale with known weights; see the README for details
  scale.tare();                         // reset the scale to 0
}

void loop() {
  if (Tare_Button.getSingleDebouncedPress()) { //去皮按键被按下过
    Serial.print("tare...");
    scale.tare();
  }
  if (Switch_Button.getSingleDebouncedPress()){ //切换单位按键被按下过
    Serial.print("switch...");
    // per_unit = !per_unit;
    //0代表g,1代表oz,2代表ct
    if(per_unit == 2){
      per_unit = 0;
    }
    else{
      per_unit++;
    }
  }

  if (scale.wait_ready_timeout(1000)) {
    // reading = round(scale.get_units());
    reading = scale.get_units();
    Serial.print("Weight: ");
    Serial.println(reading);
    if (reading != lastReading) {
      displayWeight(reading);
    }
    lastReading = reading;
  }else {
    Serial.println("HX711 not found.");
  }
}

调试tips

  1. 测校准因子时,建议等到串口能连续输出在0左右的值后,再把测量的物体放上去
  2. 测一部手机时,串口输出值应该在7w到12w之间
  3. 如果出现读值跳变异常,可能是HX711压力传感器之间的连接问题(我们组的那四个脚甚至需要掰成一个奇怪的形状才能读值正常==
  4. 用来计算校准因子的物品重量最好准确,校准因子和最后的测重值似乎不是线性相关,所以参数差一点点都可能会导致侧重结果误差较大
  5. 测重时,如果初始显示值不为0,可以使用去皮功能调整到0

带计数功能的代码

  • 只使用了两个按键,用切换单位的按键按三下切到计数功能
  • 对单个物品的重量读取是在Getting weight显示结束后
  • 在显示Put时放上要计数的物品

#include <Arduino.h>
#include "HX711.h"
#include "soc/rtc.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Pushbutton.h>
#include <esp32-hal-cpu.h>

// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 4;

//Button
#define Tare_BUTTON_PIN 14    //去皮按键
#define Switch_BUTTON_PIN 12  //切换单位按键

HX711 scale;
float reading ;
float lastReading ;
float singleWeight;

#define CALIBRATION_FACTOR 465.344 //校准因子

//OLED Display
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 32  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1  // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Pushbutton Tare_Button(Tare_BUTTON_PIN);
Pushbutton Switch_Button(Switch_BUTTON_PIN);

int per_unit = 0; //g, oz, ct。单位切换,默认为g,依次为克、盎司、克拉、到3时切换到计量模式

void Count(float singleWeight){
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("SingleWeight:");
  display.display();

  display.setCursor(0, 15);
  display.setTextSize(2);
  char weightStr[10];
  dtostrf(singleWeight, 5, 1, weightStr); //通过函数将float数转换成表示一位小数的字符串
  display.print(weightStr);
  display.print(" ");
  display.print("g");
  display.display();
  delay(2000);

  Serial.print("Putting things to count on the scale...");
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Put");
  display.display();
  delay(3000);
  reading = scale.get_units();

  int Quantity = round(reading / singleWeight);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Quantity:");
  display.display();

  display.setCursor(0, 15);
  display.setTextSize(2);
  display.print(Quantity); 
  display.display();
  delay(3000);
}
void displayWeight(float weight) {
  // if(per_unit == 3){
  //   Count();
  //   return;
  // }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Weight:");
  display.display();
  display.setCursor(0, 15);
  display.setTextSize(2);
  // display.print(weight);
  
  char weightStr[10];
  if(per_unit == 1){
    weight = 0.0353 * weight;
  }
  else if (per_unit == 2){
    weight = 5 * weight;
  }
  dtostrf(weight, 5, 1, weightStr); //通过函数将float数转换成表示一位小数的字符串
  display.print(weightStr);
  display.print(" ");
  if(per_unit == 0){
    display.print("g");
  }
  else if(per_unit == 1){
    display.print("oz"); //盎司
  }
  else if(per_unit == 2){
    display.print("ct"); //克拉
  }
  display.display();
}

void setup() {
  Serial.begin(115200);
  // rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
  setCpuFrequencyMhz(100);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
    
      ;
  }
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);

  Serial.println("Initializing the scale");
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);

  scale.set_scale(CALIBRATION_FACTOR);  // this value is obtained by calibrating the scale with known weights; see the README for details
  scale.tare();                         // reset the scale to 0
}

void loop() {
  if (Tare_Button.getSingleDebouncedPress()) { //去皮按键被按下过
    Serial.print("tare...");
    scale.tare();
  }
  if (Switch_Button.getSingleDebouncedPress()){ //切换单位按键被按下过
    Serial.print("switch...");
    // per_unit = !per_unit;
    //0代表g,1代表oz,2代表ct
    if(per_unit == 3){
      per_unit = 0;
    }
    else{
      per_unit++;
    }
  }

  if (scale.wait_ready_timeout(1000)) {
    // reading = round(scale.get_units());
    reading = scale.get_units();
    if(per_unit == 3){
      Serial.print("Getting singleWeight...");     
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(WHITE);
      display.setCursor(0, 0);
      display.println("Getting weight"); 
      display.display();
      delay(2500);
      reading = scale.get_units();
      singleWeight = reading;
      Count(reading);
      per_unit = 0;
    }
    Serial.print("Weight: ");
    Serial.println(reading);
    if (reading != lastReading) {
      displayWeight(reading);
    }
    lastReading = reading;
  }else {
    Serial.println("HX711 not found.");
  }
}
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值