查看: 655|回复: 8

blinker物联网教程——24、宠物喂食器

[复制链接]

该用户从未签到

发表于 2021-10-10 10:10 | 显示全部楼层 |阅读模式
本帖最后由 海神 于 2021-10-14 10:26 编辑

简介

家里有喂宠物猫的同学都知道,每天喂食、喂水、铲屎、陪玩等工作对于宠物必不可少,但总有那么一次两次,忘记给自家的宝贝喂食。这对宠物的身心造成很大的影响。作为技术小达人的自己,怎么会允许这样的事情发生呢?那本节就带大家制作一个智能宠物喂食器,来解决这样的问题。

机械部分
首先我们设计机型装置,这里参考并改良了网友的螺旋挤出结构,可以通过运动转轴,挤出颗粒粮食。   连接挤出结构我们使用了一个大扭力的连续旋转舵机,提供一个相对大输出力矩,用于推动粮食挤出。在挤出结构中优化了转轴结构,并保留与通道的一定间隙,以避免卡料情况的发生,测试了多种直径的猫粮狗粮,都可以正常连续挤出。
电子部分
采用wifiduino与blinker配合,实现喂食器的物联网功能。将运动舵机与挤出结构连接,使用wifiduino控制舵机运动就相当于控制喂食器的挤出结构。同时再使用blinker的app,可以手机远程操作。为了更好的连接舵机,我制作了一个wifiduino扩展板,优化舵机供电,并且添加了wifi连接的状态指示灯,添加了蜂鸣器用于播放声音,还提供了一个按键,在没有网络的状态下,手动按按键也可以控制出粮。
外观:本案例采用木质结构,通过简单搭建、组装就可以获得一个外观相对完善的,可以持续使用的喂食器。
功能描述
可以实现 远程投喂,定时投喂,定量投喂。同时内设音乐,在喂宠物前先播放音乐,召唤宠物,调整宠物心情。此外,在无网络情况下可点击内置按键,手动喂猫。 在卡料情况下,可自动清除卡料。宠物喂食,放心出门几天不用愁。
设计图展示
3.png

硬件清单


序号名称数量单位
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

cat05.png
3D模型文件下载:https://www.most3d.cn/model/35617/
木板加工文件下载: 宠物喂食器图纸.rar (79.33 KB, 下载次数: 3)

组装视频




硬件电路板连接


我们使用的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的展示界面。当然这个界面还可以根据自己需求再做优化调整。
  1. {¨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¨|÷}
复制代码
pic2234.jpg

程序代码

  1. #define BLINKER_WIFI

  2. #include <Blinker.h>
  3. #include <Servo.h>
  4. #include <EEPROM.h>

  5. #define Gled_pin D11   //绿色指示灯引脚 用于指示wifi连接成功
  6. #define Rled_pin D10   //红色指示灯引脚  指示wifi正在连接或者连接失败
  7. #define Servo_pin D4   //定义舵机连接引脚
  8. #define Buzzer_pin D8  //蜂鸣器引脚
  9. #define Button_pin  D13  //按键引脚

  10. Servo servo;
  11. int feedamount = 300;
  12. int feed_EA = 1;
  13. BlinkerSlider Slider1("ran-feedamount"); //喂食量滑块(通过延时时间控制出食量)
  14. void   Slider1_feedamount(int32_t amount)
  15. {
  16.   feedamount = amount >= 1000 ? 1000 : amount <= 1 ? 1
  17.                : amount;
  18.   Slider1.print(feedamount);
  19.   BLINKER_LOG("feedamount:", feedamount);
  20. }

  21. BlinkerButton Button("btn-handfeed"); //喂食
  22. void   Button_callback(const String &state)
  23. {
  24.   BLINKER_LOG("get button state: ", state);
  25.   if (state == BLINKER_CMD_BUTTON_TAP && feed_EA)
  26.   {
  27.     feed_EA = 1;
  28.     BLINKER_LOG("get feedamount: ", feedamount);
  29.     feed_cat();
  30.     Blinker.vibrate();
  31.     Button.color("#00ffff");
  32.     Button.text("出料完成");
  33.     Button.print();
  34.     feed_EA = 1;
  35.   }
  36. }


  37. BlinkerButton Button1("btn-autoclear"); //自动清理
  38. void   Button1_callback(const String &state)
  39. {
  40.   BLINKER_LOG("get button state: ", state);
  41.   Button1.color("#FF000F");
  42.   Button1.print("on");
  43.   auto_clear();
  44. }

  45. int voiceea = 0;
  46. BlinkerButton Button2("btn-voiceea"); //启动&关闭声音
  47. void   Button2_callback(const String &state)
  48. {
  49.   BLINKER_LOG("get button state: ", state);
  50.   if (state == "on")
  51.   {
  52.     voiceea = 1;
  53.     Button2.color("#00ffff");
  54.     Button2.print("on");
  55.   } else if (state == "off") {
  56.     voiceea = 0;
  57.     Button2.color("#ffff00");
  58.     Button2.print("off");
  59.   }
  60. }




  61. void auto_clear()
  62. { //自动清料
  63.   //Buzzer_pin
  64.   for (int i = 0; i < 10; i++)
  65.   {
  66.     servo.write(180);
  67.     Blinker.delay(100);
  68.     servo.write(0);
  69.     Blinker.delay(100);
  70.   }
  71.   servo.write(90);
  72.   Button1.color("#0F00fF");
  73.   Button1.print("off");
  74. }


  75. float tone_list[7] = {261.6, 293.7, 329.6, 349.2, 392.0, 440.0, 493.9};
  76. 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};
  77. 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};
  78. 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};
  79. float dur = 500;

  80. void playmusic()
  81. { //播放音乐
  82.   if (voiceea)
  83.   {
  84.     Button.color("#00ffff");
  85.     Button.text("播放铃声中");
  86.     Button.print();
  87.     for (int i = (1); i <= (sizeof(music_list) / sizeof(music_list[0])); i = i + (1))
  88.     {
  89.       pinMode(Buzzer_pin, OUTPUT);
  90.       tone(Buzzer_pin, tone_list[(int)(music_list[(int)(i - 1)] - 1)] * pow(2, high_list[(int)(i - 1)]));
  91.       Blinker.delay((dur * rhythm_list[(int)(i - 1)]));
  92.       pinMode(Buzzer_pin, OUTPUT);
  93.       noTone(Buzzer_pin);
  94.       Blinker.delay(10);
  95.     }
  96.   }
  97. }

  98. void feed_cat() //喂食出料
  99. {

  100.   playmusic();
  101.   servo.write(0);
  102.   Button.color("#ff00ff");
  103.   Button.text("出料中");
  104.   Button.print();
  105.   Blinker.delay(50);

  106.   Blinker.delay(feedamount * 10);
  107.   servo.write(90);
  108. }


  109. char ssid[] = "mxxxxxn";
  110. char pswd[] = "cdxxxxxxxx1";

  111. const char auth[] = "8c4xxxxxxxd4";

  112. void setup()
  113. {
  114.   Serial.begin(115200);
  115.   BLINKER_DEBUG.stream(Serial);
  116.   Blinker.begin(auth, ssid, pswd);
  117.   pinMode(Gled_pin, OUTPUT);
  118.   pinMode(Rled_pin, OUTPUT);
  119.   digitalWrite(Rled_pin, HIGH);
  120.   digitalWrite(Gled_pin, LOW);
  121.   servo.attach(D4);
  122.   servo.write(90);//360度舵机静止
  123.   Slider1.attach(Slider1_feedamount);

  124.   Button.attach(Button_callback);
  125.   Button1.attach(Button1_callback);
  126.   Button2.attach(Button2_callback);
  127.   while(1){
  128.        Blinker.run();
  129.       if (Blinker.connected()) {
  130.         digitalWrite(Gled_pin, HIGH);
  131.         digitalWrite(Rled_pin, LOW);
  132.         Blinker.push("喂猫机上线!");
  133.         break;
  134.       }
  135.   }
  136. }


  137. void state_feedback()  //状态反馈
  138. {
  139.   if (voiceea) {
  140.     Button2.color("#00ffff");
  141.     Button2.print("on");
  142.   } else {
  143.     Button2.color("#ffff00");
  144.     Button2.print("off");
  145.   }
  146.   Slider1.print(feedamount);

  147. }

  148. int wifimode = 0;
  149. void loop()
  150. {
  151.   switch (wifimode)
  152.   {
  153.     case 0:
  154.       Blinker.run();
  155.       if (Blinker.connected()) {
  156.         digitalWrite(Gled_pin, HIGH);
  157.         digitalWrite(Rled_pin, LOW);
  158.         wifimode = 1;
  159.       //  Blinker.push("喂猫机上线!");
  160.       }
  161.       if (digitalRead(Button_pin) == 0) {
  162.         feed_cat(); //手动出料
  163.       }
  164.       break;
  165.     case 1:
  166.       Blinker.run();
  167.       runmode();
  168.       break;
  169.   }
  170. }

  171. unsigned long lasttimes = 0;
  172. void runmode()
  173. {
  174.   if (millis() > lasttimes + 120000)
  175.   {
  176.     state_feedback();
  177.     if (!Blinker.connected()) {
  178.       wifimode = 0;
  179.       digitalWrite(Gled_pin, LOW);
  180.       digitalWrite(Rled_pin, HIGH);
  181.     }
  182.     lasttimes = millis();
  183.   }
  184.   if (digitalRead(Button_pin) == 0) {
  185.     feed_cat(); //手动出料
  186.   }
  187. }
