Spisu treści:
Wideo: Kontrola dostępu do karmy dla kota (ESP8266 + serwomotor + drukowanie 3D): 5 kroków (ze zdjęciami)
2025 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2025-01-13 06:58
Ten projekt omawia proces, którego użyłem do stworzenia automatycznej miski na karmę dla mojego starszego kota z cukrzycą Chaz. Widzisz, musi zjeść śniadanie, zanim będzie mógł dostać insulinę, ale często zapominam odebrać jego danie przed pójściem spać, co psuje mu apetyt i odrzuca harmonogram insuliny. To danie wykorzystuje serwomotor do zamykania pokrywy nad jedzeniem między północą a 7:30. Szkic Arduino mikrokontrolera NodeMCU ESP8266 wykorzystuje protokół NTP (Network Time Protocol) do sterowania harmonogramem.
Ten projekt może nie być odpowiedni dla młodszych, bardziej aktywnych kotów. Chaz jest tak stary i słaby, że nie ma ochoty podważać miski, ale jest to możliwe.
Jeśli jesteś nowicjuszem w Arduino lub ESP8266, możesz skorzystać z następujących przewodników dotyczących wymagań wstępnych:
- Instrukcje klasy Arduino
- Instruktażowa klasa Internetu rzeczy
Kieszonkowe dzieci
- Drukarka 3D (używam Creality CR-10s Pro)
- Filament do drukarki 3D (używam złotego PLA)
- Mikrokontroler Wi-Fi NodeMCU ESP8266
- Kabel USB (A do microB)
- Zasilacz USB
- Mikrosilnik serwo
- Mały śrubokręt i śruby
- Podłączyć przewód
- Kołki nagłówka
- Płyta Perma-proto
Aby być na bieżąco z tym, nad czym pracuję, śledź mnie na YouTube, Instagramie, Twitterze, Pintereście i subskrybuj mój newsletter. Jako partner Amazon zarabiam na kwalifikujących się zakupach, których dokonujesz za pomocą moich linków afiliacyjnych.
Krok 1: Części drukowane w 3D
Uchwyt na miskę na karmę dla kota jest oparty na projekcie Ardy Lai na Thingiverse. Zwiększyłem ją, aby pomieścić miskę mojego kota, a także skróciłem ją, ponieważ powiększanie jej sprawiło, że była zbyt wysoka. Dodałem uchwyt na mikrosilnik i kilka otworów na kable do poprowadzenia do środka.
Wymodelowałem prostą pokrywę za pomocą Tinkercad, zaprojektowaną do przymocowania do klaksonu mikro serwa. Możesz pobrać mój projekt bezpośrednio z Tinkercad i/lub pobrać pliki STL dołączone do tego kroku.
Wydrukowałem części na mojej drukarce Creality CR-10s Pro ze złotym filamentem PLA.
Ujawnienie: w chwili pisania tego tekstu jestem pracownikiem firmy Autodesk, która produkuje Tinkercad.
Krok 2: Przymocuj pokrywę do serwomotoru
Użyłem małego wiertła, aby zwiększyć rozmiar otworów na serwoklanie, a następnie użyłem śrub, aby przymocować serwo do drukowanej w 3D pokrywy.
Krok 3: Zbuduj obwód NodeMCU ESP8266
Obwód jest kontrolowany przez mikrokontroler Wi-Fi NodeMCU ESP8266. Użyłem pinów nagłówka na płycie perma-proto, aby łatwo odłączyć mikrosilnik. Serwonapędy są podłączone do NodeMCU w następujący sposób:
Żółty przewód serwa: NodeMCU D1
Czerwony przewód serwo: zasilanie NodeMCU (3V3 lub VIN)
Czarny przewód serwo: masa NodeMCU (GND)
Krok 4: Prześlij kod Arduino i przetestuj
Zainstaluj zespół silnika/pokrywy w wycięciu w kształcie silnika w części drukowanej 3D uchwytu miski. Podłącz nagłówek silnika do styków nagłówka płytki mikrokontrolera i podłącz obwód do komputera za pomocą kabla USB.
Szkic Arduino wykorzystuje Network Time Protocol do pobrania aktualnego czasu, a następnie otwiera lub zamyka pokrywę zgodnie z ustalonym harmonogramem. Skopiuj następujący kod, zaktualizuj dane uwierzytelniające Wi-Fi i przesunięcie czasu UTC, a następnie prześlij go na swoją płytę NodeMCU za pomocą Arduino IDE.
#włączać
#include #include #include ESP8266WiFiMulti wifiMulti; // Utwórz instancję klasy ESP8266WiFiMulti o nazwie 'wifiMulti' WiFiUDP UDP; // Utwórz instancję klasy WiFiUDP do wysyłania i odbierania adresu IP timeServerIP; // time.nist.gov adres serwera NTP const char* NTPServerName = "time.nist.gov"; const int NTP_PACKET_SIZE = 48; // znacznik czasu NTP znajduje się w pierwszych 48 bajtach wiadomości bajt NTPBuffer[NTP_PACKET_SIZE]; // bufor do przechowywania pakietów przychodzących i wychodzących Servo myservo; // utwórz obiekt servo do sterowania serwo // na większości płyt można utworzyć dwanaście obiektów serwo int pos = 0; // zmienna do przechowywania pozycji serwa void setup() { myservo.attach(5); // dołącza serwomechanizm na pinie 5 aka D1 do obiektu serwo //domyślnie otwiera pokrywę Serial.println("otwieranie pokrywy"); for (pos = 95; pos >= 0; pos -= 1) { // przechodzi z 95 stopni do 0 stopni myservo.write(pos); // powiedz serwo, aby przeszło na pozycję w zmiennej 'pos' delay(15); // czeka 15ms, aż serwo osiągnie pozycję } Serial.begin(115200); // Rozpocznij komunikację szeregową, aby wysyłać wiadomości do komputera delay(10); Serial.println("\r\n"); startWiFi(); // Spróbuj połączyć się z określonymi punktami dostępu. Następnie czekaj na połączenie startUDP(); if(!WiFi.hostByName(NTPServerName,timeServerIP)) { // Uzyskaj adres IP serwera NTP Serial.println("Wyszukiwanie DNS nie powiodło się. Ponowne uruchamianie."); Serial.flush(); ESP.reset(); } Serial.print("IP serwera czasu:\t"); Serial.println(IPSerweraCzasu); Serial.println("\r\nWysyłanie żądania NTP…"); sendNTPpacket(IPSerweraCzasu); } unsigned long intervalNTP = 60000; // Żądaj czasu NTP co minutę unsigned long prevNTP = 0; unsigned long lastNTPResponse = millis(); uint32_t timeUNIX = 0; unsigned long prevActualTime = 0; void loop() { unsigned long currentMillis = millis(); if (currentMillis - prevNTP > intervalNTP) { // Jeśli od ostatniego żądania NTP minęła minuta prevNTP = currentMillis; Serial.println("\r\nWysyłanie żądania NTP…"); sendNTPpacket(IPSerweraCzasu); // Wyślij żądanie NTP } uint32_t time = getTime(); // Sprawdź, czy nadeszła odpowiedź NTP i pobierz czas (UNIX) if (time) { // Jeśli otrzymano nowy znacznik czasu timeUNIX = czas; Serial.print("Odpowiedź NTP:\t"); Serial.println(timeUNIX); ostatnia odpowiedźNTP = bieżąca Millis; } else if ((currentMillis - lastNTPResponse) > 3600000) { Serial.println("Ponad 1 godzina od ostatniej odpowiedzi NTP. Ponowne uruchamianie."); Serial.flush(); ESP.reset(); } uint32_t aktualnyCzas = czasUNIX + (bieżącyMillis - ostatnia odpowiedźNTP)/1000; uint32_t EasternTime = timeUNIX - 18000 + (bieżącyMillis - ostatnia odpowiedź NTP)/1000; if (actualTime != prevActualTime && timeUNIX != 0) { // Jeśli od ostatniego wydruku minęła sekunda prevActualTime = aktualnyTime; Serial.printf("\rczas UTC:\t%d:%d:%d", getHours(actualTime), getMinutes(actualTime), getSeconds(actualTime)); Serial.printf("\rEST (-5):\t%d:%d:%d ", getHours(easternTime), getMinutes(easternTime), getSeconds(easternTime)); Serial.println(); } // 7:30 if(getHours(easternTime) == 7 && getMinutes(easternTime) == 30 && getSeconds(easternTime) == 0){ //otwórz pokrywę Serial.println("otwieranie pokrywy"); for (pos = 95; pos >= 0; pos -= 1) { // przechodzi z 95 stopni do 0 stopni myservo.write(pos); // powiedz serwo, aby przeszło na pozycję w zmiennej 'pos' delay(15); // czeka 15ms, aż serwo osiągnie pozycję } } // północ if(getHours(easternTime) == 0 && getMinutes(easternTime) == 0 && getSeconds(easternTime) == 0){ //zamknij pokrywę Serial. println("zamykanie pokrywy"); for (poz = 0; poz <= 95; poz += 1) { // przechodzi od 0 stopni do 95 stopni // w krokach co 1 stopień myservo.write(poz); // powiedz serwo, aby przeszło na pozycję w zmiennej 'pos' delay(15); // czeka 15ms, aż serwo osiągnie pozycję } } /* // test if(getHours(easternTime) == 12 && getMinutes(easternTime) == 45 && getSeconds(easternTime) == 0){ //zamknij pokrywę Serial.println("zamykanie pokrywy"); for (pos = 0; pos = 0; pos -= 1) { // przechodzi z 95 stopni do 0 stopni myservo.write(pos); // powiedz serwo, aby przeszło na pozycję w zmiennej 'pos' delay(15); // czeka 15ms, aż serwo osiągnie pozycję } } */ } void startWiFi() { // Spróbuj połączyć się z określonymi punktami dostępowymi. Następnie poczekaj na połączenie wifiMulti.addAP("ssid_from_AP_1", "twoje_hasło_do_AP_1"); // dodaj sieci Wi-Fi, z którymi chcesz się połączyć //wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); //wifiMulti.addAP("ssid_from_AP_3", "twoje_hasło_do_AP_3"); Serial.println("Łączenie"); while (wifiMulti.run() != WL_CONNECTED) { // Czekaj na połączenie Wi-Fi delay(250); Serial.print('.'); } Serial.println("\r\n"); Serial.print("Połączony z"); Serial.println(WiFi. SSID()); // Powiedz nam, do jakiej sieci jesteśmy połączeni Serial.print("adres IP:\t"); Serial.print(WiFi.localIP()); // Wyślij adres IP ESP8266 do komputera Serial.println("\r\n"); } void startUDP() { Serial.println("Uruchamianie UDP"); UDP.początek(123); // Rozpocznij nasłuchiwanie komunikatów UDP na porcie 123 Serial.print("Lokalny port:\t"); Serial.println(UDP. LocalPort()); Serial.println(); } uint32_t getTime() { if (UDP.parsePacket() == 0) { // Jeśli nie ma (jeszcze) odpowiedzi return 0; } UDP.read (NTPBuffer, NTP_PACKET_SIZE); // wczytaj pakiet do bufora // Połącz 4 bajty znacznika czasu w jedną 32-bitową liczbę uint32_t NTPTime = (NTPBuffer[40] << 24) | (NTPBuffer[41] << 16) | (NTPBuffer[42] << 8) | NTPBuffer[43]; // Konwertuj czas NTP na sygnaturę czasową UNIX: // Czas uniksowy zaczyna się 1 stycznia 1970 r. To 2208988800 sekund w czasie NTP: const uint32_t seventyYears = 2208988800UL; // odejmij siedemdziesiąt lat: uint32_t UNIXTime = NTPTime - seventyYears; zwróć czas UNIX; } void sendNTPpacket(IPAddress&adres) { memset(NTPBuffer, 0, NTP_PACKET_SIZE); // ustaw wszystkie bajty w buforze na 0 // Zainicjuj wartości potrzebne do utworzenia żądania NTP NTPBuffer[0] = 0b11100011; // LI, Wersja, Tryb // wyślij pakiet żądający znacznika czasu: UDP.beginPacket(adres, 123); // Żądania NTP są kierowane do portu 123 UDP.write(NTPBuffer, NTP_PACKET_SIZE); UDP.endPacket(); } inline int getSeconds(uint32_t UNIXTime) { return UNIXTime % 60; } inline int getMinutes(uint32_t UNIXTime) { return UNIXTime / 60 % 60; } inline int getHours(uint32_t UNIXTime) { return UNIXTime / 3600 % 24; }
Krok 5: Użyj go
Poprowadź przewody do wnętrza uchwytu na miskę i podłącz karmnik dla kota do gniazdka za pomocą zasilacza sieciowego USB. Sposób, w jaki napisany jest prosty kod, ma być uruchamiany w stanie „otwartym” i zmienia położenie pokrywy tylko w progach czasowych określonych w szkicu Arduino.
Dziękujemy za śledzenie! Jeśli stworzysz własną wersję, chciałbym ją zobaczyć w sekcji Zrobiłem to poniżej!
Jeśli podoba Ci się ten projekt, możesz zainteresować się niektórymi z moich innych:
- Uchwyt na pryzmat do tęczowych portretów
- Ściana do przechowywania sklejki z wieżą dla kota
- Lampiony LED Mason Jar (pokrywka z nadrukiem 3D)
- Suche pudełko na filament do drukarki 3D
- Awaryjne źródło zasilania USB (druk 3D)
- Świecące gumowe cukierki LED
- Geometryczna donica z nadrukiem 3D z drenażem
- Świecące kwiaty drukowane w 3D
- Jak zainstalować diody LED pod skuterem (z Bluetooth)
Aby być na bieżąco z tym, nad czym pracuję, obserwuj mnie na YouTube, Instagramie, Twitterze i Pintereście.