DIY 智能糖果分配机:Arduino + 舵机 + 红外传感器
组件与供应
| Arduino UNO | ×1 |
| 180° 舵机 | ×1 |
| 16x2 I2C LCD 液晶屏 (白字蓝底) | ×1 |
| 12mm 按钮开关 | ×2 |
| PHPoC 扩展板 (可选,用于网络功能) | ×1 |
| 红外避障/测距传感器 | ×1 |
| 电源开关 | ×1 |
| 面包板 | ×1 |
所需工具
- 电烙铁
软件
- Arduino IDE
项目介绍
项目概述
这是一个简易的糖果分配机,核心部件仅需:红外传感器检测杯子、舵机控制出糖、按钮选择份量。制作步骤分为:硬件组装、Arduino 编程、外壳与机械结构制作、电子安装、测试使用。
代码编写是最大挑战,参考了 gatoninja236 的作品 并简化实现。
外壳与机械结构制作
步骤 1:布局元件
在纸板上摆放所有元件,用不同颜色导线区分,便于测试和排错。
步骤 2:设计盒子尺寸
- 正面/背面:20cm × 16cm (背面用亚克力板)
- 侧面:12cm × 16cm
- 顶部/底部:20cm × 12cm
步骤 3:组装与开孔
用美纹纸胶带临时固定,确认尺寸后再永久粘接。开孔尺寸:
- LCD:7.2cm × 2.5cm
- 按钮:1.2cm × 1.2cm
- 糖果杯槽:9cm × 12cm (长×高),9cm × 9cm (宽×深)
- 红外传感器孔位
设计阶梯状出糖口,防止糖果一次掉落过多。
步骤 4:电路板安装
面包板与 Arduino 叠放,用亚克力固定,节省空间。
步骤 5:元件安装
依次安装 LCD、按钮、舵机、电源开关,理线整齐。
步骤 6:完成外观
最终成品外观展示。
代码说明
代码使用 Wire.h、LiquidCrystal_I2C.h、Servo.h 库。两个按钮分别对应“少量”和“大量”两种出糖模式,按下后提示放杯,红外检测到杯子后驱动舵机旋转出糖,完成后显示“Thank You”并软件复位重置。
//------LIBRARIES-----
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
//------LIBRARIES-----
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myservo;
int pos = 90;
int buttonCLK = 7;
int buttonAntiCLK = 6;
int set = 0;
const int avoidPin = 5;
void setup() {
lcd.begin();
lcd.clear();
myservo.attach(9);
pinMode(buttonCLK, INPUT);
pinMode(buttonAntiCLK, INPUT);
pinMode(avoidPin, INPUT);
Serial.begin(9600);
lcd.backlight();
lcd.setCursor(3,0); lcd.print("Welcome to");
lcd.setCursor(3,1); lcd.print("Candy Land");
delay(2000);
lcd.clear();
lcd.setCursor(0,0); lcd.print("How much candy?");
lcd.setCursor(0,1); lcd.print("A Little A Lot");
delay(5000);
}
void loop() {
if(digitalRead(buttonCLK) == HIGH) {
lcd.clear(); lcd.print("Please Place Cup"); delay(2000); lcd.clear(); set = 1;
}
if(digitalRead(buttonAntiCLK) == HIGH) {
lcd.clear(); lcd.print("Please Place Cup"); delay(2000); lcd.clear(); set = 2;
}
if(set == 1) IRCLK();
if(set == 2) IRAntiCLK();
}
void TurnClockwise() {
Serial.println("Candy 1 Being Dispensed");
CandyText1();
for(pos = 90; pos < 180; pos += 1) { myservo.write(pos); delay(15); }
if(pos == 180) { delay(2000); ThankYouText(); }
}
void TurnAntiClockwise() {
Serial.println("Candy 2 Being Dispensed");
CandyText2();
for(pos = 90; pos < 180; pos += 1) { myservo.write(pos); delay(20); }
if(pos == 180) { delay(3000); ThankYouText(); }
}
void IRCLK() {
delay(1000);
boolean avoidVal = digitalRead(avoidPin);
lcd.setCursor(0,0); lcd.print("Detecting Cup");
lcd.setCursor(0,14); lcd.print("...");
if(avoidVal == LOW) { lcd.clear(); lcd.print("Cup Placed"); delay(2000); TurnClockwise(); }
}
void IRAntiCLK() {
delay(1000);
boolean avoidVal = digitalRead(avoidPin);
lcd.setCursor(0,0); lcd.print("Detecting Cup");
lcd.setCursor(0,14); lcd.print("...");
if(avoidVal == LOW) { lcd.clear(); lcd.print("Cup Placed"); delay(2000); TurnAntiClockwise(); }
}
void CandyText1() { lcd.clear(); lcd.setCursor(4,0); lcd.print("Pouring"); lcd.setCursor(1,1); lcd.print("Little Candy"); }
void CandyText2() { lcd.clear(); lcd.setCursor(4,0); lcd.print("Pouring"); lcd.setCursor(3,1); lcd.print("Lot Candy"); }
void ThankYouText() { lcd.clear(); lcd.setCursor(5,0); lcd.print("Thank"); lcd.setCursor(6,1); lcd.print("You"); delay(15); software_Reset(); }
void software_Reset() { asm volatile ("jmp 0"); }
原理图
按颜色连线即可,原理图见项目附件。
制造工艺