本帖最后由 海神 于 2022-5-17 16:14 编辑
简介
家里有喂宠物猫的同学都知道,每天喂食、喂水、铲屎、陪玩等工作对于宠物必不可少,但总有那么一次两次,忘记给自家的宝贝喂食。这对宠物的身心造成很大的影响。作为技术小达人的自己,怎么会允许这样的事情发生呢?那本节就带大家制作一个智能宠物喂食器,来解决这样的问题。
机械部分
首先我们设计机型装置,这里参考并改良了网友的螺旋挤出结构,可以通过运动转轴,挤出颗粒粮食。 连接挤出结构我们使用了一个大扭力的连续旋转舵机,提供一个相对大输出力矩,用于推动粮食挤出。在挤出结构中优化了转轴结构,并保留与通道的一定间隙,以避免卡料情况的发生,测试了多种直径的猫粮狗粮,都可以正常连续挤出。
电子部分
采用wifiduino与blinker配合,实现喂食器的物联网功能。将运动舵机与挤出结构连接,使用wifiduino控制舵机运动就相当于控制喂食器的挤出结构。同时再使用blinker的app,可以手机远程操作。为了更好的连接舵机,我制作了一个wifiduino扩展板,优化舵机供电,并且添加了wifi连接的状态指示灯,添加了蜂鸣器用于播放声音,还提供了一个按键,在没有网络的状态下,手动按按键也可以控制出粮。
外观:本案例采用木质结构,通过简单搭建、组装就可以获得一个外观相对完善的,可以持续使用的喂食器。
功能描述
可以实现 远程投喂,定时投喂,定量投喂。同时内设音乐,在喂宠物前先播放音乐,召唤宠物,调整宠物心情。此外,在无网络情况下可点击内置按键,手动喂猫。 在卡料情况下,可自动清除卡料。宠物喂食,放心出门几天不用愁。
设计图展示
硬件清单
序号 | 名称 | 数量 | 单位 | 1 | 木板 | 1 | 套 | 2 | 3D打印件 | 1 | 套 | 3 | wifiduino主板 | 1 | 块 | 4 | 宠物喂食器扩展板 | 1 | 块 | 5 | 连续旋转舵机(配舵盘、螺丝) | 1 | 个 | 6 | M3*8圆头十字螺丝 | 8 | 颗 | 7 | M3螺母 | 8 | 颗 | 8 | M3自攻丝螺丝 | 6 | 颗 | 9 | M4*5圆头十字螺丝 | 4 | 颗 | 10 | M4螺母 | 4 | 颗 | 11 | M2*8圆头十字螺丝 | 22 | 颗 | 12 | M2螺母 | 22 | 颗 |
硬件购买链接
3D模型文件下载:https://www.most3d.cn/model/35617/
木板加工文件下载:
宠物喂食器图纸.rar
(79.33 KB, 下载次数: 119)
组装视频
硬件电路板连接
我们使用的360度连续旋转舵机供电范围是4.8V~6V。
如果采用7~9V的电源适配器给wifiduino主板供电,要给舵机供电可以在主板的两个位置取电,一是VIN引脚输出对应7~9V,二是5V引脚,输出电压为5V。但直接供电会存在两个问题。
问题一 如果采用VIN供电,那么电压超出了舵机供电范围,不能直接供电
问题二 如果用主板的5V供电,但这个5V输出对应的电流比较有限,也就是驱动能力有限,我们采用的大扭力舵机需要较大的驱动能力,经过测试主板输出5V的电流不足驱动舵机,在舵机转动时,可能会导致主板死机。
所以这里我们做了一个wifiduino扩展板,引出了3针接口专门用来连接舵机,而供电是采用vin过来的电,通过一个大电流输出的5V稳压芯片,输出5V连接在3针的供电引脚中。
上传程序步骤 1、使用microUSB将主控器与电脑连接
2、准备手机、下载手机app——blinker ,点击“+”——“独立设备”——“网络接入”——“阿里云” 复制设备Key编号
3、安装编程软件arduinoIDE,打开下列示例程序,将原程序中的Key值、宠物喂食器的主控器要连接的wifi的账号(SSID)和密码 进行修改 ssid[] pswd[] auth[],然后点击上传程序
4、确认程序下载成功,打开app,将之前新建的设备名称修改为宠物喂食器,app的控制界面可以直接参考配置,点击“设置”——“界面配置”,将下面配置文本复制到框内,点击“更新配置”完成。这样就配置好了,app的展示界面。当然这个界面还可以根据自己需求再做优化调整。
- {¨version¨¨2.0.0¨¨config¨{¨headerColor¨¨transparent¨¨headerStyle¨¨dark¨¨background¨{¨img¨¨assets/img/bg/f1.jpg¨¨isFull¨»}}¨dashboard¨|{¨type¨¨btn¨¨ico¨¨fas fa-cat¨¨mode¨É¨t0¨¨喂食¨¨t1¨¨文本2¨¨bg¨É¨cols¨Í¨rows¨Í¨key¨¨btn-handfeed¨´x´Í´y´Î¨speech¨|÷¨lstyle¨Ë}{ßCßDßE¨fal fa-power-off¨ßGÊßH¨声音提示¨ßJßKßLÉßMËßNËßO¨btn-voiceea¨´x´É´y´ÎßQ|÷ßRÊ}{ßC¨ran¨ßH¨喂食量¨¨clr¨¨#389BEE¨¨max¨¢G8¨min¨ÉßLÉßMÑßNËßO¨ran-feedamount¨´x´É´y´¤AßQ|÷ßRË}{ßCßDßEßSßGÉßH¨卡料自动清理¨ßJßKßLÉßMËßNËßO¨btn-autoclear¨´x´É´y´ÐßQ|÷ßX¨#EA0909¨ßRÊ}{ßC¨deb¨ßGÉßLÉßMÑßNÌßO¨debug¨´x´É´y´Ê}÷¨actions¨|÷¨triggers¨|÷}
复制代码
程序代码
- #define BLINKER_WIFI
- #include <Blinker.h>
- #include <Servo.h>
- #include <EEPROM.h>
- #define Gled_pin D11 //绿色指示灯引脚 用于指示wifi连接成功
- #define Rled_pin D10 //红色指示灯引脚 指示wifi正在连接或者连接失败
- #define Servo_pin D4 //定义舵机连接引脚
- #define Buzzer_pin D8 //蜂鸣器引脚
- #define Button_pin D13 //按键引脚
- Servo servo;
- int feedamount = 300;
- int feed_EA = 1;
- BlinkerSlider Slider1("ran-feedamount"); //喂食量滑块(通过延时时间控制出食量)
- void Slider1_feedamount(int32_t amount)
- {
- feedamount = amount >= 1000 ? 1000 : amount <= 1 ? 1
- : amount;
- Slider1.print(feedamount);
- BLINKER_LOG("feedamount:", feedamount);
- }
- BlinkerButton Button("btn-handfeed"); //喂食
- void Button_callback(const String &state)
- {
- BLINKER_LOG("get button state: ", state);
- if (state == BLINKER_CMD_BUTTON_TAP && feed_EA)
- {
- feed_EA = 1;
- BLINKER_LOG("get feedamount: ", feedamount);
- feed_cat();
- Blinker.vibrate();
- Button.color("#00ffff");
- Button.text("出料完成");
- Button.print();
- feed_EA = 1;
- }
- }
- BlinkerButton Button1("btn-autoclear"); //自动清理
- void Button1_callback(const String &state)
- {
- BLINKER_LOG("get button state: ", state);
- Button1.color("#FF000F");
- Button1.print("on");
- auto_clear();
- }
- int voiceea = 0;
- BlinkerButton Button2("btn-voiceea"); //启动&关闭声音
- void Button2_callback(const String &state)
- {
- BLINKER_LOG("get button state: ", state);
- if (state == "on")
- {
- voiceea = 1;
- Button2.color("#00ffff");
- Button2.print("on");
- } else if (state == "off") {
- voiceea = 0;
- Button2.color("#ffff00");
- Button2.print("off");
- }
- }
- void auto_clear()
- { //自动清料
- //Buzzer_pin
- for (int i = 0; i < 10; i++)
- {
- servo.write(180);
- Blinker.delay(100);
- servo.write(0);
- Blinker.delay(100);
- }
- servo.write(90);
- Button1.color("#0F00fF");
- Button1.print("off");
- }
- float tone_list[7] = {261.6, 293.7, 329.6, 349.2, 392.0, 440.0, 493.9};
- long music_list[] = {1, 1, 5, 5, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 5, 5, 4, 4, 3, 3, 2, 5, 5, 4, 4, 3, 3, 2, 1, 1, 5, 5, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1};
- long high_list[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- float rhythm_list[] = {1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2};
- float dur = 500;
- void playmusic()
- { //播放音乐
- if (voiceea)
- {
- Button.color("#00ffff");
- Button.text("播放铃声中");
- Button.print();
- for (int i = (1); i <= (sizeof(music_list) / sizeof(music_list[0])); i = i + (1))
- {
- pinMode(Buzzer_pin, OUTPUT);
- tone(Buzzer_pin, tone_list[(int)(music_list[(int)(i - 1)] - 1)] * pow(2, high_list[(int)(i - 1)]));
- Blinker.delay((dur * rhythm_list[(int)(i - 1)]));
- pinMode(Buzzer_pin, OUTPUT);
- noTone(Buzzer_pin);
- Blinker.delay(10);
- }
- }
- }
- void feed_cat() //喂食出料
- {
- playmusic();
- servo.write(0);
- Button.color("#ff00ff");
- Button.text("出料中");
- Button.print();
- Blinker.delay(50);
- Blinker.delay(feedamount * 10);
- servo.write(90);
- }
- char ssid[] = "mxxxxxn";
- char pswd[] = "cdxxxxxxxx1";
- const char auth[] = "8c4xxxxxxxd4";
- void setup()
- {
- Serial.begin(115200);
- BLINKER_DEBUG.stream(Serial);
- Blinker.begin(auth, ssid, pswd);
- pinMode(Gled_pin, OUTPUT);
- pinMode(Rled_pin, OUTPUT);
- digitalWrite(Rled_pin, HIGH);
- digitalWrite(Gled_pin, LOW);
- servo.attach(D4);
- servo.write(90);//360度舵机静止
- Slider1.attach(Slider1_feedamount);
- Button.attach(Button_callback);
- Button1.attach(Button1_callback);
- Button2.attach(Button2_callback);
- while(1){
- Blinker.run();
- if (Blinker.connected()) {
- digitalWrite(Gled_pin, HIGH);
- digitalWrite(Rled_pin, LOW);
- Blinker.push("喂猫机上线!");
- break;
- }
- }
- }
- void state_feedback() //状态反馈
- {
- if (voiceea) {
- Button2.color("#00ffff");
- Button2.print("on");
- } else {
- Button2.color("#ffff00");
- Button2.print("off");
- }
- Slider1.print(feedamount);
- }
- int wifimode = 0;
- void loop()
- {
- switch (wifimode)
- {
- case 0:
- Blinker.run();
- if (Blinker.connected()) {
- digitalWrite(Gled_pin, HIGH);
- digitalWrite(Rled_pin, LOW);
- wifimode = 1;
- // Blinker.push("喂猫机上线!");
- }
- if (digitalRead(Button_pin) == 0) {
- feed_cat(); //手动出料
- }
- break;
- case 1:
- Blinker.run();
- runmode();
- break;
- }
- }
- unsigned long lasttimes = 0;
- void runmode()
- {
- if (millis() > lasttimes + 120000)
- {
- state_feedback();
- if (!Blinker.connected()) {
- wifimode = 0;
- digitalWrite(Gled_pin, LOW);
- digitalWrite(Rled_pin, HIGH);
- }
- lasttimes = millis();
- }
- if (digitalRead(Button_pin) == 0) {
- feed_cat(); //手动出料
- }
- }
复制代码
成品演示视频:
系列教程
——blinker物联网教程——1、物联网及blinker介绍
blinker物联网教程——2、搭建编程环境
blinker物联网教程——3、主控硬件wifiduino
blinker物联网教程——4、控制开关灯
blinker物联网教程——5、认识传感器
blinker物联网教程——6、wifi智能插座
blinker物联网教程——7、室内温湿度计
blinker物联网教程——8、定时任务-定时震动器
blinker物联网教程——9、blinker语音识别-芝麻开门
blinker物联网教程——10、日照时间分析
blinker物联网教程——11、自动灌溉
blinker物联网教程——12、调色盘
blinker物联网教程——13、公园噪音监测
blinker物联网教程——14、智能停车场
blinker物联网教程——15、物联网天气时钟
16、空气加湿器
17、远程烟雾报警
18、气象站
blinker物联网教程——19、接入小度智能音箱
20、语音氛围灯
21、远程控制电脑开关机
22、手机控制空调
blinker物联网教程——23、wifi智能小车
blinker物联网教程——24、智能宠物喂食器
25、xxxx
26、xxxxx
|