M5Stack Launches CardputerZero, a Pocket-Sized Linux Computer for Makers and Developers
May 26, 2026 — M5Stack, a global provider of modular IoT and embedded development platforms, today announced the launch of CardputerZero, a new handheld Linux...
· Wakes up when a conversation begins
· Shows an active working state while Claude is busy
· Alerts the user when authorization is required
· Allows approvals or rejections directly on the device
It is much more than a simple status indicator, for it behaves more like a desktop pet with personality. The project includes 18 built-in ASCII pet characters, each with multiple animation states. It also supports custom GIF character packs, making it easy for developers to create their own personalized Buddy. On top of that, it includes interactive behaviors such as:
· Shake detection
· Flip-to-sleep
· Automatic screen timeout
· LED alerts during authorization requests
Depending on Claude’s state, the Buddy can appear sleepy, idle, busy, waiting for attention, celebrating, dizzy, or even showing affection—making the interaction feel much more lively and expressive.
Getting started is also relatively straightforward. Developers can flash the firmware to the StickC Plus using PlatformIO, enable Developer Mode in Claude Desktop, open the Hardware Buddy window, and pair the device over Bluetooth. Once connected, the desktop app and hardware can automatically reconnect and continuously stay in sync.

It is no surprise that StickC Plus was chosen for Claude’s first official example. With its built-in screen, buttons, IMU, and BLE, it already covers nearly all the core requirements of a Claude Buddy without needing additional peripherals. Its compact form factor makes it easy to hold in your hand or place directly on your desk. It works well as a status display while also remaining convenient for quick interactions. If you want to quickly experience Claude Buddy, or build an eye-catching AI desk companion, StickC Plus is a highly recommended choice.
Recommended in Anthropic’s Developer Conference: Build with Claude on Cardputer-Adv
Besides the BLE-based desktop pet approach, another highly interesting direction comes from Anthropic’s developer conference, Build with Claude, where M5Stack Cardputer-Adv is used as the core device and has been well received by participating developers.
Compared with StickC Plus, which focuses more on desktop presence and status feedback, the Cardputer-Adv route emphasizes something different: letting Claude Code directly participate in the hardware creation process itself. In other words, Claude can help not only write applications, but also assist with flashing, deployment, and iteration.

More info: https://claude.com/code-with-claude/makers
Technically, this solution follows a UIFlow + MicroPython rapid development path, combined with Claude Code and related skills for setup and deployment. The project repository already includes scripts, Buddy app packages, and an extensible app directory. Developers can either run the existing project directly or continue adding their own .py applications to expand functionality over time. For anyone who wants to experience the idea of “AI helping me build hardware applications”, Cardputer-Adv is a very representative and exciting option.
Cardputer-Adv itself is also well suited to this role. With its built-in keyboard and screen, interaction feels more natural, whether for navigating menus, displaying Claude status, or running lightweight applications. Combined with the ESP32-S3’s connectivity and expandability, it naturally fits the concept of a portable AI mini terminal. It can become: a weather assistant, a pixel pet, a pocket utility tool, or simply your own personalized Claude Buddy.

One of the biggest advantages of this workflow is how direct it feels. You connect the Cardputer-Adv, open Claude Code, and enter “m5-onboard go”.
From there, the toolchain can automatically handle device detection, firmware flashing, app installation, rebooting, and startup. This makes it especially suitable for hackathons, workshops, and rapid prototyping sessions—bringing the vision of “build what you imagine” much closer to reality.
More M5Stack Devices Are Joining the Claude Desktop Buddy Ecosystem
Beyond these two examples, many other M5Stack host devices are also well suited to Claude Buddy-style projects. The community is already beginning to adapt related ideas to devices such as StickC Plus2, StickS3, Paper, and more.
A good Desktop Buddy needs to bring together display, interaction, connectivity, and local processing, and these are exactly the strengths shared by many M5Stack host devices. Whether it is from the Core, Stick, Atom, Cardputer, or E-Paper product lines, M5Stack offers a broad and mature hardware portfolio for developers to choose from.
For Claude Buddy-style applications, devices with a screen, buttons, or input methods, sensors, BLE, or Wi-Fi connectivity are naturally strong candidates.
![]() |
![]() |
![]() |
![]() |
M5Stack continues to be a go-to device for developers for several reasons:
· Ready to use out of the box — highly integrated and easy to develop with
· Low barrier to entry — support for multiple development platforms, including Arduino, UIFlow, ESP-IDF, MicroPython and more
· Great for visual presentation and demos — ideal for desktop setups, demos, workshops, exhibitions, and event showcases
· Complete hardware ecosystem — covering controllers, expansion modules, sensors, and accessories for fast prototyping and continuous expansion
· Large developer community — widely recognized by the global maker community, with abundant documentation and community resources
From Software Assistant to Physical Companion
The rise of Claude Buddy is just one example of how large-model AI is moving from the software world into the physical world. As more AI applications begin to leave the chat window and enter desktop devices, portable terminals, and real-world interaction scenarios, hardware is becoming an increasingly important bridge between AI and everyday life.
With its complete hardware ecosystem, highly integrated product design, and developer-friendly experience, M5Stack is becoming an important physical platform for developers around the world to connect large AI models with the real world. It is also opening up broader possibilities for AI desk companions, smart terminals, and innovative prototyping.
Bring Claude to Your Desk: Exploring Claude Desktop Buddy Projects with M5Stack
o Install and enable the ESPHome Builder add-on in Home Assistant
Open ESPHome Builder in Home Assistant and create an empty configuration file:
o Click the NEW DEVICE button at the bottom right
o In the dialog click CONTINUE
o Select Empty Configuration

