Bộ nhả snack (có “twist”) – Treat dispencer (with a twist)

Bộ nhả snack cho thú cưng: mỗi lần bấm là ra 1 phần. Nếu bấm 3 lần trong vòng 5 phút sẽ vào chế độ Overfed, LED đỏ nhấp nháy và bấm tiếp sẽ bị xịt nước. Hết 30 phút sẽ trở lại bình thường.

👁️
532
Lượt Xem
❤️
18
Lượt Thích
📥
19
Lượt Tải
Cập Nhật May 02, 2026
Chi tiết
Tải xuống
Bình Luận
Khoe bản in
Remix

Mô tả

Bộ nhả snack đặc biệt này cho thú cưng của bạn được ăn món khoái khẩu, nhưng chỉ tới một mức nhất định. Nếu nó ăn quá nhiều thì sẽ phải chờ, và nếu vẫn cố bấm để lấy thêm, nó sẽ bị xịt một ít nước thẳng vào mặt.

Logic của dự án:

  • Mỗi lần nhấn nút – sẽ nhả ra 1 phần snack.
  • Nếu nút được nhấn 3 lần mà không có khoảng cách 5 phút giữa các lần nhấn – chế độ Overfed sẽ bật.
  • Khi đang ở chế độ overfed, đèn LED đỏ sẽ nhấp nháy. Nếu nhấn nút khi overfed đang bật, thay vì nhả snack – hệ thống sẽ xịt nước.
  • Sau 30 phút kể từ khi chế độ overfed bắt đầu, nó sẽ kết thúc, và nhấn nút sẽ nhả snack lại như bình thường.

component

amount

Arduino uno

1

Small 5v pump

1

Servo motor

1

Red led

2

push button

1

330 ohm resistor

1

Software:

tôi dùng Fusion360 để thiết kế dự án này.

Code:

Code được viết bằng phần mềm arduino IDE, đoạn code:

#include <Servo.h>

// Pins
const int leverPin = 7;      // Lever sensor (button/microswitch)
const int ledPin = 8;        // Red LED (changed to pin 8)
const int waterPin = 5;      // Water spray relay
const int servoPin = 6;      // Treat dispenser servo

// Timing settings
const unsigned long treatWindow = 300000;   // 5 minutes in ms
const unsigned long cooldownTime = 1800000; // 30 minutes in ms (adjust up to 60 min if needed)
const unsigned long sprayDuration = 150;   // 0.2 second spray
const unsigned long leverDebounce = 500;    // ms to prevent double-counting pulls
const unsigned long ledBlinkInterval = 500; // Blink interval for LED in ms

Servo treatServo;

// Tracking variables
int treatCount = 0;
unsigned long firstTreatTime = 0;
bool overfed = false;
unsigned long overfedStart = 0;
unsigned long lastBlinkTime = 0;
bool ledState = false;

void setup() {
  pinMode(leverPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  pinMode(waterPin, OUTPUT);
  treatServo.attach(servoPin);
  treatServo.write(78);
  digitalWrite(ledPin, LOW);
  digitalWrite(waterPin, LOW);

  Serial.begin(9600);
}

void loop() {
  // Read lever state (active LOW if using pullup)
  if (digitalRead(leverPin) == LOW) {
    delay(leverDebounce);  // debounce
    handleLeverPull();
    while (digitalRead(leverPin) == LOW); // wait until released
  }

  // Handle blinking LED while overfed
  if (overfed) {
    if (millis() - lastBlinkTime >= ledBlinkInterval) {
      ledState = !ledState;
      digitalWrite(ledPin, ledState ? HIGH : LOW);
      lastBlinkTime = millis();
    }
  }

  // Reset overfed state after cooldown
  if (overfed && millis() - overfedStart >= cooldownTime) {
    overfed = false;
    treatCount = 0;
    digitalWrite(ledPin, LOW);
    ledState = false;
    Serial.println("Cooldown complete. System reset.");
  }
}

void handleLeverPull() {
  Serial.println("Lever pulled");

  // If in overfed state, spray water
  if (overfed) {
    Serial.println("Overfed: spraying water");
    sprayWater();
    return;
  }

  // Dispense treat
  dispenseTreat();

  unsigned long now = millis();

  // If first treat, start the window
  if (treatCount == 0) {
    firstTreatTime = now;
    treatCount = 1;
    Serial.println("First treat");
  } else if (now - firstTreatTime <= treatWindow) {
    treatCount++;
    Serial.print("Treat count in window: ");
    Serial.println(treatCount);

    if (treatCount >= 3) {
      overfed = true;
      overfedStart = now;
      lastBlinkTime = now;
      digitalWrite(ledPin, HIGH);
      ledState = true;
      Serial.println("Overfed state activated. Red LED blinking.");
    }
  } else {
    // Outside of time window, reset count
    firstTreatTime = now;
    treatCount = 1;
    Serial.println("Time window expired. Restarting count.");
  }
}

void dispenseTreat() {
  treatServo.write(115);  // Open position (adjust as needed)
  delay(500);
  treatServo.write(75);   // Close position
  Serial.println("Treat dispensed.");
}

void sprayWater() {
  digitalWrite(waterPin, HIGH);
  delay(sprayDuration);
  digitalWrite(waterPin, LOW);
  Serial.println("Water spray complete.");
}

3D print:

  • Mình dùng PLA cho dự án này, cho tất cả các chi tiết.
  • Infill khoảng 15% cho mỗi bản in.
  • Support sẽ thay đổi tùy theo từng chi tiết.

Giấy phép

Tác phẩm này được cấp phép theo

Creative Commons — Attribution — Noncommercial

CC-BY-NC

Yêu cầu ghi công
Remix & phái sinh Được phép
Sử dụng thương mại Không được phép

File mô hình

TẤT CẢ FILE MÔ HÌNH (22 Tập tin)
Đang tải files, vui lòng chờ...
Vui lòng đăng nhập để bình luận.

Chưa có bình luận nào. Hãy là người đầu tiên!

Vui lòng đăng nhập để khoe bản in của bạn.

Chưa có bản in nào được khoe. Hãy là người đầu tiên!

Remix (0)