Initialisation dépot
This commit is contained in:
95
src/README.md
Normal file
95
src/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Introduction
|
||||
|
||||
This is the source files folder for the EasyDccMouse.
|
||||
|
||||
EasyDccMouse is a system to remote control DCC scale locomotive, it is based on a ESP32 with tft display, touch screen, encoder and battery.
|
||||
|
||||
EasyDccMouse sends actions to a DCC centrale station.
|
||||
|
||||
|
||||
```
|
||||
+------------------------------------------------------+
|
||||
| [O] [⇄] [ID] [⚡] | <-- Header with 4 icons:
|
||||
| ON Dir DCC Power | [O] Status (ON/OFF)
|
||||
| | [⇄] Direction (Forward/Reverse)
|
||||
| [================== Train ===================] | [ID] DCC id
|
||||
| | [⚡] Power/Connection
|
||||
| |██████████████████████████████████████████| | <-- Model picture (190x40 px)
|
||||
| |
|
||||
| ___ |
|
||||
| .-' '-. |
|
||||
| .' '. |
|
||||
| / \ |
|
||||
| | /\ /\ | | <-- Speedometer (arc + needle)
|
||||
| | / \ / \ | |
|
||||
| | / \_/ \ | |
|
||||
| |/ \| |
|
||||
| '---------------' |
|
||||
| | | |
|
||||
| | | |
|
||||
| Needle |
|
||||
| |
|
||||
| [F1] [F2] [F3] [F4] [F5] [F6] [F7] [F8] | <-- Function pad (row 1)
|
||||
| [F9] [F10][F11][F12][F13][F14][F15][F16] | <-- Function pad (row 2)
|
||||
+------------------------------------------------------+
|
||||
```
|
||||
|
||||
# Implementation
|
||||
|
||||
|
||||
## How to draw speedometer with arc and needle on my TFT display?
|
||||
|
||||
To draw an arc-style speedometer with a moving needle on your TFT display (e.g., ILI9341), you can use the TFT_eSPI library. Here’s a step-by-step example:
|
||||
|
||||
1. **Draw the arc:**
|
||||
- Use `drawArc()` or draw multiple short lines to approximate an arc.
|
||||
- Example: Draw an arc from 135° to 45° (like a semicircle at the bottom).
|
||||
|
||||
2. **Draw the needle:**
|
||||
- Calculate the angle for the needle based on the speed value.
|
||||
- Use `drawLine()` from the center of the arc to the edge at the calculated angle.
|
||||
|
||||
3. **Display the speed value:**
|
||||
- Use `setCursor()` and `print()` to show the numeric speed.
|
||||
|
||||
**Example code:**
|
||||
```cpp
|
||||
#include <TFT_eSPI.h>
|
||||
#include <math.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
void drawSpeedometer(int speed) {
|
||||
int cx = 120, cy = 120, r = 80; // Center and radius
|
||||
int minAngle = 135, maxAngle = 45; // Degrees
|
||||
int minSpeed = 0, maxSpeed = 100;
|
||||
|
||||
// Draw arc (approximate with lines)
|
||||
for (int a = minAngle; a >= maxAngle; a -= 3) {
|
||||
float rad = a * 3.14159 / 180.0;
|
||||
int x1 = cx + (r - 10) * cos(rad);
|
||||
int y1 = cy + (r - 10) * sin(rad);
|
||||
int x2 = cx + r * cos(rad);
|
||||
int y2 = cy + r * sin(rad);
|
||||
tft.drawLine(x1, y1, x2, y2, TFT_WHITE);
|
||||
}
|
||||
|
||||
// Draw needle
|
||||
float angle = minAngle - (float)(speed - minSpeed) / (maxSpeed - minSpeed) * (minAngle - maxAngle);
|
||||
float rad = angle * 3.14159 / 180.0;
|
||||
int nx = cx + (r - 20) * cos(rad);
|
||||
int ny = cy + (r - 20) * sin(rad);
|
||||
tft.drawLine(cx, cy, nx, ny, TFT_RED);
|
||||
|
||||
// Draw speed value
|
||||
tft.setCursor(cx - 20, cy + 30);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextSize(2);
|
||||
tft.printf("%d", speed);
|
||||
}
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
- Clear the previous needle before drawing a new one for smooth animation.
|
||||
- Adjust `cx`, `cy`, and `r` for your display size.
|
||||
- You can enhance the arc with tick marks and labels for a more realistic look.
|
||||
157
src/main.cpp
Normal file
157
src/main.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <Arduino.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include <WiFi.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <EEPROM.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include <SD.h>
|
||||
|
||||
#include "color.h"
|
||||
|
||||
void launchWiFiConfig();
|
||||
|
||||
// Read WiFi credentials from EEPROM
|
||||
#define WIFI_SSID_ADDR 0
|
||||
#define WIFI_PASS_ADDR 64
|
||||
#define WIFI_MAX_LEN 32
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
char output[80];
|
||||
#define DEBUG_MSG(...) snprintf(output,80, __VA_ARGS__ ); \
|
||||
Serial.println(output);
|
||||
#else
|
||||
#define DEBUG_MSG(...)
|
||||
#endif
|
||||
|
||||
/* tft */
|
||||
#define TFT_BL 21
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
char wifi_ssid[WIFI_MAX_LEN];
|
||||
char wifi_pass[WIFI_MAX_LEN];
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
DEBUG_MSG("CYD DCC mouse Demo");
|
||||
// Turn on backlight and initialize TFT
|
||||
pinMode(TFT_BL, OUTPUT);
|
||||
digitalWrite(TFT_BL, HIGH); // Backlight ON
|
||||
DEBUG_MSG("Backlight ON");
|
||||
tft.init();
|
||||
DEBUG_MSG("TFT init done");
|
||||
|
||||
DEBUG_MSG("Rotation set");
|
||||
|
||||
// Print hello world on tft
|
||||
tft.fillScreen(COLOR_BLACK);
|
||||
tft.setTextColor(COLOR_WHITE);
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println("Initialize Network...");
|
||||
|
||||
DEBUG_MSG("Reading WiFi credentials from EEPROM");
|
||||
EEPROM.begin(128);
|
||||
for (int i = 0; i < WIFI_MAX_LEN; i++) {
|
||||
wifi_ssid[i] = EEPROM.read(WIFI_SSID_ADDR + i);
|
||||
wifi_pass[i] = EEPROM.read(WIFI_PASS_ADDR + i);
|
||||
}
|
||||
wifi_ssid[WIFI_MAX_LEN-1] = '\0';
|
||||
wifi_pass[WIFI_MAX_LEN-1] = '\0';
|
||||
|
||||
bool ssid_found = strlen(wifi_ssid) > 0 && wifi_ssid[0] != 0xFF;
|
||||
bool pass_found = strlen(wifi_pass) > 0 && wifi_pass[0] != 0xFF;
|
||||
|
||||
if (!ssid_found || !pass_found)
|
||||
{
|
||||
DEBUG_MSG("WiFi credentials not found in EEPROM");
|
||||
tft.setCursor(10, 25);
|
||||
tft.setTextColor(COLOR_ORANGE);
|
||||
tft.println("WiFi credentials missing!");
|
||||
tft.setCursor(10, 40);
|
||||
tft.setTextColor(COLOR_YELLOW);
|
||||
tft.println("Please connect to CYD_Config AP");
|
||||
tft.setCursor(10, 55);
|
||||
tft.println("and set WiFi credentials");
|
||||
launchWiFiConfig(); // Function to start WiFi configuration mode (not implemented here)
|
||||
|
||||
} else {
|
||||
// Ok connect to WiFi
|
||||
tft.setCursor(60, 10);
|
||||
tft.setTextColor(COLOR_GREEN);
|
||||
tft.println("OK");
|
||||
DEBUG_MSG("WiFi SSID: %s", wifi_ssid);
|
||||
DEBUG_MSG("WiFi PASS: %s", wifi_pass);
|
||||
}
|
||||
// Try to open SD card and read content
|
||||
if (!SD.begin()) {
|
||||
tft.println("SD Card not found!");
|
||||
while (1); // or handle error as needed
|
||||
}
|
||||
if (!SD.exists("/loco")) {
|
||||
tft.println("loco/ folder not found!");
|
||||
while (1); // or handle error as needed
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// tft.fillScreen(TFT_PURPLE);
|
||||
// Serial.println("RED");
|
||||
// delay(1000);
|
||||
// tft.fillScreen(TFT_GREEN);
|
||||
// Serial.println("GREEN");
|
||||
// delay(1000);
|
||||
// tft.fillScreen(TFT_YELLOW);
|
||||
// Serial.println("BLUE");
|
||||
// delay(1000);
|
||||
// tft.fillScreen(TFT_BLACK);
|
||||
// Serial.println("BLACK");
|
||||
// delay(1000);
|
||||
// tft.fillScreen(TFT_WHITE);
|
||||
// Serial.println("WHITE");
|
||||
// delay(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* launchWiFiConfig() - Placeholder function to start WiFi configuration mode
|
||||
* In a real implementation, this would start an access point and web server to allow the user
|
||||
* to enter their WiFi credentials through a web interface. For this demo, it's just a placeholder.
|
||||
*/
|
||||
void launchWiFiConfig()
|
||||
{
|
||||
// Start WiFi in AP mode, set up a web server, and handle incoming connections to save new credentials to EEPROM
|
||||
WiFi.softAP("CYD_Config", "12345678");
|
||||
IPAddress myIP = WiFi.softAPIP();
|
||||
DEBUG_MSG("AP IP address: %s", myIP.toString().c_str());
|
||||
AsyncWebServer server(80);
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
String html = "<html><body><h2>WiFi Config</h2>"
|
||||
"<form action='/save' method='post'>"
|
||||
"SSID: <input name='ssid'><br>"
|
||||
"Password: <input name='pass' type='password'><br>"
|
||||
"<input type='submit' value='Save'></form></body></html>";
|
||||
request->send(200, "text/html", html);
|
||||
});
|
||||
server.on("/save", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
String ssid, pass;
|
||||
if (request->hasParam("ssid", true)) ssid = request->getParam("ssid", true)->value();
|
||||
if (request->hasParam("pass", true)) pass = request->getParam("pass", true)->value();
|
||||
for (int i = 0; i < WIFI_MAX_LEN; i++) {
|
||||
EEPROM.write(WIFI_SSID_ADDR + i, i < ssid.length() ? ssid[i] : 0);
|
||||
EEPROM.write(WIFI_PASS_ADDR + i, i < pass.length() ? pass[i] : 0);
|
||||
}
|
||||
EEPROM.commit();
|
||||
request->send(200, "text/html", "<html><body>Saved! Reboot device.</body></html>");
|
||||
});
|
||||
server.begin();
|
||||
tft.setCursor(10, 120);
|
||||
tft.setTextColor(COLOR_CYAN);
|
||||
tft.println("Connect to CYD_Config AP");
|
||||
tft.setCursor(10, 135);
|
||||
tft.println("Open 192.168.4.1 in browser");
|
||||
while (true) { delay(1000); }
|
||||
}
|
||||
Reference in New Issue
Block a user