o (Optional) Give the file a name
o Click EDIT on the newly created configuration file

o Then copy the contents of configuration.yaml from the example repository into your config file:

Modify network or API information as needed. For example, create an API Encryption Key for authentication:
api:
encryption:
key: "Your_Encryption_Key"
You can also change the timezone setting, for example:
timezone: America/Los_Angeles # Pacific
# timezone: America/New_York # Eastern
After editing, click SAVE and then INSTALL, choose Manual download.

This will generate code and compile the project.
When the build finishes, select Factory format to download the firmware.

Upload firmware
Open ESPHome Web in your browser to upload the firmware.
Connect StamPLC to the host via USB-C, click CONNECT and select the device.
Click INSTALL, select the previously downloaded firmware, and click INSTALL again to flash the device.
After flashing completes the device will automatically reset and boot.

Add device to Home Assistant Integrations
When the device boots it will connect to the configured Wi‑Fi. Under Settings -> Devices & services you should see the device.

Click Add to add StamPLC to Home Assistant. If you set an API Encryption Key, you may need to enter it here.
Example StamPLC dashboards:


Live device in action:

Expansion
The StamPLC support expansion via 16 pin headers on the right side of the device.
StamPLC AC is an AC relay expansion module compatible with the StamPLC host. The module integrates AC load control and entire system power supply functions, effectively simplifying power wiring during application development. It features a contact-type relay (single-pole single-throw - normally open), supporting up to AC 240V@10A line switching. It also includes a built-in AC-DC isolated conversion circuit supporting AC 100 ~ 240V input, capable of simultaneously powering the relay load and providing a stepped-down DC 12V output for the main system. A programmable tri-color RGB LED is available for working status indication.
Configure the StamPLC AC
In addition to previous StamPLC configurations, several components are required
o Add a new IO Expander
pi4ioe5v6408:
- id: pi4ioe5v6408_1
address: 0x43
# Configuration of i2c GPIO Expander 2
# on the StamPLC AC expansion
- id: pi4ioe5v6408_2
address: 0x44
o Add a new switch for AC Relay
switch:
...
# led indicator on StamPLC AC expansion
- platform: gpio
restore_mode: ALWAYS_OFF
id: "ac_relay_led_red"
pin:
pi4ioe5v6408: pi4ioe5v6408_2
number: 5
inverted: true
mode:
output: true
- platform: gpio
restore_mode: ALWAYS_OFF
id: "ac_relay_led_green"
pin:
pi4ioe5v6408: pi4ioe5v6408_2
number: 6
inverted: true
mode:
output: true
- platform: gpio
restore_mode: ALWAYS_OFF
id: "ac_relay_led_blue"
pin:
pi4ioe5v6408: pi4ioe5v6408_2
number: 7
inverted: true
mode:
output: true
o UI Update the UI display
display:
...
lambda: |-
...
it.print(5, 80, id(font1), Color(orange), "Relays 1-4");
it.filled_rectangle(5, 99, 25, 25, id(r1).state ? id(red) : id(grey));
it.filled_rectangle(34, 99, 25, 25, id(r2).state ? id(red) : id(grey));
it.filled_rectangle(63, 99, 25, 25, id(r3).state ? id(red) : id(grey));
it.filled_rectangle(92, 99, 25, 25, id(r4).state ? id(red) : id(grey));
it.print(141, 80, id(font1), Color(orange), "AC Expansion"); // The AC Relay Expansion
it.filled_rectangle(141, 99, 25, 25, id(ac_r1).state ? id(red) : id(grey));
...
When finishing the configuration, recompile and upload the firmware. Then, you should be able to control additional AC relay in your Home Assistant:

Turn on/off the switch, the UI element on LCD will change accordingly.

StamPLC PoE is an Ethernet control module designed for the StamPLC host. It supports PoE (Power over Ethernet) technology, enabling both data transmission and power supply through a single Ethernet cable. The module integrates a W5500 embedded Ethernet controller with a built-in TCP/IP protocol stack, providing 8 independent hardware sockets, a 10/100M Ethernet data link layer (MAC), and physical layer (PHY). It supports mainstream network communication methods such as UDP and TCP.
To enable PoE functionality, disable the wifi, display, and spi components (remove their declarations/definitions from the configuration file). Then add the following to the original configuration file:
ethernet:
id: ethernet_1
type: W5500
clk_pin: GPIO7
mosi_pin: GPIO8
miso_pin: GPIO9
cs_pin: GPIO11
clock_speed: 20MHz
Save and install, then upload the firmware. Use a PoE switch or router to power the device while providing network connectivity.

