{"id":35881757,"url":"https://github.com/tscholze/dotnet-iot-raspberrypi-tobot","last_synced_at":"2026-01-08T18:04:19.072Z","repository":{"id":329734986,"uuid":"1097772117","full_name":"tscholze/dotnet-iot-raspberrypi-tobot","owner":"tscholze","description":"Modern robotics meets modern .NET - A unified C# driver and demo platform for Pimoroni Explorer HAT, Pan-Tilt HAT, and ultrasonic sensors on Raspberry Pi","archived":false,"fork":false,"pushed_at":"2025-12-21T12:55:26.000Z","size":3811,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-23T04:00:25.148Z","etag":null,"topics":["blazor","csharp","dotnet","gpio","micropython-rpi-pico","pimoroni","pimoroni-explorer","pimoroni-tilt-and-pan-hat","raspberry-pi","rpi-pico"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tscholze.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-16T19:49:49.000Z","updated_at":"2025-12-21T12:55:30.000Z","dependencies_parsed_at":"2025-12-23T04:00:34.953Z","dependency_job_id":null,"html_url":"https://github.com/tscholze/dotnet-iot-raspberrypi-tobot","commit_stats":null,"previous_names":["tscholze/dotnet-iot-raspberrypi-tobot"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/tscholze/dotnet-iot-raspberrypi-tobot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tscholze%2Fdotnet-iot-raspberrypi-tobot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tscholze%2Fdotnet-iot-raspberrypi-tobot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tscholze%2Fdotnet-iot-raspberrypi-tobot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tscholze%2Fdotnet-iot-raspberrypi-tobot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tscholze","download_url":"https://codeload.github.com/tscholze/dotnet-iot-raspberrypi-tobot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tscholze%2Fdotnet-iot-raspberrypi-tobot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28247288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2026-01-08T02:00:06.591Z","response_time":241,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blazor","csharp","dotnet","gpio","micropython-rpi-pico","pimoroni","pimoroni-explorer","pimoroni-tilt-and-pan-hat","raspberry-pi","rpi-pico"],"created_at":"2026-01-08T18:01:53.555Z","updated_at":"2026-01-08T18:04:19.058Z","avatar_url":"https://github.com/tscholze.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Avatar](_docs/avatar_3.png)\n\n# 🤖 Tobot - .NET Robotics Platform for Raspberry Pi\n\n\u003e **Modern robotics meets modern .NET** - A unified C# driver and demo platform for Pimoroni Explorer HAT, Pan-Tilt HAT, and ultrasonic sensors on Raspberry Pi\n\n[![.NET 10](https://img.shields.io/badge/.NET-10.0-512BD4?logo=dotnet)](https://dotnet.microsoft.com/)\n[![C# 13](https://img.shields.io/badge/C%23-13.0-239120?logo=csharp)](https://docs.microsoft.com/en-us/dotnet/csharp/)\n[![Raspberry Pi](https://img.shields.io/badge/Raspberry%20Pi-Compatible-C51A4A?logo=raspberry-pi)](https://www.raspberrypi.org/)\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n\n---\n\n## ? What is Tobot?\n\n**Tobot** is a complete .NET robotics platform combining custom 3D-printed hardware with professional-grade software to create a powerful, extensible robot built for the future. Based on a collection of exceptional **Pimoroni** components (Explorer HAT Pro, Pan-Tilt HAT, Stack HAT, Blinkt!, and more), Tobot features a **fully custom-designed chassis** that you can print and assemble yourself on compact 3D printers.\n\nAt its core, Tobot is designed to run on **two Raspberry Pi boards** working in tandem—providing ample compute power for computer vision, machine learning, autonomous navigation, and real-time control. One Pi handles hardware interfacing and motor control, while the second can focus on AI workloads, web services, or video processing.\n\nThe software stack centers around the `TobotController`, a unified C# API that orchestrates every sensor, motor, LED, and servo. Whether you're building your first robot, teaching programming, experimenting with edge AI, or creating a sophisticated autonomous system, Tobot provides everything you need in a clean, scalable, and well-documented platform.\n\n### ✨ Why Tobot?\n\n- **⚡ Modern C#** - Leverage C# 13 and .NET 10 features for robotics\n- **📦 Package-Based Architecture** - Logical organization by functionality\n- **📚 Comprehensive Documentation** - XML docs on every member, extensive guides\n- **🎯 Ready-to-Run Demos** - Interactive examples for every feature\n- **🔌 Unified Controller** - One `TobotController` surfaces every LED, motor, sensor, and servo\n- **✅ Production Ready** - Robust error handling and resource management\n- **🎓 Educational** - Perfect for learning robotics and C# together\n\n---\n\n## How it looks\n\n### Tobot\n\u003cdiv align=\"center\" style=\"display:flex; gap:12px; justify-content:center; flex-wrap:wrap;\"\u003e\n    \u003cimg src=\"_docs/bot-1.jpeg\" alt=\"Tobot robot build\" height=\"260\" /\u003e\n    \u003cimg src=\"_docs/bot-2.jpeg\" alt=\"Frame front\" height=\"260\" /\u003e\n    \u003cimg src=\"_docs/bot-3.jpeg\" alt=\"Frame back\" height=\"260\" /\u003e\n\u003c/div\u003e\n\n### Tobot.Web\n\u003cdiv align=\"center\" style=\"display:flex; gap:12px; justify-content:center; flex-wrap:wrap;\"\u003e\n    \u003cimg src=\"_docs/web-home-1.png\" alt=\"Web remote home screen\" height=\"260\" /\u003e\n\u003c/div\u003e\n\n### Tobo.PicoRemote\n\u003cdiv align=\"center\" style=\"display:flex; gap:12px; justify-content:center; flex-wrap:wrap;\"\u003e\n    \u003cimg src=\"_docs/pico-remote-1.jpeg\" alt=\"Pico remote handheld controller\" height=\"260\" /\u003e\n\u003c/div\u003e\n\n### CAD constructions\n\u003cdiv align=\"center\" style=\"display:flex; gap:12px; justify-content:center; flex-wrap:wrap;\"\u003e\n    \u003cimg src=\"_docs/cad-1.png\" alt=\"CAD of the chassis\" height=\"260\" /\u003e\n    \u003cimg src=\"_docs/cad-2.png\" alt=\"CAD of the remote\" height=\"260\" /\u003e\n\u003c/div\u003e\n---\n\n## What Tobot is Based On\n\n### 🏗️ Chassis\n\nThe Tobot chassis is **fully custom designed** and optimized for accessibility and ease of manufacturing. All parts are specifically engineered to fit on **small 3D printers** like the **BambuLab A1 mini**, making it possible to build your own robot without needing industrial-scale equipment.\n\n**Key Features:**\n- Optimized for compact bed sizes (180×180mm print area)\n- Uses standard **PLA filament** - no exotic materials needed\n- Compatible with eco-friendly filament from [Recycling Fabrik](https://www.recyclingfabrik.com/) or [BambuLab](https://bambulab.com/)\n- Modular design for easy assembly and modifications\n- All STL files available in the repository for customization\n\nWhether you're a hobbyist with a small printer or an educator setting up a classroom fleet, the Tobot chassis is designed to be practical, affordable, and sustainable.\n\n---\n\n### 🔧 Hardware\n\nTobot's hardware foundation is built on exceptional components from the amazing team at [**Pimoroni**](https://shop.pimoroni.com/), a company renowned for their creativity, quality, and maker-friendly products.\n\n**Core Components:**\n\n| Component                                                                                                                            | Description                                                           | Shop Link                                                                                                                 |\n| ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |\n| **[Explorer HAT Pro](https://shop.pimoroni.com/products/explorer-hat)**                                                              | Motor drivers, LEDs, analog inputs, digital I/O, and capacitive touch | [Buy Now](https://shop.pimoroni.com/products/explorer-hat)                                                                |\n| **[pHAT Stack HAT](https://shop.pimoroni.com/products/phat-stack?srsltid=AfmBOooMtYout7YyKwNvmt7mzZK2IQPd3pf0JJF4NLPTJSem_P65BVwC)** | Stacking connector for adding multiple HATs                           | [Buy Now](https://shop.pimoroni.com/products/phat-stack?srsltid=AfmBOooMtYout7YyKwNvmt7mzZK2IQPd3pf0JJF4NLPTJSem_P65BVwC) |\n| **[Pan-Tilt HAT](https://shop.pimoroni.com/products/pan-tilt-hat)**                                                                  | Servo-driven camera mount for dynamic viewing                         | [Buy Now](https://shop.pimoroni.com/products/pan-tilt-hat)                                                                |\n| **[Blinkt!](https://shop.pimoroni.com/products/blinkt)**                                                                             | 8 RGB LED strip for visual feedback                                   | [Buy Now](https://shop.pimoroni.com/products/blinkt)                                                                      |\n\n**Additional Components:**\n- HC-SR04 ultrasonic distance sensor\n- Standard jumper wires for flexible connections\n- Raspberry Pi (any 40-pin GPIO model)\n- 5V power supply (adequate for servos and motors)\n\n**Current Setup:**  \nThe prototype uses **jumper wires** to connect components, providing flexibility during development and easy debugging. Future iterations may include custom PCBs or ribbon cable solutions for cleaner integration.\n\n**Why Pimoroni?**  \nPimoroni's products are thoughtfully designed, thoroughly documented, and backed by an active community. Their commitment to open-source hardware and education aligns perfectly with Tobot's mission.\n\n---\n\n### 💻 Software\n\nTobot is built entirely on the **modern .NET ecosystem**, leveraging cutting-edge frameworks and libraries to deliver a professional, maintainable, and powerful robotics platform.\n\n**Technology Stack:**\n\n| Layer                       | Technology                 | Purpose                                      |\n| --------------------------- | -------------------------- | -------------------------------------------- |\n| **Framework**               | .NET 10                    | Modern runtime with C# 13 language features  |\n| **Web UI**                  | ASP.NET Core Blazor        | Interactive, real-time web interface         |\n| **Real-time Communication** | SignalR                    | Bidirectional communication for live updates |\n| **Hardware Access**         | System.Device.Gpio NuGet   | Low-level GPIO, I2C, PWM control             |\n| **Operating System**        | Raspberry Pi OS (Bookworm) | Official, stock Raspberry Pi distribution    |\n| **System Telemetry**        | Tobot.Pi                   | Hostname, Wi‑Fi SSID/IP, temp, load, mem, disk, uptime, freq |\n\n**Why .NET?**\n- **Cross-platform**: Runs natively on ARM-based Raspberry Pi\n- **Performance**: Compiled code with optimized memory management\n- **Tooling**: World-class IDEs (Visual Studio, VS Code) with IntelliSense and debugging\n- **Modern Language**: C# 13 with pattern matching, async/await, and strong typing\n- **Ecosystem**: NuGet package ecosystem with thousands of libraries\n- **Long-term Support**: Microsoft's commitment to .NET on IoT\n\n**Architecture Highlights:**\n- **Unified Controller**: `TobotController` abstracts all hardware complexity\n- **Package-based Organization**: Clean separation of concerns by functionality\n- **XML Documentation**: Every public API is fully documented\n- **Async/Await**: Non-blocking operations for responsive control\n- **Resource Safety**: Proper disposal patterns throughout\n\nNo custom kernel modules, no modified OS images - just standard Raspberry Pi OS with .NET SDK installed. This makes Tobot easy to set up, maintain, and extend.\n\n---\n\n## ⚡ Quick Demo\n\n```csharp\nusing Tobot.Device;\n\n// Initialize the unified controller (all hats + sensors)\nusing var controller = new TobotController();\n\n// Light show!\ncontroller.SetAllLeds(true);\n\n// Drive forward\ncontroller.DriveMotors(100, 100);\n\n// React to sensors\nif (controller.ReadDigitalInput(1))\n{\n    controller.StopMotors();\n    controller.SetAllLeds(false);\n}\n\n// Read analog sensors\ndouble voltage = controller.ReadAnalogValue(1);\nConsole.WriteLine($\"Sensor: {voltage:F2}V\");\n\n// Touch detection\nif (controller.ReadTouchSensor(1))\n{\n    Console.WriteLine(\"Button pressed!\");\n}\n```\n\n---\n\n## 🎯 What's Included?\n\n### 📦 Tobot.Device Library\n\nA professional-grade driver library for the Explorer HAT with:\n\n| Package        | Components                             | Description                                |\n| -------------- | -------------------------------------- | ------------------------------------------ |\n| **🚗 Motor**    | `Motor`, `MotorCollection`             | H-bridge motor control with variable speed |\n| **💡 LED**      | `Led`, `LedCollection`                 | Onboard LED control and patterns           |\n| **📊 Analog**   | `AnalogInput`, `AnalogInputCollection` | 0-5V analog input via ADS1015 ADC          |\n| **🔌 Digital**  | `DigitalInput/Output`, Collections     | Digital I/O with event support             |\n| **👆 Touch**    | `TouchSensor`, `TouchCollection`       | Capacitive touch via CAP1208               |\n| **📐 Distance** | `HcSr04Sensor`                         | Ultrasonic range finding with averaging    |\n\n#### 🧭 Pan-Tilt HAT\n\nSupport for the Pimoroni Pan-Tilt HAT is baked into `TobotController`, which proxies every motion command to the onboard microcontroller at I2C address `0x15` (same protocol as the official Python library).\n\n- Access via `TobotController.SetPanAngle`, `SetTiltAngle`, `PanTilt`, and `GetPanTiltAngles`\n- Configurable idle timeout (query with `GetPanTiltIdleTimeout`)\n- Automatic servo enable/disable and retry handling\n\nExample:\n\n```csharp\nusing Tobot.Device;\n\nusing var controller = new TobotController();\n\n// Center\ncontroller.PanTilt(0, 0);\n\n// Move\ncontroller.SetPanAngle(30);\ncontroller.SetTiltAngle(-10);\n\n// Read back (optional)\nvar (pan, tilt) = controller.GetPanTiltAngles();\nConsole.WriteLine($\"Pan: {pan}°, Tilt: {tilt}°\");\n```\n\nNotes:\n- Requires I2C enabled on the Pi (`raspi-config`) and device visible at `0x15` (`i2cdetect -y 1`).\n- Servos need an adequate 5V supply connected to the HAT; the Pi’s USB power is not sufficient to drive servos.\n- Default servo pulse range is 575–2325 µs (≈ -90°…+90°). Idle timeout defaults to 2s.\n\n#### 📐 HC-SR04 Ultrasonic Distance\n\n`TobotController` wraps the HC-SR04 ultrasonic range finder via the `HcSr04Sensor` manager, providing both basic distance measurement and advanced directed object detection.\n\n**Basic Distance Reading:**\n- Call `TryReadDistance` for non-throwing reads or `ReadDistance` to enforce a measurement\n- Adjustable sample count for noise reduction (defaults to 5 readings)\n- Shares the controller's GPIO instance so trigger/echo pins are automatically managed\n\n**Directed Object Detection:**\nThe HC-SR04 sensor can determine if an object is to the left, center, or right when combined with the Pan-Tilt HAT. Two approaches are supported:\n\n1. **Autonomous Sweep Detection** (`FindClosestObject`) - The sensor actively sweeps left to right (-45° to +45°) and reports the closest object's direction\n2. **Direction Classification** (`GetObjectDirection`) - Lightweight direction labeling based on current pan angle without sweeping (use when pan is controlled externally)\n\nExample - Autonomous Detection:\n\n```csharp\nusing Tobot.Device;\n\nusing var controller = new TobotController();\n\nvar detectedObject = controller.FindClosestObject();\nif (detectedObject != null)\n{\n    Console.WriteLine($\"Distance: {detectedObject.Distance:F1} cm\");\n    Console.WriteLine($\"Direction: {detectedObject.Direction}\"); // Left, Center, or Right\n    Console.WriteLine($\"Pan angle: {detectedObject.PanAngle}°\");\n}\n```\n\nExample - Simple Direction Classification:\n\n```csharp\nusing Tobot.Device;\n\nusing var controller = new TobotController();\n\n// Position pan manually (your control logic)\ncontroller.SetPanAngle(-30);\nThread.Sleep(500);\n\n// Read distance and get direction classification\nif (controller.TryReadDistanceWithDirection(-30, out double distanceCm, out var direction))\n{\n    Console.WriteLine($\"Distance: {distanceCm:F1} cm\");\n    Console.WriteLine($\"Direction: {direction}\"); // Left, Center, or Right\n}\n\n// Or just get direction without distance reading\nvar objectDirection = controller.GetObjectDirection(-30);\nConsole.WriteLine($\"Object is to the {objectDirection}\");\n```\n\n**Direction Classification:**\n- **Left**: Pan angle \u003c -5°\n- **Center**: Pan angle between -5° and +5°\n- **Right**: Pan angle \u003e +5°\n\n### 🎮 Tobot Console Application\n\nAn interactive showcase featuring:\n\n- **LED Light Show** - Mesmerizing patterns and effects\n- **Input Monitor** - Real-time digital input tracking\n- **Output Control** - Power external devices\n- **Analog Reader** - Sensor voltage monitoring\n- **Motor Control** - Precision movement and speed\n- **Touch Demo** - Capacitive touch detection\n- **Robot System** - Complete autonomous control\n- **System Check** - Hardware diagnostics\n- **Pan-Tilt Demo** - Servo movement showcase\n- **HC-SR04 Distance** - Ultrasonic range finding\n- **Observable Distance** - Reactive sensor monitoring\n- **Random Drive** - Autonomous obstacle avoidance\n- **Directed Detection** - Autonomous object localization with direction\n- **Direction Classifier** - Manual pan with direction classification\n- **Pi System Info** - Hostname, Wi‑Fi SSID/IP, CPU temp, load, memory, disk, uptime, CPU freq\n\n### 🌐 Tobot.Web Application\n\nA modern web-based control interface featuring:\n\n- **SignalR Integration** - Real-time bidirectional communication\n- **Remote Control** - Control your robot from any device on the network\n- **Live Updates** - Receive real-time feedback from all sensors and actuators\n- **Interactive UI** - Clean, responsive Blazor interface\n- **Event Monitoring** - Track all robot actions in real-time\n- **Multi-Device Support** - Access from phones, tablets, or computers\n- **URL-Triggered Actions** - Trigger robot commands via query parameters\n\n#### Available Pages\n\n**Simple Control** (`/simple`)\n- Styled button interface for motors, LEDs, and digital outputs\n- Real-time event log showing all hub activity\n- Speed control sliders for motors\n- Connection status indicator\n\n**Remote Control** (`/remote`)\n- Minimal, unstyled button interface\n- Supports query parameter `action` for URL-triggered commands\n- Ideal for embedded frames or remote triggers\n\n**Bot** (`/bot`)\n- Animated reactive eyes with mood states\n- Distance sensor visualization\n- Click-to-toggle random autonomous driving\n- Responsive mood changes based on sensor data\n\n#### Remote Control Query Parameters\n\nThe `/remote` page supports triggering actions via URL query parameter `action`:\n\n```\nhttp://[raspberry-pi-ip]:5247/remote?action=forward\nhttp://[raspberry-pi-ip]:5247/remote?action=backward\nhttp://[raspberry-pi-ip]:5247/remote?action=stop\nhttp://[raspberry-pi-ip]:5247/remote?action=left\nhttp://[raspberry-pi-ip]:5247/remote?action=right\nhttp://[raspberry-pi-ip]:5247/remote?action=light-on\nhttp://[raspberry-pi-ip]:5247/remote?action=light-off\n```\n\nSupported action values:\n- **Movement**: `forward`, `backward`, `stop`, `left`, `right`\n- **Lights**: `light-on` (or `lighton`), `light-off` (or `lightoff`)\n\nUse cases:\n- Trigger actions from external scripts or dashboards\n- Create custom control buttons/links\n- Automate robot behavior via HTTP requests\n\n### 🎮 Tobot.PicoRemote Application\n\nA wireless remote control firmware for the **Raspberry Pi Pico W** with **Pimoroni PicoKeypad**, enabling control of Tobot from a handheld 16-button wireless controller.\n\nFeatures:\n- **16-Key RGB Keypad** - Intuitive button layout with visual LED feedback\n- **WiFi Connectivity** - Sends HTTP GET requests to Tobot.Web's `/remote` endpoint\n- **Status Indicators** - Real-time LED display of boot, WiFi, and remote endpoint status\n- **Controller Layout**:\n  - Directional controls: Up (forward), Down (backward), Left, Right\n  - Center Stop button\n  - Special function keys for Light On/Off and additional controls\n- **Configuration** - Easily customizable host, port, and key mappings\n\nRequirements:\n- Raspberry Pi Pico W (WiFi capable)\n- Pimoroni PicoKeypad (16 RGB backlit keys)\n- MicroPython with `picokeypad` library\n- WiFi credentials in `secret.py` (SSID and PASSWORD)\n- Network access to Tobot.Web application\n\nUsage:\n```bash\n# Configure WiFi credentials\necho \"SSID = 'your-wifi-name'\" \u003e Tobot.PicoRemote/secret.py\necho \"PASSWORD = 'your-wifi-password'\" \u003e\u003e Tobot.PicoRemote/secret.py\n\n# Upload remote-control.py to Pico W via Thonny or similar\n# The firmware will auto-start and connect to your Tobot.Web instance\n```\n\nNote: Update `REMOTE_HOST` and `REMOTE_PORT` in `remote-control.py` to match your Tobot.Web deployment.\n\n---\n\n### 🖥️ Pi System Info\n\nThe `Tobot.Pi` library exposes Raspberry Pi telemetry via `PiSystemInfo` and publishes periodic `PiStatusSnapshot` updates.\n\nHighlights:\n- Hostname and Wi‑Fi details: SSID + primary Wi‑Fi IPv4\n- CPU metrics: temperature (°C rounded) and frequency (MHz)\n- Load averages: 1/5/15 minutes\n- Memory: total/available (kB) with easy MB display in demo\n- Disk: total/free in GiB (root mount)\n- Uptime: seconds (rendered as days/hours/minutes in demo)\n- Events: `TemperatureChanged` (thresholded) and `StatusChanged` (full snapshot)\n\nQuick usage:\n\n```csharp\nusing Tobot.Pi;\n\n// One-shot reads\nConsole.WriteLine($\"Host: {PiSystemInfo.GetHostName()}\");\nConsole.WriteLine($\"Wi‑Fi SSID: {PiSystemInfo.GetWifiSsid() ?? \"(not connected)\"}\");\nvar wifiIps = PiSystemInfo.GetIpAddresses(includeIPv6: false, wifiOnly: true);\nConsole.WriteLine($\"Wi‑Fi IP: {(wifiIps.Count \u003e 0 ? wifiIps[0].ToString() : \"(none)\")}\");\n\n// Subscribe to periodic snapshots (includes load/mem/disk/uptime/freq)\nPiSystemInfo.StatusChanged += (s, snap) =\u003e\n{\n    Console.WriteLine($\"Temp {snap.CpuTempC}°C | Load {snap.LoadAvg1Minute:F2}/{snap.LoadAvg5Minutes:F2}/{snap.LoadAvg15Minutes:F2} | Free {snap.DiskFreeGiB:F1} GiB\");\n};\nPiSystemInfo.StartTemperaturePublishing();\n```\n\n---\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- Raspberry Pi (any model with 40-pin GPIO)\n- Pimoroni Explorer HAT\n- Pimoroni PanTilt HAT\n- HC-SR04 ultrasonic sensor\n- .NET 10 SDK\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/yourusername/tobot.git\ncd tobot\n\n# Build the solution\ndotnet build\n\n# Run the interactive demo\ndotnet run --project Tobot\n```\n\n### Your First Robot in 30 Seconds\n\n```bash\n# Quick system check\ndotnet run --project Tobot check\n\n# LED light show\ndotnet run --project Tobot led\n\n# Full robot control\ndotnet run --project Tobot robot\n```\n\n📖 **Detailed instructions:** See [Tobot/QUICKSTART.md](Tobot/QUICKSTART.md)\n\n---\n\n## 🧰 Scripts\n\nAll helper scripts live in `scripts/` at the project root.\n\n- `scripts/run-tobot-web-kiosk.sh`: Starts the `Tobot.Web` Blazor app and opens it in Firefox kiosk mode on the Raspberry Pi at `http://localhost:5247/bot`.\n- `scripts/add-to-autostart.sh`: Installs a user systemd service (`tobot-web-kiosk.service`) that runs the kiosk script automatically after the graphical session starts.\n- `scripts/remove-from-autostart.sh`: Disables and removes the autostart user service.\n\nUsage:\n\n```bash\nchmod +x scripts/run-tobot-web-kiosk.sh\nchmod +x scripts/add-to-autostart.sh\nchmod +x scripts/remove-from-autostart.sh\n\n# Run once (non-autostart)\n./scripts/run-tobot-web-kiosk.sh\n\n# Enable autostart (user service)\n./scripts/add-to-autostart.sh\n\n# Remove autostart\n./scripts/remove-from-autostart.sh\n\n# Check status\nsystemctl --user status tobot-web-kiosk.service --no-pager\n\n# Optional: keep user services running at boot without login\nsudo loginctl enable-linger $USER\n```\n\nNotes:\n- Requires `firefox` (or `firefox-esr`) installed on the Raspberry Pi.\n- Binds the web app to `0.0.0.0:5247` so it’s reachable on your LAN.\n- Adjust the script if you prefer Chromium (`chromium-browser --kiosk`).\n- The autostart unit runs after `graphical-session.target` and sets `DISPLAY=:0`. If `systemctl --user` is unavailable in your session, run from the desktop session or enable linger as shown above.\n\n---\n\n## 🏛️ Architecture\n\nTobot follows a clean, modular architecture:\n\n```\nTobot/\n├── Tobot/                             Console demo application\n│   ├── Program.cs                     Interactive demos\n│   ├── README.md                      Usage guide\n│   └── QUICKSTART.md                  5-minute setup\n│\n├── Tobot.Device/                      Hardware driver library\n│   ├── ExplorerHat/                   Explorer HAT components\n│   │   ├── ExplorerHat.cs             Main controller\n│   │   ├── Motor/                     Motor control package\n│   │   ├── Led/                       LED control package\n│   │   ├── Analog/                    Analog input package\n│   │   ├── Digital/                   Digital I/O package\n│   │   └── Touch/                     Touch sensor package\n│   ├── HcSr04/                        Ultrasonic distance helpers\n│   │   └── HcSr04.cs                  High-level HC-SR04 manager\n│   └── PanTiltHat/                    Pan-Tilt HAT (MCU @ 0x15)\n│       ├── PanTiltHat.cs              High-level pan/tilt API (MCU protocol)\n│       └── Pca9685.cs                 (Optional) PCA9685 helper (not required for MCU mode)\n│\n├── Tobot.Web/                         Web control interface\n│   ├── Program.cs                     ASP.NET Core application\n│   ├── Hubs/                          SignalR hubs\n│   │   ├── TobotHub.cs                Main control hub\n│   │   └── TobotHubEvents.cs          Event constants\n│   └── Components/                    Blazor UI components\n│       └── Pages/                     Web pages\n│           ├── Simple.razor           Styled control interface\n│           ├── Remote.razor           URL-triggered control interface\n│           └── Bot.razor              Animated reactive eyes\n│\n├── Tobot.Pi/                          Raspberry Pi system telemetry library\n│   ├── PiSystemInfo.cs                Host/IP (Wi‑Fi), SSID, CPU temp, load avg, memory, disk (GiB), uptime, CPU freq\n│   └── PiStatusSnapshot.cs            DTO for periodic status snapshots + events\n│\n└── Tobot.PicoRemote/                  Pico W wireless remote firmware\n    ├── remote-control.py              Main firmware (MicroPython)\n    └── secret.py.example              WiFi credentials template\n```\n\n### Key Design Principles\n\n- Context-Related Packaging: Group by functionality for clarity\n- Self-Contained Packages: Avoid cross-package dependencies\n- Clean APIs: Intuitive, discoverable interfaces\n- Comprehensive Docs: XML documentation across the codebase\n- Resource Safety: Consistent `IDisposable` usage and cleanup\n\n---\n\n## 🎯 Features \u0026 Capabilities\n\nAll snippets below assume you have already created `var controller = new TobotController();` (or are inside a scope where a controller instance is available).\n\n### 🚗 Motor Control\n```csharp\ncontroller.DriveMotor(1, 100);   // Full speed ahead\ncontroller.DriveMotor(1, 75);    // 75% forward\ncontroller.DriveMotor(1, -50);   // 50% backward\ncontroller.StopMotors();         // Emergency stop\n```\n\n### 💡 LED Control\n```csharp\ncontroller.SetLedState(1, true); // Individual LED\ncontroller.SetAllLeds(true);     // All LEDs\ncontroller.ToggleLed(2);         // Toggle state\n```\n\n### 🔌 Digital I/O\n```csharp\n// Read input\nbool state = controller.ReadDigitalInput(1);\n\n// Event-driven\ncontroller.RegisterInputChangedHandler(1, (s, e) =\u003e\n\tConsole.WriteLine($\"Changed: {e.ChangeType}\")\n);\n\n// Control output\ncontroller.SetDigitalOutput(1, true);\ncontroller.ToggleDigitalOutput(1);\n```\n\n### 📊 Analog Input (0-5V)\n```csharp\ndouble voltage = controller.ReadAnalogValue(1);\nConsole.WriteLine($\"Voltage: {voltage:F2}V\");\n```\n\n### 👆 Capacitive Touch\n```csharp\nif (controller.ReadTouchSensor(1))\n{\n\tConsole.WriteLine(\"Touched!\");\n}\n\nbyte allSensors = controller.ReadTouchState();\n```\n\n### 📐 Ultrasonic Distance (HC-SR04)\n\nBasic distance measurement:\n```csharp\nif (controller.TryReadDistance(out double distanceCm, samples: 5))\n{\n    Console.WriteLine($\"Distance: {distanceCm:F1} cm\");\n}\nelse\n{\n    Console.WriteLine(\"Measurement failed\");\n}\n```\n\nDirected object detection (with Pan-Tilt HAT):\n```csharp\n// Option 1: Autonomous sweep - finds closest object and its direction\nvar detected = controller.FindClosestObject();\nif (detected != null)\n{\n    Console.WriteLine($\"Closest object: {detected.Distance:F1} cm\");\n    Console.WriteLine($\"Direction: {detected.Direction}\"); // Left, Center, or Right\n}\n\n// Option 2: Simple direction classification\n// (use when pan is controlled externally)\ncontroller.SetPanAngle(-30);\nThread.Sleep(500);\n\nif (controller.TryReadDistanceWithDirection(-30, out double distance, out var direction))\n{\n    Console.WriteLine($\"Object at {distance:F1} cm to the {direction}\");\n}\n\n// Or just classify direction without distance reading\nvar dir = controller.GetObjectDirection(-30); // Left, Center, or Right\n```\n\n---\n\n## 📚 Documentation\n\n| Document                                                                                             | Description            |\n| ---------------------------------------------------------------------------------------------------- | ---------------------- |\n| [Tobot/README.md](Tobot/README.md)                                                                   | Demo application guide |\n| [Tobot/QUICKSTART.md](Tobot/QUICKSTART.md)                                                           | 5-minute setup         |\n| [Tobot.Device/ExplorerHat/README.md](Tobot.Device/ExplorerHat/README.md)                             | API reference          |\n| [Tobot.Device/ExplorerHat/FILE_STRUCTURE.md](Tobot.Device/ExplorerHat/FILE_STRUCTURE.md)             | File organization      |\n| [Tobot.Device/ExplorerHat/PACKAGE_ORGANIZATION.md](Tobot.Device/ExplorerHat/PACKAGE_ORGANIZATION.md) | Package guide          |\n\n---\n\n## 📖 Learning Resources\n\n### Example Projects\n\n1. **Line Following Robot**\n   ```csharp\n   // Use analog sensors to detect line\n   double left = controller.ReadAnalogValue(1);\n   double right = controller.ReadAnalogValue(2);\n   \n   if (left \u003e 2.5) controller.DriveMotor(1, 50);\n   if (right \u003e 2.5) controller.DriveMotor(2, 50);\n   ```\n\n2. **Touch-Controlled Light Show**\n   ```csharp\n   for (int i = 1; i \u003c= 4; i++)\n   {\n       if (controller.ReadTouchSensor(i))\n           controller.ToggleLed(i);\n   }\n   ```\n\n3. **Obstacle Avoiding Robot**\n   ```csharp\n   double distance = controller.ReadAnalogValue(1);\n   if (distance \u003e 3.0)\n   {\n       controller.StopMotors();\n       controller.SetAllLeds(true); // Warning!\n   }\n   ```\n\n### Code Examples\n\nAll demos in `Tobot/Program.cs` are fully commented and ready to modify. Each example is self-contained and demonstrates best practices.\n\n---\n\n## 🔧 Hardware Specifications\n\n### Explorer HAT Features\n\n| Feature             | Quantity | Specifications             |\n| ------------------- | -------- | -------------------------- |\n| **Digital Inputs**  | 4        | 5V tolerant, buffered      |\n| **Digital Outputs** | 4        | 500mA sink-to-ground       |\n| **Analog Inputs**   | 4        | 0-5V, 12-bit ADC (ADS1015) |\n| **Motor Drivers**   | 2        | H-bridge, PWM capable      |\n| **Onboard LEDs**    | 4        | Status indicators          |\n| **Touch Sensors**   | 8        | Capacitive (CAP1208)       |\n\n### Pin Mapping\n\n\u003cdetails\u003e\n\u003csummary\u003e🔍 Click to view complete pin mapping\u003c/summary\u003e\n\n#### Digital Inputs (BCM GPIO)\n- Input 1: GPIO 23\n- Input 2: GPIO 22\n- Input 3: GPIO 24\n- Input 4: GPIO 25\n\n#### Digital Outputs (BCM GPIO)\n- Output 1: GPIO 6\n- Output 2: GPIO 12\n- Output 3: GPIO 13\n- Output 4: GPIO 16\n\n#### LEDs (BCM GPIO)\n- LED 1: GPIO 4\n- LED 2: GPIO 17\n- LED 3: GPIO 27\n- LED 4: GPIO 5\n\n#### Motors (BCM GPIO)\n- Motor 1: Enable 19, Forward 20, Backward 21\n- Motor 2: Enable 26, Forward 7, Backward 8\n\n#### I2C Devices\n- ADS1015 ADC: Address 0x48\n- CAP1208 Touch: Address 0x28\n\n\u003c/details\u003e\n\n---\n\n## ⚙️ Advanced Usage\n\n### Custom Robot Control Loop\n\n```csharp\nusing var controller = new TobotController();\n\n// Setup\ncontroller.SetAllLeds(false);\ncontroller.StopMotors();\n\n// Main control loop\nwhile (true)\n{\n    // Read sensors\n    bool goButton = controller.ReadDigitalInput(1);\n    bool stopButton = controller.ReadDigitalInput(2);\n    double frontSensor = controller.ReadAnalogValue(1);\n\t\n    // Decision logic\n    if (stopButton || frontSensor \u003e 3.0)\n    {\n        // Emergency stop\n        controller.StopMotors();\n        controller.SetLedState(1, true);\n    }\n    else if (goButton)\n    {\n        // Move forward\n        controller.DriveMotors(80, 80);\n        controller.SetLedState(2, true);\n    }\n    else\n    {\n        // Idle\n        controller.StopMotors();\n        controller.SetAllLeds(false);\n    }\n\t\n    await Task.Delay(50); // 20Hz update rate\n}\n```\n\n### Async/Await Support\n\n```csharp\npublic async Task MonitorSensorsAsync(CancellationToken ct)\n{\n    using var controller = new TobotController();\n\t\n    while (!ct.IsCancellationRequested)\n    {\n        var voltage = controller.ReadAnalogValue(1);\n        Console.WriteLine($\"Sensor: {voltage:F2}V\");\n\t\t\n        await Task.Delay(100, ct);\n    }\n}\n```\n\n---\n\n## 🤝 Contributing\n\nThis project welcome contributions! Whether it's:\n\n- 🐛 Bug reports\n- 💡 Feature requests  \n- 📝 Documentation improvements\n- 💻 Code examples\n- 🔧 Driver enhancements\n\nPlease note, that I am developing this project for my self and there is no intend to make it a \"market product\" in sense of warranty, liability, etc.\n\nFor more, please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n---\n\n## 🗺️ Roadmap\n\n### Current Features\n- Complete Explorer HAT driver\n- Pan-Tilt HAT (experimental)\n- Interactive demo application\n- Comprehensive documentation\n- Package-based architecture\n\n### 🔮 Planned Features \n- [X] PWM motor speed control\n- [ ] Advanced pattern library\n- [ ] Configuration system\n- [ ] Logging framework\n- [ ] Unit test coverage\n- [ ] CI/CD pipeline\n\n---\n\n## 💻 Why .NET for Robotics?\n\n### Modern Language Features\n- **Pattern Matching** - Clean state machine logic\n- **Async/Await** - Non-blocking sensor reading\n- **LINQ** - Elegant data processing\n- **Strong Typing** - Catch errors at compile time\n\n### Excellent Tooling\n- **Visual Studio / VS Code** - World-class IDEs\n- **IntelliSense** - Discover APIs as you code\n- **Debugging** - Full breakpoint support\n- **Package Management** - NuGet ecosystem\n\n### Performance\n- **Native ARM** - Optimized for Raspberry Pi\n- **Efficient Memory** - Garbage collection tuned for IoT\n- **Low Latency** - Real-time control capable\n\n---\n\n## 🙏 Acknowledgments\n\n- **Pimoroni** - For creating the amazing Explorer HAT hardware\n- **.NET Team** - For bringing .NET to ARM/IoT devices\n- **Open Source Community** - For inspiration and support\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) file for details.\n\n---\n\n## 🔗 Links\n\n- **Hardware**: [Pimoroni Explorer HAT](https://shop.pimoroni.com/products/explorer-hat)\n- **Documentation**: [.NET IoT Libraries](https://github.com/dotnet/iot)\n- **Community**: [Raspberry Pi Forums](https://forums.raspberrypi.com/)\n- **Support**: [Open an Issue](https://github.com/yourusername/tobot/issues)\n\n---\n\n## 🚀 Get Started Now!\n\n```bash\ngit clone https://github.com/yourusername/tobot.git\ncd tobot\ndotnet run --project Tobot\n```\n\n**Ready to build something amazing?** The future of robotics is .NET! ???\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**Made with ❤️ for makers, educators, and robotics enthusiasts**\n\n[⭐ Star this repo](https://github.com/yourusername/tobot) | [📚 Read the docs](Tobot/README.md) | [🚀 Quick start](Tobot/QUICKSTART.md)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftscholze%2Fdotnet-iot-raspberrypi-tobot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftscholze%2Fdotnet-iot-raspberrypi-tobot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftscholze%2Fdotnet-iot-raspberrypi-tobot/lists"}