Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <WiFi.h>
- #include <AsyncTCP.h>
- #include <ESPAsyncWebServer.h>
- #include <SPIFFS.h>
- const char* ssid = "ChainsawNetwork";
- const char* password = "password";
- const int hallPin = 4; // GPIO pin connected to the Hall effect sensor
- const float wheelDiameterInches = 20.0; // Wheel diameter in inches
- const float wheelCircumference = wheelDiameterInches * PI; // Wheel circumference in inches
- volatile unsigned long lastTriggerTime = 0;
- volatile unsigned long rpm = 0;
- volatile unsigned long totalDistance = 0;
- volatile bool hallEffectState = false;
- // AsyncWebSocket server and clients
- AsyncWebSocket ws("/ws");
- AsyncWebSocketClient *client = NULL;
- // Function to calculate RPM and distance
- void IRAM_ATTR hallEffectISR() {
- unsigned long currentTime = micros();
- unsigned long timeSinceLastTrigger = currentTime - lastTriggerTime;
- if (timeSinceLastTrigger > 2000) { // Noise filter (ignore false triggers)
- rpm = 60000000 / timeSinceLastTrigger;
- lastTriggerTime = currentTime;
- hallEffectState = true;
- if (client && client->status() == WS_CONNECTED) {
- // Send RPM to WebSocket client
- String rpmData = String(rpm);
- client->text(rpmData);
- }
- // Calculate distance
- float distance = wheelCircumference / 63360.0; // Convert to miles
- totalDistance += distance;
- }
- }
- // Handle WebSocket events
- void onWebSocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) {
- if (type == WS_EVT_CONNECT) {
- Serial.println("WebSocket client connected");
- client->ping();
- } else if (type == WS_EVT_DISCONNECT) {
- Serial.println("WebSocket client disconnected");
- client = NULL;
- }
- }
- // Handle root endpoint
- void handleRoot(AsyncWebServerRequest* request) {
- String htmlContent = getHTMLContent();
- request->send(200, "text/html", htmlContent);
- }
- // Handle wheel size adjustment
- void handleWheelSize(AsyncWebServerRequest* request) {
- if (request->hasParam("size")) {
- float newSize = request->getParam("size")->value().toFloat();
- // Update wheel circumference
- // wheelCircumference = newSize;
- request->send(200);
- } else {
- request->send(400);
- }
- }
- // Handle clear distance data
- void handleClearDistance(AsyncWebServerRequest* request) {
- totalDistance = 0;
- request->send(200);
- }
- String getHTMLContent() {
- String htmlContent = R"HTML(
- <!DOCTYPE html>
- <html>
- <head>
- <title>Speedometer</title>
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
- <style>
- #chartContainer {
- width: 100%;
- height: 300px;
- }
- #sizeForm {
- margin-top: 20px;
- }
- .indicator {
- display: inline-block;
- width: 15px;
- height: 15px;
- border-radius: 50%;
- margin-right: 5px;
- }
- .indicator-on {
- background-color: green;
- }
- .indicator-off {
- background-color: red;
- }
- </style>
- <script>
- var rpmValue = document.getElementById('rpmValue');
- var speedValue = document.getElementById('speedValue');
- var wheelSizeInput = document.getElementById('wheelSize');
- var chart = null;
- var rpmData = [];
- var speedData = [];
- var hallEffectIndicator = document.getElementById('hallEffectIndicator');
- // WebSocket connection
- var ws = new WebSocket('ws://' + location.host + '/ws');
- ws.onmessage = function(event) {
- var rpm = event.data;
- rpmValue.textContent = rpm;
- // Calculate speed in mph
- var speed = rpm * wheelCircumference * 60 / 63360.0; // Convert RPM to MPH
- speedValue.textContent = speed.toFixed(2);
- // Add RPM and speed to data arrays
- var timestamp = new Date().getTime();
- rpmData.push({ x: timestamp, y: parseInt(rpm) });
- speedData.push({ x: timestamp, y: parseFloat(speed) });
- // Remove old data points
- var currentTime = timestamp;
- rpmData = rpmData.filter(function(data) {
- return (currentTime - data.x) <= 60000; // Keep data for the last 60 seconds
- });
- speedData = speedData.filter(function(data) {
- return (currentTime - data.x) <= 60000; // Keep data for the last 60 seconds
- });
- // Update the chart
- if (chart) {
- chart.update();
- }
- };
- // Form submission for wheel size adjustment
- var sizeForm = document.getElementById('sizeForm');
- sizeForm.addEventListener('submit', function(event) {
- event.preventDefault();
- var newSize = wheelSizeInput.value;
- var formData = new FormData();
- formData.append('size', newSize);
- fetch('/wheel', {
- method: 'POST',
- body: formData
- }).then(function(response) {
- if (response.ok) {
- console.log('Wheel size updated successfully');
- } else {
- console.log('Failed to update wheel size');
- }
- }).catch(function(error) {
- console.log('Error:', error);
- });
- });
- // Chart initialization
- document.addEventListener('DOMContentLoaded', function() {
- var ctx = document.getElementById('chartContainer').getContext('2d');
- chart = new Chart(ctx, {
- type: 'line',
- data: {
- datasets: [
- {
- label: 'RPM',
- data: rpmData,
- borderColor: 'blue',
- fill: false
- },
- {
- label: 'Speed (MPH)',
- data: speedData,
- borderColor: 'green',
- fill: false
- }
- ]
- },
- options: {
- scales: {
- x: {
- type: 'time',
- time: {
- unit: 'second'
- }
- },
- y: {
- beginAtZero: true,
- title: {
- display: true,
- text: 'Value'
- }
- }
- }
- }
- });
- });
- // Hall effect indicator update
- setInterval(function() {
- if (hallEffectIndicator) {
- if (hallEffectState) {
- hallEffectIndicator.className = 'indicator indicator-on';
- } else {
- hallEffectIndicator.className = 'indicator indicator-off';
- }
- }
- }, 500);
- // Function to display Hall effect sensor status in Serial Monitor
- setInterval(function() {
- if (hallEffectState) {
- console.log("Hall effect sensor: ON");
- } else {
- console.log("Hall effect sensor: OFF");
- }
- }, 1000);
- </script>
- </head>
- <body>
- <h1>Speedometer</h1>
- <h2>Current RPM: <span id="rpmValue">0</span></h2>
- <h2>Current Speed: <span id="speedValue">0.00</span> mph</h2>
- <div class="indicator" id="hallEffectIndicator"></div>
- <div id="chartContainer"></div>
- <form id="sizeForm">
- <label for="wheelSize">Wheel Size (in):</label>
- <input type="number" id="wheelSize" step="0.01" value="20.0">
- <button type="submit">Update</button>
- </form>
- <h2>Total Distance: <span id="totalDistance">0.00</span> miles</h2>
- <button onclick="clearDistance()">Clear Distance</button>
- </body>
- </html>
- )HTML";
- return htmlContent;
- }
- void setup() {
- Serial.begin(115200);
- // Create access point (Wi-Fi network)
- WiFi.softAP(ssid, password);
- // Get the IP address of the access point
- IPAddress IP = WiFi.softAPIP();
- Serial.print("Access Point IP address: ");
- Serial.println(IP);
- pinMode(hallPin, INPUT_PULLUP);
- attachInterrupt(digitalPinToInterrupt(hallPin), hallEffectISR, FALLING);
- if (SPIFFS.begin(true)) {
- Serial.println("SPIFFS mounted successfully");
- } else {
- Serial.println("An error occurred while mounting SPIFFS");
- return;
- }
- // Create WebSocket server
- ws.onEvent(onWebSocketEvent);
- // Create HTTP server
- AsyncWebServer server(80);
- server.addHandler(&ws);
- server.on("/", HTTP_GET, handleRoot);
- server.on("/wheel", HTTP_POST, handleWheelSize);
- server.on("/cleardistance", HTTP_POST, handleClearDistance);
- server.begin();
- Serial.println("Access the web interface at:");
- Serial.print("Web address: http://");
- Serial.println(IP);
- Serial.print("WebSocket address: ws://");
- Serial.println(IP);
- }
- void loop() {
- if (Serial.available()) {
- // Forward serial input to WebSocket client
- if (client && client->status() == WS_CONNECTED) {
- String input = Serial.readStringUntil('\n');
- client->text(input);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment