Something went wrong. Try again.
Fine-tuning a small LLM into a Nodrix (ESP32/Arduino) build assistant — a hands-on, end-to-end study of LoRA: data curation, training, eval… huggingface.co/spaces/decoded-cipher/nodrix-build-assistant
Something went wrong. Try again.
14 kB · 22 lines
at master
1234567891011121314151617181920212223{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Write a Nodrix sketch controlling three lights from three dashboard toggles."}, {"role": "assistant", "content": "```cpp\n#include <Nodrix.h>\n\nconst int LIVING = 16;\nconst int BEDROOM = 17;\nconst int PORCH = 18;\n\nNODRIX_WRITE(\"light_living\") { digitalWrite(LIVING, value.asBool()); }\nNODRIX_WRITE(\"light_bedroom\") { digitalWrite(BEDROOM, value.asBool()); }\nNODRIX_WRITE(\"light_porch\") { digitalWrite(PORCH, value.asBool()); }\n\nvoid setup() {\n pinMode(LIVING, OUTPUT);\n pinMode(BEDROOM, OUTPUT);\n pinMode(PORCH, OUTPUT);\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n}\n```\n\nOne handler per bound variable. Relay boards are often active-LOW \u2014 invert the write if\nyours is."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "How do I react to a value written from the dashboard?"}, {"role": "assistant", "content": "Use the `NODRIX_WRITE` macro at file scope. It runs whenever the cloud writes that variable, and the library acks the write for you.\n\n```cpp\nNODRIX_WRITE(\"led\") {\n digitalWrite(LED_BUILTIN, value.asBool());\n}\n```\n\nDelivery is at-least-once, so keep the handler idempotent."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Why GPIO34 for the sensor specifically?"}, {"role": "assistant", "content": "It's an ADC1 pin, and ADC1 keeps working while Wi-Fi is on. The ESP32's ADC2 pins are borrowed by the radio, so an analog read there returns garbage once you're connected. GPIO34 is also input-only with no internal pull-up, which is exactly what an analog sensor output wants."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "What happened to Particle?"}, {"role": "assistant", "content": "Digi International acquired Particle in January 2026 for $50 million and is integrating it into its OEM Solutions business. Particle's platform continues to operate \u2014 this is a change of ownership and direction, not a shutdown \u2014 but the center of gravity is now enterprise and OEM device programs rather than the maker community Particle grew up with."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Do these ESP32 projects need paid cloud services?"}, {"role": "assistant", "content": "No. Every build here reports to a nodrix instance you deploy to your own Cloudflare account, which for student-scale telemetry sits inside Cloudflare's free plan \u2014 no per-device fees, no message caps, no data-retention limit counting down. That matters for a project you'll run for months or demo repeatedly: the free tiers of hosted IoT platforms are sized to run out exactly when your project starts working."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Should I poll or use the WebSocket?"}, {"role": "assistant", "content": "Use the always-on WebSocket (Nodrix.begin) for controllers that need zero-latency writes \u2014 on Cloudflare the socket hibernates, so an idle connection costs almost nothing. Use HTTP polling (Nodrix.beginHTTP, then poll each wake) for battery devices that wake, report, and sleep \u2014 there's no session to keep alive."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "My dashboard has a slider bound to \"speed\". How do I use its value on the device?"}, {"role": "assistant", "content": "Read it inside a `NODRIX_WRITE(\"speed\")` handler with the accessor that matches the type:\n\n```cpp\nNODRIX_WRITE(\"speed\") {\n if (value.isNull()) return;\n analogWrite(MOTOR_PIN, constrain(value.asInt(), 0, 255));\n}\n```\n\nGuard with `isNull()` so a device connecting before the slider is set doesn't apply 0."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Is there an open-source alternative to Ubidots?"}, {"role": "assistant", "content": "Yes. nodrix is open-source (MIT) and you deploy it to your own Cloudflare account rather than paying for a hosted plan. Ubidots is a polished commercial platform billed by data points / devices; nodrix has no license cost and your bill is just your Cloudflare usage."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Why the SCD41 instead of an MQ-135 or MH-Z19?"}, {"role": "assistant", "content": "Because it measures CO2 honestly. The MQ-135 is a cheap MOX gas sensor that doesn't report CO2 in real ppm \u2014 it drifts, needs constant recalibration, and conflates gases. The MH-Z19 is a genuine NDIR CO2 sensor and a reasonable older choice, but the Sensirion SCD41 is a current photoacoustic CO2 sensor that also gives you temperature and humidity from one I2C part, with \u00b1(40 ppm + 5%) accuracy. For a monitor you'll trust enough to act on, the SCD41 is the right sensor in 2026."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Does Claude need my hardware to be online to answer questions?"}, {"role": "assistant", "content": "For live state, yes \u2014 reading a sensor's current value asks your instance, which holds what the device last reported. But the history lives in your instance regardless, so Claude can analyze a week of temperature data whether or not the board is awake right now. A deep-sleeping battery sensor's last reading is always queryable."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Write a deep-sleep soil-moisture logger with Nodrix."}, {"role": "assistant", "content": "```cpp\n#include <Nodrix.h>\n#include <esp_sleep.h>\n\n#define SLEEP_MINUTES 30\n\nvoid setup() {\n Nodrix.beginHTTP(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n Nodrix.send(\"soil\", analogRead(34));\n Nodrix.flush();\n Nodrix.poll();\n esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_MINUTES * 60ULL * 1000000ULL);\n esp_deep_sleep_start();\n}\n\nvoid loop() {}\n```"}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "I'm migrating from Particle. What replaces Particle.function()?"}, {"role": "assistant", "content": "```cpp\n#include <Nodrix.h>\n\nNODRIX_WRITE(\"led\") { // was: Particle.function(\"led\", ...)\n digitalWrite(LED_PIN, value.asBool());\n}\n\nvoid setup() {\n pinMode(LED_PIN, OUTPUT);\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n static unsigned long last = 0;\n if (millis() - last >= 30000) {\n last = millis();\n Nodrix.send(\"temperature\", readTemp()); // was: Particle.publish(\"temperature\", ...)\n }\n}\n```"}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "How do I get data back to the ESP32 over HTTP?"}, {"role": "assistant", "content": "Register a handler for the variable with NODRIX_WRITE. The library polls a control endpoint (or holds a WebSocket open while awake), applies each write, and acks it for you."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "What do I need to include to use Nodrix?"}, {"role": "assistant", "content": "One header, and the library exposes a ready-made global object called `Nodrix` \u2014 you never construct one yourself.\n\n```cpp\n#include <Nodrix.h>\n```\n\nIt depends on ArduinoJson and WebSocketsClient; install both from the Library Manager alongside Nodrix."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Can I check whether a control variable has ever been set?"}, {"role": "assistant", "content": "Yes \u2014 `value.isNull()` is true when the cloud has no value for that variable yet. Return early on null rather than acting on a default, otherwise a fresh device applies 0 or an empty string on its first connect."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Is there an open-source alternative to Particle?"}, {"role": "assistant", "content": "For the Wi-Fi side of what Particle does \u2014 telemetry, remote control, dashboards, webhooks-style automations \u2014 yes: nodrix is open source (MIT) and deploys to your own Cloudflare account, so there's no vendor cloud in the loop at all. There is no like-for-like open-source replacement for Particle's managed cellular connectivity; that part of Particle is genuinely hard to substitute."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Why does my dev board drain fast even in deep sleep?"}, {"role": "assistant", "content": "Usually the board, not the chip. Many dev boards keep a USB-serial chip, an always-on LDO regulator, or a power LED alive in sleep, turning the ESP32's ~10 \u00b5A into hundreds of microamps or more. For real battery builds pick a board designed for low sleep current, or power the bare module directly."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Can a sleeping device still receive commands?"}, {"role": "assistant", "content": "Yes, on its schedule. A deep-sleep device can't be pushed to instantly, but it polls the control endpoint right after it sends telemetry each wake and applies anything queued. Commands wait in the cloud and land on the next wake \u2014 seconds to minutes later, not never."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Does the Pico W verify the HTTPS certificate?"}, {"role": "assistant", "content": "Be aware: MicroPython's urequests encrypts the connection but does not verify the server certificate by default \u2014 there's no CA store loaded, so it's confidential but unauthenticated, similar to setInsecure() on an ESP. For anything sensitive, pass an SSLContext with the server's certificate. The traffic is still TLS-encrypted either way."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Can I control a device from a Grafana dashboard?"}, {"role": "assistant", "content": "Not in any built-in way \u2014 Grafana is read-only by design. It visualizes and alerts on data; it has no concept of writing state back to a device. The day your project wants a toggle that flips a relay, you're building an ingest-plus-command service yourself. Downlink is the sharpest single difference in this comparison: in nodrix a toggle widget writes a variable and the board's handler fires."}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Should I handle TLS differently on an ESP8266 versus an ESP32-C3?"}, {"role": "assistant", "content": "```cpp\n#include <Nodrix.h>\n\nvoid setup() {\n#if defined(ESP8266)\n Nodrix.setFingerprint(HOST_FP); // chain validation is heavy for 40 KB of heap\n#else\n Nodrix.setCACert(ROOT_CA_PEM); // C3: validate the chain properly, RAM is a non-issue\n#endif\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n}\n```"}]}{"messages": [{"role": "system", "content": "You are the Nodrix build assistant. You help ESP32 and Arduino developers build projects with the Nodrix library. Use only real Nodrix APIs."}, {"role": "user", "content": "Why send latitude and longitude as two variables instead of one?"}, {"role": "assistant", "content": "Because that's what the map widget binds to: a marker follows a lat variable and a lng variable as a pair. Two plain numeric variables also stay useful individually \u2014 both are charted, queryable through the read API, and usable in automations without unpacking anything."}]}