基于单片机设计智能宠物喂食器

1任务:
设计制作一个基于单片机的宠物喂食器,能够按计划或手动喂食宠物,确保宠物的合理饮食和健康成长。
2要求:
(1)定时喂食功能: 设定每天的喂食时间表,宠物喂食器按照设定的时间自动喂食,保证宠物的饮食规律。
(2)定量喂食功能: 定量控制宠物的食物分配,根据不同大小和品种的宠物,设定合适的食物分配量,确保宠物摄取恰当的食物。
(3)手动喂食功能: 设计一个按钮或触摸屏,允许主人手动触发喂食过程,可以根据需要进行额外的喂食。
(4)食物存储容器: 设计一个可拆卸的食物容器,装载和储存宠物的食物,容易清洗和补充。
(5)系统稳定性和硬件设计: 确保系统的稳定性和可靠性,包括电路设计、驱动器、传感器等方面的考虑。
3说明:
(1)硬件和软件实现: 描述所选用的单片机和相关的传感器、执行器等硬件组件的使用,同时介绍所需的软件开发环境和编程语言。
(2)系统集成与测试: 将硬件和软件进行集成,并进行功能测试、性能评估等,确保宠物喂食器满足设计要求。
(3)节能与安全性: 分析和评估系统的能耗情况,并确保喂食器的安全性,如防止卡住、食物溢出等问题。
(4)结果与分析: 展示实验结果,对比分析系统的性能和喂食效果,并给出改进的建议。 

 4 硬件搭建:

基于单片机设计智能宠物喂食器_第1张图片

 5软件编程(一接入onenet平台部分,二功能实现部分)

(1)

#include

#include

#include

//设置用于连接温湿度传感器的引脚

#define DHTPIN 19  //根据硬件连接确定引脚编号(注意,这里我连接的是D7,也就是GPIO13)

#define led  2

#define LED_BUILTIN 2

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

float h,t;

// 引入 wifi 模块,并实例化,不同的芯片这里的依赖可能不同

#include

static WiFiClient espClient;

// 引入阿里云 IoT SDK

#include "AliyunIoTSDK.h"

// 设置产品和设备的信息,从阿里云设备信息里查看

#define PRODUCT_KEY "a1eMrKgKacD"

#define DEVICE_NAME "esp32"

#define DEVICE_SECRET "284e56bcb8052e38ba4e1f7cbb2e92a7"//(这三个东西在阿里云里面)

#define REGION_ID "cn-shanghai"

// 设置 wifi 信息

#define WIFI_SSID "www"//(这里面连你自己家的WiFi,注意要是2.4G频段的,5G的不行)

#define WIFI_PASSWD "12345678"//(你自己家的WiFi密码)

void setup()

{

    Serial.begin(115200);

    pinMode(LED_BUILTIN, OUTPUT);

    digitalWrite(LED_BUILTIN, HIGH);

    // 初始化 wifi

    wifiInit(WIFI_SSID, WIFI_PASSWD);

    //初始化 iot,需传入 wifi 的 client,和设备产品信息

    AliyunIoTSDK::begin(espClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, REGION_ID);

    // 绑定一个设备属性回调,当远程修改此属性,会触发 powerCallback

    // PowerSwitch 是在设备产品中定义的物联网模型的 id

    // AliyunIoTSDK::bindData("温湿度",CurrentTemperature);

    // // 发送一个数据到云平台,LightLuminance 是在设备产品中定义的物联网模型的 id

    AliyunIoTSDK::bindData("LED", LED);

     

   pinMode(DHTPIN,INPUT);

    dht.begin();

}

void loop()

{

   

  AliyunIoTSDK::loop();  

  AliyunIoTSDK::send("temperature",t);

  AliyunIoTSDK::send("Humidity",h);

   //发送LED状态到云平台(高电平:1;低电平:0)

    AliyunIoTSDK::send("LEDPIN", digitalRead(LED_BUILTIN));

  h = dht.readHumidity();

  t = dht.readTemperature();                

  Serial.print("Temperature:");                      

  Serial.println(t);                                    

  delay(1000);

  Serial.print("Humidity:");                            

  Serial.print(h);                                    

  Serial.println("%");                                

  delay(1000);

}