Ready for Deployment
With the firmware flashed and your expansion modules configured, your StamPLC is no longer just a piece of hardware—it is now a sophisticated gateway for your automation needs. The beauty of this setup lies in its modularity; whether you are scaling up with StamPLC PoE for high-reliability data or utilizing StamPLC AC relays for heavy-duty switching, the combination with Home Assistant provides a unified, professional interface for it all.
Now that your foundation is built, you can move beyond basic setup and start creating the complex logic, schedules, and automations that make your industrial or home environment truly intelligent.
Industrial Automation at Your Fingertips: A Step-by-Step Guide to Deploying StamPLC within Home Assistant
· It features a generous 5″ TFT touchscreen (1280×720), compatible with LVGL.
· Includes a front-facing 2 MP SC2356 camera (1600×1200) for capturing images and video.
· Equipped with one USB-A port, one USB-C port, and a Micro SD card slot (card not included).
· It has two expansion ports for external sensors (GROVE and M5BUS) and a connector for a LoRa antenna.
· Features two microphones, a speaker, and a 3.5mm jack, meaning you can also use it to control Assist.
· If you chose the "TAB5 Kit," it comes with a Li-ion battery that you can easily replace (allowing you to have a spare one charged and ready).
In short, these characteristics make it the perfect candidate for a portable, autonomous control device with great tactile feedback. Additionally, as it is based on an ESP32-P4, the M5Stack TAB5 can be integrated into HA via ESPHome.
Prerequisites
To integrate the M5Stack TAB5 into HA, you will first need:
· Your M5Stack Tab5 (with or without the battery).
· To have ESPHome installed in Home Assistant.
· A USB-C DATA cable to power the board (you will not be able to install the software with a charge-only cable).
Configuration in ESPHome
Follow these steps to integrate the M5Stack TAB5 into HA:
1. In Home Assistant, go to your ESPHome add-on and click on New device > Continue > New Device Setup.
2. Give your device a name (for example, “M5stack Tab5”) and click “Next.”
3. For the device type, select “ESP32-C6.” You will notice in the background that a new block has been created for your device.
4. Click “Skip” and then click “Edit” on your device's block. Copy the code that appears and save it, as you will need parts of it later.
5. Copy the following code and use it to replace the previous code in ESPHome.
substitutions:
# Device customization
# Personalización del dispositivo
name: m5stack-tab5
friendly_name: M5stack Tab5
####################################
esphome:
name: ${name}
friendly_name: ${friendly_name}
esp32:
board: esp32-p4-evboard
flash_size: 16MB
framework:
type: esp-idf
advanced:
enable_idf_experimental_features: true
esp32_hosted:
variant: esp32c6
active_high: true
clk_pin: GPIO12
cmd_pin: GPIO13
d0_pin: GPIO11
d1_pin: GPIO10
d2_pin: GPIO9
d3_pin: GPIO8
reset_pin: GPIO15
slot: 1
logger:
hardware_uart: USB_SERIAL_JTAG
psram:
mode: hex
speed: 200MHz
api:
encryption:
key: "F8WsdfddfKt1XvQV9pU32443dsfdsf"
ota:
- platform: esphome
password: "sdffds23b12747edfq43543"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "M5Stack-Tab5 Fallback Hotspot"
password: "sdfdMtQR34rfww"
# Sensors configuration
# Configuración de sensores
binary_sensor:
- platform: gpio
id: charging
name: "Charging Status"
pin:
pi4ioe5v6408: pi4ioe2
number: 6
mode: INPUT_PULLDOWN
- platform: gpio
id: headphone_detect
name: "Headphone Detect"
pin:
pi4ioe5v6408: pi4ioe1
number: 7
i2c:
- id: bsp_bus
sda: GPIO31
scl: GPIO32
frequency: 400kHz
pi4ioe5v6408:
- id: pi4ioe1
address: 0x43
# 0: O - wifi_antenna_int_ext
# 1: O - speaker_enable
# 2: O - external_5v_power
# 3: NC
# 4: O - lcd reset
# 5: O - touch panel reset
# 6: O - camera reset
# 7: I - headphone detect
- id: pi4ioe2
address: 0x44
# 0: O - wifi_power
# 1: NC
# 2: NC
# 3: O - usb_5v_power
# 4: O - poweroff pulse
# 5: O - quick charge enable (inverted)
# 6: I - charging status
# 7: O - charge enable
select:
- platform: template
id: wifi_antenna_select
name: "WiFi Antenna"
options:
- "Internal"
- "External"
optimistic: true
on_value:
- if:
condition:
lambda: return i == 0;
then:
- switch.turn_off: wifi_antenna_int_ext
else:
- switch.turn_on: wifi_antenna_int_ext
# The DAC Output select needs to be manually (or with an automation) changed to `LINE1` for the onboard speaker
- platform: es8388
dac_output:
name: DAC Output
adc_input_mic:
name: ADC Input Mic
sensor:
- platform: ina226
address: 0x41
adc_averaging: 16
max_current: 8.192A
shunt_resistance: 0.005ohm
bus_voltage:
name: Battery Voltage
current:
name: Battery Current
# Positive means discharging
# Negative means charging
switch:
- platform: gpio
id: wifi_power
name: "WiFi Power"
pin:
pi4ioe5v6408: pi4ioe2
number: 0
restore_mode: ALWAYS_ON
- platform: gpio
id: usb_5v_power
name: "USB Power"
pin:
pi4ioe5v6408: pi4ioe2
number: 3
- platform: gpio
id: quick_charge
name: "Quick Charge"
pin:
pi4ioe5v6408: pi4ioe2
number: 5
inverted: true
- platform: gpio
id: charge_enable
name: "Charge Enable"
pin:
pi4ioe5v6408: pi4ioe2
number: 7
- platform: gpio
id: wifi_antenna_int_ext
pin:
pi4ioe5v6408: pi4ioe1
number: 0
- platform: gpio
id: speaker_enable
name: "Speaker Enable"
pin:
pi4ioe5v6408: pi4ioe1
number: 1
restore_mode: ALWAYS_ON
- platform: gpio
id: external_5v_power
name: "External 5V Power"
pin:
pi4ioe5v6408: pi4ioe1
number: 2
# Display configuration
# Configuración de la pantalla
esp_ldo:
- voltage: 2.5V
channel: 3
font:
- file: "gfonts://Kanit"
id: font_title
size: 100
light:
- platform: monochromatic
output: backlight_pwm
name: "Display Backlight"
id: backlight
restore_mode: RESTORE_DEFAULT_ON
default_transition_length: 250ms
output:
- platform: ledc
pin: GPIO22
id: backlight_pwm
frequency: 1000Hz
touchscreen:
- platform: gt911
interrupt_pin: GPIO23
update_interval: never
reset_pin:
pi4ioe5v6408: pi4ioe1
number: 5
calibration:
x_min: 0
x_max: 720
y_min: 0
y_max: 1280
id: touch
display:
- platform: mipi_dsi
dimensions:
height: 1280
width: 720
model: M5Stack-Tab5
reset_pin:
pi4ioe5v6408: pi4ioe1
number: 4
show_test_card: true
rotation: 90
lvgl:
touchscreens: touch
buffer_size: 100%
style_definitions:
- id: style_title
align: CENTER
text_font: font_title
widgets:
- label:
styles: style_title
text: 'Hola Aguacater@s!!'
# Media configuration and voice assistant
# Configuración multimedia y asistente de voz
audio_dac:
- platform: es8388
id: es8388_dac
audio_adc:
- platform: es7210
id: es7210_adc
bits_per_sample: 16bit
sample_rate: 16000
i2s_audio:
- id: mic_bus
i2s_lrclk_pin: GPIO29
i2s_bclk_pin: GPIO27
i2s_mclk_pin: GPIO30
media_player:
- platform: speaker
name: None
id: speaker_player
announcement_pipeline:
speaker: tab5_speaker
format: FLAC
sample_rate: 48000
num_channels: 1
on_announcement:
# Stop the wake word (mWW or VA) if the mic is capturing
- if:
condition:
- microphone.is_capturing:
then:
- micro_wake_word.stop:
on_idle:
# Since VA isn't running, this is the end of user-intiated media playback. Restart the wake word.
- if:
condition:
not:
voice_assistant.is_running:
then:
- micro_wake_word.start:
micro_wake_word:
id: mww
models:
- okay_nabu
- hey_mycroft
- hey_jarvis
on_wake_word_detected:
- voice_assistant.start:
wake_word: !lambda return wake_word;
microphone:
- platform: i2s_audio
id: tab5_microphone
i2s_din_pin: GPIO28
sample_rate: 16000
bits_per_sample: 16bit
adc_type: external
# Commented out to avoid duplicates (see above)
# Comentado para evitar duplicidades (ver arriba)
#select:
# The DAC Output select needs to be manually (or with an automation) changed to `LINE1` for the onboard speaker
# - platform: es8388
# dac_output:
# name: DAC Output
# adc_input_mic:
# name: ADC Input Mic
speaker:
- platform: i2s_audio
id: tab5_speaker
i2s_dout_pin: GPIO26
audio_dac: es8388_dac
dac_type: external
channel: mono
buffer_duration: 100ms
bits_per_sample: 16bit
sample_rate: 48000
voice_assistant:
id: va
microphone: tab5_microphone
media_player: speaker_player
micro_wake_word: mww
on_end:
# Wait a short amount of time to see if an announcement starts
- wait_until:
condition:
- media_player.is_announcing:
timeout: 0.5s
# Announcement is finished and the I2S bus is free
- wait_until:
- and:
- not:
media_player.is_announcing:
- not:
speaker.is_playing:
- micro_wake_word.start:
on_client_connected:
- micro_wake_word.start:
on_client_disconnected:
- micro_wake_word.stop:
6. Important note: This code does not include the credentials required for the device to connect to your WiFi and your Home Assistant instance, so you must add them manually. Specifically, I am referring to the following lines from the code you copied in step 4.
# Enable Home Assistant API
api:
encryption:
key: "bg6hash6sjdjsdjk02hh0qnQeYVwm123vdfKE8BP5"
ota:
- platform: esphome
password: "asddasda27aab65a48484502b332f"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Assist Fallback Hotspot"
password: "ZsasdasdHGP2234"
7. What you need to do is find the corresponding lines in the code (at the beginning) and add the relevant information.
8. Now, click "Save" and "Install." Select "Manual download" and wait for the code to compile.
9. Once finished, select the "Modern format" option to download the corresponding '.bin' file.
10. Connect the M5Stack TAB5 to your computer using the USB-C data cable via the side port.
11. Now go to the ESPHome Web page and click "Connect." In the pop-up window, select your board and click "Connect."
12. Now click "Install" and select the '.bin' file obtained in step 9. Click "Install" once more.
13. Return to Home Assistant and go to Settings > Devices & Services. Your device should normally be discovered and appear at the top, simply waiting for you to click the "Configure" button. Otherwise, click the "Add Integration" button, search for "ESPHome," and enter your board's IP address in the "Host" field. As always, I recommend that you assign a static IP in your router to avoid future issues if it changes.
14. Finally, go to Settings > Devices & Services > ESPHome. Click the "Configure" link for your device. In the pop-up window, check the box "Allow the device to perform Home Assistant actions" and click "Submit." This will allow us to control our devices directly from the screen.
If everything went well, you should see the following on your screen:

