Posted on

Build Pi Meowagotchi: a Raspberry Pi E-Paper Cat with an ESP32 Remote

Build a virtual cat that lives on a Raspberry Pi e-paper display, responds to the Pi’s health and accepts care from an optional round ESP32 touchscreen remote.

Round ESP32 touchscreen with Feed, Play, Pet, Clean, Nap and Wake controls beside a Raspberry Pi e-paper display showing a sleeping Meowagotchi cat.
The touchscreen sends care requests; the Raspberry Pi owns and displays the cat.

Pi Meowagotchi is one build split across two open-source repositories. pi-meowagotchi runs the pet and e-paper display. pi-meowagotchi-controls turns a DFRobot round ESP32-S3 display into its physical remote.

What you will build

PartRole
Raspberry Pi and e-paper panelRuns the simulation, stores the cat, reads Pi vitals and renders the display.
Private Meow Meow Scratch appShares state and configuration and carries pending care actions between devices.
ESP32-S3 round touchscreenQueues feed, play, pet, clean, nap and wake requests. It does not store pet state.

The Pi is always the authority. A tap on the remote creates a pending action, the Pi applies it once, then marks it accepted or rejected. This avoids two devices trying to maintain competing versions of the same pet.

ESP32 touchscreen
       |
       | queues a private care action
       v
Meow Meow Scratch actions endpoint
       |
       | polled and acknowledged
       v
Raspberry Pi ----> pet state ----> e-paper displayCode language: PHP (php)

What you need

For the e-paper cat

  • A Raspberry Pi Zero 2 W with pre-soldered headers, or another compatible Pi with network access and SPI support
  • A supported Waveshare e-paper HAT or panel
  • Raspberry Pi OS with Python 3.11 or newer
  • A suitable power supply and storage for the Pi

The project was developed and tested on a Pi Zero 2 W running Debian 13 (Trixie) with a Waveshare 2.13-inch V4 250×122 panel. The renderer scales to the dimensions reported by other panel modules in the waveshare-epaper bundle, but you must select the driver that matches your exact panel revision.

For the touchscreen remote

The linked catalogue pages are compatibility-oriented retailer links. Reuse suitable hardware you already own. Prices, availability and package contents can change, so check each retailer listing before ordering.

Core project hardware

The DFR1221 does not include an accelerometer. Touch controls work without one. If you enable shake tracking, you must add and wire the LIS3DH separately.

1. Install the cat on the Raspberry Pi

Enable SPI in raspi-config → Interface Options → SPI, then reboot. Confirm that Linux created the SPI devices:

ls /dev/spidev*

Clone and install the Raspberry Pi half of the project:

git clone https://github.com/meowmeowscratch/pi-meowagotchi.git
cd pi-meowagotchi
./install.shCode language: PHP (php)

The installer creates /opt/meowagotchi, installs a systemd service and adds the meowagotchi command. You may leave the Meow app key blank for this first local test.

If your panel is not the Waveshare 2.13-inch V4, run meowagotchi panels and set the matching panel value in /opt/meowagotchi/config.toml. There is no reliable automatic revision detection. Setting the wrong driver can prevent the display from working.

2. Verify local care and display output

systemctl status meowagotchi
meowagotchi status
meowagotchi feed
meowagotchi pet

The status command should report the cat’s needs, health and mood. Care commands are safe while the display service is running. Commands that drive the panel directly are different: stop the service before using once or clear, because two processes must not compete for the SPI bus.

If you want to inspect the display without hardware, the repository also provides meowagotchi preview, which renders the room to a PNG on a workstation.

3. Connect the private backend

The cat can remain local indefinitely. The backend becomes necessary when you add the touchscreen, because it carries the remote’s care requests to the Pi.

From a checkout of pi-meowagotchi on a machine with Python 3.11 or newer, install the optional Meow dependencies and run the idempotent provisioning script:

python3 -m pip install -e ".[meow]"
export MEOW_PLATFORM_API_KEY="YOUR_PLATFORM_TOKEN"
export MEOW_USERNAME="YOUR_USERNAME"
python3 scripts/init_app.pyCode language: JavaScript (javascript)

This creates a private meowagotchi app with state and config static endpoints plus an actions collection. Use the platform token only for provisioning. Create or select an app-scoped key with read/write access to this app for both devices.

Put the app key and account name in the Pi’s protected environment file:

sudoedit /opt/meowagotchi/.env

