{"slug": "raspberry-pi-picow-lerobot-so-arm100-controlled-via-a-webpage-mqtt-openai", "title": "Raspberry Pi PicoW + LeRobot SO-ARM100 controlled via a webpage/mqtt/openai", "summary": "Developer AdrianCX released picohive-robotarm, an open-source firmware that runs a standalone Raspberry Pi Pico W or Pico 2 W controller for LeRobot SO-100/SO-101 arms, controllable over Wi-Fi through a built-in web page, MQTT, or an OpenAI Responses API-compatible endpoint. The firmware builds via os/build_via_podman.sh for pico_w, pico2_w, or a Linux simulation with simulated servos, and the developer reports 150KB of free heap in the worst case on the Pico. Setup follows LeRobot's procedure: assign servo IDs at 115200 baud, calibrate joint limits from the web page, and map 3D positions so the arm knows orientation before sending targets.", "body_md": "Standalone Raspberry Pi Pico W / Pico 2 W controller for an [SO-101 / SO-100](https://github.com/TheRobotStudio/SO-ARM100) arm\n\nCan control over WiFi via an internal Web Page, MQTT or openAI response API compatible remote\\\n\nVideo: [https://www.youtube.com/shorts/e_Y3U83MK2A](https://www.youtube.com/shorts/e_Y3U83MK2A)\n\nI had an RC car and a LeRobot SO-ARM100 and wanted to see if I can combine them and use an LLM to control...\n\nThe arm is drawn in 3D from what the servos report; click a dot to put a target down, **Go** (or Enter) sends the jaws there.\n\n| Calibration | AI | Drive | \n|---|---|---|\n\n- **Calibration** : set up limits for joints so arm doesn't self destruct... (don't ask)\n- **3D mapping** : tell robot which way is left or up\n- **Poses** : various poses described for openAI LLM knowledge base\n- **AI** : chat box with status responses. The microphone needs https\n- **Drive** : Virtual joystick to control the wheels, or you can connect a gamepad\n\n1. \n**Picohive***(optional)* - for Debug logs and OTA updates\n Add Device on[picohive](https://picohive.com) (generate the UUID, MQTT password and log key, pick a name)\n Open the device, go to**Device Config** , press**Export** and copy the line for step 4 below\n2. \n**OpenAI***(optional)* - for AI chat box\n An API key and a model (ex:`gpt-6.1-sol` ) on a server that has responses API with storage\n\n1. **Flash** a pico, it starts as access point`picow_config` /`randompassword` (...ultra secure password...)\n2. **Connect** to the access point, the page opens by itself, if not, use[http://192.168.4.1](http://192.168.4.1)\n3. **Configure wifi** and a user/pass for the web ui\n4. **Optional** :\n 4.1.**Remote server** enter line from picohive for logging/OTA/crash reporting\n 4.2.**OpenAI** enter the URL, key, model and prompt\n5. **Reboot** - joins your wifi, you can access via its new IP now (find it in picohive logs or on router)\n6. **Reconfigure** any time from its new ip address\n\nTip\n\nIf you need to wipe, just use the [universal `flash_nuke.uf2`](https://github.com/Gadgetoid/pico-universal-flash-nuke) to wipe the flash then re-flash the firmware\n\nThis follows LeRobot, in short:\n\n1. \nAdd servos one at a time to pico to set their IDs to not overlap (and baud rate to 115200, 1M was too much for my setup with 1K resistor)\n2. \nBuild up the arm and connect things\n3. \nCalibrate from web page (just press the calibrate and move the arm by hand so it learns limits)\n4. \nGo to 3D model and map some positions so it knows left from right and up from down...\n\n```\ngit clone --recursive https://github.com/AdrianCX/picohive-robotarm.git\ncd picohive-robotarm\nos/build_via_podman.sh pico2_w      # or pico_w\n```\n\nFlash `build/<board>/robotarm.uf2`\nLater updates for OTA need the encrypted file `robotarm.uf2.encrypted`\nBefore you build your own, create your own OTA keys and certificate, as described in [os/docs/ota.md](https://github.com/AdrianCX/picohive-robotarm/blob/main/os/docs/ota.md). The HTTPS certificate is `util/make_cert.sh <address>`.\n\nThe same app builds on Linux with simulated servos \n\nUseful to work on web page with valgrind and gdb\n\n```\nos/build_via_podman.sh linux        # build/linux/robotarm\nos/run_via_podman.sh                # http://localhost:8080, https://localhost:8443\nos/run_via_podman.sh --valgrind     # or --gdb\n[2026-10-25 13:52:12] 192.168.100.69 657 app[build/pico_w/robotarm] version[1.0] os[b697060-dirty] buildid[db40f1ac39e2b3ee3d07d2199aa628118cf588b3] Heap[12308/223652] Free[211344] MinFree[151552] LargestFree[192458] Stack[4236/16384] lastRestartReason[reboot_command]\n```\n\nThere's quite a lot of free memory on pico even in worst case (150KB), stack usage is reasonable\n\nWiring (defaults in `src/config/general_config.h`, change them there if you wire it differently):\n\n- Servo bus: GPIO 0 (uart0 tx) through 1k, and GPIO 1 (rx), both onto the servos' data wire, 115200 baud (`ARM_BAUDRATE` )\n- Servos: 12V and ground straight from the supply, the Pico's ground joins them\n- Front DRV8833: left front on GPIO 17/16, right front on GPIO 18/19\n- Rear DRV8833: left rear on GPIO 15/14, right rear on GPIO 12/13 (forward/back of each)\n- GPIO 20 to both drivers' sleep (EEP), held high\n- Pico: 5V from a buck converter into VSYS\n\nThe bus is half duplex - one data wire shared by every servo. The pico's pins are 3.3V: check a servo's data wire idles at or below that, or put a level shifter in between. The Waveshare bus servo driver board does all of this already, and plugs into the same two pins.\n\nTwo pins of one motor share a PWM slice (gpio/2 % 8, even A, odd B), keep that if you move them. `MOTOR_PWM 1` drives the pins as PWM, 0 is on/off.\n\nThe diagram is generated: `python3 docs/pictures/wiring.py docs/pictures/wiring.svg`\n\nArm:\n\n- [SO-101](https://github.com/TheRobotStudio/SO-ARM100) printed parts, or a kit\n- 6x STS3215 servos, 12V\n- 2 batteries (26650)\n- Printed parts for this build in `stl/`\n\nElectronics:\n\n- [Raspberry Pi Pico 1 W] - you should use Pico2 to add a camera later\n- 5V buck converter for Pico (mini360 is fine)\n- 1k resistor\n- 2x [DRV8833 motor driver](https://www.tinytronics.nl/en/mechanics-and-actuators/motor-controllers-and-drivers/stepper-motor-controllers-and-drivers/drv8833-bipolar-stepper-motor-and-dc-motor-motor-controller)\n\nChassis *(optional)*:\n\n- 4x DC motors and wheels\n\nAGPL-3.0-or-later for this app. The `os/` submodule is MPL-2.0, see its LICENSE.", "url": "https://wpnews.pro/news/raspberry-pi-picow-lerobot-so-arm100-controlled-via-a-webpage-mqtt-openai", "canonical_source": "https://github.com/AdrianCX/picohive-robotarm", "published_at": "2026-10-25 20:52:34+00:00", "updated_at": "2026-10-25 21:12:19.176809+00:00", "lang": "en", "topics": ["robotics", "ai-agents", "ai-tools", "developer-tools", "large-language-models"], "entities": ["Raspberry Pi Pico W", "Raspberry Pi Pico 2 W", "LeRobot SO-ARM100", "SO-101", "AdrianCX", "picohive", "OpenAI", "DRV8833"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/raspberry-pi-picow-lerobot-so-arm100-controlled-via-a-webpage-mqtt-openai", "markdown": "https://wpnews.pro/news/raspberry-pi-picow-lerobot-so-arm100-controlled-via-a-webpage-mqtt-openai.md", "text": "https://wpnews.pro/news/raspberry-pi-picow-lerobot-so-arm100-controlled-via-a-webpage-mqtt-openai.txt", "jsonld": "https://wpnews.pro/news/raspberry-pi-picow-lerobot-so-arm100-controlled-via-a-webpage-mqtt-openai.jsonld"}}