Initial commit: mata avispas Arduino code and README
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
# mata avispas
|
||||||
|
|
||||||
|
Flyback high voltage generator (≈12 kV output) controlled by an ESP32‑C3.
|
||||||
|
|
||||||
|
Features
|
||||||
|
- ESP32‑C3 runs as a Wi‑Fi Access Point (AP) so you can connect directly to it.
|
||||||
|
- A simple web server lets you adjust the PWM frequency/duty cycle that drives the XY‑MOS driver.
|
||||||
|
- PWM output is generated on a GPIO using the LEDC hardware (high‑resolution, glitch‑free).
|
||||||
|
- Safety: the PWM can be disabled via the web page.
|
||||||
|
|
||||||
|
Hardware notes
|
||||||
|
- XY‑MOS driver expects a PWM signal (typically 5 V logic) on its INPUT pin.
|
||||||
|
- Connect ESP32‑C3 GPIO to XY‑MOS INPUT through a level‑shifter if needed (ESP32‑C3 is 3.3 V tolerant, most XY‑MOS accept 3.3 V).
|
||||||
|
- Flyback transformer secondary should be properly insulated and terminated with a high‑voltage diode/Cockcroft‑Walton multiplier if you need DC.
|
||||||
|
- Always use proper shielding, grounding, and never touch the output while powered.
|
||||||
|
|
||||||
|
How to build
|
||||||
|
1. Install the ESP32 Arduino core (Boards Manager → esp32 by Espressif Systems).
|
||||||
|
2. Select "ESP32C3 Dev Module" (or your specific board).
|
||||||
|
3. Copy this folder to your Arduino sketchbook or open with PlatformIO/VSCode.
|
||||||
|
4. Compile and upload.
|
||||||
|
5. After upload, the ESP32‑C3 will start an AP named `MataAvispas_AP` (password `avispas123`).
|
||||||
|
6. Connect your phone/laptop to that AP, open a browser to `http://192.168.4.1` and adjust PWM.
|
||||||
|
|
||||||
|
License: MIT – feel free to adapt.
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* mata avispas – Flyback high voltage generator controller
|
||||||
|
* ESP32‑C3 as Access Point + Web server to configure PWM driving an XY‑MOS driver
|
||||||
|
*
|
||||||
|
* PWM output: GPIO2 (adjustable via LEDC)
|
||||||
|
* Web page: http://192.168.4.1
|
||||||
|
* AP SSID: MataAvispas_AP
|
||||||
|
* AP Password: avispas123
|
||||||
|
*
|
||||||
|
* The page lets you set:
|
||||||
|
* - Frequency (Hz) : 100 – 20000
|
||||||
|
* - Duty cycle (%) : 0 – 100
|
||||||
|
* - Enable/Disable output
|
||||||
|
*
|
||||||
|
* Uses the ESP32 Arduino core (https://github.com/espressif/arduino-esp32)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <WebServer.h>
|
||||||
|
|
||||||
|
// ==== USER SETTINGS ====
|
||||||
|
const char* AP_SSID = "MataAvispas_AP";
|
||||||
|
const char* AP_PASSWORD = "avispas123";
|
||||||
|
const uint8_t PWM_GPIO = 2; // XY‑MOS INPUT pin
|
||||||
|
const uint8_t PWM_CHANNEL = 0; // LEDC channel 0
|
||||||
|
const uint8_t PWM_RESOLUTION = 10; // 10‑bit resolution => 0‑1023
|
||||||
|
// =======================
|
||||||
|
|
||||||
|
WebServer server(80);
|
||||||
|
|
||||||
|
// Current PWM state
|
||||||
|
uint32_t pwmFrequency = 1000; // default 1 kHz
|
||||||
|
uint32_t pwmDuty = 512; // 50 % of 1023
|
||||||
|
bool pwmEnabled = false;
|
||||||
|
|
||||||
|
// HTML page (stored in PROGMEM to save RAM)
|
||||||
|
const char INDEX_HTML[] PROGMEM = R"rawliteral(
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, charset=utf-8">
|
||||||
|
<title>Mata Avispas – PWM Config</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, Helvetica, sans-serif; margin: 20px; background:#f4f4f4; }
|
||||||
|
.container { max-width: 480px; margin: auto; background:#fff; padding:20px; box-shadow:0 0 10px rgba(0,0,0,.1); border-radius:8px; }
|
||||||
|
h1 { color:#2c3e50; text-align:center; }
|
||||||
|
label { display:block; margin-top:15px; font-weight:bold; }
|
||||||
|
input[type="number"], input[type="range"] { width:100%; padding:8px; margin-top:5px; }
|
||||||
|
.btn { display:inline-block; margin-top:20px; padding:10px 20px; background:#27ae60; color:#fff; border:none; border-radius:4px; cursor:pointer; }
|
||||||
|
.btn.disabled { background:#95a5a6; cursor:not-allowed; }
|
||||||
|
.status { margin-top:15px; padding:10px; background:#ecf0f1; border-radius:4px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Mata Avispas</h1>
|
||||||
|
<div class="status" id="status">PWM: <span id="pwmState">OFF</span></div>
|
||||||
|
|
||||||
|
<label for="freq">Frequency (Hz)</label>
|
||||||
|
<input type="number" id="freq" min="100" max="20000" value="1000">
|
||||||
|
<small>Range: 100 – 20000 Hz</small>
|
||||||
|
|
||||||
|
<label for="duty">Duty cycle (%)</label>
|
||||||
|
<input type="range" id="duty" min="0" max="100" value="50">
|
||||||
|
<span id="dutyVal">50</span>%
|
||||||
|
|
||||||
|
<label for="enable">Output</label>
|
||||||
|
<select id="enable">
|
||||||
|
<option value="0">Disabled</option>
|
||||||
|
<option value="1">Enabled</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button class="btn" id="sendBtn">Apply Settings</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const freqIn = document.getElementById('freq');
|
||||||
|
const dutyIn = document.getElementById('duty');
|
||||||
|
const dutyVal = document.getElementById('dutyVal');
|
||||||
|
const enableIn = document.getElementById('enable');
|
||||||
|
const btn = document.getElementById('sendBtn');
|
||||||
|
const status = document.getElementById('status');
|
||||||
|
const pwmState = document.getElementById('pwmState');
|
||||||
|
|
||||||
|
dutyIn.addEventListener('input', () => {
|
||||||
|
dutyVal.textContent = dutyIn.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const data = {
|
||||||
|
freq: parseInt(freqIn.value),
|
||||||
|
duty: parseInt(dutyIn.value),
|
||||||
|
en: parseInt(enableIn.value)
|
||||||
|
};
|
||||||
|
fetch('/set', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(resp => {
|
||||||
|
if (resp.ok) {
|
||||||
|
pwmState.textContent = resp.enabled ? 'ON' : 'OFF';
|
||||||
|
status.innerHTML = `PWM: <strong>${resp.enabled ? 'ON' : 'OFF'}</strong> (freq: ${resp.freq} Hz, duty: ${resp.duty}%)`;
|
||||||
|
status.style.background = resp.enabled ? '#dff0d8' : '#f2dede';
|
||||||
|
} else {
|
||||||
|
alert('Error: ' + resp.msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert('Network error: ' + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load current settings on page load
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
fetch('/get')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
freqIn.value = data.freq;
|
||||||
|
dutyIn.value = data.duty;
|
||||||
|
dutyVal.textContent = data.duty;
|
||||||
|
enableIn.value = data.enabled ? '1' : '0';
|
||||||
|
pwmState.textContent = data.enabled ? 'ON' : 'OFF';
|
||||||
|
status.innerHTML = `PWM: <strong>${data.enabled ? 'ON' : 'OFF'}</strong> (freq: ${data.freq} Hz, duty: ${data.duty}%)`;
|
||||||
|
status.style.background = data.enabled ? '#dff0d8' : '#f2dede';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
)rawliteral";
|
||||||
|
|
||||||
|
void handleRoot() {
|
||||||
|
server.send_P(200, "text/html", INDEX_HTML, strlen_P(INDEX_HTML));
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleGet() {
|
||||||
|
String json = "{";
|
||||||
|
json += "\"freq\":" + String(pwmFrequency) + ",";
|
||||||
|
json += "\"duty\":" + String(map(pwmDuty, 0, (1<<PWM_RESOLUTION)-1, 0, 100)) + ",";
|
||||||
|
json += "\"enabled\":" + String(pwmEnabled ? "true" : "false");
|
||||||
|
json += "}";
|
||||||
|
server.send(200, "application/json", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSet() {
|
||||||
|
if (server.method() != HTTP_POST) {
|
||||||
|
server.send(405, "text/plain", "Method Not Allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!server.hasArg("plain")) {
|
||||||
|
server.send(400, "text/plain", "Missing JSON body");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String body = server.arg("plain");
|
||||||
|
// Very simple JSON parsing (expects {"freq":N,"duty":M,"en":0|1})
|
||||||
|
int freq = 1000;
|
||||||
|
int duty = 50;
|
||||||
|
int en = 0;
|
||||||
|
|
||||||
|
int idx = body.indexOf("\"freq\":");
|
||||||
|
if (idx >= 0) {
|
||||||
|
String sub = body.substring(idx + 7);
|
||||||
|
freq = sub.substring(0, sub.indexOf(",")).toInt();
|
||||||
|
}
|
||||||
|
idx = body.indexOf("\"duty\":");
|
||||||
|
if (idx >= 0) {
|
||||||
|
String sub = body.substring(idx + 7);
|
||||||
|
duty = sub.substring(0, sub.indexOf(",")).toInt();
|
||||||
|
}
|
||||||
|
idx = body.indexOf("\"en\":");
|
||||||
|
if (idx >= 0) {
|
||||||
|
String sub = body.substring(idx + 5);
|
||||||
|
en = sub.substring(0, sub.indexOf("}")).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp values
|
||||||
|
if (freq < 100) freq = 100;
|
||||||
|
if (freq > 20000) freq = 20000;
|
||||||
|
if (duty < 0) duty = 0;
|
||||||
|
if (duty > 100) duty = 100;
|
||||||
|
|
||||||
|
// Update PWM
|
||||||
|
pwmFrequency = freq;
|
||||||
|
pwmDuty = map(duty, 0, 100, 0, (1<<PWM_RESOLUTION)-1);
|
||||||
|
pwmEnabled = (en == 1);
|
||||||
|
|
||||||
|
if (pwmEnabled) {
|
||||||
|
ledcSetup(PWM_CHANNEL, pwmFrequency, PWM_RESOLUTION);
|
||||||
|
ledcAttachPin(PWM_GPIO, PWM_CHANNEL);
|
||||||
|
ledcWrite(PWM_CHANNEL, pwmDuty);
|
||||||
|
} else {
|
||||||
|
ledcDetachPin(PWM_GPIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
String json = "{";
|
||||||
|
json += "\"ok\":true,\"freq\":" + String(pwmFrequency) + ",";
|
||||||
|
json += "\"duty\":" + String(duty) + ",";
|
||||||
|
json += "\"enabled\":" + String(pwmEnabled ? "true" : "false");
|
||||||
|
json += "}";
|
||||||
|
server.send(200, "application/json", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
// Set PWM GPIO as output (safe default)
|
||||||
|
pinMode(PWM_GPIO, OUTPUT);
|
||||||
|
digitalWrite(PWM_GPIO, LOW);
|
||||||
|
|
||||||
|
// Start AP
|
||||||
|
WiFi.mode(WIFI_AP);
|
||||||
|
WiFi.softAP(AP_SSID, AP_PASSWORD);
|
||||||
|
IPAddress apIP = WiFi.softAPIP();
|
||||||
|
Serial.print("AP IP address: ");
|
||||||
|
Serial.println(apIP);
|
||||||
|
|
||||||
|
// Web server routes
|
||||||
|
server.on("/", HTTP_GET, handleRoot);
|
||||||
|
server.on("/get", HTTP_GET, handleGet);
|
||||||
|
server.on("/set", HTTP_POST, handleSet);
|
||||||
|
server.begin();
|
||||||
|
Serial.println("HTTP server started");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
server.handleClient();
|
||||||
|
// Nothing else needed; PWM runs in hardware
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user