已经为桌子上这一坨单片机折腾了三天,总是觉得自己可以当天搞完[拍桌]
想到很久没更了,还是写点经历和过程吧,一些收获如能给你带来帮助,不胜荣幸。
基于arduino的智能狗粮机
第一部分 任务需求
~~
一、现状:
~~
在波谲云诡的国际局势中,快节奏的生活像一把达摩克利斯剑悬在当代人的头上,许多人在忙碌与盲目中碌碌终生。作为新时代的新青年,时代的弄潮儿,青年人理应在纷乱的环境中寻求自我,很多人选择养宠物来坚守自己的初心,但是无奈常常因为忙于一个ppt一次加班一次出差忘记给小动物喂食,让它们蜷缩在阴冷的角落里挨饿,可怜!弱小!又无助!!!无数真实的故事,令人扼腕。很多人会想,如果有一个机器能够自动喂狗粮,那可该有多好!无奈囿于市面上的狗粮投食机价格太高功能离奇,丰满的理想被骨感的钱包所掣肘。
**
二、目的:
**
为了养汪星人、喵星人等动物时,增加其成活概率,从而为忙碌主人的闲暇生活增添更多欢乐,我们产品诣在实现培养过程的半无人化,从而达到人与其他生命和谐共处。
三、功能:
1.水泵定时定量抽水,给动物提供饮用水。
2.装置定时定量喂食(狗粮猫粮)
3.显示时间
4.显示一周喂食次数,每周一零点清零。
5.喂食前鸣奏特殊铃声,提醒动物吃食。
6.夜晚喂食时LED灯照射,避免动物在黑暗环境下无法看清食物的量导致浪费。
7.自定义喂食间隔和投食量。
8.利用8*8点阵组建字模“做狗狗精彩不停”(……),让小狗和主人感受到不一般的温暖。
第二部分 任务总体设计
1.水泵定时定量抽水,给动物提供饮用水。
利用增水泵和硅胶水管,通过水管泵水的时间控制流量。
2 .装置定时定量喂食(狗粮猫粮)
设想:双仓双闸装置,具体示意图如附件一。
注:实现程度仍需老师指导。
3.显示时间:
利用四位数码管,定向显示时间编程即可。
4.显示一周喂食次数,每周一零点清零:
利用一位数码管,编程使数次每周一零点清零
5.喂食前鸣奏特殊铃声,提醒动物吃食:
利用蜂鸣器,在投食前一分钟,编程使蜂鸣器演奏音乐《天空之城》。
6.夜晚喂食时LED灯照射,避免动物在黑暗环境下无法看清食物的量导致浪费。
7.自定义喂食间隔和投食量。
在电脑上编程设置时间间隔和投食量参数。
- 利用88点阵组建字模“做狗狗精彩不停”(……),让小狗和主人感受到不一般的温暖。
利用88LED显示屏字模提取软件构建字模,设置时间间隔,循环播放。
附件一:(自动狗粮机示意图)
以上是计划中的任务总体设计…注意…计划中
一条华丽的分割线
实践得真知,这句话比较真实。实践得现实。
看起来很简单的八个功能,其实每个的实现都遇到了很多问题。
骏洁说:“我们 arduino 的实现历程,除了瓶底就是瓶颈”
一、水泵定时抽水
经过讨论我们决定从水泵入手 //这是错误的开始
但是当时并没有同学成功实现水泵功能,因为没有成功的案例,大部分人都选择放弃或者观望。关键是有关水泵网上找到的代码,可能是兼容性的问题,在我们的板子上都会有蛇皮结果hhh
最后总归是成功了。直接放图:
代码很简单,可能是因为接触的问题很多人没有成功叭。
注意一定要加公母线,用胶带缠一圈。
int water=3;
void setup(){
pinMode(3,OUTPUT);
}
void loop(){
digitalWrite(water,HIGH);
delay(3000);
digitalWrite(water,LOW);
for(long a = 0; a<=6*60*60; a++){
delay(1000);
}
}
二、 8*8点阵显示
最初准备做的“做狗狗精彩不停”实在是太睿智了[-_-||]
还是换成了一个简单美观的图hiahia
这里的主要难点是不同型号的8*8点阵的兼容性存在较大差异,我们的串口和网上找的教程的串口完全不同,助教提供的串口序号有一个口有问题,这都是需要不断调试才能得到的结论,另外在这里可以使用模拟端口去实现数字端口的功能。
(当然还有很多字的显示,这是显示了一个大写的I)
目前可以实现的还包括跳动的爱心 ❥
其实通过字模软件基本可以实现各种字的各种字体,当然也可以用手自己模拟画。
下面就该粘代码了
int x[] = {18,17,16,15,14,13,12,11};
int y[] = {6,7,8,9,5,4,3,2};
void setup()
{
for(int i=0;i<=7;i++){
pinMode(y[i],OUTPUT);//定义小灯接口为输出接口
}
for(int i=0;i<=7;i++)
pinMode(x[i],OUTPUT);//定义小灯接口为输出接口
clear_();
//pinMode(inpin,INPUT);//定义按键接口为输入接口
}
void clear_(void)//清除屏幕
{
for(int i=0;i<8;i++)
digitalWrite(y[i], LOW);
for(int i=0;i<8;i++)
digitalWrite(x[i], HIGH);
}
void putChar(unsigned char c[]){
unsigned char data;
for(int j=0;j<8;j++){
data = c[j];
for(int i=0;i<8;i++){
if(data & 0x01){
clear_();
digitalWrite(y[j],HIGH);
digitalWrite(x[i],LOW);
delay(1);
}
data >>= 1;
}
}
}
unsigned char love[] = {0xe7,0x99,0x81,0x81,0x81,0x42,0x24,0x18};
unsigned char I[] = {0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x3c};
unsigned char U[] = {0x00,0x42,0x42,0x42,0x42,0x42,0x24,0x18};
void loop()
{
for(int i=0;i<50;i++)
putChar(I);
for(int i=0;i<50;i++)
putChar(love);
for(int i=0;i<50;i++)
putChar(U);
}
三、狗粮自动投食机(精华)
智能狗粮机的精华所在。
因为这个模块的大部分功能都没有现成的工具,DIY为主。先看一下实体图:
是不是看上去很傻
但是真正做一个这样的东西真的很折磨人,从舵机的摆动角,选用的角速度使狗粮能够大致稳定的释放一定量同时不至于产生过大阻力使舵机驱动的纸板受阻变形等等都是需要反复测试,尝试之后才能选择一个相对优解。同时,狗粮机的高度,四根筷子做支撑的相互角度,舵机高度,都是相互影响相互制约的,这就导致了错误时整个装置的很多部分都要重新定规格重新制作。
说来感觉很轻松,但是其中收了很多罪只有我和骏洁老弟可以感受啦哈哈哈,希望大家也不要受这么大的罪了。
舵机定时摆动的代码:
#include <Servo.h>
Servo myservo;
int potpin=A0;
int pos=0,val;//定义舵机转动位置
int servoPin=9;
void setup(){
myservo.attach(9);//设置舵机控制针脚
pinMode(servoPin,OUTPUT);
}
void loop(){
for(pos=0;pos<30;pos++){
myservo.write(pos);
delay(15);
}
delay(1000);
for(pos=30;pos>=1;pos--){
myservo.write(pos);
delay(15);
}
for (int i=1;i<=*6*60;i++) delay(1000);
}
p.s. 最后选择了 30° 的摆动角和 delay(15)所带来的角速度。
俯视图:
选择了舵机嵌入矿泉水瓶,水瓶里记得留一些水保持稳定性但是不要过多防止湿度过大损坏舵机。
四、蜂鸣器播放就餐前音乐
饭前播放好听的音乐让人食欲大增,对狗狗应该也是一样。
在音乐方面我们选择了 《天空之城》
实测效果很不错。
这个功能比较显然,就直接贴代码了:
#define NOTE_D0 -1
#define NOTE_D1 294
#define NOTE_D2 330
#define NOTE_D3 350
#define NOTE_D4 393
#define NOTE_D5 441
#define NOTE_D6 495
#define NOTE_D7 556
#define NOTE_DL1 147
#define NOTE_DL2 165
#define NOTE_DL3 175
#define NOTE_DL4 196
#define NOTE_DL5 221
#define NOTE_DL6 248
#define NOTE_DL7 278
#define NOTE_DH1 589
#define NOTE_DH2 661
#define NOTE_DH3 700
#define NOTE_DH4 786
#define NOTE_DH5 882
#define NOTE_DH6 990
#define NOTE_DH7 112
#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.25
#define SIXTEENTH 0.625
int tune[] = {
NOTE_D0,NOTE_D0,NOTE_D0,NOTE_D6,NOTE_D7,NOTE_DH1,NOTE_D7,NOTE_DH1,NOTE_DH3,NOTE_D7,NOTE_D7,NOTE_D7,NOTE_D3,NOTE_D3,
NOTE_D6,NOTE_D5,NOTE_D6,NOTE_DH1,NOTE_D5,NOTE_D5,NOTE_D5,NOTE_D3,NOTE_D4,NOTE_D3,NOTE_D4,NOTE_DH1,
NOTE_D3,NOTE_D3,NOTE_D0,NOTE_DH1,NOTE_DH1,NOTE_DH1,NOTE_D7,NOTE_D4,NOTE_D4,NOTE_D7,NOTE_D7,NOTE_D7,NOTE_D0,NOTE_D6,NOTE_D7,
NOTE_DH1,NOTE_D7,NOTE_DH1,NOTE_DH3,NOTE_D7,NOTE_D7,NOTE_D7,NOTE_D3,NOTE_D3,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_DH1,
NOTE_D5,NOTE_D5,NOTE_D5,NOTE_D2,NOTE_D3,NOTE_D4,NOTE_DH1,NOTE_D7,NOTE_D7,NOTE_DH1,NOTE_DH1,NOTE_DH2,NOTE_DH2,NOTE_DH3,NOTE_DH1,NOTE_DH1,NOTE_DH1,
NOTE_DH1,NOTE_D7,NOTE_D6,NOTE_D6,NOTE_D7,NOTE_D5,NOTE_D6,NOTE_D6,NOTE_D6,NOTE_DH1,NOTE_DH2,NOTE_DH3,NOTE_DH2,NOTE_DH3,NOTE_DH5,
NOTE_DH2,NOTE_DH2,NOTE_DH2,NOTE_D5,NOTE_D5,NOTE_DH1,NOTE_D7,NOTE_DH1,NOTE_DH3,NOTE_DH3,NOTE_DH3,NOTE_DH3,NOTE_DH3,
NOTE_D6,NOTE_D7,NOTE_DH1,NOTE_D7,NOTE_DH2,NOTE_DH2,NOTE_DH1,NOTE_D5,NOTE_D5,NOTE_D5,NOTE_DH4,NOTE_DH3,NOTE_DH2,NOTE_DH1,
NOTE_DH3,NOTE_DH3,NOTE_DH3,NOTE_DH3,NOTE_DH6,NOTE_DH6,NOTE_DH5,NOTE_DH5,NOTE_DH3,NOTE_DH2,NOTE_DH1,NOTE_DH1,NOTE_D0,NOTE_DH1,
NOTE_DH2,NOTE_DH1,NOTE_DH2,NOTE_DH2,NOTE_DH5,NOTE_DH3,NOTE_DH3,NOTE_DH3,NOTE_DH3,NOTE_DH6,NOTE_DH6,NOTE_DH5,NOTE_DH5,
NOTE_DH3,NOTE_DH2,NOTE_DH1,NOTE_DH1,NOTE_D0,NOTE_DH1,NOTE_DH2,NOTE_DH1,NOTE_DH2,NOTE_DH2,NOTE_D7,NOTE_D6,NOTE_D6,NOTE_D6,NOTE_D6,NOTE_D7
};
float duration[]= {
1,1,1,0.5,0.5, 1+0.5,0.5,1,1, 1,1,1,0.5,0.5,
1+0.5,0.5,1,1, 1,1,1,1, 1+0.5,0.5,1,1,
1,1,0.5,0.5,0.5,0.5, 1+0.5,0.5,1,1, 1,1,1,0.5,0.5,
1+0.5,0.5,1,1, 1,1,1,0.5,0.5, 1+0.5,0.5,1,1,
1,1,1,0.5,0.5, 1,0.5,0.25,0.25,0.25,0.5, 0.5,0.5,0.5,0.25,0.5,1,
0.5,0.5,0.5,0.5,1,1, 1,1,1,0.5,0.5, 1+0.5,0.5,1,1,
1,1,1,0.5,0.5, 1.5,0.5,1,1, 1,1,1,1,
0.5,0.5,1,1,0.5,0.5, 1.5,0.25,0.5,1, 1,1,1,1,
1,1,1,1, 1,1,1,1, 0.5,0.5,1,1,0.5,0.5,
1,0.5,0.5,1,1, 1,1,1,1, 1,1,1,1,
0.5,0.5,1,1,0.5,0.5, 1,0.5,0.25,0.5,1, 1,1,1,0.5,0.5
};
int length;
int tonePin=13;
void setup(){
pinMode(tonePin,OUTPUT);
length = sizeof(tune)/sizeof(tune[0]);
}
void loop(){
for(int x=0;x<length;x++){
tone(tonePin,tune[x]);
delay(400 * duration[x]);
noTone(tonePin);
}
delay(5000);
}
五、按键控制LED灯暗灭
作为智能家居的一部分,肯定是需要包含灯光照明的功能的。
在这里我们选择了较为简单的单色LED灯。
原本也曾考虑了三色灯,主要是太占数字端口了(又是三个)而且其实好像也没有必要。但是三色灯的效果是很漂亮的。
代码还是一贯的简单:
const int buttonPin = 2;
const int ledPin = 8;
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {
if (digitalRead(buttonPin) == HIGH){
delay(20);
if (digitalRead(buttonPin) == HIGH) {
digitalWrite(ledPin,!digitalRead(ledPin));
while(digitalRead(buttonPin)==HIGH);
}
}
}
六、显示功能
采用了一个液晶显示屏和电位器,用电位器来调整电阻从而调节显示亮度。
代码:
#include <LiquidCrystal.h>
LiquidCrystal LCD(12, 11, 4, 5, 6, 7);
void setup(){
LCD.begin(16, 2);
}
void loop(){
LCD.setCursor(1, 0);
LCD.print("Remember to");
LCD.setCursor(1, 1);
LCD.print("feed your dog");
}
最后,粘一下开发文档中的内容。
第五部分 项目开中存在的问题分析与创新性说明
(针对新工科课程的动手实践,遇到的问题,以及解决问题的思路,以及对本项目创新性的说明)
1.问题分析:
在实践过程中我们小组遇到了很多问题,在这里提出收获较大的几个,将解决问题的过程、思路进行阐释。
问题一:不同型号的同种设备有时存在较大差异性,兼容性问题导致试验结果出错。
在88点阵和四位数码管的使用过程中,我们惊奇的发现,我们现有的设备引脚的设置和网上能查到的有很大差别,比如88点阵,网上所能查到的全都是8+8型引脚,而我们的是12+6型,这就导致我们无法直接使用现有设备。经过老师的引导和自己反复的试验,终于得到了正确的引脚连接方式。所以对于这类设备兼容性导致的问题,我们总结的解决方法有两条:一是在网上单独购买标准化设备,二是了解其引脚对应的功效,然后做实验确定其功效。在这里我们采取的是第二种解决方法。
问题二:试验参数很多是需要在试验过程中得到的,其他途径获得的参数很多情况下具备时间、空间的差异性,不能直接引用到试验参数中。
在制作自动喂食机的过程中,我们遇到了很多目标待测参数,从舵机的摆动角,选用的角速度使狗粮能够大致稳定的释放一定量同时不至于产生过大阻力使舵机驱动的纸板受阻变形等等都是需要反复测试,尝试之后才能选择一个相对优解。
问题三:试验参数、试验设备之间具有相关性。狗粮机的高度,四根筷子做支撑的相互角度,舵机高度,都是相互影响相互制约的,如果随意的将狗粮机的高度确定,四根筷子做支撑的相互角度,舵机高度等参量的数据都受到了限制,很多时候难以避免出现问题。相关的设备其中出现一个文艺就导致了整个装置的很多部分都要重新制定参数。
2.智能狗粮机的创新性说明:
(1)通过继电器和程序实现了可控时间间隔,可控水量的供水。让宠物主人在外出时也可以放心宠物的饮水问题。
(2)DIY的狗粮机和舵机的创新性使用,对比网上使用的杠杆实现开关,更具备简易性,也开拓了舵机使用的一种新思路。
(3)狗粮机和按键控制LED照明结合,符合了智能家居的理念,满足了主人在黑暗环境下想检查狗粮情况的需求,同时也可以满足日常照明需求,节能环保。
(4)饭前蜂鸣器演奏《天空之城》舒缓的音乐,经过多次演奏后可以构建宠物的条件反射,养成良好的生活规律,避免了不规律的饮食时间和量,在一定程度上对宠物的健康起到了积极作用。
(5)8*8点阵和液晶屏显示装置的显示,体现出主人对宠物——人类的伙伴的爱与关心,营造温暖的家的氛围。