산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

쉽게 조립할 수 있는 애완동물 사료 공급기

구성품 및 소모품

Arduino Nano R3
소형 하우징을 사용하려면 Arduino Nano를 사용하는 것이 가장 좋습니다.
× 1
Adafruit 실시간 시계
× 1
연속 회전 서보
× 1
시리얼 디스펜서
× 1
홀 센서 UNIPOLAR
× 1
막대 자석 3mm 지름, 5mm 길이
× 6
Adafruit RGB 백라이트 LCD - 16x2
× 1
lcd i2c 배낭
× 1
Apem 푸시 버튼 순간 IP67
× 1
작은 푸시 버튼 순간
× 1
LED(일반)
× 6
플랜지가 있는 Hammond Multi ABS 하우징
× 1

앱 및 온라인 서비스

LCD 문자 생성기

이 프로젝트 정보

업데이트 2018-09-06

내 두 개의 애완 동물 모이통은 지난 7 개월 동안 완벽하게 작동합니다. 우리는 낮 동안 애완 동물을 돌보지만 이제는 정기적으로 사료를 먹습니다. 시스템에 매우 만족합니다!

왜 또 다른 펫 피더인가?

애완 동물 사료 공급기의 내 버전은 Arduino 마이크로 컨트롤러를 기반으로 합니다. 사용한 재료가 비교적 저렴하고 만들기도 쉬운 것 같아요!

물론 주변에 많은 버전이 있지만 필요한 기능으로 빌드할 준비가 된 완전한 프로젝트를 찾을 수 없었기 때문에 처음부터 시작했습니다.

기능은 다음과 같습니다.

