智能体重秤/zh

来自Microduino Wikipedia
跳转至: 导航搜索

概述

  • 项目名称:Microduino智能电子称
  • 目的:显示体重并声音播报
  • 难度:中
  • 耗时:2小时
  • 制作者:
  • 简介:

它能够称量出我们的体重,并将体重显示在OLED屏幕上,而且还能通过喇叭将体重数据播报出来。

Weightall.jpg

材料清单

  • Microduino设备
模块 数量 功能
Microduino-Core/zh 1 核心板
Microduino-USBTTL/zh 1 下载程序
Microduino-Audio/zh 1 音频模块
Microduino-Amplifier/zh 1 声音放大
Microduino-OLED/zh 1 显示
Microduino-Duo-h/zh 1 扩展板,降低高度
Microduino-BM/zh 1 供电
Microduino-Weight/zh 1 连接压力传感器
  • 其他设备
名称 数量 功能
压力传感器(带底座,带喇叭) 1 测重力
USB线 1 下载程序,供电
电池 1 供电
螺丝 1 固定模块

实验原理

Mircoduino-Weight模块和底座上的压力传感器组成惠斯通电桥,能够测量底座上承受的重量,然后核心Core收集该体重数据并实时显示到OLED屏上,使用户能够观察到体重秤上的数据变化。然后在体重秤测量的数据稳定后,核心CPU即认为此时的体重数据即为测量到的最终体重,并控制Audio模块播报出此时的体重数据。

Weightyuanli.jpg
  • 称重传感器

电阻应变式称重传感器是基于这样一个原理:弹性体(弹性元件,敏感梁)在外力作用下产生弹性变形,使粘贴在它表面的电阻应变片(转换元件)也随同产生变形,电阻应变片变形后,它的阻值将发生变化(增大或减小),再经相应的测量电路把这一电阻变化转换为芯片可以识别的电信号。 为了测量称重传感器的应变片的电阻变化,通常采用应变片组成桥式电路(惠斯通电桥)来进行测量,当被测重力作用在应变片上时,粘附在弹性体上的惠斯通电桥就产生不平衡输出,该输出信号正比于被测重力。 惠斯通电桥中,R1、R2、R3、R4为应变电阻,Ui为激励电压,Uo为输出电压,根据分析,可以得出Uo的输出表达式为: 因此最终可通过测量Uo的输出电压间接测量出应变片的电阻变化,也就是应变片承受额重力。

Huisitong.png

文档

调试

  • 下载程序:

将Microduino-Core与Microduino-USBTTL叠加(无上下顺序),通过USB数据与电脑连接起来。

Download1.jpg

打开Arduino IDE编程软件,点击【文件】->【打开】

Dl1.jpg

浏览到项目程序地址,点击“WeighingScale.ino”程序打开。

Dl2.jpg

点击【工具】,在板选项里面选择板卡(Microduino-Core),在处理器选项里面选择处理器(Atmega328p@16M,5V),再在端口选项里面选择正确的端口号,然后直接烧录程序。

Dl3.jpg

使用USB数据线将Microduino-Audio模块与电脑连接。

Dl4.jpg

连接成功能显示出一个名为Microduino Audio的CD驱动器,然后执行以下步骤:

Dl5.jpg

打开CD驱动器后会出现音乐更新软件Music Update tool,选择“音频加载”选项;

Dl6.jpg

点击“浏览”,选择“体重”文件夹中的所有音频文件,将音频文件添加到软件中;

Dl7.jpg

在”更新下载”选项中选择“更新”,更新完成后,音频文件就已写入flash中。

Dl8.jpg
  • 搭建:

使用螺丝将Microduino-Duo-H2和Microduino-OLED固定到外壳的面板上。

Weightbuild1.jpg

把用到的设备叠加到Microduino-Duo-H2上。 *Microduino-Core *Microduino-Audio *Microduino-Amplifier *Microduino-BM *Microduino-Weight

Weightbuild2.jpg