# Add:
MEOW_APP_API_KEY="YOUR_APP_KEY"
MEOW_USERNAME="YOUR_USERNAME"

sudo systemctl restart meowagotchiCode language: PHP (php)

After the restart, local state remains available as an offline cache. The Pi also polls for remote configuration and pending actions.

4. Prepare the round touchscreen

Clone the controller repository on the workstation you will use to flash the board:

git clone https://github.com/meowmeowscratch/pi-meowagotchi-controls.git
cd pi-meowagotchi-controlsCode language: PHP (php)

The board needs DFRobot’s DFR1221-specific MicroPython firmware. A stock ESP32_GENERIC_S3 build does not include the required LVGL display and touch driver. Follow the controller repository’s current DFR1221 setup guide for the complete flashing procedure.

On Debian or Ubuntu, extract the retained DFRobot package, put the board into bootloader mode, identify its serial port and run the repository’s flashing helper:

sudo apt install unrar
./tools/setup_dfr1221_vendor.sh

ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null

DFR1221_FIRMWARE=vendor/dfrobot/dfr1221-micropython/Micropython/firmware/micropython_firmware.bin \
  ./tools/flash_dfr1221.sh /dev/ttyACM0 --yesCode language: JavaScript (javascript)

Flashing replaces the board’s factory firmware. Verify the port and board before continuing, then press RESET or reconnect USB when the flash completes.

5. Configure and deploy the remote

Create .env in the controller repository. It is ignored by Git and is converted to a device-only settings.py during deployment:

WIFI_NAME="YOUR_WIFI_NAME"
WIFI_PASS="YOUR_WIFI_PASSWORD"
MEOW_APP_API_KEY="YOUR_APP_KEY"Code language: JavaScript (javascript)

Use the same app-scoped key as the Pi. Never put the platform token on the controller: the remote needs permission to send care requests, not to create or reshape apps.

python3 -m venv .venv
.venv/bin/python -m pip install mpremote
./tools/deploy.sh /dev/ttyACM0

The deployment uploads the DFRobot screen driver and project modules, joins Wi-Fi and installs the pinned MicroPython client on the board. Reset the controller after a successful upload. It should set its clock with NTP, draw the six-segment control face and show READY in the centre.

6. Test the complete path

  1. Confirm the Pi service is running and has network access.
  2. Tap FEED once on the controller.
  3. Check that the selected label briefly inverts and the hub reports FEED queued.
  4. Run meowagotchi status on the Pi and confirm that hunger improved.
  5. Watch journalctl -u meowagotchi -f if the action does not appear.

The remote deliberately ignores repeated taps within 450 milliseconds and emits one action when a finger is held down. The centre and the area outside the wheel are dead zones.

Optional: add shake-to-play

Wire an I2C LIS3DH to suitable GPIO pins on the DFR1221, then extend the controller’s .env:

SHAKE_ENABLED=true
IMU_SDA_PIN=YOUR_SDA_GPIO
IMU_SCL_PIN=YOUR_SCL_GPIOCode language: JavaScript (javascript)

Deploy again after changing settings. A qualifying shake queues play and highlights the PLAY segment. The settings generator rejects shake mode if either pin is missing.

Troubleshooting

  • No e-paper output: confirm SPI is enabled, the service user can access SPI and GPIO, and panel matches the exact Waveshare model and revision.
  • The cat is upside down: set rotate = 180 in /opt/meowagotchi/config.toml, then restart the service.
  • The remote says offline: recheck Wi-Fi credentials, signal and NTP access.
  • The remote says API 401: replace the app key and confirm it has access to the private meowagotchi app.
  • A tap queues but nothing changes: confirm the Pi has the same app credentials and inspect its systemd journal for action-polling errors.
  • The board has no display or touch after flashing: confirm you used DFRobot’s DFR1221 firmware and uploaded its matching screen.py, not generic ESP32-S3 firmware.

Credential and device safety

  • Keep the platform token on the provisioning workstation only.
  • Use an app-scoped key with access limited to the private Meowagotchi app on devices.
  • Never commit either repository’s .env file or generated controller settings.
  • Disconnect power before changing panel or accelerometer wiring.
  • Stop the display service before manually running a command that drives the e-paper panel.

Project source and next steps

Start with the Pi and local CLI, then add the private backend and touchscreen only after the cat is stable. That keeps display, connectivity and controller problems separate while you build. Before leaving either device running unattended, review the production checklist.