Additionally, with this code, you will be able to:
· Control and monitor the device's sensors in Home Assistant (such as battery percentage, activating the speaker, turning on the screen…).
· Use the screen to create your control dashboard and manage your devices.
· Expose your M5Stack Tab5 as a media player entity, allowing you to use it to play audio notifications or the radio.
· Use it as a voice assistant if you have already configured Assist.
From here on, the way you use the panel depends on your imagination!
Source: AguacaTEC
Author: TitoTB
Turn M5Stack Tab5 into a Portable Home Assistant Control Panel
git clone https://huggingface.co/AXERA-TECH/immich
File Description:
m5stack@raspberrypi:~/rsp/immich $ ls -lh
total 421M
drwxrwxr-x 2 m5stack m5stack 4.0K Oct 10 09:12 asset
-rw-rw-r-- 1 m5stack m5stack 421M Oct 10 09:20 ax-immich-server-aarch64.tar.gz
-rw-rw-r-- 1 m5stack m5stack 0 Oct 10 09:12 config.json
-rw-rw-r-- 1 m5stack m5stack 7.6K Oct 10 09:12 docker-deploy.zip
-rw-rw-r-- 1 m5stack m5stack 104K Oct 10 09:12 immich_ml-1.129.0-py3-none-any.whl
-rw-rw-r-- 1 m5stack m5stack 9.4K Oct 10 09:12 README.md
-rw-rw-r-- 1 m5stack m5stack 177 Oct 10 09:12 requirements.txt
unzip docker-deploy.zip
cp example.env .env
4. Start the container
docker compose -f docker-compose.yml -f docker-compose.override.yml up -d
If started successfully, the information is as follows:
m5stack@raspberrypi:~/rsp/immich $ docker compose -f docker-compose.yml -f docker-compose.override.yml up -d
WARN[0000] /home/m5stack/rsp/immich/docker-compose.override.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 3/3
✔ Container immich_postgres Started 1.0s
✔ Container immich_redis Started 0.9s
✔ Container immich_server Started 0.9s
(mich) m5stack@raspberrypi:~/rsp/immich $ python -m immich_ml
[10/10/25 09:50:12] INFO Starting gunicorn 23.0.0
[10/10/25 09:50:12] INFO Listening at: http://[::]:3003 (8698)
[10/10/25 09:50:12] INFO Using worker: immich_ml.config.CustomUvicornWorker
[10/10/25 09:50:12] INFO Booting worker with pid: 8699
2025-10-10 09:50:13.589360675 [W:onnxruntime:Default, device_discovery.cc:164 DiscoverDevicesForPlatform] GPU device discovery failed: device_discovery.cc:89 ReadFileContents Failed to open file: "/sys/class/drm/card1/device/vendor"
[INFO] Available providers: ['AXCLRTExecutionProvider']
/home/m5stack/rsp/immich/mich/lib/python3.11/site-packages/immich_ml/models/clip/cn_vocab.txt
[10/10/25 09:50:16] INFO Started server process [8699]
[10/10/25 09:50:16] INFO Waiting for application startup.
[10/10/25 09:50:16] INFO Created in-memory cache with unloading after 300s
of inactivity.
[10/10/25 09:50:16] INFO Initialized request thread pool with 4 threads.
[10/10/25 09:50:16] INFO Application startup complete.
In your browser, enter the Raspberry Pi IP address and port 3003, for example: 192.168.20.27:3003
Note: The first visit requires registering an administrator account; the account and password are saved locally.

