Bird Feeder is a project that aims to build a self-contained system which integrates a Pet Feeder manufactured by Nooie which will dispense food for birds via donations through a livestream. The Bird Feeder is projected to be placed in the bird house of Kalisto Tierpark located in Kamp-Lintfort.
The Nooie Pet Feeder features a microcontroller board manufactured by Tuya. Tuya is an IoT and cloud development service provider with a varied range of products. The pet feeder can be controlled through Tuya’s cloud development platform. While cloud development is useful, we would like to control the pet feeder locally for security and latency reasons.
To control the pet feeder locally, we will be using Home Assistant. Home Assistant is a Linux based open-source software generally used for smart home automation. We will be using a Raspberry Pi to install Home Assistant, which will be our main control hub.
Additionally, an e-paper display will be used to display last donation information to show people physically present that this service actually exists.
This guide was written using Home Assistant version 2024.5.x.
![]() |
---|
Diagram 1: System Architecture |
BUSY, RES, DC, CS
.//Most Important Import #include <SPI.h> #include "Display_EPD_W21_spi.h" #include "Display_EPD_W21.h" #include "frame.h" #include "GUI_Paint.h" #include "font.h" #if 1 unsigned char BlackImage[EPD_ARRAY]; //Define canvas space #endif //Most Important Part void setup() { pinMode(D5, INPUT); //BUSY pinMode(D0, OUTPUT); //RES pinMode(D3, OUTPUT); //DC pinMode(D1, OUTPUT); //CS //SPI SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); SPI.begin(); Serial.begin(9600); Serial.print(111); } //Tips// /* 1.Flickering is normal when EPD is performing a full screen update to clear ghosting from the previous image so to ensure better clarity and legibility for the new image. 2.There will be no flicker when EPD performs a partial refresh. 3.Please make sue that EPD enters sleep mode when refresh is completed and always leave the sleep mode command. Otherwise, this may result in a reduced lifespan of EPD. 4.Please refrain from inserting EPD to the FPC socket or unplugging it when the MCU is being powered to prevent potential damage.) 5.Re-initialization is required for every full screen update. 6.When porting the program, set the BUSY pin to input mode and other pins to output mode. */ void loop() { Serial.print(111); #if 1 //Partial refresh demostration. EPD_Init_Fast(); //Full screen refresh initialization. EPD_WhiteScreen_White(); //Clear screen function. EPD_DeepSleep(); //Enter the sleep mode and please do not delete it, otherwise it will reduce the lifespan of the screen. delay(2000); //Delay for 2s. //Partial refresh demo support displaying a clock at 5 locations with 00:00. If you need to perform partial refresh more than 5 locations, please use the feature of using partial refresh at the full screen demo. //After 5 partial refreshes, implement a full screen refresh to clear the ghosting caused by partial refreshes. //////////////////////Partial refresh time///////////////////////////////////// Paint_NewImage(BlackImage, EPD_WIDTH, EPD_HEIGHT, 0, WHITE); //Set canvas parameters, GUI image rotation, please change 0 to 0/90/180/270. Paint_SelectImage(BlackImage); //Select current settings. EPD_Init(); //Full screen refresh initialization. Paint_Clear(WHITE); //Clear canvas. const char * Message = "Welcome to Kalisto"; Paint_DrawString_EN(400 - (((strlen(Message) * 32) / 2)), 240 - (64 / 2), Message, & Font64, WHITE, BLACK); EPD_Display(BlackImage); //Display GUI image. EPD_DeepSleep(); //EPD_DeepSleep,Sleep instruction is necessary, please do not delete!!! delay(20000); //Delay for 2s. // Full screen update clear the screen. EPD_Init(); //Full screen refresh initialization. EPD_WhiteScreen_White(); //Clear screen function. EPD_DeepSleep(); //Enter the sleep mode and please do not delete it, otherwise it will reduce the lifespan of the screen. delay(2000); //Delay for 2s. #endif delay(300000); // The program stops here }
esphome: name: display friendly_name: display on_boot: priority: 200.0 then: - component.update: eink_display - delay: 5s - logger.log: "Initial sensor data received: Refreshing display..." - script.execute: update_screen esp32: board: esp32-s3-devkitc-1 framework: type: arduino # Enable logging logger: # Enable Home Assistant API api: encryption: key: "7QLJzR30itSBn30kootHbIE6FI8jmUtAl7/fcytRxis=" ota: platform: esphome password: "81ceca8aa7f29a76601df5539733d32f" wifi: ssid: !secret wifi_ssid password: !secret wifi_password # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Display Fallback Hotspot" password: "WgV5TWXpXcpT" captive_portal: script: - id: update_screen then: - component.update: eink_display font: - file: "gfonts://Roboto" id: roboto_64 size: 64 spi: clk_pin: GPIO7 mosi_pin: GPIO9 mqtt: broker: hafeeder.local port: 1883 username: "mqtt" password: "1234" text_sensor: - platform: mqtt_subscribe name: "Data from topic" id: mytext topic: birdfeeder qos: 2 on_value: then: - script.execute: update_screen display: - platform: waveshare_epaper model: 7.50in-bV3 id: eink_display cs_pin: GPIO2 dc_pin: GPIO4 busy_pin: GPIO6 reset_pin: GPIO1 update_interval: never lambda: |- it.printf(400, 240, id(roboto_64), TextAlign::TOP_CENTER, id(mytext).state.c_str());
Home Assistant Community Store (HACS) is a third-party download manager for Home Assistant which contains various custom integrations. We need to install LocalTuya integration through HACS to locally control the pet feeder. This guide was written using HACS version 1.34.0.
wget -O - https://get.hacs.xyz | bash -
LocalTuya integration is what we need to control the pet feeder locally. This guide was written for LocalTuya version 5.2.1.