前言
这也是帮人做的毕设之一,功能完善,资料也完备,相对以往代码写的规范,代码相对以往变得更加简洁好看,视频也有录制。
项目下载链接
一、所需材料
1、硬件
HC-SR04超声波测距模块 |
---|
带IIC转换板LCD1602 |
JQ8400FL10P语音模块 |
UNO R3开发板 |
三色LED灯 |
LCD1602 IIC |
积木按键 |
小面包板 |
木板若干 |
杜邦若干 |
2、软件
Arduino IDE |
---|
微信语音合成小程序 |
3、接线
RGB三色彩灯接线
灯 | UNO |
---|---|
R | 4 |
G | 5 |
B | 6 |
超声波传感器接线
超声波传感器 | UNO |
---|---|
Tr | 2 |
Ech | 3 |
JQ8400语音模块
JQ8400 | UNO |
---|---|
7 | ONE LINE |
按键接线
按键 | UNO |
---|---|
OUT | A0 |
LCD1602接线
LCD1602 | UNO |
---|---|
SDA | SDA |
SCL | SCL |
二、Arduino部分
1、库函数引入
2、选择开发板
3、代码
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); //0x27
#define TrigPin 2
#define EchoPin 3
float distance;
int alarmvalue = 6; //设置初始警报值为15cm
#define BUF_LEN 10
char Dis_Buf[BUF_LEN];
//LED灯
#define rled 4 //红灯io
#define yled 5 //黄灯io
#define gled 6 //绿灯io
//语音模块
#define SDAPin 7 //语音模块onewrite io
#define RLED_Read digitalRead(rled)
#define YLED_Read digitalRead(yled)
#define GLED_Read digitalRead(gled)
//按键变量
int adc_key_val[5] = {30, 80, 165, 350, 500 };
int NUM_KEYS = 5;
int adc_key_in;
int key = -1;
int oldkey = -1;
boolean Page;
#define Home true
#define Setting false
boolean Dis_Sta;
#define Safe true
#define Alarm false
#define S1 0
#define S2 1
#define S3 2
#define S4 3
#define S5 4
unsigned long Timing = 0; //用于定时读取
void setup()
{ // 初始化串口通信及连接SR04的引脚
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(TrigPin, OUTPUT);
// 要检测引脚上输入的脉冲宽度,需要先设置为输入状态
pinMode(EchoPin, INPUT);
pinMode(SDAPin, OUTPUT);
pinMode(rled, OUTPUT);
pinMode(yled, OUTPUT);
pinMode(gled, OUTPUT);
digitalWrite(rled, LOW);
digitalWrite(yled, LOW);
digitalWrite(gled, LOW);
Dis_Sta = Safe;
Page = Home;
Home_Page();
}
void loop()
{
switch (Page) {
case Home:
if (millis() - Timing >= 300) {
Timing = millis();
Get_Distance(); //测距
if (distance < alarmvalue) { //小于安全距离
if (Dis_Sta == Safe) { //上一次为安全距离,这次为过近距离
Dis_Sta = Alarm;
//警告界面,语音播报
lcd.clear();
Alarm_Page();
//语音播报
say_control();
LED_ON();
} else { //上一次依然是过近距离
LED_REVERSE(); //反转LED状态,达到闪烁的效果
}
} else { //安全距离
if (Dis_Sta == Alarm) {
LED_OFF();
Dis_Sta = Safe;
lcd.clear();
Home_Page();
}
uint8_t integer = distance * 100 / 100;
uint8_t decimal = int(distance * 100) % 100;
snprintf(Dis_Buf, BUF_LEN, "%02d.%02d", integer, decimal);
lcd.setCursor(4, 1);
lcd.print(Dis_Buf);
Serial.print("Dis_Buf: ");
Serial.println(Dis_Buf);
}
}
Home_Ctrl(); //Home_Page下的按键控制
break;
case Setting:
Setting_Ctrl(); //Setting_Page下的按键控制
break;
}
}
/*
0123456789012345
" Distance: "
" xx.xx cm "
*/
void Home_Page() {
lcd.setCursor(4, 0);
lcd.print("Distance:");
lcd.setCursor(10, 1);
lcd.print("cm");
}
void Home_Ctrl() {
adc_key_in = analogRead(0); // 读取模拟A0数值
key = get_key(adc_key_in); // 转化成按键
if (key != oldkey) {
delay(50); //等待反弹时间
adc_key_in = analogRead(0); // 读取模拟口A0数值
key = get_key(adc_key_in); // 转换成按键
if (key != oldkey) {
oldkey = key;
if (key > 0) {
if (key = S5) { //5#按键进入设置界面
Serial.println("S5 OK");
Page = Setting;
lcd.clear();
Setting_Page();
}
}
}
}
}
/*
0123456789012345
"The setting page"
" alarm: xx cm "
*/
void Setting_Page() {
lcd.setCursor(0, 0);
lcd.print("The setting page");//
lcd.setCursor(2, 1);
lcd.print("alarm:");
LCD_Setting_Num();
lcd.setCursor(12, 1);
lcd.print("cm");
}
void Setting_Ctrl() {
adc_key_in = analogRead(0); //读取模拟A0数值
key = get_key(adc_key_in); //转化成按键
if (key != oldkey) {
delay(50); //等待反弹时间
adc_key_in = analogRead(0); //读取模拟口A0数值
key = get_key(adc_key_in); //转换成按键
if (key != oldkey) {
oldkey = key;
if (key > 0) {
switch (key) {
case S1:
alarmvalue += 1;
LCD_Setting_Num();
break;
case S2:
alarmvalue += 1;
LCD_Setting_Num();
break;
case S3:
alarmvalue -= 1;
LCD_Setting_Num();
break;
case S4:
alarmvalue -= 1;
LCD_Setting_Num();
break;
case S5:
Page = Home;
lcd.clear();
Home_Page();
break;
}
}
}
}
}
void LCD_Setting_Num() {
snprintf(Dis_Buf, BUF_LEN, "%02d", alarmvalue);
lcd.setCursor(9, 1);
lcd.print(Dis_Buf);
}
/*
0123456789012345
"The distance is "
" too short "
*/
void Alarm_Page() {
lcd.setCursor(0, 0);
lcd.print("The distance is");
lcd.setCursor(3, 1);
lcd.print("too short");
}
void Get_Distance() {
// 产生一个10us的高脉冲去触发TrigPin
digitalWrite(TrigPin, LOW);
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(TrigPin, LOW);
// 检测脉冲宽度,并计算出距离
distance = pulseIn(EchoPin, HIGH) / 58.00;
Serial.print(distance);
Serial.println("cm");
}
// 将ADC值转换为键数
int get_key(unsigned int input) {
int k;
for (k = 0; k < NUM_KEYS; k++) {
if (input < adc_key_val[k]) {
return k;
}
}
if (k >= NUM_KEYS)k = -1; // 没有按下有效的键
return k;
}
//发送语音模块串口指令函数
void S(bool s) {
digitalWrite(SDAPin, s);
}
void sendData(unsigned char addr) {
S(1);
delayMicroseconds(1000);
S(0);
delayMicroseconds(3200);
for (int i = 0; i < 8; i++) {
S(1);
if (addr & 0x01) {
delayMicroseconds(600);
S(0);
delayMicroseconds(200);
} else {
delayMicroseconds(200);
S(0);
delayMicroseconds(600);
}
addr >>= 1;
}
S(1);
}
//语音指令
void say_control() {
sendData(0x11);//发送语音指令
delay(2200);//语音时长
}
void LED_ON() {
digitalWrite(rled, HIGH);
digitalWrite(yled, HIGH);
digitalWrite(gled, HIGH);
}
void LED_OFF() {
digitalWrite(rled, LOW);
digitalWrite(yled, LOW);
digitalWrite(gled, LOW);
}
void LED_REVERSE() {
digitalWrite(rled, !RLED_Read);
digitalWrite(yled, !YLED_Read);
digitalWrite(gled, !GLED_Read);
}
4、演示视频
三、使用说明
1、项目方案
功能1:(坐姿提醒)
使用超声波模块检测距离,当坐姿不端时,测距小于标准距离,语音提示,有灯光提示,屏幕文字显示提醒
功能2:(调节报警距离)
屏幕实时显示当前的测距,按键可以调节报警距离
功能3:
自定义语音提示
2、页面切换
各页面切换实现方法:
主界面:
显示距离
距离过小进入报警界面
S5进入设置界面
设置界面:
按键控制±,
S5返回主界面
报警界面:
怎么返回
测距大于安全距离则返回
小于安全距离且原本为安全时
警告界面
小于安全距离且原本时警告界面时
不作反应
大于安全距离且原本为安全时
不做反应
大于安全距离且原本为警告界面时
返回主页
页面设计
功能介绍:
-
LCD共有三个界面
主界面(Home_Page)
警报界面(Alarm_Page)
设置界面(Setting_Page) -
主界面
在主界面之下,时刻显示着当前超声波传感器的读值
Distance:
xx.xx cm -
“设置界面”
在设置界面时刻显示着当前的警报设置距离
The setting page
alarm:xx cm -
“警报界面”
The distance is
Too short
按键使用:
S1 :可进入设置状态
S2 :可增加设置距离
S3 :可减少设置距离
S4 :可减少设置距离
S5 :可自由切换两个页面