<울>
  • *정확한 분량*이 매번 배달됩니다! (홀 센서 사용)
  • 하루에 두 번 먹이기
  • *매우* 정확한 실시간 시계(정품 DS3231 칩만 해당)
  • 디스플레이와 LED 표시기가 있는 두 타이머에 대해 예정된 수유를 개별적으로 취소할 수 있습니다. 취소는 설정한 시간이 지나면 자동으로 리셋됩니다.
  • 수동 공급 기능(버튼 누름당 한 부분)
  • 두 번의 급식 시간에 따라 조절 가능한 양(1-9인분)
  • 메인 화면의 모든 설정 매개변수 개요
  • 손쉬운 메뉴 시스템 탐색
  • 수유 성공 시 LED 표시
  • LCD 백라이트 타이머(30초 후 꺼짐, 아무 버튼이나 누르면 켜짐)
  • 시간 및 기타 설정은 메모리(EEPROM)에 안전하게 저장됩니다.
  • 데모 비디오:

    동영상은 여기를 클릭하세요

    자세한 설명 동영상:여기를 클릭하세요

    슬로우 모션 액션의 펫 피더! 여기를 클릭하세요

    사진:

    필요한 부품:

    <울>
  • 1x 시리얼 디스펜서(Ebay에서 저렴)
  • 시리얼 디스펜서 마운트를 만들기 위한 나무 조각
  • 1x Arduino Uno
  • 1x I2C DS3231(매우 정확함) 또는 DS1307 실시간 클록
  • 1x LCD 디스플레이 16자/2줄
  • LCD 디스플레이용 I2C 백팩 1개
  • 1x 회전 서보 계속 (좋은 것을 사세요!)
  • 1x Honeywell SS443R 단극 홀 센서
  • 1x 12Volts/1 Amp 외부 전원 공급 장치(벽 사마귀)
  • 7x 푸시 버튼 - 순간
  • LED 6개(빨간색 2개, 녹색 3개, 노란색 1개)
  • 2x 저항 1KΩ(빨간색 LED용)
  • 4x 저항 560Ω(녹색 및 노란색 LED용)
  • 전자 제품용 인클로저 1개
  • 외부 서보와 홀 센서를 연결하기 위한 전원 플러그 암 및 커넥터
  • 많은 HOT GLUE.
  • 가능하면 서보에 더 높은 전압을 사용하는 것이 가장 좋습니다. 더 많은 힘! 내 HSR-2645CRH 서보는 7,4볼트를 사용할 수 있으므로 이 작업도 수행하려면 다음이 필요합니다.

    <울>
  • 성능 보드
  • LM317T 가변 전압 조정기
  • 출력 전압을 설정하기 위한 3개의 저항(1KΩ, 150kΩ 및 4K7)
  • 2개의 극성 커패시터(220µF, 10µF)
  • 방열판 필요 없음, 서보는 매일 1-2초만 회전합니다;)
  • 온라인에서 많은 LM317 계산기를 찾을 수 있습니다.

    애완동물 사료 용기

    가장 저렴하고 사용하기 쉬운 시리얼 디스펜서는 많은 상점과 Ebay에서 찾을 수 있습니다. Ebay에서 배송료 포함 15유로에 듀얼 시리얼 디스펜서를 구입했습니다(영국에서 네덜란드로)

    문제는 피더용 거치대를 만드는 것이었고 인터넷을 둘러봐도 별로 도움이 되지 않아 창고를 둘러보다 아름다운 삼나무 조각을 발견했습니다.

    플라스틱 시리얼 디스펜서를 잡고 있는 나무는 두께가 3cm라 흔들림이 없어요! 구멍(내 피더 베이스는 86mm)이 꽉 조여져 있는지 확인해야 하므로 드릴링 전에 측정하십시오! 너무 큰 구멍보다 작은 구멍을 뚫고 모양을 만드는 것이 좋습니다.

    사진을 보고 왜 그리고 어떻게 함께 어울리는지 알아보세요.

    디스펜서 패들 휠에 대한 서보 및 부착물

    좋은 서보를 구입하십시오. 먼저 연속 회전을 위해 수정한 MG996R 서보를 구입했지만 돈 낭비였습니다... 그런 다음 고품질의 서보를 얻었습니다. 제 경우에는 HSR-2645CRH Servo

    연속 회전 모델이어야 합니다!! 저처럼 일반 서보를 수정하려고 하지 마세요. 성능이 거의 좋지 않았으며 중지할 때 즉각적이지 않았습니다.

    서보 시험의 비디오:여기를 클릭하십시오

    디스펜서 패들 휠에 대한 서보 연결

    이제 질문이 생겼습니다. 서보를 피더 패들 휠에 연결하는 방법은 무엇입니까? 처음에는 프로젝트에서 가장 어려운 부분처럼 보였지만 실제로는 매우 간단했습니다.

    나는 5mm 폴리카보네이트 조각을 가지고 프렛쏘로 약 6cm의 원형 디스크를 잘라냈습니다. 중앙에 8mm의 구멍을 뚫었습니다(피더 축의 두께. 이 플라스틱 축은 패들 휠에서 제거 가능)

    바깥쪽에는 자석 두께인 3mm의 구멍 6개를 뚫습니다. 이것은 피더 페달 휠의 위치에 대한 Arduino 피드백을 제공하는 데 사용됩니다.

    패들 휠에는 6개의 고무 패들이 있기 때문에 6개의 자석을 사용하여 폴리카보네이트 디스크의 가장자리에 분할했습니다. 360도를 6으로 나누면 60도입니다. 막대 자석이 꼭 맞을 것입니다.

    홀 센서는 6개의 자석을 각각 감지하여 해당 정보를 사용하여 패들 휠을 정확하게 위치시키고 정지시킬 수 있습니다. 서보 정지 지연 시간 변수는 이후 지연을 추가하는 데 사용됩니다. 먹이기, 중단하기 전 서보. 따라서 이 지연으로 패들 휠의 정확한 위치를 조정할 수 있습니다. 이것은 '정지' 위치가 잘못된 경우 피드가 패들 휠을 완전히 벗어나지 않기 때문에 중요합니다. 또한 홀 센서의 위치는 경우에 따라 다를 수 있습니다. 서보 정지 지연 가변 시간을 조정하면 해결됩니다.

    이제 패들 휠 축을 폴리카보네이트 디스크에 붙일 수 있습니다.

    흰색 원형 서보 혼은 3개의 M3 볼트로 폴리카보네이트 디스크에 볼트로 고정되어 있습니다. 여분의 너트를 스페이서로 사용하고 너무 조이지 마십시오!

    이제 서보는 피더 어셈블리의 일부이므로 나무 마운트에 넣고 서보 아래의 나무 조각 높이를 측정할 수 있습니다.

    홀 센서

    제가 사용한 홀센서는 UNIPOLAR 타입입니다. 자석이 근처에 있고 출력을 다시 HIGH로 재설정하기 위해 자석의 역 극성이 필요하지 않은 경우 LOW 출력을 제공합니다. 따라서 Unipolar 홀 센서를 사용하면 훨씬 쉽습니다.

    <코드>!!! 홀 센서에는 10KΩ 풀업 저항이 필요합니다.

    홀 센서 바로 위에 0805 SMD 저항을 장착했지만 원하는 대로 할 수 있습니다. 이 저항기를 잊지 마세요!

    그런 다음 오래된 볼펜을 가지고 플라스틱을 센서 홀더로 사용했습니다.

    전자 하우징

    플랜지가 있는 Hammond ABS 하우징을 사용했습니다. 120 x 65 x 40mm

    외부 연결을 위해 저렴한 중국산 커넥터가 아닌 암 정밀 소켓 커넥터를 사용했습니다. 저는 모든 프로젝트에서 이것을 많이 사용합니다. (찾기 힘든) 실패를 일으키는 잘못된 연결보다 더 나쁜 것은 없습니다.

    Arduino 프로그래밍을 더 쉽게 하기 위해 외부 FTDI 연결이 있습니다.

    전면 패널

    싸고 예쁜 전면패널을 만들기 위해 많은 노력을 했습니다...

    먼저 Mod Podge를 사용하여 하우징 전면에 종이 레이저 프린트를 붙이고 더 많은 Mod Podge로 덮었습니다. --> 실패

    그런 다음 폴리우레탄 아크릴레이트 분산액을 기반으로 한 투명 바니시를 사용해 보았습니다. 건조시 내구성이 매우 강합니다. 나는 하우징에 종이를 아주 잘 붙였고 전면 패널 인쇄물의 윗면을 바니싱한 것은 매우 좋아 보였지만 인쇄물의 레이저 프린터 토너 부분에 붙지 않을 것입니다. --> 실패

    그 후 전면 패널의 레이저 프린트를 가져와서 상판만 라미네이팅 pcv로 라미네이팅 했습니다. 매우 좋은 마감 처리로 전면을 보호하고 색상을 아름답게 들어 올립니다. 그런 다음 다시 라미네이트 용지를 바니시로 하우징에 붙였습니다. 내 생각은 바니시가 종이에 스며들어 방수가 되는 것이었습니다. 하지만 작동하지 않는 두꺼운 종이를 사용하고 방수 기능을 테스트하기 위해 젖게 했기 때문에 종이가 하우징에서 말렸습니다. --> 부분적으로 실패했습니다. 추가 조사가 필요합니다.

    또 다른 시도:레이저 인쇄용 특수 알루미늄 호일을 구입했습니다. 한 장에 2,25유로. 결과는 좋았지만 특별한 투명 호일로 토너를 보호하고 싶었습니다. 사진 1에서 보듯이 불완전한 부분을 제거하지 못했기 때문에 성공하지 못했습니다:

    그런 다음 투명 바니시로 보호하려고 한 번 더 시도하여 알루미늄 호일을 매우 고광택으로 만들었습니다! 하지만... 역시나 바니쉬가 토너에 잘 붙지 않아 바니쉬를 영구적으로 포기했습니다...

    마지막으로... 보호 장치 없이 호일 인쇄를 사용했습니다... 자주 처리하면 진저 인쇄가 보일 것입니다(이 페이지 상단의 사진에서 BACK 버튼 아래, 닭 사료의 하우징 참조). 그래서 이상적이지는 않지만 여전히 좋습니다. 충분합니다.

    더 많은 사진은 허용되지 않습니다.

    그게 다야... 있다 재미있어요!

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • Pet Feed-O-Matic v 1.1 - 2018년 2월 20일
  • Pet Feed-O-Matic v 1.1 - 2018-02-20Arduino
    v 1.1:Cancel1 또는 2 버튼을 누르면 설명이 표시됩니다.
    // c++ stuff...//#include //#line 1//#line 1 "/Users/Erik/Documents/ PlatformIO/Projects/180202-151127-uno/src/Pet_Feeder_1_1_ENG.cpp"/* _ _ /\ | | (_) / \ _ __ __| |_ _ _ _ __ ___ / /\ \ | '__/ _` | | | | | '_ \ / _ \ / ____ \| | | (_| | |_| | | | | | (_) | /_/ \_\_| \__,_|\__,_|_|_| |_|\___/ _____ _ ______ _ | __ \ | | | ____| | | | |__) |__| |_ | |__ ___ ___ __| | ___ _ __ | ___/ _ \ __| | __/ _ \/ _ \/ _` |/ _ \ '__| | | | __/ |_ | | | __/ __/ (_| | __/ | |_| \___|\__| |_| \___|\___|\__,_|\___|_| 에릭 드 루이터 -------- -------------------------------------------------- ------------------- 해야 할 일:- 원격 급지? - 메뉴 편집 가능한 항목으로 피더 정지 지연 마지막 변경:dinsdag 20 2월 2018 - 17:20:28 기능:- *정확한 양* 매번!(홀 센서 사용) - 하루에 한 번 두 번 급식 - *매우* 정확한 실시간 시계(정품 DS3231 칩만 해당) - 디스플레이와 LED 표시기가 있는 두 타이머에 대해 개별적으로 예정된 급식 취소 . 시간 경과 후 자동 리셋 - 수동 급지 기능(버튼 누름당 1인분) - 2회 급이 각각에 대해 조정 가능한 부분(1-9인분) - 메인 화면에서 모든 설정 매개변수 개요 - 간편한 메뉴 탐색 시스템 - 급지 성공 시 LED 표시 - LCD 백라이트 타이머(30초 후 꺼짐, 아무 버튼이나 누르면 켜짐) - 홀 센서 고장 시 백업 - 홀 센서가 작동하면 Hass 센서 LED가 자정까지 깜박입니다. 실패 - 시간 및 기타 설정은 EEPROM 웹사이트에 안전하게 저장됩니다. LCD HD44780 문자 생성기 웹사이트에서 나만의 LCD 기호를 만들 수 있습니다. https://omerk.github.io/lcdchargen/ Arduino 스케치 큰 글자 주석 생성기 http://patorjk.com /software/taag/#p=display&c=c%2B%2B&f=Big&t=댓글 수정:zondag 2018년 1월 28일 - 20:17:10 *////////////////// ////////////////////////////////////////////////////// /////////////// 사용자 변경 가능 변수///////////////////////////////// ////////////////////////////////////////////////////// 홀 센서 실패 백업 기능에 사용됩니다. // 간격 시간은 피더의 60도 회전보다 약간 커야합니다. // 피더 (한 부분) #define HALL_SENSOR_BACKUP_VALUE 300// 피더 서보가 피더를 멈추기 전에 지연. 이렇게 하면// 회전하는 페달 휠이 올바른 위치에서 멈추게 할 수 있습니다.#define FEEDER_STOP_DELAY 100// 버튼을 누른 후 lcd 백라이트가 켜지도록 합니다.#define LCD_BACKLIGHT_ON_TIME 30000// ms#define에 설정된 시간 초과 후 저장하지 않고 메뉴를 종료합니다. MENU_TIMEOUT_VALUE 7000///////////////////////////////////////////////// ///////////////////////////////// https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C- 라이브러리#include // https:// github.com/JChristensen/Button#include // http:// github.com/JChristensen/DS3232RTC#include // http:// www.arduino.cc/playground/Code/Time#include // http:// arduino.cc/en/Reference/Wire (Arduino IDE에 포함)#include  #include // CONNECTIONS://// LCD (I2C 모듈):// SCL - A5// SDA - A4// VCC// GND// 인터럽트 hal 센서 핀#define HALL_SENSOR_PIN 3#define BUTTON_BACK_PIN 4#define BUTTON_UP_PIN 5#define BUTTON_DOWN_PIN 6#define BUTTON_SELECT_PIN 7#define BUTTON_CANCEL1_PI N 8#define BUTTON_CANCEL2_PIN 9#define BUTTON_MANUAL_PIN 10#define LED_CANCEL1_PIN A0#define LED_CANCEL2_PIN A1#define LED_SUCCESS1_PIN_PIN A2#define LED_SUCCESS1_PIN_PIN A2#define LED_SUCCESS2_PIN 주소 정의 LED_SUCCESS2_PIN A3//피더 핀 서보 출력 정의 (16x2) 0x27 또는 0x3FLiquidCrystal_I2C lcd(0x3F, 16, 2);// 버튼 라이브러리 설정 정의// 20밀리초의 디바운스 시간은 일반적으로 촉각 버튼 스위치에 잘 작동합니다.// 반복하기 전에 DEBOUNCE_MS 20//ms 필요 길게 누르기#define REPEAT_FIRST 1000// 길게 누르기 반복 간격#define REPEAT_INCR 200// 간단하게 하기 위해 Arduino의 내부 풀업 저항을 사용합니다.#define PULLUP true#define INVERT true// 버튼을 선언합니다.Button buttonSelect (BUTTON_SELECT_PIN, PULLUP , INVERT, DEBOUNCE_MS);버튼 버튼 위로(BUTTON_UP_PIN, PULLUP, INVERT, DEBOUNCE_MS);버튼 아래로 버튼(BUTTON_DOWN_PIN, PULLUP, INVERT, DEBOUNCE_MS);버튼 뒤로 버튼(BUTTON_BACK_PIN, PULLUP, INVERT_MS) 버튼 이전 버튼 취소1(BUTTON_CANCEL1_PIN, PULLUP, INVERT, DEBOUNCE_MS); 버튼 버튼 취소2(BUTTON_CANCEL2_PIN, PULLUP, INVERT, DEBOUNCE_MS); 버튼 버튼 수동(BUTTON_MANUAL_PIN, PULLUP, INVERT_); count (스케치가 시작될 때 다르다는 것을 보장하기 위해 초기화됨)int lastCount =-1;// 긴 누름에 대한 반복을 구동하는 데 사용되는 가변 시간unsigned long rpt =REPEAT_FIRST;// 메뉴 시간 초과 unsigned long timeoutValue =0;// 수동 취소 공급 시간 변수boolean manualCancelFeed1 =false;boolean manualCancelFeed2 =false;// 수동 공급 optionboolean manualFeed =false;// 공급량(단위)int feedAmount1 =1;int feedAmount2 =1;bool feederSuccess =false;// 피더 부분int 부분 =0;int 회전 =0;// 입력 actionsenum {btnSELECT, btnUP, btnDOWN, btnBACK, btnCANCEL1, btnCANCEL2, btnMANUAL, trigTIMEOUT};// FSM(Finite State Machine) enum STATES의 상태 { 메인, MENU_EDIT _FEEDTIME1, MENU_EDIT_FEEDTIME2, MENU_EDIT_FEEDAMOUNT, MENU_EDIT_TIME, MENU_EDIT_DATE, MENU_EDIT_SETTINGS는 EDIT_FEED_TIME1_HOUR, EDIT_FEED_TIME1_MINUTE, EDIT_FEED_TIME1_ON_OFF, EDIT_FEED_TIME2_HOUR, EDIT_FEED_TIME2_MINUTE, EDIT_FEED_TIME2_ON_OFF, EDIT_FEED_AMOUNT1, EDIT_FEED_AMOUNT2, EDIT_HOUR는 EDIT_MINUTE는 EDIT_DAY는 EDIT_MONTH는 EDIT_YEAR는 EDIT_SERVO_STOP_DELAY, EDIT_SERVO_BACKUP_DELAY는} // 현재 상태를 유지 systemSTATES 상태;int8_t userInput;int8_t trigger;int Second;int Minute;int Hour;int Day;int Month;int Year;int8_t DoW;String day_of_week;unsigned char address, data;int testt =0;int feed_time1_hour;int feed_time1_minute;bool feed_time1_active =false;bool alarm1Activated =false;int feed_time2_hour;int feed_time2_minute;bool feed_time2_active =false;bool alarm2Activated =false;//값을 편집할 때 깜박임 기능에 사용uint32_t 깜박임_간격2 =500;uint32_t 깜박임_previoust 0;boolean flash_state =false; // 사용 값을 편집할 때 깜박임 기능 suint32_t spiningWheel_interval =170;uint32_t spiningWheel_previousMillis =0;uint32_t spiningWheel_currentMillis =0;int spiningWheelSymbol =0;// 홀 센서 실패 백업 기능에 사용// 1회전 간격 시간은 60도보다 다소 커야 합니다. 피더의 (일부).uint32_t hallSensorBackup_interval =HALL_SENSOR_BACKUP_VALUE;uint32_t hallSensorBackup_currentMillis =0;boolean hallSensorFail =false;// lcd 백라이트 timeruint32_t;lcdpressBacklight_interval=LCD_BACKLIGHT_ON에 사용됨 // LCD 디스플레이 바이트에 대한 사용자 정의 기호 정의 bell_symbol_Char[8] ={ B00100, B01110, B01110, B01110, B11111, B00100, B00000, 1010,1010,1010,1010,10000};byte inverted_one_Char[8] ={ 1,10b111 , 0b10001, 0b11111};byte inverted_two_Char[8] ={ 0b11111, 0b11011, 0b10101, 0b11101, 0b11011, 0b10111, 0b10};by1,1, TE arrow_up_Char [8] ={0b00100, 0b01110, 0b11111, 0b01110, 0b01110, 0b01110, 0b01110, 0b00000} 바이트 arrow_down_Char [8] ={0b00000, 0b01110, 0b01110, 0b01110, 0b01110, 0b11111, 0b01110, 0b00100} 바이트 inverted_p_Char [8] ={0b11111, 0b10001, 0b10101, 0b10001, 0b10111, 0b10111, 0b11111, 0b00000} 바이트 backslash_Char [8] ={0b00000, 0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00000, 0b00000} 바이트 thickDash_Char [8 ] ={ 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000};휘발성 부울 hallSensorActivated =false;//SensorI HallSensorActivated =false;//인터럽트 1 // 홀 센서 LED 켜기 digitalWrite(LED_HALL_SENSOR_PIN, HIGH);}// 이 라인은 이 스케치를 C++ 파일로 만드는 데 필요합니다.// Atom// 텍스트 편집기와 PlatformIO 추가로 코드를 편집하기 때문에 사용합니다. -onvoid HallSensorIsr();void setup();void loop();void change_states();void check_inputs();void transition(int trigger);void check_alarm();void check_manual_feed();void display_menu_option_set_feedtime1();void display_menu_option_set_feedtime2 (); 무효 display_menu_option_set_feed_amount(); 무효 display_menu_option_set_time(); 무효 display_menu_option_set_date(); 무효 자정_reset(); 무효 display_time(); 무효 displayFeedingAmouts(); 무효 displayFeedingTimes(); 무효 set_feedAmount(); 무효 (), set_feeding1_time() 무효, set_feeding2_time() 무효, get_time() 무효, get_date 무효(), write_time() 무효, write_date() 무효, write_feeding_time1() 무효, write_feeding_time2() 무효, write_feedamount 무효(), get_feedamount 무효 (); 무효 get_feed_time1(); 무효 get_feed_time2(); 무효 check_RTC();byte decToBcd(byte val);byte bcdToDec(byte val); void 선행_0(int 숫자); void blinkFunction(); void displaySpinningWheel(); void startFeederServo(); void stopFeederServo(); void activateFeeder(int 부분); void check_LcdBacklight();void lcd_backlight_ON();void ledsAndLcdDisplayStartup();void hallSensorCheck();#line 355// ************************** ************************************************** **// SETUPvoid ​​setup(){ // LCD 화면 활성화 lcd.begin(); // LCD 백라이트를 켜고 백라이트 끄기 타이머 시작 lcd_backlight_ON(); // I2C 시작 Wire.begin(); // 피더의 회전을 감지하기 위한 홀센서 입력/이송량 출력 체크 pinMode(HALL_SENSOR_PIN, INPUT_PULLUP); 핀모드(LED_HALL_SENSOR_PIN, 출력); 핀모드(SERVO_OUTPUT_PIN, 출력); 핀모드(LED_CANCEL1_PIN, 출력); 핀모드(LED_CANCEL2_PIN, 출력); 핀모드(LED_SUCCESS1_PIN, 출력); 핀모드(LED_SUCCESS2_PIN, 출력); // LED의 기본 상태를 OFF로 설정 digitalWrite(LED_CANCEL1_PIN, LOW); 디지털 쓰기(LED_CANCEL2_PIN, LOW); 디지털 쓰기(LED_SUCCESS1_PIN, LOW); 디지털 쓰기(LED_SUCCESS2_PIN, LOW); 디지털 쓰기(LED_HALL_SENSOR_PIN, LOW); lcd.createChar(0, ThickDash_Char); lcd.createChar(1, bell_symbol_Char); lcd.createChar(2, 백슬래시_Char); lcd.createChar(3, 반전된_p_Char); lcd.createChar(4, inverted_one_Char); lcd.createChar(5, inverted_two_Char); lcd.createChar(6, arrow_up_Char); lcd.createChar(7, arrow_down_Char); // 피더 서보를 기본 상태 OFF로 설정합니다. stopFeederServo(); Wire.begin(); // RTC를 Syncprovider로 설정 setSyncProvider(RTC.get); // RTC와의 재동기화 시간(초) setSyncInterval(60); // SQW 핀의 기본 구형파를 비활성화합니다. RTC.squareWave(SQWAVE_NONE); // 홀 센서에 인터럽트 연결(unput이 LOW로 변할 때) // 피더 샤프트가 60도 회전할 때마다 홀 센서는 // 인터럽트를 생성해야 합니다. attachInterrupt(INT1, HallSensorIsr, FALLING); // 표시 테스트 ledsAndLcdDisplayStartup(); // FSM 상태의 초기 상태 =MAIN; // Arduino 메모리에서 저장된 알람 값을 읽습니다. get_feed_time1(); get_feed_time2();}// SETUP 종료// *************************************** ***************************************// LOOPvoid ​​루프(){ // 상태 변경 FSM change_states(); // 입력(버튼) 확인 check_inputs(); // 알람이 호출되었는지 확인 check_alarm(); // 수동 피드가 요청되었는지 확인 check_manual_feed(); // at midnight, reset some variables midnight_reset(); // check connection RTC check_RTC(); // Check the Hall sensor function hallSensorCheck(); // check if lcd backlight must be turned off check_LcdBacklight();}// End of LOOP// ******************************************************************************// ******************************************************************************// ******************************************************************************// ******************************************************************************//******************************************************************************// Finite State Machinevoid change_states(){ // states switch (state) { //--------------------------------------- case MAIN:display_time(); displayFeedingAmouts(); displayFeedingTimes(); 부서지다; //--------------------------------------- case MENU_EDIT_FEEDTIME1:display_menu_option_set_feedtime1(); 부서지다; //--------------------------------------- case MENU_EDIT_FEEDTIME2:display_menu_option_set_feedtime2(); 부서지다; //--------------------------------------- case MENU_EDIT_FEEDAMOUNT:display_menu_option_set_feed_amount(); 부서지다; //--------------------------------------- case MENU_EDIT_TIME:display_menu_option_set_time(); 부서지다; //--------------------------------------- case MENU_EDIT_DATE:display_menu_option_set_date(); 부서지다; //--------------------------------------- case EDIT_FEED_TIME1_HOUR:set_feeding1_time(); 부서지다; //--------------------------------------- case EDIT_FEED_TIME1_MINUTE:set_feeding1_time(); 부서지다; //--------------------------------------- case EDIT_FEED_TIME1_ON_OFF:set_feeding1_time(); 부서지다; //--------------------------------------- case EDIT_FEED_TIME2_HOUR:set_feeding2_time(); 부서지다; //--------------------------------------- case EDIT_FEED_TIME2_MINUTE:set_feeding2_time(); 부서지다; //--------------------------------------- case EDIT_FEED_TIME2_ON_OFF:set_feeding2_time(); 부서지다; //--------------------------------------- case EDIT_FEED_AMOUNT1:set_feedAmount(); 부서지다; //--------------------------------------- case EDIT_FEED_AMOUNT2:set_feedAmount(); 부서지다; //--------------------------------------- case EDIT_HOUR:set_time(); 부서지다; //--------------------------------------- case EDIT_MINUTE:set_time(); 부서지다; //--------------------------------------- case EDIT_DAY:set_date(); 부서지다; //--------------------------------------- case EDIT_MONTH:set_date(); 부서지다; //--------------------------------------- case EDIT_YEAR:set_date(); 부서지다; //--------------------------------------- }}//******************************************************************************// Check INPUTSvoid check_inputs(){ // first check if timeout has occurred if ( millis() - timeoutValue> MENU_TIMEOUT_VALUE ) { userInput =trigTIMEOUT; transition(userInput); } // check state of buttons buttonSelect.read(); buttonUp.read(); buttonDown.read(); buttonBack.read(); buttonManual.read(); buttonCancel1.read(); buttonCancel2.read(); // check manual cancel Feed1 button switch (buttonCancel1.wasPressed()) { case 1:// invert variable value (true to false and vise versa) manualCancelFeed1 =!manualCancelFeed1; //turn on lcd backlight manually lcd_backlight_ON(); // message when Cancel1 button is pressed if (manualCancelFeed1 ==1) { lcd.clear(); lcd.setCursor(0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #1"); lcd.setCursor(0, 1); lcd.print("cancelled once "); 지연(2000); lcd.clear(); } else if (manualCancelFeed1 ==0) { lcd.clear(); lcd.setCursor(0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #1"); lcd.setCursor(0, 1); lcd.print("canceling undone"); 지연(2000); lcd.clear(); } 부서지다; } // check manual cancel Feed2 button switch (buttonCancel2.wasPressed()) { case 1:// invert variable value (true to false and vise versa) manualCancelFeed2 =!manualCancelFeed2; //turn on lcd backlight manually lcd_backlight_ON(); // message when Cancel1 button is pressed if (manualCancelFeed2 ==1) { lcd.clear(); lcd.setCursor(0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #2"); lcd.setCursor(0, 1); lcd.print("cancelled once "); 지연(2000); lcd.clear(); } else if (manualCancelFeed2 ==0) { lcd.clear(); lcd.setCursor(0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #2"); lcd.setCursor(0, 1); lcd.print("canceling undone"); 지연(2000); lcd.clear(); } 부서지다; } // check manual Feed button switch (buttonManual.wasPressed()) { case 1:manualFeed =true; //turn on lcd backlight manually lcd_backlight_ON(); 부서지다; } // check MENU/SELECT button switch (buttonSelect.wasPressed()) { case 1:userInput =btnSELECT; //turn on lcd backlight manually lcd_backlight_ON(); transition(userInput); 부서지다; } // check UP button switch (buttonUp.wasPressed()) { case 1:userInput =btnUP; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); 부서지다; } // check long press UP button switch (buttonUp.wasReleased()) { case 1:long_press_button =false; rpt =REPEAT_FIRST; 부서지다; } switch (buttonUp.pressedFor(rpt)) { case 1:// increment the long press interval rpt +=REPEAT_INCR; long_press_button =true; userInput =btnUP; transition(userInput); 부서지다; } // check DOWN button switch (buttonDown.wasPressed()) { case 1:userInput =btnDOWN; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); 부서지다; } // check long press DOWN button switch (buttonDown.wasReleased()) { case 1:long_press_button =false; rpt =REPEAT_FIRST; 부서지다; } switch (buttonDown.pressedFor(rpt)) { case 1:// increment the long press interval rpt +=REPEAT_INCR; long_press_button =true; userInput =btnDOWN; transition(userInput); 부서지다; } // check btnBACK button switch (buttonBack.wasPressed()) { case 1:userInput =btnBACK; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); 부서지다; }}//******************************************************************************// Check for state transition triggervoid transition(int trigger){ switch (state) { //--------------------------------------- case MAIN:// set time-out timr timeoutValue =millis(); if (trigger ==btnSELECT) { lcd.clear(); state =MENU_EDIT_FEEDTIME1; } else if (trigger ==btnBACK) { //lcd.clear(); //state =ALARM1_AND_2_TIME; } 부서지다; //--------------------------------------- case MENU_EDIT_FEEDTIME1:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { //no action, this is the first menu } else if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_FEEDTIME2; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_FEED_TIME1_HOUR; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } 부서지다; //--------------------------------------- case MENU_EDIT_FEEDTIME2:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_FEEDTIME1; } else if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_FEEDAMOUNT; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_FEED_TIME2_HOUR; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } 부서지다; //--------------------------------------- case MENU_EDIT_FEEDAMOUNT:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_FEEDTIME2; } else if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_TIME; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_FEED_AMOUNT1; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } 부서지다; //--------------------------------------- case MENU_EDIT_TIME:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_FEEDTIME2; } if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_DATE; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_HOUR; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } 부서지다; //--------------------------------------- case MENU_EDIT_DATE:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_TIME; } else if (trigger ==btnDOWN) { //no action, end of menu items! } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_DAY; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } 부서지다; //--------------------------------------- case EDIT_FEED_TIME1_HOUR:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers...This file has been truncated, please download it to see its full contents.

    회로도

    Arduino based Pet Feeder I used Arduino IDE 1.8.2. BE CAREFUL NOT TO HAVE TWO VERSIONS OF THE SAME LIBRARIES IN YOUR LIBRARIES FOLDER!! arduino_pet_feeder_final_eng_v1_0-ino_hex_libraries_dsoo0HscCr.zip

    제조공정

    1. 애완동물 사료
    2. Arduino Nano RP 2040을 사용하는 DIY Photoshop 편집 콘솔
    3. Arduino 스파이봇
    4. 꽃 - Arduino Nano, CrazyCircuits, DFRobot
    5. 수제 16x8 매트릭스의 Arduino Nano 테트리스 게임
    6. Arduino Tamagotchi 클론 - 디지털 애완동물
    7. Arduino Nano:조이스틱으로 2개의 스테퍼 모터 제어
    8. 원격 제어 애완동물 사료 공급기
    9. Arduino Nano가 있는 휴대용 가이거 계수기
    10. Arduino Nano용 TFT Shield - 시작