复制代码

成品演示视频:









该用户从未签到

发表于 2021-10-10 21:42 | 显示全部楼层
老板那个红色的螺旋件哪里买的,还是3D自己打印的

点评

3D打印的,晚点我把模型文件放出来  详情 回复 发表于 2021-10-11 09:34

该用户从未签到

 楼主| 发表于 2021-10-11 09:34 | 显示全部楼层
ytying1001 发表于 2021-10-10 21:42
老板那个红色的螺旋件哪里买的,还是3D自己打印的

3D打印的,晚点我把模型文件放出来

该用户从未签到

发表于 2021-10-11 09:58 | 显示全部楼层
舵机转一个来回挤一次是吧

点评

转一圈就出一次量,可以设定每次出料的量以及出料的次数  详情 回复 发表于 2021-10-11 10:12

该用户从未签到

 楼主| 发表于 2021-10-11 10:12 | 显示全部楼层
myself1820 发表于 2021-10-11 09:58
舵机转一个来回挤一次是吧

转一圈就出一次量,可以设定每次出料的量以及出料的次数

该用户从未签到

发表于 2021-10-11 10:16 | 显示全部楼层
不错不错,外观再美化一下就更好了

该用户从未签到

发表于 2021-10-13 15:42 | 显示全部楼层
好棒,请问模型文件在哪里呀

点评

已经上传  详情 回复 发表于 2021-10-14 09:59

签到天数: 5 天

[LV.2]偶尔看看I

发表于 2021-10-14 09:28 | 显示全部楼层
棒棒的!学习一下

该用户从未签到

 楼主| 发表于 2021-10-14 09:59 | 显示全部楼层
不爱吃芹菜 发表于 2021-10-13 15:42
好棒,请问模型文件在哪里呀

已经上传
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

热门推荐

交作业:第1个作品,红外避障小车
交作业:第1个作品,红外
交作业:第1个作品,红外避障小车。 经过N次调整优化,终于把红外避障小车“使
【Arduino】168种传感器模块系列实验(112)---GY-521三轴模块
【Arduino】168种传感器模
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
Arduino引脚图
Arduino引脚图
Arduino UNO R3 (CH340G)引脚 持续更新中·····
求助,验证结果没有报错,但验证过程中有报:Error while de...
求助,验证结果没有报错,
这是报红的信息 但结果并没有报错
blinker实时数据功能使用方法
blinker实时数据功能使用
自blinker 2.5.8起,点灯将提供实时数据功能。 使用实时数据功能,可以将数据更新频率
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表