把Microduino-OLED接到Microduino-Duo-H2的OLED接口,压力传感器接到Microduino-Weight模块,电池接到Microduino-BM模块,喇叭接到Micrdouino-Amplifier模块。

Weightbuild3.jpg
Weightbuild4.jpg

打开外壳中BM模块的电源开关,确认模块电源灯点亮。如果电池不能正常供电,可以用USB供电来激活电池。 启动后可以以看到OLED上显示“体重管家”

Weightbuild5.jpg
Weightbuild6.jpg

可以站在体重秤上测量自己的体重,体重数据显示稳定后喇叭会播报出“您的体重为XX公斤”。

Weightbuild7.jpg

程序说明

  • 主程序部分
#include "HX711.h"        //称重传感器库 
#include "U8glib.h" 
#include "oled.h"        //OLED显示界面 
#include "audio.h"        //音频控制 
#include <I2Cdev.h> 
#include <Wire.h>        //添加必须的库文件 
#include <SoftwareSerial.h> 
 
float Weight = 0.0, Weight_cg = 0; 
long time = 0;            //测量时间 
boolean flag = false;    //播报语音标志位 
int music_vol = 28;     //初始音量0~30 
 
void setup() 
{ 
    Init_Hx711();                //初始化HX711模块连接的IO设置 
 
    Serial.begin(115200); 
    audio_init(DEVICE_Flash, MODE_One_END, music_vol);    
//初始化Audio模块 
    delay(500); 
    Get_Maopi();            //获取毛皮重量 
    Wire.begin(); 
} 
 
//播报语音 
void broadcast(int num) 
{ 
    int decade = num / 10; //十位数 
    int unit = num % 10;    //个位数 
    audio_choose(11);        //播报“您的体重” 
    delay(1600); 
    audio_choose(decade + 1);    //播报十位数 
    delay(400); 
    audio_choose(1);        //播报“十” 
    delay(400); 
    if(unit) 
    { 
        audio_choose(unit + 1);    //播报个位数 
        delay(400); 
    } 
    audio_choose(12);        //播报“公斤” 
} 
 
void loop() 
{ 
    Weight = Get_Weight() / 1000;        //测量重量 
    u8g.firstPage(); 
    do 
    { 
        drawWeight(Weight);                //显示重量 
    } 
    while( u8g.nextPage() ); 
 
    if(Weight > 25)                //重量大于25公斤,播报功能有效 
    { 
        if(Weight > Weight_cg)        //重量还没有稳定 
        { 
            Weight_cg = Weight; 
            time = millis() + 2000;   //更新测量时间 
        } 
        else if(millis() > time && flag == false) 
//在2S内测量重量没有增大,说明测量值已稳定 
        { 
            broadcast((int)Weight);        //播报重量 
            flag = true;                    //播报标志位置位 
        } 
    } 
    else                //重量小于25公斤 
    { 
        Weight_cg = 0;            //不判断重量是否稳定 
        flag = false;            //播报标志位清零 
    } 
    delay(200); 
} 
  • Audio音频部分
#include "arduino.h" 
#include <SoftwareSerial.h> 
 
SoftwareSerial mySerial(2, 3); // RX, TX 
//#define AUDIO_PORT Serial1    //Core+ 
#define AUDIO_PORT mySerial  //Core 
 
byte sn_reset[4] =                //复位指令 
{ 
    0x7E, 0x02, 0x0C, 0xEF 
}; 
 
byte sn_choose[6] =                //选择曲目指令 
{ 
    0x7E, 0x04, 0x03, 0x00, 0x01, 0xEF 
}; 
 
byte sn_vol[5] =                    //调节音量指令 
{ 
    0x7E, 0x03, 0x06, 0x18, 0xEF 
}; 
 
byte sn_device[5] =                //设备设置指令 
{ 
    0x7E, 0x03, 0x09, 0x01, 0xEF 
}; 
 