Once configured, you can upload images.

The first time, you need to configure the machine learning server. Refer to the diagram below to enter the configuration.

Set the URL to the Raspberry Pi IP address and port 3003, e.g., 192.168.20.27:3003.
If using Chinese search for the CLIP model, set it to ViT-L-14-336-CN__axera; for English search, set it to ViT-L-14-336__axera.

After setup, save the configuration.

The first time, you need to manually go to the Jobs tab and trigger SMART SEARCH.

Enter the description of the image in the search bar to retrieve relevant images.

Through this hands-on project, we’ve not only built a powerful smart photo album platform, but also experienced the exceptional performance of the M5Stack LLM‑8850 Card in edge AI computing. Whether setting up a private photo album on your Raspberry Pi or deploying intelligent image processing in security scenarios, the M5Stack LLM‑8850 Card delivers efficient, stable computing power you can rely on.
It brings AI closer to where your data resides, enabling faster, more secure processing and turning your ideas into reality. If you’re looking for a solution for on-device AI inference, give M5Stack LLM‑8850 Card a try — it might just become the core engine of your next project.
LLM‑8850 Card in Action: Creating an AI‑Powered Photo Management Platform with Immich
l Prerequisites
l Mounting and configuring the LoRa Gateway
l LoRa node configuration
l Check the communication
l Sending information
l Customize your Gateway
l Acknowledgments
What is LoRa and how does it work?
LoRa (an acronym for "Long Range") is a radio frequency communication protocol that enables long-distance data transmission (up to 10 km in open fields) with very low power consumption. Therefore, it offers two major advantages:
However, it also has its limitations, as its data transfer speed is slow. In practice, this means it's perfect for sending simple data (commands to our devices, numbers, or text strings), but it's not a suitable protocol for transmitting photos or videos.
Additionally, you should consider the frequency LoRa uses in your geographic area. For example, in Europe it's 868 MHz, while in the US and most of Latin America it's 915 MHz.
Prerequisites
To integrate LoRa into Home Assistant, you will need the following components:
Mounting and configuring the LoRa Gateway
We are going to be using the M5Stack Core S3 SE along with the LoRa868 V1.1 module (now the LoRa868 v1.2 module is available). This is a modular device that's very easy to expand by simply assembling the components.