// 初始化 wifi 连接

void wifiInit(const char *ssid, const char *passphrase)

{

    WiFi.mode(WIFI_STA);

    WiFi.begin(ssid, passphrase);

    while (WiFi.status() != WL_CONNECTED)

    {

        delay(1000);

        Serial.println("WiFi not Connect");

    }

    Serial.println("Connected to AP");

     digitalWrite(led, LOW);

}

//回调函数

void LED(JsonVariant L)//固定格式,修改参数l

{

  int LED = L["LED"];//参数l

  if (LED == 1)

  {

    digitalWrite(LED_BUILTIN, LOW);

  }

  else

  {

    digitalWrite(LED_BUILTIN, HIGH);

  }

}

(2)

#include

#include

#include

#include//舵机

#include //称重模块

#include //oled父类库

#include //oled1306

#define USE_MULTCORE 1//使用多核心

#include //LCD1602

#include //DS1302时钟


 

unsigned long s=0;//将存储上次的时间

unsigned long a=0;//将存储上次的时间

unsigned long b=0;//将存储上次的时间

unsigned long c=0;//将存储上次的时间

unsigned long d=0;//将存储上次的时间

unsigned long e=0;//将存储上次的时间

unsigned long f=0;//将存储上次的时间

unsigned long g=0;//将存储上次的时间

#define  water  4  //水深管脚0

#define  buzzer 5 //蜂鸣器

#define  relay   18 //创建继电器

#define TrigPin  16//号引脚触发端

#define EchoPin  17//号引脚接收端

#define Lan      13//蓝色

#define Hong     12//红色

#define Lv       14//绿色

char xiaoshi;//小时

char fengzhong;//分钟

char miao;//秒

int  x=1;//工作模式,1自动,2手动

float z=0;//喂养打开时间,由宠物重量决定

int y=0;//喂养的食物重量

int w=1;//喂养开关1关闭,2打开

int t=1;//1未喂养2已喂养



 

float distance_cm;//存储距离单位值cm

//DS1302初始化

LiquidCrystal_I2C lcd(0x27,16,2);  // 将LCD地址设置为0x27,用于16个字符和2行显示

namespace {

const int kCePin   = 27;  //RST

const int kIoPin   = 26; //DAT

const int kSclkPin = 25;   //CLK

// Create a DS1302 object.

DS1302 rtc(kCePin, kIoPin, kSclkPin);

//星期几

String dayAsString(const Time::Day day) {

  switch (day) {

    case Time::kSunday: return "1";

    case Time::kMonday: return "2";

    case Time::kTuesday: return "3";

    case Time::kWednesday: return "4";

    case Time::kThursday: return "5";

    case Time::kFriday: return "6";

    case Time::kSaturday: return "7";

  }

  return "(unknown day)";

}

//输出时间

void printTime() {

  Time t = rtc.time(); // 获取当前时间和日期

  const String day = dayAsString(t.day);

  // Format the time and date and insert into the temporary buffer. //格式化时间和日期并插入临时缓冲区。

  char buf[50];   //定义一个字符型数组用来存放日期数据(用于串口打印)

  char DateBuf[12];  //定义一个字符型数组用来存放日期数据(由于1602每行只能打印16个字符,所以日期和时间分两个数组存)

  char TimeBuf[10];//定义一个字符型数组用来存放时间数据(由于1602每行只能打印16个字符,所以日期和时间分两个数组存)

  snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d",day.c_str(),t.yr, t.mon, t.date,t.hr, t.min, t.sec);

   //把日期和时间数据存放到数组中

  snprintf(DateBuf,sizeof(DateBuf),"%04d-%02d-%02d",t.yr, t.mon, t.date); //把日期数据存放到数组中

  snprintf(TimeBuf,sizeof(TimeBuf),"%02d:%02d:%02d",t.hr, t.min, t.sec);  //把时间数据存放到数组中

  Serial.println(buf);  //串口打印输出日期与时间

  lcd.setCursor(0,0);   //设置1602的光标到第0行第0个字符处

  lcd.print(DateBuf);   //在LCD光标所在处打印DateBuf数组里的数据

  lcd.setCursor(12,0);   //设置1602的光标到第0行第0个字符处

  lcd.print("W:");

  lcd.print(day.c_str());

  lcd.setCursor(0,1);   //设置1602的光标到第1行第3个字符处

  lcd.print(TimeBuf);   //在LCD光标所在处打印TimeBuf数组里的数据

   xiaoshi=t.hr;

  fengzhong=t.min;

  miao=t.sec;

}

}  