byte sn_pause[4] =                //暂停指令 
{ 
    0x7E, 0x02, 0x0E, 0xEF 
}; 
 
byte sn_play[4] =                //播放指令 
{ 
    0x7E, 0x02, 0x0D, 0xEF 
}; 
 
byte sn_mode[5] =                //设置播放模式指令 
{ 
    0x7E, 0x03, 0x11, 0x00, 0xEF 
}; 
 
byte sn_down[4] =                //选择下一曲目指令 
{ 
    0x7E, 0x02, 0x01, 0xEF 
}; 
 
byte sn_up[4] =                    //选择上一曲目指令 
{ 
    0x7E, 0x02, 0x02, 0xEF 
}; 
 
byte sn_eq[5] =                    //设置播放风格指令 
{ 
    0x7E, 0x03, 0x07, 0x01, 0xEF 
}; 
 
//----------------------------- 
void audio_pause()                //音频暂停 
{ 
    AUDIO_PORT.write(sn_pause, 4); 
    delay(50); 
} 
 
void audio_play()                //音频播放 
{ 
    AUDIO_PORT.write(sn_play, 4); 
    delay(50); 
} 
 
//play eq    (Normal/Pop/Rock/Jazz/Classic/Base)  0-5 
void audio_eq(byte _audio_eq)            //设置播放风格 
{ 
    sn_mode[3] = _audio_eq; 
    AUDIO_PORT.write(sn_eq, 5); 
    delay(100); 
} 
 
#define MODE_loopAll 0 
#define MODE_loopOne 1 
#define MODE_One_STOP 2 
#define MODE_One_END  4 
//play mode    (ALL/FOL/ONE/RAM/ONE_STOP)  0-4 
void audio_mode(byte _audio_mode)        //设置播放模式 
{ 
    sn_mode[3] = _audio_mode; 
    AUDIO_PORT.write(sn_mode, 5); 
    delay(100); 
} 
 
#define DEVICE_Flash  5 
#define DEVICE_TF  1 
//device select    (U/TF/AUX/SLEEP/FLASH)  0-4 
void audio_device(byte _audio_device)        //设置存储方式 
{ 
    sn_device[3] = _audio_device; 
    AUDIO_PORT.write(sn_device, 5); 
    delay(1500); 
} 
 
void audio_down()                //播放下一曲目 
{ 
    AUDIO_PORT.write(sn_down, 4); 
    delay(500); 
} 
 
void audio_up()                    //播放上一曲目 
{ 
    AUDIO_PORT.write(sn_up, 4); 
    delay(500); 
} 
 
void audio_vol(byte _audio_vol)        //设置音量 
{ 
    sn_vol[3] = _audio_vol; 
    AUDIO_PORT.write(sn_vol, 5); 
    delay(50); 
} 
 
void audio_choose(byte _audio_choose)    //选择曲目 
{ 
    sn_choose[4] = _audio_choose; 
    AUDIO_PORT.write(sn_choose, 6); 
    delay(100); 
} 
 
void audio_reset()                    //复位 
{ 
    AUDIO_PORT.write(sn_reset, 4); 
    delay(500); 
} 
//初始化 
void audio_init(int _audio_init_device, int _audio_init_mode, int _audio_init_vol) 
{ 
    AUDIO_PORT.begin(9600); 
    delay(500); 
    audio_reset(); 
    audio_device(_audio_init_device); 
    audio_mode(_audio_init_mode); 
    audio_vol(_audio_init_vol); 
    audio_pause(); 
} 
  • OLED显示部分
#include "U8glib.h" 
 
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); 
 
