forked from ctdo/blitzer
feature: api with highscore, last 10 speed measures and manual flashing as well as setting the speedlimit via api, hardcoded for mch2022
This commit is contained in:
parent
fc3a617c60
commit
79f110c0ce
|
@ -3,4 +3,4 @@
|
||||||
.clang_complete
|
.clang_complete
|
||||||
.gcc-flags.json
|
.gcc-flags.json
|
||||||
.pio
|
.pio
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -12,6 +12,5 @@
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
board = d1_mini
|
board = d1_mini
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
lib_deps = me-no-dev/ESP Async WebServer@^1.2.3
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Blitzer</title>
|
||||||
|
<style type="text/css">
|
||||||
|
body, html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 10px 20px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 70px;
|
||||||
|
background-color: red;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Blitzercontrol</h1>
|
||||||
|
<h2>Highscore</h2>
|
||||||
|
<span id="highscore">23km/h</span>
|
||||||
|
<h2>Letzte Messungen</h2>
|
||||||
|
<ul id="lastSpeeds">
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
</ul>
|
||||||
|
<h2>Manuelle Steuerung</h2>
|
||||||
|
<button class="btn" onclick="flash()">Flash</button>
|
||||||
|
<h2>Speed setting</h2>
|
||||||
|
<input id="threshold" type="text" /> km/h<br />
|
||||||
|
<button onclick="setSpeed()">Set Speed</button>
|
||||||
|
<script type="text/javascript">
|
||||||
|
const highscoreElem = document.getElementById("highscore");
|
||||||
|
const lastSpeeds = document.getElementById("lastSpeeds");
|
||||||
|
const thresholdFieldElem = document.getElementById("threshold");
|
||||||
|
function flash() {
|
||||||
|
fetch('/flash').then(() => {});
|
||||||
|
}
|
||||||
|
function setSpeed() {
|
||||||
|
console.log('/set?speed=' + thresholdFieldElem.value);
|
||||||
|
fetch('/set?speed=' + thresholdFieldElem.value);
|
||||||
|
}
|
||||||
|
function getData() {
|
||||||
|
fetch('/data.json')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
highscoreElem.innerText = data.highscore + ' km/h';
|
||||||
|
let c = lastSpeeds.children;
|
||||||
|
for(let i=0; i<data.lastSpeeds.length; i++) {
|
||||||
|
c[i].innerText = data.lastSpeeds[i] + ' km/h';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
window.setInterval(getData, 1000)
|
||||||
|
getData();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,121 +1,11 @@
|
||||||
#include <Arduino.h>
|
#include <main.h>
|
||||||
|
|
||||||
float flashspeed=20; //in kmh
|
|
||||||
unsigned long flashdeadtime=1000; //in ms
|
|
||||||
|
|
||||||
#define PIN_SW1 D6
|
|
||||||
#define PIN_SW2 D5
|
|
||||||
#define PIN_TRIGGER D7
|
|
||||||
volatile boolean sw1_flag = false;
|
|
||||||
volatile boolean sw2_flag = false;
|
|
||||||
|
|
||||||
unsigned long sw1_lastTime=0;
|
|
||||||
unsigned long sw2_lastTime=0;
|
|
||||||
|
|
||||||
float calib_distance=0.062; //distance of sensors in meters
|
|
||||||
|
|
||||||
#define SWDEBOUNCE 100000
|
|
||||||
|
|
||||||
ICACHE_RAM_ATTR void interrupt_sw1();
|
|
||||||
ICACHE_RAM_ATTR void interrupt_sw2();
|
|
||||||
float getLastSpeed1();
|
|
||||||
float getLastSpeed2();
|
|
||||||
void doTrigger1();
|
|
||||||
void doTrigger2();
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
pinMode(PIN_SW1, INPUT_PULLUP);
|
handleSetup();
|
||||||
pinMode(PIN_SW2, INPUT_PULLUP);
|
|
||||||
pinMode(PIN_TRIGGER, OUTPUT);
|
|
||||||
attachInterrupt(digitalPinToInterrupt(PIN_SW1), interrupt_sw1, FALLING);
|
|
||||||
attachInterrupt(digitalPinToInterrupt(PIN_SW2), interrupt_sw2, FALLING);
|
|
||||||
digitalWrite(PIN_TRIGGER, HIGH); //active low
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
beginWiFi();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
handleLoop();
|
||||||
if (sw1_flag){
|
|
||||||
sw1_flag=false;
|
|
||||||
sw1_lastTime=micros();
|
|
||||||
Serial.println("SW1");
|
|
||||||
doTrigger1();
|
|
||||||
}
|
|
||||||
if (sw2_flag){
|
|
||||||
sw2_flag=false;
|
|
||||||
sw2_lastTime=micros();
|
|
||||||
Serial.println("SW2");
|
|
||||||
doTrigger2();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void doTrigger1() {
|
|
||||||
static unsigned long last_flash=0;
|
|
||||||
|
|
||||||
|
|
||||||
float speed=getLastSpeed1();
|
|
||||||
|
|
||||||
if (speed*3.6<0.1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis()-last_flash>flashdeadtime) { //deadtime
|
|
||||||
last_flash=millis();
|
|
||||||
|
|
||||||
if (speed*3.6 >= flashspeed) {
|
|
||||||
Serial.print("> Speed="); Serial.print(speed*3.6); Serial.println(" km/h");
|
|
||||||
Serial.println("Flash");
|
|
||||||
pinMode(PIN_TRIGGER, INPUT); //high impedance
|
|
||||||
delay(100);
|
|
||||||
pinMode(PIN_TRIGGER, OUTPUT); digitalWrite(PIN_TRIGGER, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void doTrigger2() {
|
|
||||||
static unsigned long last_flash=0;
|
|
||||||
|
|
||||||
float speed=getLastSpeed2();
|
|
||||||
|
|
||||||
|
|
||||||
if (speed*3.6<0.1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis()-last_flash>flashdeadtime) { //deadtime
|
|
||||||
last_flash=millis();
|
|
||||||
|
|
||||||
if (speed*3.6 >= flashspeed) {
|
|
||||||
Serial.print("> Speed="); Serial.print(speed*3.6); Serial.println(" km/h");
|
|
||||||
Serial.println("Flash");
|
|
||||||
pinMode(PIN_TRIGGER, INPUT); //high impedance
|
|
||||||
delay(100);
|
|
||||||
pinMode(PIN_TRIGGER, OUTPUT); digitalWrite(PIN_TRIGGER, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ICACHE_RAM_ATTR void interrupt_sw1() {
|
|
||||||
if (sw1_lastTime+SWDEBOUNCE<micros()){
|
|
||||||
sw1_flag=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ICACHE_RAM_ATTR void interrupt_sw2() {
|
|
||||||
if (sw2_lastTime+SWDEBOUNCE<micros()){
|
|
||||||
sw2_flag=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float getLastSpeed1() {
|
|
||||||
return calib_distance/((sw1_lastTime-sw2_lastTime)/1000000.0);
|
|
||||||
}
|
|
||||||
float getLastSpeed2() {
|
|
||||||
return calib_distance/((sw2_lastTime-sw1_lastTime)/1000000.0);
|
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef main_h
|
||||||
|
#define main_h
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <speed.h>
|
||||||
|
#include <webserver.h>
|
||||||
|
#endif
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
|
const char index_html[] PROGMEM = R"rawliteral(
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Blitzer</title>
|
||||||
|
<style type="text/css">
|
||||||
|
body, html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 10px 20px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 70px;
|
||||||
|
background-color: red;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Blitzercontrol</h1>
|
||||||
|
<h2>Highscore</h2>
|
||||||
|
<span id="highscore">23km/h</span>
|
||||||
|
<h2>Letzte Messungen</h2>
|
||||||
|
<ul id="lastSpeeds">
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
</ul>
|
||||||
|
<h2>Manuelle Steuerung</h2>
|
||||||
|
<button class="btn" onclick="flash()">Flash</button>
|
||||||
|
<h2>Speed setting</h2>
|
||||||
|
<input id="threshold" type="text" /> km/h<br />
|
||||||
|
<button onclick="setSpeed()">Set Speed</button>
|
||||||
|
<script type="text/javascript">
|
||||||
|
const highscoreElem = document.getElementById("highscore");
|
||||||
|
const lastSpeeds = document.getElementById("lastSpeeds");
|
||||||
|
const thresholdFieldElem = document.getElementById("threshold");
|
||||||
|
function flash() {
|
||||||
|
fetch('/flash').then(() => {});
|
||||||
|
}
|
||||||
|
function setSpeed() {
|
||||||
|
console.log('/set?speed=' + thresholdFieldElem.value);
|
||||||
|
fetch('/set?speed=' + thresholdFieldElem.value);
|
||||||
|
}
|
||||||
|
function getData() {
|
||||||
|
fetch('/data.json')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
highscoreElem.innerText = data.highscore + ' km/h';
|
||||||
|
let c = lastSpeeds.children;
|
||||||
|
for(let i=0; i<data.lastSpeeds.length; i++) {
|
||||||
|
c[i].innerText = data.lastSpeeds[i] + ' km/h';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
window.setInterval(getData, 1000)
|
||||||
|
getData();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
)rawliteral";
|
|
@ -0,0 +1,131 @@
|
||||||
|
#include <speed.h>
|
||||||
|
|
||||||
|
#define PIN_SW1 D6
|
||||||
|
#define PIN_SW2 D5
|
||||||
|
#define PIN_TRIGGER D7
|
||||||
|
volatile boolean sw1_flag = false;
|
||||||
|
volatile boolean sw2_flag = false;
|
||||||
|
|
||||||
|
unsigned long sw1_lastTime = 0;
|
||||||
|
unsigned long sw2_lastTime = 0;
|
||||||
|
|
||||||
|
float flashspeed = 20; // in kmh
|
||||||
|
unsigned long flashdeadtime = 1000; // in ms
|
||||||
|
float calib_distance = 0.062; // distance of sensors in meters
|
||||||
|
float lastMeasuredSpeeds[10];
|
||||||
|
float highscore = 0;
|
||||||
|
|
||||||
|
unsigned long last_flash = 0;
|
||||||
|
|
||||||
|
#define SWDEBOUNCE 100000
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR void interrupt_sw1();
|
||||||
|
ICACHE_RAM_ATTR void interrupt_sw2();
|
||||||
|
float getLastSpeed1();
|
||||||
|
float getLastSpeed2();
|
||||||
|
|
||||||
|
void handleSetup()
|
||||||
|
{
|
||||||
|
pinMode(PIN_SW1, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_SW2, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_TRIGGER, OUTPUT);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_SW1), interrupt_sw1, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_SW2), interrupt_sw2, FALLING);
|
||||||
|
digitalWrite(PIN_TRIGGER, HIGH); // active low
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleLoop()
|
||||||
|
{
|
||||||
|
// reset micros within the first half second to care for overflowing micros
|
||||||
|
if (micros() < 500000) {
|
||||||
|
sw1_flag = false;
|
||||||
|
sw1_lastTime = 0;
|
||||||
|
sw2_flag = false;
|
||||||
|
sw2_lastTime = 0;
|
||||||
|
}
|
||||||
|
if (millis() < 500) {
|
||||||
|
last_flash = 0;
|
||||||
|
}
|
||||||
|
if (sw1_flag)
|
||||||
|
{
|
||||||
|
sw1_flag = false;
|
||||||
|
sw1_lastTime = micros();
|
||||||
|
Serial.println("SW1");
|
||||||
|
doTrigger(getLastSpeed1());
|
||||||
|
}
|
||||||
|
if (sw2_flag)
|
||||||
|
{
|
||||||
|
sw2_flag = false;
|
||||||
|
sw2_lastTime = micros();
|
||||||
|
Serial.println("SW2");
|
||||||
|
doTrigger(getLastSpeed2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doTrigger(float speed)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (speed < 0.1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millis() - last_flash > flashdeadtime)
|
||||||
|
{ // deadtime
|
||||||
|
last_flash = millis();
|
||||||
|
|
||||||
|
if (speed >= flashspeed)
|
||||||
|
{
|
||||||
|
addLastSpeed(speed);
|
||||||
|
Serial.print("> Speed=");
|
||||||
|
Serial.print(speed);
|
||||||
|
Serial.println(" km/h");
|
||||||
|
flash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash() {
|
||||||
|
Serial.println("Flash");
|
||||||
|
pinMode(PIN_TRIGGER, INPUT); // high impedance
|
||||||
|
delay(100);
|
||||||
|
pinMode(PIN_TRIGGER, OUTPUT);
|
||||||
|
digitalWrite(PIN_TRIGGER, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addLastSpeed(float speed)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
lastMeasuredSpeeds[i] = lastMeasuredSpeeds[i + 1];
|
||||||
|
}
|
||||||
|
lastMeasuredSpeeds[9] = speed;
|
||||||
|
if (highscore < speed) {
|
||||||
|
highscore = speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR void interrupt_sw1()
|
||||||
|
{
|
||||||
|
if (sw1_lastTime + SWDEBOUNCE < micros())
|
||||||
|
{
|
||||||
|
sw1_flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR void interrupt_sw2()
|
||||||
|
{
|
||||||
|
if (sw2_lastTime + SWDEBOUNCE < micros())
|
||||||
|
{
|
||||||
|
sw2_flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float getLastSpeed1()
|
||||||
|
{
|
||||||
|
return calib_distance / ((sw1_lastTime - sw2_lastTime) / 1000000.0) * 3.6;
|
||||||
|
}
|
||||||
|
float getLastSpeed2()
|
||||||
|
{
|
||||||
|
return calib_distance / ((sw2_lastTime - sw1_lastTime) / 1000000.0) * 3.6;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef speed_h
|
||||||
|
#define speed_h
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
extern float flashspeed;
|
||||||
|
extern float highscore;
|
||||||
|
extern unsigned long flashdeadtime;
|
||||||
|
extern float calib_distance;
|
||||||
|
|
||||||
|
extern float lastMeasuredSpeeds[10];
|
||||||
|
void flash();
|
||||||
|
void handleLoop();
|
||||||
|
void handleSetup();
|
||||||
|
void doTrigger(float speed);
|
||||||
|
void addLastSpeed(float speed);
|
||||||
|
#endif
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <webserver.h>
|
||||||
|
|
||||||
|
AsyncWebServer server(80);
|
||||||
|
|
||||||
|
void beginWiFi() {
|
||||||
|
WiFi.setHostname("chaoswestbliz");
|
||||||
|
WiFi.begin("MCH2022-open", "");
|
||||||
|
while(WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
server.on("/", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||||
|
request->send(200, "text/html", index_html);
|
||||||
|
});
|
||||||
|
server.on("/set", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||||
|
String s;
|
||||||
|
String message;
|
||||||
|
if (request->hasParam("speed")) {
|
||||||
|
s = request->getParam("speed")->value();
|
||||||
|
flashspeed = s.toFloat();
|
||||||
|
message = "Speed set successfully";
|
||||||
|
} else {
|
||||||
|
message = "No message sent";
|
||||||
|
}
|
||||||
|
Serial.print("Speed set to ");
|
||||||
|
Serial.print(s);
|
||||||
|
Serial.println("km/h");
|
||||||
|
request->send(200, "text/plain", "OK");
|
||||||
|
});
|
||||||
|
server.on("/flash", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||||
|
flash();
|
||||||
|
request->send(200, "text/plain", "OK");
|
||||||
|
});
|
||||||
|
server.on("/data.json", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||||
|
String response = "{\"highscore\":";
|
||||||
|
response.concat(highscore);
|
||||||
|
response.concat(",\"lastSpeeds\": [");
|
||||||
|
for(int i=0;i<10;i++) {
|
||||||
|
response.concat(lastMeasuredSpeeds[i]);
|
||||||
|
if(i<9) {
|
||||||
|
response.concat(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.concat("]}");
|
||||||
|
request->send(200, "application/json", response);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.begin();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef webserver_h
|
||||||
|
#define webserver_h
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <speed.h>
|
||||||
|
#include <site.h>
|
||||||
|
|
||||||
|
void beginWiFi();
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue