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.
16 kB · 24 lines
at master
12345678910111213141516171819202122232425{"q": "How do I toggle an LED from a dashboard widget and have the board report its real state back?", "a": "```cpp\nNODRIX_WRITE(\"led\") {\n digitalWrite(LED_PIN, value.asBool() ? HIGH : LOW);\n Nodrix.send(\"led\", value.asBool());\n}\n```"}{"q": "Can one sketch control several things at once? I need a living room light, a bedroom light and a fan.", "a": "```cpp\nNODRIX_WRITE(\"light_living\") { digitalWrite(LIVING, value.asBool()); }\nNODRIX_WRITE(\"light_bedroom\") { digitalWrite(BEDROOM, value.asBool()); }\nNODRIX_WRITE(\"fan\") { digitalWrite(FAN, value.asBool()); }\n```"}{"q": "I'm moving a DHT11 feed off Adafruit IO. What does the equivalent Nodrix sketch look like?", "a": "```cpp\n#include <Nodrix.h>\n#include <DHT.h>\n\nDHT dht(4, DHT11);\n\nvoid setup() {\n dht.begin();\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n Nodrix.send(\"temperature\", dht.readTemperature()); // was feed(\"temperature\")->save(t)\n}\n```"}{"q": "What replaces Blynk's BLYNK_WRITE(V1) in Nodrix? I have an ESP32 with a DHT sensor and an LED.", "a": "```cpp\n#include <Nodrix.h>\n#include <DHT.h>\n\nDHT dht(4, DHT11);\n\nNODRIX_WRITE(\"led\") { // Blynk's BLYNK_WRITE(V1), minus the vendor cloud\n digitalWrite(LED_PIN, value.asBool());\n}\n\nvoid setup() {\n dht.begin();\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n Nodrix.send(\"temperature\", dht.readTemperature()); // was Blynk.virtualWrite(V2, t)\n}\n```"}{"q": "How do I build an ESP32 air quality monitor with an SCD4x sensor that reports CO2 to a dashboard?", "a": "```cpp\n#include <Nodrix.h>\n#include <SensirionI2cScd4x.h>\n#include <Wire.h>\n\nconst char* WIFI_SSID = \"your-ssid\";\nconst char* WIFI_PASS = \"your-password\";\nconst char* HOST = \"nodrix.you.workers.dev\";\nconst char* TOKEN = \"tok_your_project_token\";\n\nSensirionI2cScd4x scd4x;\n\nvoid setup() {\n Wire.begin();\n scd4x.begin(Wire, 0x62);\n scd4x.stopPeriodicMeasurement(); // clean state after a reset\n scd4x.startPeriodicMeasurement();\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n static unsigned long lastReading = 0;\n if (millis() - lastReading >= 30000) {\n lastReading = millis();\n\n uint16_t co2 = 0;\n float temperature = 0, humidity = 0;\n if (scd4x.readMeasurement(co2, temperature, humidity) == 0 && co2 > 0) {\n Nodrix.send(\"co2\", (int)co2);\n Nodrix.send(\"temperature\", temperature);\n Nodrix.send(\"humidity\", humidity);\n }\n }\n}\n```"}{"q": "How do I build automatic plant watering on an ESP32 with a soil sensor and a pump I can also trigger by hand?", "a": "```cpp\n#include <Nodrix.h>\n\nconst char* WIFI_SSID = \"your-ssid\";\nconst char* WIFI_PASS = \"your-password\";\nconst char* HOST = \"nodrix.you.workers.dev\";\nconst char* TOKEN = \"tok_your_project_token\";\n\nconst int SENSOR_PIN = 34;\nconst int PUMP_PIN = 26;\nconst int DRY = 3200; // raw ADC reading in dry air \u2014 calibrate\nconst int WET = 1300; // raw ADC reading submerged \u2014 calibrate\nconst int BURST_MS = 5000;\n\nint readMoisture() {\n long sum = 0;\n for (int i = 0; i < 16; i++) { sum += analogRead(SENSOR_PIN); delay(10); }\n return constrain(map(sum / 16, DRY, WET, 0, 100), 0, 100);\n}\n\nNODRIX_WRITE(\"pump\") {\n if (!value.asBool()) { digitalWrite(PUMP_PIN, LOW); return; }\n digitalWrite(PUMP_PIN, HIGH);\n delay(BURST_MS);\n digitalWrite(PUMP_PIN, LOW);\n Nodrix.send(\"pump\", false);\n Nodrix.event(\"watered\");\n}\n\nvoid setup() {\n pinMode(PUMP_PIN, OUTPUT);\n digitalWrite(PUMP_PIN, LOW);\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n static unsigned long lastReading = 0;\n if (millis() - lastReading >= 5UL * 60 * 1000) {\n lastReading = millis();\n Nodrix.send(\"soil_moisture\", readMoisture());\n }\n}\n```"}{"q": "Should I handle TLS differently on an ESP8266 versus an ESP32-C3?", "a": "```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```"}{"q": "Does the ESP32-C6 need anything special for a Nodrix relay project?", "a": "```cpp\n#include <Nodrix.h>\n\nNODRIX_WRITE(\"relay\") {\n digitalWrite(10, value.asBool());\n}\n\nvoid setup() {\n pinMode(10, OUTPUT);\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n}\n```"}{"q": "Show me a complete battery-powered ESP32 sketch that reads a DHT11, reports it, and deep sleeps for 15 minutes.", "a": "```cpp\n#include <WiFi.h>\n#include <Nodrix.h>\n#include <DHT.h>\n#include <esp_sleep.h>\n\n#define SLEEP_MINUTES 15\nconst char* HOST = \"nodrix.you.workers.dev\"; // bare host, no https://\nconst char* TOKEN = \"tok_your_project_token\";\n\nDHT dht(4, DHT11);\n\nvoid setup() {\n dht.begin();\n fastConnect(); // RTC-cached association (above)\n if (WiFi.status() == WL_CONNECTED) {\n Nodrix.beginHTTP(HOST, TOKEN); // reuses the live connection\n Nodrix.send(\"temperature\", dht.readTemperature());\n Nodrix.flush(); // POST the reading\n Nodrix.poll(); // apply queued commands while we're up\n }\n esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_MINUTES * 60ULL * 1000000ULL);\n esp_deep_sleep_start(); // execution ends here; wakes into setup()\n}\n\nvoid loop() {}\n```"}{"q": "How do I build an ESP32 energy meter with a PZEM-004T and log power to a dashboard?", "a": "```cpp\n#include <Nodrix.h>\n#include <PZEM004Tv30.h>\n\nconst char* WIFI_SSID = \"your-ssid\";\nconst char* WIFI_PASS = \"your-password\";\nconst char* HOST = \"nodrix.you.workers.dev\";\nconst char* TOKEN = \"tok_your_project_token\";\n\nPZEM004Tv30 pzem(Serial2, 16, 17);\n\nvoid setup() {\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n static unsigned long lastReading = 0;\n if (millis() - lastReading >= 10000) {\n lastReading = millis();\n\n float voltage = pzem.voltage();\n float current = pzem.current();\n float power = pzem.power();\n float energy = pzem.energy();\n\n if (isnan(voltage)) return; // meter not answering \u2014 skip, don't send garbage\n\n Nodrix.send(\"voltage\", voltage);\n Nodrix.send(\"current\", current);\n Nodrix.send(\"power\", power);\n Nodrix.send(\"energy_kwh\", energy);\n }\n}\n```"}{"q": "How do I build a GPS tracker on an ESP32 that pushes its location to a dashboard?", "a": "```cpp\n#include <Nodrix.h>\n#include <TinyGPSPlus.h>\n\nconst char* WIFI_SSID = \"your-ssid\"; // or the phone hotspot in the vehicle\nconst char* WIFI_PASS = \"your-password\";\nconst char* HOST = \"nodrix.you.workers.dev\";\nconst char* TOKEN = \"tok_your_project_token\";\n\nTinyGPSPlus gps;\n\ndouble lastLat = 0, lastLng = 0;\n\nvoid setup() {\n Serial2.begin(9600, SERIAL_8N1, 16, 17);\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n while (Serial2.available()) gps.encode(Serial2.read());\n if (!gps.location.isValid()) return;\n\n static unsigned long lastSend = 0;\n bool moved = TinyGPSPlus::distanceBetween(\n gps.location.lat(), gps.location.lng(), lastLat, lastLng) > 15;\n unsigned long interval = moved ? 5000 : 60000;\n\n if (millis() - lastSend >= interval) {\n lastSend = millis();\n lastLat = gps.location.lat();\n lastLng = gps.location.lng();\n Nodrix.send(\"lat\", gps.location.lat());\n Nodrix.send(\"lng\", gps.location.lng());\n Nodrix.send(\"speed_kmh\", gps.speed.kmph());\n }\n}\n```"}{"q": "How do I connect an ESP32 with a BME280 to the cloud over HTTPS with the certificate pinned?", "a": "```cpp\n#include <Nodrix.h>\n#include <Adafruit_BME280.h>\n\nconst char* HOST = \"nodrix.you.workers.dev\"; // bare host, no https://\nconst char* TOKEN = \"tok_your_project_token\";\n\nAdafruit_BME280 bme;\n\nvoid setup() {\n Serial.begin(115200);\n bme.begin(0x76); // 0x76 or 0x77, per your board\n Nodrix.setCACert(ROOT_CA); // omit for the insecure default\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n```"}{"q": "How do I send BME280 readings every 10 seconds without flooding the connection?", "a": "```cpp\nvoid loop() {\n Nodrix.run();\n\n static uint32_t last = 0;\n if (millis() - last > 10000) {\n last = millis();\n Nodrix.send(\"temperature\", bme.readTemperature());\n Nodrix.send(\"humidity\", bme.readHumidity());\n }\n}\n```"}{"q": "How do I control a relay from the dashboard?", "a": "```cpp\nNODRIX_WRITE(\"relay\") {\n digitalWrite(RELAY_PIN, value.asBool());\n}\n```"}{"q": "How do I make an ESP32 reconnect quickly after deep sleep so it uses less battery?", "a": "```cpp\n#include <esp_sleep.h> // deep-sleep API\n\nRTC_DATA_ATTR bool rtcValid = false;\nRTC_DATA_ATTR uint8_t rtcBssid[6];\nRTC_DATA_ATTR int32_t rtcChannel;\n\n#define SLEEP_MINUTES 15\n\nvoid fastConnect() {\n WiFi.mode(WIFI_STA);\n if (rtcValid)\n WiFi.begin(WIFI_SSID, WIFI_PASS, rtcChannel, rtcBssid, true); // cached path\n else\n WiFi.begin(WIFI_SSID, WIFI_PASS); // first boot\n\n uint32_t start = millis();\n while (WiFi.status() != WL_CONNECTED && millis() - start < 8000) delay(50);\n\n if (WiFi.status() == WL_CONNECTED) {\n memcpy(rtcBssid, WiFi.BSSID(), 6);\n rtcChannel = WiFi.channel();\n rtcValid = true;\n } else {\n rtcValid = false; // force a full scan next time\n }\n}\n\nvoid setup() {\n Serial.begin(115200);\n bme.begin(0x76);\n fastConnect();\n if (WiFi.status() == WL_CONNECTED) {\n Nodrix.beginHTTP(HOST, TOKEN); // reuses the live connection\n Nodrix.send(\"temperature\", bme.readTemperature());\n Nodrix.send(\"humidity\", bme.readHumidity());\n Nodrix.flush(); // POST the batch\n Nodrix.poll(); // grab any queued commands while we're up\n }\n esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_MINUTES * 60ULL * 1000000ULL);\n esp_deep_sleep_start(); // execution ends here; wakes back into setup()\n}\n\nvoid loop() {} // intentionally empty for a deep-sleep design\n```"}{"q": "How do I get notified when a DS18B20 temperature crosses a threshold?", "a": "```cpp\n#include <Nodrix.h>\n#include <OneWire.h>\n#include <DallasTemperature.h>\n\nconst char* WIFI_SSID = \"your-ssid\";\nconst char* WIFI_PASS = \"your-password\";\nconst char* HOST = \"nodrix.you.workers.dev\";\nconst char* TOKEN = \"tok_your_project_token\";\n\nOneWire oneWire(4);\nDallasTemperature sensors(&oneWire);\n\nvoid setup() {\n sensors.begin();\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n static unsigned long lastReading = 0;\n if (millis() - lastReading >= 60000) {\n lastReading = millis();\n sensors.requestTemperatures();\n float t = sensors.getTempCByIndex(0);\n if (t > -100) Nodrix.send(\"temperature\", t); // -127 = sensor disconnected\n }\n}\n```"}{"q": "How do I handle a control write from the cloud over the always-on WebSocket?", "a": "```cpp\n#include <Nodrix.h>\n\nNODRIX_WRITE(\"relay\") {\n digitalWrite(RELAY_PIN, value.asBool());\n}\n\nvoid setup() {\n pinMode(RELAY_PIN, OUTPUT);\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN); // always-on WebSocket\n}\n\nvoid loop() {\n Nodrix.run(); // control in, telemetry out, acks, reconnect\n}\n```"}{"q": "How does a battery device pick up commands that were queued while it was asleep?", "a": "```cpp\n#include <esp_sleep.h> // deep-sleep API\n\nvoid setup() {\n Nodrix.beginHTTP(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n Nodrix.send(\"soil\", analogRead(34));\n Nodrix.flush(); // POST telemetry\n Nodrix.poll(); // fetch + apply queued writes, then ack\n\n esp_sleep_enable_timer_wakeup(15ULL * 60 * 1000000);\n esp_deep_sleep_start();\n}\n```"}{"q": "How do I build an ESP32 smart home controller that drives several lights?", "a": "```cpp\n#include <Nodrix.h>\n\n#define WIFI_SSID \"your-wifi\"\n#define WIFI_PASS \"your-password\"\n#define HOST \"nodrix.you.workers.dev\"\n#define TOKEN \"tok_your_project_token\"\n\nconst int LIGHT_LIVING = 16;\nconst int LIGHT_BEDROOM = 17;\nconst int LIGHT_PORCH = 18;\nconst int FAN = 19;\n\nconst int RELAY_ON = LOW; // most relay boards are active-LOW \u2014 swap if yours isn't\nconst int RELAY_OFF = HIGH;\n\nvoid setRelay(int pin, const char* var, bool on) {\n digitalWrite(pin, on ? RELAY_ON : RELAY_OFF);\n Nodrix.send(var, on); // echo the real state so the dashboard stays honest\n}\n\nNODRIX_WRITE(\"light_living\") { setRelay(LIGHT_LIVING, \"light_living\", value.asBool()); }\nNODRIX_WRITE(\"light_bedroom\") { setRelay(LIGHT_BEDROOM, \"light_bedroom\", value.asBool()); }\nNODRIX_WRITE(\"light_porch\") { setRelay(LIGHT_PORCH, \"light_porch\", value.asBool()); }\nNODRIX_WRITE(\"fan\") { setRelay(FAN, \"fan\", value.asBool()); }\n\nvoid setup() {\n int pins[] = { LIGHT_LIVING, LIGHT_BEDROOM, LIGHT_PORCH, FAN };\n for (int p : pins) { pinMode(p, OUTPUT); digitalWrite(p, RELAY_OFF); }\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n}\n```"}{"q": "How do I build an ESP32 weather station with a BME280?", "a": "```cpp\n#include <Nodrix.h>\n#include <Adafruit_BME280.h>\n\nconst char* WIFI_SSID = \"your-ssid\";\nconst char* WIFI_PASS = \"your-password\";\nconst char* HOST = \"nodrix.you.workers.dev\";\nconst char* TOKEN = \"tok_your_project_token\";\n\nAdafruit_BME280 bme;\n\nvoid setup() {\n bme.begin(0x76); // some breakouts are at 0x77\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n\nvoid loop() {\n Nodrix.run();\n\n static unsigned long lastReading = 0;\n if (millis() - lastReading >= 60000) {\n lastReading = millis();\n Nodrix.send(\"temperature\", bme.readTemperature());\n Nodrix.send(\"humidity\", bme.readHumidity());\n Nodrix.send(\"pressure\", bme.readPressure() / 100.0F); // Pa \u2192 hPa\n }\n}\n```"}{"q": "How do I connect an ESP8266 with a DHT11 to a Nodrix dashboard?", "a": "```cpp\n#include <Nodrix.h>\n#include <DHT.h>\n\nconst char* HOST = \"nodrix.you.workers.dev\"; // bare host, no https://\nconst char* TOKEN = \"tok_your_project_token\";\n\nDHT dht(D2, DHT11);\n\nvoid setup() {\n Serial.begin(115200);\n dht.begin();\n Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n}\n```"}{"q": "How do I send readings from an ESP8266 on a timed interval?", "a": "```cpp\nvoid loop() {\n Nodrix.run();\n\n static uint32_t last = 0;\n if (millis() - last > 10000) {\n last = millis();\n Nodrix.send(\"temperature\", dht.readTemperature());\n Nodrix.send(\"humidity\", dht.readHumidity());\n }\n}\n```"}{"q": "How does deep sleep work on an ESP8266 with Nodrix?", "a": "```cpp\n#define SLEEP_MINUTES 15\n\nvoid setup() {\n Serial.begin(115200);\n dht.begin();\n Nodrix.beginHTTP(WIFI_SSID, WIFI_PASS, HOST, TOKEN);\n Nodrix.send(\"temperature\", dht.readTemperature());\n Nodrix.send(\"humidity\", dht.readHumidity());\n Nodrix.flush(); // POST the batch\n Nodrix.poll(); // grab queued commands while awake\n ESP.deepSleep((uint64_t)SLEEP_MINUTES * 60ULL * 1000000ULL); // wakes via GPIO16 -> RST\n}\n\nvoid loop() {} // intentionally empty for a deep-sleep design\n```"}{"q": "I'm migrating from Particle. What replaces Particle.function()?", "a": "```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```"}