static unsigned char u8g_logo_bits1[] U8G_PROGMEM = 
{ 
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xF8, 0xC7, 0xFF, 0xFF, 0xFC, 0xE7, 0xFF, 0xFF, 0xFC,    0xE7, 0xFF, 0x7F, 0xFE, 0xE7, 0xFF, 0x7F, 0xFE, 0xE7, 0xFF, 0x3F,    0xFF, 0xE7, 0xE7, 0x3F, 0x03, 0x00, 0xC0, 0xBF, 0xFF, 0xC1, 0xFF,    0x1F, 0xFE, 0xC1, 0xFF, 0x1F, 0xFF, 0xA4, 0xFF, 0x2F, 0xFF, 0xA4,    0xFF, 0x27, 0x7F, 0xA6, 0xFF, 0x37, 0x7F, 0x66, 0xFF, 0x3B, 0x3F,    0x67, 0xFF, 0x3D, 0x3F, 0xE7, 0xFE, 0x3F, 0x9F, 0xE7, 0xFC, 0x3F,    0xDF, 0xE7, 0xF9, 0x3F, 0xEF, 0xE7, 0xF1, 0x3F, 0xE7, 0xE7, 0xE3,    0x3F, 0xF3, 0xE7, 0xC2, 0x3F, 0x1B, 0x00, 0xE0, 0x3F, 0xFD, 0xE7,    0xFF, 0x3F, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF,    0xE7, 0xFF, 0x3F, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF, 0xE7, 0xFF, 0xBF,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //"体",0 
}; 
 
static unsigned char u8g_logo_bits2[] U8G_PROGMEM = 
{ 
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,    0xFF, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0x07, 0xE0, 0xFF, 0x3F, 0x78,    0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0xF3, 0x07,    0x00, 0x00, 0xE0, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F, 0x7E, 0xFF,    0x7F, 0x00, 0x00, 0xFC, 0x7F, 0x7E, 0x7E, 0xFE, 0x7F, 0x7E, 0x7E,    0xFE, 0x7F, 0x7E, 0x7E, 0xFE, 0x7F, 0x00, 0x00, 0xFE, 0x7F, 0x7E,    0x7E, 0xFE, 0x7F, 0x7E, 0x7E, 0xFE, 0x7F, 0x7E, 0x7E, 0xFE, 0x7F,    0x00, 0x00, 0xFE, 0x7F, 0x7E, 0x7E, 0xFE, 0xFF, 0x7F, 0xFE, 0xFF,    0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0xFC, 0x1F, 0x00, 0x00,    0xF8, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F,    0xFE, 0xE7, 0x03, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //"重",1 
}; 
 
static unsigned char u8g_logo_bits3[] U8G_PROGMEM = 
{ 
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF,     0xFF, 0x7F, 0xFE, 0xE7, 0xFF, 0x3F, 0xFE, 0xE7, 0xFF, 0x3F, 0xBF,    0xF3, 0xF7, 0x1F, 0x00, 0x03, 0xE0, 0xDF, 0xFD, 0xBD, 0xFF, 0xCF,    0xF9, 0x3E, 0xFF, 0xE7, 0x3B, 0x7F, 0xFE, 0xFB, 0x7B, 0x7E, 0xFF,    0xEF, 0x7F, 0xFE, 0xE7, 0x0F, 0x00, 0x00, 0xC0, 0xEF, 0xFF, 0xFF,    0xE7, 0xE7, 0xFF, 0xBF, 0xF3, 0xE3, 0x00, 0x00, 0xFB, 0xFF, 0xFC,    0x9F, 0xFF, 0xFF, 0xFC, 0x9F, 0xFF, 0xFF, 0xFC, 0x9F, 0xFF, 0xFF,    0x00, 0x80, 0xFF, 0xFF, 0xFC, 0x9F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF,    0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xFC, 0x3F,    0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC,    0x3F, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF,    0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //"管",2 
}; 
 
