pridany zdrojak pre arduino a AGENTS.md
This commit is contained in:
76
AGENTS.md
Normal file
76
AGENTS.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## Project Structure & Module Organization
|
||||
|
||||
This repository contains a small ESP8266/ESP32 Arduino project for monitoring water level with conductive electrodes.
|
||||
|
||||
- `arduino/arduino.ino` contains the Arduino sketch and main application logic.
|
||||
- `README.md` gives the high-level project purpose.
|
||||
- `LICENSE` contains licensing information.
|
||||
- `.agents/` is reserved for agent/tooling metadata and should not be treated as firmware source.
|
||||
|
||||
Keep Arduino source files inside the `arduino/` sketch directory so Arduino IDE can open and build the project correctly.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
|
||||
Use Arduino IDE or `arduino-cli` with the ESP8266 or ESP32 board package installed.
|
||||
|
||||
Examples:
|
||||
|
||||
```sh
|
||||
arduino-cli compile --fqbn esp8266:esp8266:nodemcuv2 arduino
|
||||
arduino-cli upload -p COM3 --fqbn esp8266:esp8266:nodemcuv2 arduino
|
||||
arduino-cli monitor -p COM3 -c baudrate=115200
|
||||
|
||||
arduino-cli compile --fqbn esp32:esp32:esp32 arduino
|
||||
arduino-cli upload -p COM3 --fqbn esp32:esp32:esp32 arduino
|
||||
arduino-cli monitor -p COM3 -c baudrate=115200
|
||||
```
|
||||
|
||||
- `compile` verifies the sketch builds for the selected board.
|
||||
- `upload` flashes the firmware to the connected board.
|
||||
- `monitor` opens the serial console used by debug output.
|
||||
|
||||
Adjust `--fqbn` and `COM3` for the actual board and port.
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
|
||||
Write C++ compatible with Arduino IDE and the ESP8266/ESP32 cores. Use two-space indentation, braces on the same line, and descriptive names.
|
||||
|
||||
- Constants: uppercase or clearly prefixed names, for example `PIN_LEVEL1`, `SLEEP_TIME_SEC`.
|
||||
- Structs and types: PascalCase, for example `WaterLevels`.
|
||||
- Functions: lower camelCase, for example `readLevels()` and `connectWifi()`.
|
||||
|
||||
Prefer small functions with one responsibility. Keep hardware pins, URLs, timings, and debug flags as constants near the top of the sketch.
|
||||
|
||||
## Hardware Notes
|
||||
|
||||
For ESP8266 conductive level sensing, use external pull-down resistors from each `PIN_LEVEL1..4` input to `GND`. The common electrode is driven to positive voltage only during measurement.
|
||||
|
||||
Avoid ESP8266 boot/strap pins for level inputs when possible, especially `GPIO0`, `GPIO2`, and `GPIO15`. Also avoid `GPIO1`/`GPIO3` unless intentionally sharing the serial port. Prefer ordinary GPIO pins such as `GPIO5`, `GPIO4`, `GPIO14`, `GPIO12`, or `GPIO13`, depending on the board and wiring.
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
There is no automated test framework in this repository. Validate changes by compiling the sketch and testing on hardware.
|
||||
|
||||
Before committing firmware changes:
|
||||
|
||||
- Compile for the target ESP8266 or ESP32 board.
|
||||
- Test `DEBUG == 1` for local level readings without Wi-Fi.
|
||||
- Test `DEBUG == 2` for repeated Wi-Fi POST requests.
|
||||
- Test `DEBUG == 0` for production sleep/wake behavior.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
|
||||
Current Git history is minimal and uses a simple message such as `Initial commit`. Keep future commits short, imperative, and specific, for example `Add WiFi timeout handling`.
|
||||
|
||||
Pull requests should include:
|
||||
|
||||
- A brief description of firmware behavior changed.
|
||||
- Board model and Arduino ESP8266/ESP32 core version used for testing.
|
||||
- Serial output or screenshots when debugging behavior changes.
|
||||
- Any required configuration changes, especially Wi-Fi, server URL, or pin mapping.
|
||||
|
||||
## Security & Configuration Tips
|
||||
|
||||
Avoid committing real Wi-Fi passwords or private server endpoints when possible. For shared changes, replace secrets with placeholders and document required local values.
|
||||
245
arduino/arduino.ino
Normal file
245
arduino/arduino.ino
Normal file
@ -0,0 +1,245 @@
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <WiFiClientSecureBearSSL.h>
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <esp_sleep.h>
|
||||
#else
|
||||
#error "This sketch supports ESP8266 and ESP32 boards only."
|
||||
#endif
|
||||
|
||||
const int PIN_COMMON_ELECTRODE = 13; // GPIO13 / D7
|
||||
const int PIN_LEVEL1 = 5; // GPIO5 / D1 - najnizsia hladina
|
||||
const int PIN_LEVEL2 = 4; // GPIO4 / D2
|
||||
const int PIN_LEVEL3 = 14; // GPIO14 / D5
|
||||
const int PIN_LEVEL4 = 12; // GPIO12 / D6 - najvyssia hladina
|
||||
|
||||
const int DEBUG = 1;
|
||||
|
||||
const char WIFI_SSID[] = "TP-Link_DD1E";
|
||||
const char WIFI_PASS[] = "33784120";
|
||||
const unsigned long SLEEP_TIME_SEC = 1800;
|
||||
const char URL_LOG[] = "https://vihorlat.tpsoft.org/hladinac/server/log.php";
|
||||
|
||||
const unsigned long WIFI_TIMEOUT_MS = 15000;
|
||||
const unsigned long MEASUREMENT_STABILIZE_MS = 50;
|
||||
|
||||
struct WaterLevels {
|
||||
int level1;
|
||||
int level2;
|
||||
int level3;
|
||||
int level4;
|
||||
};
|
||||
|
||||
void initPins();
|
||||
WaterLevels readLevels();
|
||||
void printLevels(const WaterLevels &levels);
|
||||
String buildPostBody(const WaterLevels &levels);
|
||||
bool connectWifi();
|
||||
bool sendLevelsToServer(const WaterLevels &levels);
|
||||
void enterDeepSleep();
|
||||
void setupLevelPin(int pin);
|
||||
void setCommonElectrodeOn();
|
||||
void setCommonElectrodeOff();
|
||||
int readLevelPin(int pin);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(200);
|
||||
Serial.println("Hladinac v0.3 started.");
|
||||
|
||||
initPins();
|
||||
|
||||
if (DEBUG == 0) {
|
||||
WaterLevels levels = readLevels();
|
||||
printLevels(levels);
|
||||
|
||||
if (connectWifi()) {
|
||||
sendLevelsToServer(levels);
|
||||
WiFi.disconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
} else {
|
||||
Serial.println("WiFi connection failed, skipping upload.");
|
||||
}
|
||||
|
||||
enterDeepSleep();
|
||||
} else if (DEBUG == 2) {
|
||||
connectWifi();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (DEBUG == 1) {
|
||||
WaterLevels levels = readLevels();
|
||||
printLevels(levels);
|
||||
delay(1000);
|
||||
} else if (DEBUG == 2) {
|
||||
WaterLevels levels = readLevels();
|
||||
printLevels(levels);
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
connectWifi();
|
||||
}
|
||||
|
||||
sendLevelsToServer(levels);
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
|
||||
void initPins() {
|
||||
pinMode(PIN_COMMON_ELECTRODE, OUTPUT);
|
||||
setCommonElectrodeOff();
|
||||
|
||||
setupLevelPin(PIN_LEVEL1);
|
||||
setupLevelPin(PIN_LEVEL2);
|
||||
setupLevelPin(PIN_LEVEL3);
|
||||
setupLevelPin(PIN_LEVEL4);
|
||||
}
|
||||
|
||||
void setupLevelPin(int pin) {
|
||||
#if defined(ESP32)
|
||||
pinMode(pin, INPUT_PULLDOWN);
|
||||
#else
|
||||
// ESP8266 pouziva externe pull-down rezistory na GND.
|
||||
pinMode(pin, INPUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setCommonElectrodeOn() {
|
||||
#if defined(ESP8266)
|
||||
digitalWrite(PIN_COMMON_ELECTRODE, HIGH);
|
||||
#else
|
||||
digitalWrite(PIN_COMMON_ELECTRODE, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setCommonElectrodeOff() {
|
||||
#if defined(ESP8266)
|
||||
digitalWrite(PIN_COMMON_ELECTRODE, LOW);
|
||||
#else
|
||||
digitalWrite(PIN_COMMON_ELECTRODE, LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
int readLevelPin(int pin) {
|
||||
#if defined(ESP8266)
|
||||
return digitalRead(pin) == HIGH ? 1 : 0;
|
||||
#else
|
||||
return digitalRead(pin) == HIGH ? 1 : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
WaterLevels readLevels() {
|
||||
WaterLevels levels;
|
||||
|
||||
// Spolocna elektroda je zapnuta iba pocas merania, aby sa znizila korozia.
|
||||
setCommonElectrodeOn();
|
||||
delay(MEASUREMENT_STABILIZE_MS);
|
||||
|
||||
levels.level1 = readLevelPin(PIN_LEVEL1);
|
||||
levels.level2 = readLevelPin(PIN_LEVEL2);
|
||||
levels.level3 = readLevelPin(PIN_LEVEL3);
|
||||
levels.level4 = readLevelPin(PIN_LEVEL4);
|
||||
|
||||
setCommonElectrodeOff();
|
||||
|
||||
return levels;
|
||||
}
|
||||
|
||||
void printLevels(const WaterLevels &levels) {
|
||||
Serial.print("level1=");
|
||||
Serial.print(levels.level1);
|
||||
Serial.print(" level2=");
|
||||
Serial.print(levels.level2);
|
||||
Serial.print(" level3=");
|
||||
Serial.print(levels.level3);
|
||||
Serial.print(" level4=");
|
||||
Serial.println(levels.level4);
|
||||
}
|
||||
|
||||
String buildPostBody(const WaterLevels &levels) {
|
||||
String body = "level1=" + String(levels.level1);
|
||||
body += "&level2=" + String(levels.level2);
|
||||
body += "&level3=" + String(levels.level3);
|
||||
body += "&level4=" + String(levels.level4);
|
||||
return body;
|
||||
}
|
||||
|
||||
bool connectWifi() {
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Serial.print("Connecting to WiFi");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||
|
||||
unsigned long startedAt = millis();
|
||||
while (WiFi.status() != WL_CONNECTED && millis() - startedAt < WIFI_TIMEOUT_MS) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println();
|
||||
Serial.print("WiFi connected, IP=");
|
||||
Serial.println(WiFi.localIP());
|
||||
return true;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println("WiFi connection timeout.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sendLevelsToServer(const WaterLevels &levels) {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.println("Cannot send data, WiFi is not connected.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
BearSSL::WiFiClientSecure client;
|
||||
#else
|
||||
WiFiClientSecure client;
|
||||
#endif
|
||||
client.setInsecure();
|
||||
|
||||
HTTPClient http;
|
||||
if (!http.begin(client, URL_LOG)) {
|
||||
Serial.println("HTTP begin failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
String body = buildPostBody(levels);
|
||||
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
|
||||
int httpCode = http.POST(body);
|
||||
if (httpCode > 0) {
|
||||
Serial.print("POST sent, HTTP code=");
|
||||
Serial.println(httpCode);
|
||||
} else {
|
||||
Serial.print("POST failed: ");
|
||||
Serial.println(http.errorToString(httpCode));
|
||||
}
|
||||
|
||||
http.end();
|
||||
return httpCode > 0 && httpCode < 400;
|
||||
}
|
||||
|
||||
void enterDeepSleep() {
|
||||
Serial.print("Entering deep sleep for ");
|
||||
Serial.print(SLEEP_TIME_SEC);
|
||||
Serial.println(" seconds.");
|
||||
Serial.flush();
|
||||
|
||||
#if defined(ESP8266)
|
||||
ESP.deepSleep((uint64_t)SLEEP_TIME_SEC * 1000000ULL);
|
||||
#else
|
||||
esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_TIME_SEC * 1000000ULL);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user