亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态

组件与物料

Arduino Nano R3 ×1
DFRobot Gravity: 土壤湿度传感器 (模拟量输出) ×1
0.96″ I2C OLED 显示屏 ×1

所需工具

应用与在线服务

项目简介

本项目制作一个能“表达情绪”的智能花盆 😜。通过土壤湿度传感器监测含水量,在 OLED 上显示对应情绪表情。植物需要水分如同我们需要食物,所以这种拟人化表达很有道理 😋。这是一个有趣的小项目,能直观监控花盆湿度。

花盆根据水位显示不同情绪表情。

完成后你将学会:

硬件部分

花盆结构设计

先要有花盆。我用 Fusion 360 设计了带电子仓的花盆,有 3D 打印机可自行打印;没有也没关系,任意花盆加个电子盒即可。

EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态
EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态
EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态
EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态
EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态
EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态
EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态

电子连接:

  • Arduino A5 → OLED SCL
  • Arduino A4 → OLED SDA
  • Arduino A0 → 土壤湿度传感器 AO

编程部分

代码看似繁杂实则简单。开头引入库 (可能需手动安装):

  • Adafruit_GFX.h
  • Adafruit_SSD1306.h

为每种情绪表情的每一帧动画编写函数 (相信我这非常耗时)。setup() 初始化显示屏。loop() 中 sensorValue = analogRead(A0); 读取传感器,根据湿度阈值分段播放对应情绪动画帧。

不同湿度下的情绪表情演示

(视频演示)

完整代码


#include 
#include 
#include 
#include 
#include 

#define OLED_RESET 0
Adafruit_SSD1306 display(OLED_RESET);

int sensorValue = 0;
int xx = 40;

/****************************************** SAD (难过) ****************************************************/
// 12 帧难过动画帧数据 (frame01 ~ frame121),每帧 128×64 位图数组
// 此处省略冗长数组,完整代码见附件下载
const unsigned char PROGMEM frame01 [] = { ... };
const unsigned char PROGMEM frame011 [] = { ... };
const unsigned char PROGMEM frame21 [] = { ... };
const unsigned char PROGMEM frame31 [] = { ... };
const unsigned char PROGMEM frame41 [] = { ... };
const unsigned char PROGMEM frame51 [] = { ... };
const unsigned char PROGMEM frame61 [] = { ... };
const unsigned char PROGMEM frame71 [] = { ... };
const unsigned char PROGMEM frame81 [] = { ... };
const unsigned char PROGMEM frame91 [] = { ... };
const unsigned char PROGMEM frame101 [] = { ... };
const unsigned char PROGMEM frame111 [] = { ... };
const unsigned char PROGMEM frame121 [] = { ... };
// const unsigned char PROGMEM frame131 [] = { ... };

/************************************************* SMILE (微笑) *************************************************/
const unsigned char PROGMEM frame02 [] = { ... };
const unsigned char PROGMEM frame012 [] = { ... };
const unsigned char PROGMEM frame22 [] = { ... };
const unsigned char PROGMEM frame32 [] = { ... };
const unsigned char PROGMEM frame42 [] = { ... };
const unsigned char PROGMEM frame52 [] = { ... };
const unsigned char PROGMEM frame62 [] = { ... };
const unsigned char PROGMEM frame72 [] = { ... };
const unsigned char PROGMEM frame82 [] = { ... };
const unsigned char PROGMEM frame92 [] = { ... };
const unsigned char PROGMEM frame102 [] = { ... };
const unsigned char PROGMEM frame112 [] = { ... };
const unsigned char PROGMEM frame122 [] = { ... };
const unsigned char PROGMEM frame132 [] = { ... };

/************************************** NEUTRAL (平静) ***************************************************/
const unsigned char PROGMEM frame03 [] = { ... };
const unsigned char PROGMEM frame013 [] = { ... };
const unsigned char PROGMEM frame23 [] = { ... };
const unsigned char PROGMEM frame33 [] = { ... };
const unsigned char PROGMEM frame43 [] = { ... };
const unsigned char PROGMEM frame53 [] = { ... };
const unsigned char PROGMEM frame63 [] = { ... };
const unsigned char PROGMEM frame73 [] = { ... };
const unsigned char PROGMEM frame83 [] = { ... };

/*************************************** BLUSHING (害羞) **************************************************************/
const unsigned char PROGMEM frame04 [] = { ... };
const unsigned char PROGMEM frame14 [] = { ... };
const unsigned char PROGMEM frame24 [] = { ... };
const unsigned char PROGMEM frame34 [] = { ... };
const unsigned char PROGMEM frame44 [] = { ... };
const unsigned char PROGMEM frame54 [] = { ... };
const unsigned char PROGMEM frame64 [] = { ... };
const unsigned char PROGMEM frame74 [] = { ... };
const unsigned char PROGMEM frame84 [] = { ... };
const unsigned char PROGMEM frame94 [] = { ... };