static unsigned char u8g_logo_bits4[] U8G_PROGMEM = 
{ 
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF,    0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xDF, 0xFF,    0xFE, 0xF7, 0x1F, 0x00, 0x00, 0xE0, 0xDF, 0xFF, 0xFF, 0xE3, 0xCF,    0xFF, 0xFF, 0xFB, 0xE7, 0xFF, 0x3F, 0xFD, 0x7F, 0x00, 0x00, 0xFE,    0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xA7, 0x7F,    0xFE, 0xFF, 0x33, 0x3F, 0xFC, 0xFF, 0x7C, 0x9E, 0xFF, 0x3F, 0x3F,    0xE6, 0xFF, 0xCF, 0x9F, 0xE8, 0xFF, 0xF7, 0xCF, 0xDD, 0xFF, 0xFF,    0xF3, 0xD8, 0xFF, 0xFF, 0x79, 0x98, 0xFF, 0x7F, 0x3E, 0xB8, 0xFF,    0x9F, 0x1F, 0x3B, 0xFF, 0xE7, 0xCF, 0x7B, 0xFE, 0xFF, 0xE7, 0xFB,    0xF8, 0xFF, 0xF9, 0xFB, 0xE1, 0xFF, 0xFC, 0xF9, 0xE3, 0x1F, 0xFF,    0xF9, 0xF7, 0xE7, 0x0F, 0xF8, 0xFF, 0xFB, 0x3F, 0xFC, 0xFF, 0xFF,    0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //"家",3 
}; 
 
void drawWeight(float num) 
{ 
    if(num > 25)            //重量大于25公斤显示重量 
    { 
        u8g.setFont(u8g_font_gdr25); 
        u8g.setPrintPos(0, 50); 
        u8g.print(num, 2); 
        u8g.setPrintPos(85, 50); 
        u8g.print("Kg"); 
    } 
    else                    //重量小于25公斤显示“体重管家”界面 
    { 
        u8g.drawXBMP( 0, 16, 32, 32, u8g_logo_bits1); 
        u8g.drawXBMP( 32, 16, 32, 32, u8g_logo_bits2); 
        u8g.drawXBMP( 64, 16, 32, 32, u8g_logo_bits3); 
        u8g.drawXBMP( 96, 16, 32, 32, u8g_logo_bits4); 
        u8g.drawLine(0, 62, 128, 62); 
    } 
} 
  • 称重部分
#include <Arduino.h> 
 
#define HX711_SCK 4 
#define HX711_DT 5 
#define GapValue 24.3 
 
long Weight_Maopi = 0, Weight_Shiwu = 0; 
//**************************************************** 
//初始化HX711 
//**************************************************** 
void Init_Hx711() 
{ 
    pinMode(HX711_SCK, OUTPUT); 
    pinMode(HX711_DT, INPUT); 
}  
//**************************************************** 
//读取HX711 
//**************************************************** 
unsigned long HX711_Read(void)    //增益128 
{ 
    unsigned long count; 
    unsigned char i; 
 
    digitalWrite(HX711_DT, HIGH); 
    delayMicroseconds(1); 
    digitalWrite(HX711_SCK, LOW); 
    delayMicroseconds(1); 
 
    count = 0; 
    while(digitalRead(HX711_DT)); 
    for(i = 0; i < 24; i++) 
    { 
        digitalWrite(HX711_SCK, HIGH); 
        delayMicroseconds(1); 
        count = count << 1; 
        digitalWrite(HX711_SCK, LOW); 
        delayMicroseconds(1); 
        if(digitalRead(HX711_DT)) 
            count++; 
    } 
    digitalWrite(HX711_SCK, HIGH); 
    count ^= 0x800000; 
    delayMicroseconds(1); 
    digitalWrite(HX711_SCK, LOW); 
    delayMicroseconds(1); 
 
    return(count); 
} 
 
//**************************************************** 
//获取毛皮重量 
//**************************************************** 
void Get_Maopi() 
{ 
    Weight_Maopi = HX711_Read(); 
} 
//**************************************************** 
//称重 
//**************************************************** 
float Get_Weight() 
{ 
    Weight_Shiwu = HX711_Read() - Weight_Maopi;                //获取实物的AD采样数值。 
    if(Weight_Shiwu < 0) 
    { 
        return 0; 
    } 
    else 
    { 
        return Weight_Shiwu / GapValue; 
    } 
} 

视频