回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

Beetle 树莓派RP2350 智能药盒提醒器 简单

头像 XIA 2025.05.24 76 2

用触摸按键控制药盒开关,OLED显示状态和服药提醒(12H制可自行修改,舵机模拟开盖)

首先特别感谢DF社区给我的机会 让我使用上了RP2350我将用它来制作各种小玩意

本章介绍的是智能药盒提醒器项目


项目简介


触摸控制舵机角度指示器项目
动特性的项目方案:
升级方案:智能药盒提醒器
用触摸按键控制药盒开关,OLED显示状态和服药
提醒,舵机模拟开盖动作
核心功能
1.场景模拟
,短触触摸键:舵机转动90°模拟开盖,OLED显
示”OPEN”和服药提醒
·再次短触:舵机归位关盖,显示”CLOSED"
。长按2秒:进入设置模式,可调整开盖角度
2.视觉反馈
OLED显示药盒状态动画
用药时间到自动闪烁提醒
所需库和安装方法
1.TTP233专用库(非必需,直接读取电平更高效)
2.按钮扩展库:
Arduino IDE搜索安装Bounce2(解决触摸抖动
问题)
3. Adafruit SSD1306(OLED显示)
Arduino IDE中搜索安装:工具→管理库….→搜
索”SSD1306”安装。
4. Servo(舵机控制)
Arduino自带库,无需额外安装。

TTP223触摸按键模块

a71b1f97978f33152c511bbb849ed1b.jpg

08ddc299f49f0dda671f119cb0fd85c.jpg

材料清单

  • TTP223触摸按键模块 X
  • RO2350 X
  • 1.3寸OLED 4针 IIC接口 X
  • SG90舵机 180度 X

接线说明
元件 Arduino引脚
OLED SCL A5
OLED SDA A4
舵机信号线 D9

触摸板输出 A1

舵机电源外接,GND共地

接线图

image.png

接线好后可以使用代码快速验证

代码
void setup(){
  pinMode(2, INPUT);
  Serial.begin(115200);
}
void loop(){
  Serial.print("Touch:");
  Serial.println(digitalRead(2));
  delay(100);
}

I2C扫描工具

使用此程序曲儿OLED地址

代码
#include <Wire.h>
void setup(){
  Wire.begin();
  Serial.begin(115200);
}
void loop(){
  byte error, address;
  for(address=1; address<127; address++){
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if(error==0) Serial.print("Found: 0x");Serial.println(address,HEX);
  }
  delay(5000);
}

一切完毕之后总代码

优化后的程序,支持多级菜单

新增功能说明
1.智能角度校准
自动记录常用开盖角度
防止超过舵机物理限位
2.用药统计
·记录最近7天开盒次数
·用药频率分析
3.安全锁定
·长按启用儿童锁
震动反馈锁定状态

代码
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Servo.h>
#include <Bounce2.h>

#define TOUCH_PIN 2
#define SERVO_PIN 9
#define ANIMATION_FRAMES 8

// OLED图形资源
const unsigned char PROGMEM medIcon[] = { /* 16x16药品图标数据 */ };
const unsigned char PROGMEM settingsIcon[] = { /* 16x16设置图标数据 */ };

enum DisplayMode { MAIN, SETTINGS, STATS };
DisplayMode currentMode = MAIN;

struct SystemState {
  int openAngle = 75;
  int closeAngle = 5;
  int openCount = 0;
  unsigned long nextRemind = 0;
  bool lidLock = false;
} sysState;

Adafruit_SSD1306 display(128, 64, &Wire, -1);
Servo lidServo;
Bounce touchDetector;

void setup() {
  initHardware();
  loadSettings();
  displayWelcome();
}

void loop() {
  handleTouchInput();
  updateReminder();
  refreshDisplay();
}

// 硬件初始化
void initHardware() {
  pinMode(TOUCH_PIN, INPUT);
  touchDetector.attach(TOUCH_PIN);
  touchDetector.interval(10);
  
  lidServo.attach(SERVO_PIN);
  lidServo.write(sysState.closeAngle);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setRotation(2); // 180度旋转显示
}

// 触摸事件处理
void handleTouchInput() {
  static unsigned long lastTap = 0;
  touchDetector.update();

  if(touchDetector.fell()) {
    unsigned long tapInterval = millis() - lastTap;
    
    if(tapInterval < 300) { // 双击
      enterSettings();
      lastTap = 0;
    } else { // 单击
      lastTap = millis();
    }
  }

  if(touchDetector.read() == HIGH && 
     millis() - lastTap > 2000) { // 长按
    toggleLidLock();
    lastTap = 0;
  }
}

// 丝滑舵机动画
void animateServo(int start, int end) {
  float increment = (end - start)/(float)ANIMATION_FRAMES;
  for(int i=0; i<ANIMATION_FRAMES; i++){
    lidServo.write(start + increment*i);
    drawLidProgress(i/(float)ANIMATION_FRAMES);
    delay(30);
  }
}

// 图形界面渲染
void refreshDisplay() {
  display.clearDisplay();
  
  switch(currentMode){
    case MAIN:
      drawMainInterface();
      break;
    case SETTINGS:
      drawSettingsMenu();
      break;
    case STATS:
      drawStatistics();
      break;
  }
  
  display.drawRect(0,0,128,64,WHITE); // 界面边框
  display.display();
}

// 主界面绘制
void drawMainInterface() {
  // 状态图标栏
  display.drawBitmap(2, 2, medIcon, 16, 16, WHITE);
  display.setCursor(20, 6);
  display.printf("%03d", sysState.openCount);
  
  // 药盒主体图形
  display.fillRoundRect(30,15,68,34,5,WHITE);
  
  // 开盖角度指示
  int angleIndicator = map(sysState.openAngle,0,180,42,86);
  display.fillTriangle(angleIndicator-3,52, angleIndicator+3,52, angleIndicator,58, WHITE);
  
  // 下次提醒时间
  display.setCursor(90, 6);
  display.printf("%02d:%02d", hour(sysState.nextRemind), minute(sysState.nextRemind));
}

// 设置菜单
void enterSettings() {
  currentMode = SETTINGS;
  refreshDisplay();
  
  while(!checkExitSettings()){
    // 参数调节逻辑
    // 通过触摸滑动修改数值
  }
  
  saveSettings();
  currentMode = MAIN;
}

还可以加上内存管理优化

代码
// 在setup()中加入内存检测
Serial.print("Free RAM: ");
Serial.println(freeMemory()); // 需安装MemoryFree库

为了显示性能提升,可以将全局刷新改为局部刷新

代码
// 使用局部刷新代替全屏刷新
display.startWrite();
display.setAddrWindow(x, y, w, h);
// 局部绘制操作...
display.endWrite();

为防止舵机大角度转动过热,可以加入舵机保护

代码
// 在animateServo()中添加
if(abs(currentAngle - targetAngle) > 90){
  delay(100); // 大角度转动增加冷却时间
}

可以参考一下渲染的建模图,3D打印还没那么快

设计智能药盒.png
流泪猫猫头 表情包 - 知乎

最后再次郑重感谢FD对我的信任,我非常感谢以及激动能有此次使用机会

虽然我只是一个电子爱好者新手,但依旧对电子热爱,以后我会继续创新,感谢DF

评论

user-avatar
  • 一只想肥的猫

    一只想肥的猫2025.06.16

    可以通用UNO板吗?

    0
    • 一只想肥的猫

      一只想肥的猫2025.06.16

      我草

      0