/**************************************************** CRYING (哭泣) **********************************************/
const unsigned char PROGMEM frame05 [] = { ... };
const unsigned char PROGMEM frame15 [] = { ... };
const unsigned char PROGMEM frame25 [] = { ... };
const unsigned char PROGMEM frame35 [] = { ... };
const unsigned char PROGMEM frame45 [] = { ... };
const unsigned char PROGMEM frame55 [] = { ... };
const unsigned char PROGMEM frame65 [] = { ... };
const unsigned char PROGMEM frame75 [] = { ... };
const unsigned char PROGMEM frame85 [] = { ... };
const unsigned char PROGMEM frame95 [] = { ... };

// 困惑表情
const unsigned char PROGMEM framec [] = { ... };

/********************************************************************************************************************************/
void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setFont(&FreeSans9pt7b);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
}

void loop() {
  sensorValue = analogRead(A0); // 读取土壤湿度

  if (sensorValue >= 80 && sensorValue < 250) { 
    // 微笑 - 土壤湿润
    display.clearDisplay(); display.drawBitmap(xx, 0, frame02, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame012, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame22, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame32, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame42, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame52, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame62, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame72, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame82, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame92, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame102, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame112, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame122, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame132, 48, 48, 1); display.display(); delay(30);
  } 
  else if (sensorValue >= 250 && sensorValue < 350) { 
    // 害羞 - 湿度适中偏高
    display.clearDisplay(); display.drawBitmap(xx, 0, frame04, 48, 48, 1); display.display(); delay(50);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame14, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame24, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame34, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame44, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame54, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame64, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame74, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame84, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame94, 48, 48, 1); display.display(); delay(70);
  } 
  else if (sensorValue >= 350 && sensorValue < 550) { 
    // 平静 - 理想湿度区间
    display.clearDisplay(); display.drawBitmap(xx, 0, frame03, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame013, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame23, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame33, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame43, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame53, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame63, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame73, 48, 48, 1); display.display(); delay(60);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame83, 48, 48, 1); display.display(); delay(500);
  } 
  else if (sensorValue >= 550 && sensorValue < 700) { 
    // 难过 - 缺水
    display.clearDisplay(); display.drawBitmap(xx, 0, frame011, 48, 48, 1); display.display(); delay(50);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame21, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame31, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame41, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame51, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame61, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame71, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame81, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame91, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame101, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame111, 48, 48, 1); display.display(); delay(70);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame121, 48, 48, 1); display.display(); delay(100);
  } 
  else if (sensorValue >= 700 && sensorValue < 800) { 
    // 哭泣 - 严重缺水
    display.clearDisplay(); display.drawBitmap(xx, 0, frame05, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame15, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame25, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame35, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame45, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame55, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame65, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame75, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame85, 48, 48, 1); display.display(); delay(30);
    display.clearDisplay(); display.drawBitmap(xx, 0, frame95, 48, 48, 1); display.display(); delay(70);
  } 
  else { 
    // 困惑 - 传感器异常或超量程
    display.clearDisplay(); display.drawBitmap(xx, 0, framec, 48, 48, 1); display.display(); delay(30);
  }
}

3D 打印模型

花盆 3D 模型文件见附件。

原理图

EmoPot:会“表达情绪”的智能花盆,可视化植物健康状态

制造工艺

  1. 萨斯奎哈纳核电站完成计划性维护,二号机组恢复发电
  2. 挖掘机全解析:类型、用途与选型指南
  3. 冲模必须更换的五大铁律信号
  4. 延长冲床与冲压工具寿命的核心策略
  5. 磨床 5 大核心加工操作详解:从平面到成形磨削
  6. 10 个利用 3D 打印的创新 DIY 开源项目
  7. 原子钟芯片技术破解包裹盗窃难题:实时追踪、成本仅几美分、明年量产
  8. AI赋能气味检测:Aryballe技术革新商业与供应链
  9. 发电机升级信号全解析:7 大关键指标判断更换时机
  10. 影响CNC制造成本的关键因素(第二部分)
  11. 预防叉车事故:零翻车、零伤害的实操安全指南
  12. 定制机加工件在四大维度超越标准件