Something important to keep in mind is that the LoRa module has some small switches on the back ('DIP switches') that modify the pin assignment, and logically, it must match what we indicate in the ESPHome code.
To do this, make sure the switches are in the following position (2, 6 and 7 on and the rest off).

From here, the process will be similar for any compatible motherboard (adapting the steps and connection diagram to the specifications of your device). The steps we followed are as follows:
1. In Home Assistant, go to your ESPHome plugin , tap “New device” and “Continue.”
2. Give your device a name (for example, “LoRa Gateway” ) and click “Next”.
3. Select “ESP32-S3” as the device type . You'll notice that a new block has been created for your device in the background.
4. Click “Skip” and click “Edit” above your device block.
5. Add the following lines to the end of your code (which come directly from the ESPHome SX127x component, adapted to our device).
captive_portal:
spi:
clk_pin: GPIO36
mosi_pin: GPIO37
miso_pin: GPIO35
sx127x:
cs_pin: GPIO6
rst_pin: GPIO7
dio0_pin: GPIO10
pa_pin: BOOST
pa_power: 14
bandwidth: 125_0kHz
crc_enable: true
frequency: 868920000
modulation: LORA
rx_start: true
sync_value: 0x12
spreading_factor: 7
coding_rate: CR_4_5
preamble_size: 8
on_packet:
then:
- lambda: |-
ESP_LOGD("lambda", "packet %s", format_hex(x).c_str());
ESP_LOGD("lambda", "rssi %.2f", rssi);
ESP_LOGD("lambda", "snr %.2f", snr);
button:
- platform: template
name: "Transmit Packet"
on_press:
then:
- sx127x.send_packet:
data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]
6. Click “Save” and “Install.” Select “Manual download” and wait for the code to compile.
7. When finished, select the “Modern format” option to download the corresponding '.bin' file.
8. Connect the M5Stack Core S3 SE to your computer using the USB-C data cable via the port on the side.
9. Now go to the ESPHome page and click "Connect." In the pop-up window, select your board and click "Connect."
10. Now click on “Install” and select the '.bin' file obtained in step 7. Again, click on “Install”.
11. Return to Home Assistant and go to Settings > Devices & Services. Your device should have been discovered and appear at the top, waiting for you to press the "Configure" button. Otherwise, click the "Add integration" button, search for "ESPHome," and enter your board's IP address in the "Host" field. As always, we recommend assigning a static IP address to your router to avoid future issues if it changes.
LoRa node configuration
Now that we have our LoRa gateway, let's configure a node to send information to it. To do this, we'll follow steps very similar to those in the previous section:
1. In Home Assistant, go to your ESPHome plugin , tap “New device” and “Continue.”
2. Give your device a name (for example, “LoRa Node” ) and click “Next”.
3. Select “ESP32” as the device type . You'll notice a new block has been created for your device in the background.
4. Click “Skip” and click “Edit” above your device block.
5. Add the following lines to the end of your code (which in this case match the example of the SX127x component of ESPHome).
captive_portal:
spi:
clk_pin: GPIO5
mosi_pin: GPIO27
miso_pin: GPIO19
# Example configuration entry
sx127x:
cs_pin: GPIO18
rst_pin: GPIO23
dio0_pin: GPIO26
pa_pin: BOOST
pa_power: 14
bandwidth: 125_0kHz
crc_enable: true
frequency: 868920000
modulation: LORA
rx_start: true
sync_value: 0x12
spreading_factor: 7
coding_rate: CR_4_5
preamble_size: 8
on_packet:
then:
- lambda: |-
ESP_LOGD("lambda", "packet %s", format_hex(x).c_str());
ESP_LOGD("lambda", "rssi %.2f", rssi);
ESP_LOGD("lambda", "snr %.2f", snr);
button:
- platform: template
name: "Transmit Packet"
on_press:
then:
- sx127x.send_packet:
data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]
6. Note that the pin assignment is different (because we're using a different device than the one we used for the Gateway), but the rest of the configuration is exactly the same as in the previous section. This is important so they can communicate with each other.
7. Click “Save” and “Install.” Select “Manual download” and wait for the code to compile.
8. When finished, select the “Modern format” option to download the corresponding '.bin' file.
9. Connect the board to your computer using the Micro USB data cable through the port on the side.
10. Now go to the ESPHome page and click "Connect." In the pop-up window, select your board and click "Connect."
11. Now click on “Install” and select the '.bin' file obtained in step 8. Again, click on “Install”.
12. Return to Home Assistant and go to Settings > Devices & Services . Your device should have been discovered and appear at the top, waiting for you to press the "Configure" button . Otherwise, click the "Add integration" button, search for "ESPHome," and enter your board's IP address in the "Host" field. As always, we recommend assigning a static IP address to your router to avoid future issues if it changes.
Check the communication
Let's do a little test to check that both devices are communicating correctly (the Gateway and the node) .
1. Make sure both devices are turned on and are online in Home Assistant and ESPHome.
2. From Home Assistant, go to Settings > Devices & Services > ESPHome and access one of them (for example, the Gateway).
3. Open a new window (without closing the previous one), enter the ESPHome plugin and access the logs of the other device (in this case, the node).
4. In the Home Assistant window, click the "Transmit Packet" button. You'll immediately see the logs from the second device recording the incoming packet.

You can perform a reverse test to verify that communication is working both ways. If everything went well, your devices are now communicating.
Sending information
Logically, the point of integrating LoRa into Home Assistant is to send some kind of useful information (such as the value of a sensor connected to the node).
1. The first step is to add the sensor you're interested in to the node board. For example, we're going to add a PIR sensor to get the long-awaited motion sensor on the mailbox. To do this, we've added the following code snippet:
binary_sensor:
- platform: gpio
pin: GPIO34
name: "PIR Sensor"
device_class: motion
id: pir_sensor
2. If you look at the code above, it's the same one we would use in any "normal" scenario. However, to send the information to our LoRa Gateway, we need to add something extra using the 'Packet Transport' component.
packet_transport:
platform: sx127x
update_interval: 5s
encryption: "password"
rolling_code_enable: true
binary_sensors:
- pir_sensor
3. Analyze the code above and observe the following:
· In the 'encryption' attribute, you have to indicate the encryption key for your message (whatever you want), so that it cannot be received by anyone on the same frequency.
· We've identified the ID of the sensor we want to send (in this case, the binary sensor with the ID "pir_sensor") . You can add any other sensors you're interested in here.
4. Now we are going to add the following to the code of our LoRa Gateway, so that it receives the information.
packet_transport:
platform: sx127x
update_interval: 5s
providers:
- name: lora-node
encryption: "password"
binary_sensor:
- platform: packet_transport
id: pir_sensor
provider: lora-node
- platform: template
name: "Buzón"
device_class: motion
lambda: return id(pir_sensor).state;
5. Now we’re going to add the following to the code of our LoRa Gateway, so it can receive the information.
Again, analyze the code and note the following:
l We have specified the ESPHome device name of our LoRa node as the data provider.
l In the ‘encryption’ attribute, we have indicated exactly the same key as in the node.
l To transform the information received into a gateway sensor, we used the “packet_transport” platform. We assigned it an “id” (you can choose any) and again indicated the LoRa node name as the provider. This is an internal ESPHome sensor.
l To display this information in Home Assistant, we created a template sensor of the same type, assigning it the value of the internal sensor created in the previous step.
6. And that's it! If you now check your gateway device in Home Assistant, you’ll see that it already shows the information from the node.

Customize your Gateway
Since we used the M5Stack Core S3 SE to integrate LoRa into Home Assistant, we can take advantage of its other features to customize it! Below, we're leaving you the full code to create a screen that notifies you when you receive letters in your mailbox!

esphome:
name: lora-gateway
friendly_name: LoRa Gateway
libraries:
- m5stack/M5GFX@^0.1.11
- m5stack/M5Unified@^0.1.11
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
psram:
mode: octal
speed: 80MHz
external_components:
- source:
type: git
url: https://github.com/m5stack/M5CoreS3-Esphome
components: [ m5cores3_display ]
refresh: 0s
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "1QrsXUgryxlF6OGsIwLj7eijyy/OMhSobQQHYWPvpb0="
ota:
- platform: esphome
password: "4844c4205ab6ab665c2d1a4be82deb57"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Lora-Gateway Fallback Hotspot"
password: "6BRaaV17Iebb"
captive_portal:
spi:
clk_pin: GPIO36
mosi_pin: GPIO37
miso_pin: GPIO35
sx127x:
cs_pin: GPIO6
rst_pin: GPIO7
dio0_pin: GPIO10
pa_pin: BOOST
pa_power: 14
bandwidth: 125_0kHz
crc_enable: true
frequency: 868920000
modulation: LORA
rx_start: true
sync_value: 0x12
spreading_factor: 7
coding_rate: CR_4_5
preamble_size: 8
on_packet:
then:
- lambda: |-
ESP_LOGD("lambda", "packet %s", format_hex(x).c_str());
ESP_LOGD("lambda", "rssi %.2f", rssi);
ESP_LOGD("lambda", "snr %.2f", snr);
packet_transport:
platform: sx127x
update_interval: 5s
providers:
- name: lora-node
encryption: "password"
binary_sensor:
- platform: packet_transport
id: pir_sensor
provider: lora-node
- platform: template
name: "Buzón"
device_class: motion
lambda: return id(pir_sensor).state;
color:
- id: green
hex: 'bfea11'
- id: red
hex: 'ff0000'
font:
- file: "gfonts://Roboto"
id: font_title
size: 18
- file: "gfonts://Roboto"
id: font_text
size: 16
image:
- file: mdi:mailbox
id: buzon_off
resize: 100x100
type: grayscale
transparency: alpha_channel
- file: mdi:email-alert
id: buzon_on
resize: 100x100
type: grayscale
transparency: alpha_channel
display:
- platform: m5cores3_display
model: ILI9342
dc_pin: 15
update_interval: 1s
id: m5cores3_lcd
lambda: |-
// Obtener dimensiones de la pantalla
int screen_width = it.get_width();
int screen_height = it.get_height();
// Título en la parte superior con margen de 20px
it.print(screen_width/2, 20, id(font_title), id(green), TextAlign::TOP_CENTER, "LoRa Gateway by Aguacatec");
// Obtener estado del sensor del buzón
bool mailbox_open = id(pir_sensor).state;
if (mailbox_open) {
// Buzón abierto - icono rojo
it.image(110, 70, id(buzon_on), id(red));
it.print(screen_width/2, 200, id(font_text), id(red), TextAlign::CENTER, "Carta recibida!!");
} else {
// Buzón cerrado - icono verde
it.image(110, 70, id(buzon_off), id(green));
it.print(screen_width/2, 200, id(font_text), id(green), TextAlign::CENTER, "No hay correspondencia");
}
Acknowledgements
To prepare this post, this video by our friend Miguel Ángel (from La Choza Digital) was extremely helpful!
Source: AguacaTEC
Author: TitoTB
Build a Long‑Range LoRa Gateway for Home Assistant with M5Stack
May 26, 2026 — M5Stack, a global provider of modular IoT and embedded development platforms, today announced the launch of CardputerZero, a new handheld Linux...
May. 22, 2026 – M5Stack, a global leader in modular IoT and embedded development platforms, today announced the launch of StopWatch, a round AMOLED-based expressive...
Feb. 6, 2026 – M5Stack, a global leader in modular IoT and embedded development platforms, today announced the release of AI Pyramid series, comprising two...
Jan. 23, 2026 – M5Stack, a global leader in modular IoT and embedded development platforms, today announced the launch of StickS3, the latest addition to...
Jan.2026, M5Stack officially announced its collaboration with SquareLine Vision, a next-generation UI design platform built to simplify and accelerate graphical interface development for embedded systems. As...
Jan. 13, 2026 — M5Stack, a global leader in modular IoT and embedded development platforms, today launched StackChan, the first community-co-created open-source AI desktop robot, built on a...
On November 17, 2025, M5Stack once again hosted its annual Open Day, welcoming global users and enthusiasts. This year’s event reached a new milestone, bringing...
Nov. 12, 2025–M5Stack, a global leader in modular IoT and embedded development platforms, today announced Arduino Nesso N1, a compact and powerful development kit co‑engineered with Arduino,...
With the outstanding modular design, excellent user experience, and innovative integration of hardware and software ecosystems, the M5Stack Series was honored with the 2025 Good...
M5Stack showcased its latest breakthroughs in modular IoT, edge computing, and smart automation at The Things Conference 2025, held at De Kromhouthal, Amsterdam — the...
September 5, 2025 – M5Stack, a global leader in modular IoT and embedded development platforms, today announced the launch of Cardputer‑Adv, the upgraded model of...
May 9, 2025 – M5Stack, a leader in modular IoT and embedded development platforms, unveils Tab5, a next-generation 5-inch smart touch terminal powered by the advanced 400MHz ESP32-P4...