int    pos=90;// 舵机角度

Servo  myservo1;//创建喂养舵机

float i,data;//定义变量i是水深传感器数值,data是深度

HX711 HX711_CH0(15, 2, 300); //初始化SCK,DT,GapValue

long chongwu1=0;//定义一个变量用于存放宠物g



 

Adafruit_SSD1306 oled(128,64,&Wire,4);//oled定义初始化

static const unsigned char PROGMEM shui[]={

0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x08,0x01,0x08,0x7D,0x90,0x05,0xA0,0x09,0x40,

0x09,0x40,0x11,0x20,0x11,0x10,0x21,0x08,0x41,0x06,0x81,0x00,0x05,0x00,0x02,0x00,/*"水",0*/

  };//水

  static const unsigned char PROGMEM shen[]={

0x00,0x00,0x27,0xFC,0x14,0x04,0x14,0xA4,0x81,0x10,0x42,0x08,0x40,0x40,0x10,0x40,

0x17,0xFC,0x20,0x40,0xE0,0xE0,0x21,0x50,0x22,0x48,0x2C,0x46,0x20,0x40,0x00,0x40,/*"深",1*/

  };//深

static const unsigned char PROGMEM chong[]={

0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x84,0x24,0x04,0x10,0x04,0x10,0xFF,0xFE,

0x04,0x80,0x08,0x88,0x08,0x90,0x10,0xA0,0x10,0xC2,0x20,0x82,0x41,0x82,0x86,0x7E,/*"宠",0*/

};//宠

static const unsigned char PROGMEM wu[]={

0x10,0x80,0x10,0x80,0x50,0x80,0x50,0xFC,0x7D,0x54,0x52,0x54,0x90,0x54,0x10,0x94,

0x1C,0x94,0xF1,0x24,0x52,0x24,0x10,0x44,0x10,0x44,0x10,0x84,0x11,0x28,0x10,0x10,/*"物",0*/

};//物

static const unsigned char PROGMEM zi[]={

0x01,0x00,0x02,0x00,0x04,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,

0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,/*"自",0*/

};//自

static const unsigned char PROGMEM shou[]={

0x00,0x10,0x00,0xF8,0x3F,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,

0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,/*"手",0*/

};//手

static const unsigned char PROGMEM dong[]={

0x00,0x40,0x00,0x40,0x7C,0x40,0x00,0x40,0x01,0xFC,0x00,0x44,0xFE,0x44,0x20,0x44,

0x20,0x44,0x20,0x84,0x48,0x84,0x44,0x84,0xFD,0x04,0x45,0x04,0x02,0x28,0x04,0x10,/*"动",0*/

};//动

static const unsigned char PROGMEM zhuang[]={

0x08,0x40,0x08,0x48,0x08,0x44,0x48,0x44,0x28,0x40,0x2F,0xFE,0x08,0x40,0x08,0x40,

0x18,0x40,0x28,0xA0,0xC8,0xA0,0x08,0x90,0x09,0x10,0x09,0x08,0x0A,0x04,0x0C,0x02,/*"状",0*/

};//状

static const unsigned char PROGMEM tai[]={

0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x02,0x80,0x04,0x40,0x0A,0x20,0x31,0x18,

0xC0,0x06,0x01,0x00,0x08,0x88,0x48,0x84,0x48,0x12,0x48,0x12,0x87,0xF0,0x00,0x00,/*"态",0*/

};//态

static const unsigned char PROGMEM wei[]={

0x00,0x00,0x03,0xF8,0x7A,0x48,0x4A,0x48,0x4B,0xF8,0x4A,0x48,0x4A,0x48,0x4B,0xF8,

0x48,0x00,0x4F,0xFE,0x7A,0x40,0x4A,0x44,0x02,0x28,0x02,0x90,0x03,0x08,0x02,0x06,/*"喂",0*/

};//喂

static const unsigned char PROGMEM shi[]={

0x01,0x00,0x02,0x80,0x04,0x40,0x0A,0x20,0x31,0x18,0xDF,0xF6,0x10,0x10,0x1F,0xF0,

0x10,0x10,0x1F,0xF0,0x10,0x08,0x11,0x90,0x10,0x60,0x12,0x10,0x14,0x08,0x18,0x04,/*"食",0*/

};//时

static const unsigned char PROGMEM wei1[]={

0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,

0x03,0x80,0x05,0x40,0x09,0x20,0x11,0x10,0x21,0x08,0xC1,0x06,0x01,0x00,0x01,0x00,/*"未",0*/

};//未

static const unsigned char PROGMEM yi[]={

0x00,0x00,0x3F,0xF0,0x00,0x10,0x00,0x10,0x00,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,

0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x04,0x20,0x04,0x20,0x04,0x1F,0xFC,0x00,0x00,/*"已",0*/

};//已


 

// void xTaskOne(void *xTask1)//任务函数一

// {  

//   while (1)

//   {

//   }

// }

void xTaskTwo(void *xTask2)//任务函数二

{

while (1)

   {  

delay(10);//多任务需要

y=(int)(chongwu1*0.07*100+0.5)/100.0;

if(x==1)

{

if( (xiaoshi==8)&& (fengzhong==0) &&(miao==0))//闹钟8:00

{

for(int i=0;i<=3;i++)//3s蜂鸣器

{

 digitalWrite(buzzer,HIGH);

 delay(1000);

 }

 digitalWrite(buzzer,LOW);

if(chongwu1>0)

{

for(pos=90;pos>=0;pos--)//打开喂养

{

  myservo1.write(pos);

  delay(15);

}

myservo1.write(0);

z=chongwu1*0.07*100;

delay(z);//宠物越重喂养时间越长

for(pos=0;pos<=90;pos++)//关闭喂养while

{

  myservo1.write(pos);

  delay(15);

}

t=2;

}

}

}

if(x==2)

{

  if(w==2)

  {

for(pos=90;pos>=0;pos--)//打开喂养

{

  myservo1.write(pos);

  delay(15);

}

  }

if(w==1)

{

for(pos=0;pos<=90;pos++)//关闭喂养while

{

  myservo1.write(pos);

  delay(15);

}

}

}

}

}

//  if( (oledhour==12)&& (oledminute==0) &&(oledsecond==0))//闹钟12:00

// {

//  unsigned long currentMillis = millis(); // 存储当前时间

// if (currentMillis - s>= 1000) { // 检查是否经过了 1000ms

// s = currentMillis;  

// for(int i=0;i<=3;i++)//3s蜂鸣器

// {

//  digitalWrite(buzzer,HIGH);

//  delay(1000);

//  }

//  do

//  {

//    myservo1.write(90);//驱动舵机打开仓库阀门90度

//   }while(shiwu1-chongwu1*0.004<0);//喂养0.4%都体重食物

//   myservo1.write(0);//驱动舵机关闭仓库阀门

//   for(int i=0;i<=3;i++)

//   {

//      myservo2.write(90);//喂食舵机打开3s

//      delay(1000);

//   }

//  myservo2.write(0);

//  while(data<4)

//  {

//   digitalWrite(relay,LOW);//继电器打开水泵

//   }

//  }

// }

// }

// if( (oledhour==17)&& (oledminute==0) &&(oledsecond==0))//闹钟17:00

// {

//  unsigned long currentMillis = millis(); // 存储当前时间

// if (currentMillis - s>= 1000) { // 检查是否经过了 1000ms

// s = currentMillis;

// for(int i=0;i<=3;i++)//3s蜂鸣器

// {

//  digitalWrite(buzzer,HIGH);

//  delay(1000);

//  }

//  do

//  {

//    myservo1.write(90);//驱动舵机打开仓库阀门90度

//   }while(shiwu1-chongwu1*0.004<0);//喂养0.4%都体重食物

//   myservo1.write(0);//驱动舵机关闭仓库阀门

//   for(int i=0;i<=3;i++)

//   {

//      myservo2.write(90);//喂食舵机打开3s

//      delay(1000);

//   }

//  myservo2.write(0);

//  while(data<4)

//  {

//   digitalWrite(relay,LOW);//继电器打开水泵

//   }

//  }

// }

// }

void setup()

{

  Serial.begin(115200);

  delay(10);//多任务需要

 #if !USE_MULTCORE

//     xTaskCreate(

//         xTaskOne,  /* 任务函数. */

//         "TaskOne", /* 名称 */

//         4096,      /* 堆栈大小. */

//         NULL,      /* 参数输入传递给任务的*/

//         1,         /* 任务的优先级*/

//         NULL);     /* 任务所在核心 */

 xTaskCreate(

       xTaskTwo,  /* Task function. */

       "TaskTwo", /* String with name of task. */

       4096,      /* Stack size in bytes. */

       NULL,      /* Parameter passed as input of the task */

       2,         /* Priority of the task.(configMAX_PRIORITIES - 1 being the highest, and 0 being the lowest.) */

       NULL);    

#else

   //最后一个参数至关重要,决定这个任务创建在哪个核上.PRO_CPU 为 0, APP_CPU 为 1,或者 tskNO_AFFINITY 允许任务在两者上运行.

   // xTaskCreatePinnedToCore(xTaskOne, "TaskOne", 4096, NULL, 1, NULL, 0);//TaskOne在 0核心

    xTaskCreatePinnedToCore(xTaskTwo, "TaskTwo", 4096, NULL, 2, NULL, 1);//TaskOne在 1核心

#endif

   

  lcd.init(); //初始化LCD

  lcd.backlight();  //打开LCD背光

  rtc.writeProtect(false);

  rtc.halt(false);

  // Make a new time object to set the date and time.

  // Wednesday, March 2, 2023 at 16:49:46.

  Time t(2023, 3, 2, 7, 59, 45, Time::kWednesday);//起初时间设定

  // Set the time and date on the chip.

  rtc.time(t);

  pinMode(buzzer,OUTPUT);//蜂鸣器管脚

  digitalWrite(buzzer,LOW);//蜂鸣器管脚高电平

  pinMode(TrigPin,OUTPUT);

  pinMode(EchoPin,INPUT);

  myservo1.attach(23,500,2500);//初始化喂养舵机D23

  pinMode(relay,OUTPUT);

  digitalWrite(relay,LOW);//继电器

 Wire.begin(/*SDA*/21,/*SCL*/22);

 oled.begin(SSD1306_SWITCHCAPVCC,0x3c);//oled初始化

 pinMode(water,INPUT);//A0输入模式

 HX711_CH0.begin();//读取支架的重量

 delay(3000);

 HX711_CH0.begin();//再次读取支架的重量

pinMode(Lan,OUTPUT);//蓝

digitalWrite(Lan,LOW);//

pinMode(Hong,OUTPUT);//红

digitalWrite(Hong,LOW);//

pinMode(Lv,OUTPUT);//绿

digitalWrite(Lv,LOW);//

}

void loop() {

delay(10);//多任务需要

chongwu();//hx711宠物

shuishen();//水深函数

unsigned long currentMillis = millis(); // 存储当前时间

if (currentMillis - a >= 1000) { // 检查是否经过了 1000ms

 a = currentMillis; // 保存上次闪烁 LED 的时间

 printTime();// LCD1602每秒钟循环并打印一次时间。

 HCSR04();   //每秒打印一次距离

 oled.clearDisplay();//清除缓存

 oled.setTextSize(2);//字体大小

 oled.setTextColor(1);//字体颜色

 oled.setCursor(32,16);//位置

 oled.print(":");//内容

 oled.print(data);//内容

 oled.print("cm");

 oled.setCursor(32,32);//位置

 oled.print(":");//内容

 oled.print(chongwu1);//宠物

 oled.print("g");

oled.setCursor(32,0);//位置

 oled.print(":");//内容

 oled.setCursor(48,48);//位置

 oled.print(":");//内容

 oled.print(y);//显示喂食物重量

 oled.print("g");//内容

 oled.drawBitmap(0,16,shui,16,16,1);//显示水

 oled.drawBitmap(16,16,shen,16,16,1);//显示深

 oled.drawBitmap(0,32,chong,16,16,1);//显示宠

 oled.drawBitmap(16,32,wu,16,16,1);//显示物

 oled.drawBitmap(0,0,zhuang,16,16,1);//显示状

 oled.drawBitmap(16,0,tai,16,16,1);//显示态

  oled.drawBitmap(0,48,wei,16,16,1);//显示喂

 oled.drawBitmap(16,48,shi,16,16,1);//显示食

 oled.drawBitmap(32,48,wu,16,16,1);//显示物

 if(x==1)

 {

 digitalWrite(Lan,HIGH);//蓝色

 oled.drawBitmap(48,0,zi,16,16,1);//显示自

 oled.drawBitmap(64,0,dong,16,16,1);//显示动

 }

 if(x==2)

 {

 digitalWrite(Hong,HIGH);//红色

 oled.drawBitmap(48,0,shou,16,16,1);//显示手

 oled.drawBitmap(64,0,dong,16,16,1);//显示动

 }

 if(t==1)

 {

oled.drawBitmap(80,0,wei1,16,16,1);//显示未

oled.drawBitmap(96,0,wei,16,16,1);//显示喂

oled.drawBitmap(112,0,shi,16,16,1);//显示养

 }

  if(t==2)

 {

oled.drawBitmap(80,0,yi,16,16,1);//显示已

oled.drawBitmap(96,0,wei,16,16,1);//显示喂

oled.drawBitmap(112,0,shi,16,16,1);//显示养

 }

 oled.display(); //将显存显示到屏幕                            

 if(data<3)//恒定水深4cm

 {

   digitalWrite(relay,HIGH);//继电器

  }

  else

  {

    digitalWrite(relay,LOW);//继电器

  }

  lcd.setCursor(9,1);   //设置1602的光标到第1行第11个字符处

  lcd.print("S:");

  lcd.print(distance_cm);   //在LCD光标所在处打印食物仓库剩余数据量

}

}

 void   shuishen()//水深

  {

 unsigned long currentMillis = millis(); // 存储当前时间

 if (currentMillis - b>= 1000) { // 检查是否经过了 1000ms

 b = currentMillis;  

i=(long)analogRead(water);//A0值  

data=(i/2261)*4;//转换

Serial.print(data);//水深

Serial.println("cm");//

  }

  }

 void chongwu()//宠物

 {

   unsigned long currentMillis = millis(); // 存储当前时间

   if (currentMillis - c>= 1000) { // 检查是否经过了 1000ms

   c= currentMillis;  

   chongwu1 = HX711_CH0.Get_Weight();   //采样当前传感器重量,该重量已经自动去皮,去皮值根据初始化程序中采样的值计算。

   Serial.print(chongwu1);     //串口输出当前重量

   Serial.println(" g");     //单位为g

  }

 }

void  HCSR04()

{

    digitalWrite(TrigPin,LOW);//设置初状态

    delayMicroseconds(2);//发送前准备

    digitalWrite(TrigPin,HIGH);//发送超声波信号

    delayMicroseconds(10);//发送持续时间

    digitalWrite(TrigPin,LOW);//结束发送超声信号

    distance_cm=float(pulseIn(EchoPin,HIGH)*17)/1000;//开始读取并换算成cm

    Serial.print(distance_cm);

    Serial.println("cm");

  }

6效果图

(1)

基于单片机设计智能宠物喂食器_第2张图片

(2)手机端

基于单片机设计智能宠物喂食器_第3张图片

                                                           (3)pc端

基于单片机设计智能宠物喂食器_第4张图片

你可能感兴趣的:(单片机,宠物,嵌入式硬件)