mirror of
https://github.com/marcogll/rotary_cotroller.git
synced 2026-03-15 11:25:21 +00:00
Add drill_vanity.ino and update README
This commit is contained in:
246
README.md
246
README.md
@@ -1,143 +1,189 @@
|
|||||||
# Proyecto de Control de Motor DC: Consola Digital v1.0
|
# Proyecto de Control de Motor DC
|
||||||
|
|
||||||
**Autor:** Marco Gallegos
|
|
||||||
**Fecha:** Enero 2024
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Descripción General
|
## 1. Descripción General
|
||||||
|
|
||||||
Este proyecto consiste en una consola de control inteligente para un motor de corriente continua (DC). Utiliza un microcontrolador **ESP8266 (HW-364A)** para gestionar la potencia a través de un driver **DRV8871**, ofreciendo una interfaz de usuario profesional con pantalla **OLED**, encoder rotatorio y botones de dirección.
|
Este proyecto implementa una consola digital de control para un motor de corriente continua (DC), orientada a operación segura, control fino de velocidad y protección mecánica/eléctrica. A diferencia de un control directo con potenciómetro, el sistema introduce:
|
||||||
|
|
||||||
El sistema prioriza la **seguridad mecánica**, implementando rampas de aceleración y una **máquina de estados** que evita arranques accidentales o cambios de giro bruscos que puedan dañar engranajes o el motor.
|
- Máquina de estados para evitar arranques accidentales.
|
||||||
|
- Aceleración y desaceleración progresiva (rampa).
|
||||||
|
- Inversión de giro con secuencia controlada.
|
||||||
|
- Interfaz hombre–máquina con encoder rotatorio, botones y pantalla OLED.
|
||||||
|
|
||||||
|
El sistema se desarrolla inicialmente sobre **HW-364A (ESP8266)**, con una ruta clara de migración a **ESP32 DevKit V1**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Especificaciones de Hardware
|
## 2. Arquitectura del Sistema
|
||||||
|
|
||||||
### 2.1 Módulo de Control (Placa Azul)
|
### 2.1 Flujo Funcional
|
||||||
|
|
||||||
La interfaz de usuario se centraliza en un módulo que incluye un **OLED de 0.96"**, un **encoder con botón** y **dos botones laterales**.
|
|
||||||
|
|
||||||
**Orden físico de los pines:**
|
|
||||||
|
|
||||||
```
|
```
|
||||||
CON | SDA | SCL | PSH | RTA | TRB | BAK | GND | VCC
|
Usuario (Encoder / Botones)
|
||||||
|
↓
|
||||||
|
ESP8266
|
||||||
|
↓
|
||||||
|
Driver DRV8871
|
||||||
|
↓
|
||||||
|
Motor DC
|
||||||
|
↓
|
||||||
|
OLED (Feedback)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2.2 Driver de Potencia (DRV8871)
|
## 3. Hardware
|
||||||
|
|
||||||
* **Voltaje de Motor:** Hasta 45V (fuente externa)
|
### 3.1 Controlador Principal
|
||||||
* **Corriente:** Pico de 3.6A
|
|
||||||
* **Control:** PWM bidireccional (Puente H)
|
- Placa: HW-364A
|
||||||
|
- MCU: ESP8266
|
||||||
|
- Lógica: 3.3 V
|
||||||
|
- Limitación crítica: GPIO reducidos
|
||||||
|
|
||||||
|
### 3.2 Sistema de Energía
|
||||||
|
|
||||||
|
- Tierra común (GND) para todo el sistema
|
||||||
|
- Motor alimentado por fuente externa independiente
|
||||||
|
- Electrónica alimentada a 3.3 V
|
||||||
|
|
||||||
|
### 3.3 Asignación de Pines
|
||||||
|
|
||||||
|
| Función | Señal | Pin |
|
||||||
|
|------|------|-----|
|
||||||
|
| OLED SDA | Datos I2C | D2 |
|
||||||
|
| OLED SCL | Reloj I2C | D1 |
|
||||||
|
| Encoder A | Giro A | D5 |
|
||||||
|
| Encoder B | Giro B | D6 |
|
||||||
|
| Botón Centro | Start | D7 |
|
||||||
|
| Botón Back | Reversa | D8 |
|
||||||
|
| Botón Confirm | Adelante | D3 |
|
||||||
|
| Driver IN1 | Motor A | D0 |
|
||||||
|
| Driver IN2 | Motor B | D4 |
|
||||||
|
|
||||||
|
### 3.4 Driver de Potencia
|
||||||
|
|
||||||
|
- Modelo: DRV8871
|
||||||
|
- Control PWM bidireccional
|
||||||
|
- Polaridad definida por IN1 / IN2
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Conexiones y Pinout
|
## 4. Lógica de Control
|
||||||
|
|
||||||
### 3.1 Módulo de Interfaz a ESP8266
|
### 4.1 Máquina de Estados
|
||||||
|
|
||||||
| Etiqueta PCB | Función | Pin ESP8266 | Observaciones |
|
| Estado | Descripción |
|
||||||
| ------------ | --------------------- | ----------- | --------------------------------------- |
|
|------|-------------|
|
||||||
| CON | Confirmar / Adelante | D3 (GPIO0) | Pin de boot. No presionar al encender |
|
| WAITING_START | Sistema armado, motor bloqueado |
|
||||||
| SDA | I2C Data (OLED) | D2 (GPIO4) | — |
|
| SELECT_DIR | Selección explícita de sentido |
|
||||||
| SCL | I2C Clock (OLED) | D1 (GPIO5) | — |
|
| RUNNING | Operación normal |
|
||||||
| PSH | Botón Encoder (Start) | D7 (GPIO13) | — |
|
| CHANGING_DIR | Inversión controlada |
|
||||||
| RTA | Encoder Fase A | D5 (GPIO14) | — |
|
|
||||||
| TRB | Encoder Fase B | D6 (GPIO12) | — |
|
### 4.2 Arranque Seguro
|
||||||
| BAK | Atrás / Reversa | D8 (GPIO15) | Pin de boot. Debe estar LOW al encender |
|
|
||||||
| GND | Tierra | G (GND) | — |
|
El motor permanece apagado hasta confirmación explícita del usuario. Previene reinicios peligrosos tras fallas de energía.
|
||||||
| VCC | Alimentación | 3V (3.3V) | — |
|
|
||||||
|
### 4.3 Selección de Sentido
|
||||||
|
|
||||||
|
- BACK → Reversa
|
||||||
|
- CONFIRM → Adelante
|
||||||
|
|
||||||
|
No existe sentido por defecto.
|
||||||
|
|
||||||
|
### 4.4 Control de Velocidad Adaptativo
|
||||||
|
|
||||||
|
- Giro lento → ±1 %
|
||||||
|
- Giro rápido (< 50 ms) → ±5 %
|
||||||
|
- Rango: 0–100 %
|
||||||
|
|
||||||
|
### 4.5 Rampa de Aceleración
|
||||||
|
|
||||||
|
Variables desacopladas:
|
||||||
|
|
||||||
|
- `targetSpeed` → intención del usuario
|
||||||
|
- `currentSpeed` → acción física
|
||||||
|
|
||||||
|
Incremento/decremento: 0.5 % por ciclo (~2.5 s a plena escala).
|
||||||
|
|
||||||
|
### 4.6 Inversión Inteligente
|
||||||
|
|
||||||
|
Secuencia obligatoria:
|
||||||
|
|
||||||
|
1. Rampa descendente hasta 0 %
|
||||||
|
2. Pausa mecánica
|
||||||
|
3. Cambio de polaridad
|
||||||
|
4. Rampa ascendente
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.2 Driver DRV8871 a ESP8266
|
## 5. Firmware
|
||||||
|
|
||||||
| Etiqueta PCB | Función | Pin ESP8266 | Observaciones |
|
### 5.1 Inicialización (`setup()`)
|
||||||
| ------------ | ------------- | ----------- | ------------------------- |
|
|
||||||
| IN1 | Entrada PWM A | D0 (GPIO16) | PWM limitado por hardware |
|
- Configuración de GPIO
|
||||||
| IN2 | Entrada PWM B | D4 (GPIO2) | Comparte LED azul interno |
|
- Motor apagado por defecto
|
||||||
|
- Botones con pull-up interno
|
||||||
|
- Inicialización OLED
|
||||||
|
|
||||||
|
### 5.2 Bucle Principal (`loop()`)
|
||||||
|
|
||||||
|
- Lectura del encoder
|
||||||
|
- Ejecución de máquina de estados
|
||||||
|
- Control de rampa
|
||||||
|
- Render de interfaz
|
||||||
|
|
||||||
|
### 5.3 Funciones Críticas
|
||||||
|
|
||||||
|
- `readEncoderSpeed()` → velocidad adaptativa
|
||||||
|
- `handleDirectionButtons()` → solicitud de inversión
|
||||||
|
- `updateMotorRamp()` → núcleo de control
|
||||||
|
- `drawInterface()` → visualización
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Lógica de Operación
|
## 6. Interfaz de Usuario
|
||||||
|
|
||||||
### 4.1 Máquina de Estados de Seguridad
|
- Flechas grandes indican sentido
|
||||||
|
- Porcentaje central = velocidad real
|
||||||
|
- Indicador secundario = velocidad objetivo
|
||||||
|
|
||||||
Para prevenir daños y accidentes, el sistema implementa cuatro estados definidos:
|
Diseño orientado a lectura inmediata.
|
||||||
|
|
||||||
* **WAITING_START (Armado):**
|
|
||||||
|
|
||||||
* Motor bloqueado
|
|
||||||
* Pantalla solicita pulsar **PSH** para iniciar
|
|
||||||
|
|
||||||
* **SELECT_DIR (Dirección):**
|
|
||||||
|
|
||||||
* Espera selección del sentido
|
|
||||||
* **CON** = Adelante
|
|
||||||
* **BAK** = Reversa
|
|
||||||
|
|
||||||
* **RUNNING (Operación):**
|
|
||||||
|
|
||||||
* Motor en giro
|
|
||||||
* Encoder ajusta `targetSpeed`
|
|
||||||
|
|
||||||
* **CHANGING_DIR (Transición):**
|
|
||||||
|
|
||||||
* Rampa baja progresivamente a 0%
|
|
||||||
* Pausa de seguridad
|
|
||||||
* Rampa sube en el nuevo sentido
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 Control de Velocidad Adaptativo
|
## 7. Limitaciones Actuales
|
||||||
|
|
||||||
* **Giro lento:** Ajustes finos de ±1%
|
- GPIO al límite
|
||||||
* **Giro rápido:** Ajustes de ±5% (intervalo entre pulsos < 50 ms)
|
- Sin indicadores periféricos
|
||||||
* **Rampa de seguridad:** Incrementos de 0.5% por ciclo
|
- Expansión restringida
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Interfaz de Usuario (HMI)
|
## 8. Versión 2 (V2)
|
||||||
|
|
||||||
La pantalla OLED presenta información crítica del sistema:
|
### 8.1 Migración a ESP32
|
||||||
|
|
||||||
* **Iconos de sentido:** Flechas grandes indicando el giro
|
- Mayor número de GPIO
|
||||||
* **Velocidad real:** Porcentaje actual aplicado por la rampa
|
- PWM por hardware
|
||||||
* **Velocidad objetivo:** Valor configurado por el usuario
|
- Escalabilidad
|
||||||
* **Alertas del sistema:**
|
|
||||||
|
|
||||||
* `SISTEMA BLOQUEADO`
|
### 8.2 LED RGB de Estado
|
||||||
* `CAMBIANDO GIRO`
|
|
||||||
|
| Color | Significado |
|
||||||
|
|------|-------------|
|
||||||
|
| Amarillo | Standby / 0 % |
|
||||||
|
| Verde | Adelante |
|
||||||
|
| Rojo | Reversa |
|
||||||
|
| Rojo/Verde | Inversión |
|
||||||
|
|
||||||
|
### 8.3 Cambios en Firmware
|
||||||
|
|
||||||
|
- Nueva función `updateLeds()`
|
||||||
|
- GPIO dedicados (25, 26, 27)
|
||||||
|
- Mezcla de color por PWM
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Hoja de Ruta — Versión 2 (V2)
|
## 9. Conclusión
|
||||||
|
|
||||||
### 6.1 Migración a ESP32
|
El sistema establece una base sólida para control seguro y profesional de motores DC, con una arquitectura preparada para evolucionar hacia una solución embebida más robusta en ESP32.
|
||||||
|
|
||||||
* Sustitución por **ESP32 DevKit V1**
|
|
||||||
* Eliminación de restricciones de GPIO
|
|
||||||
* PWM por hardware con mayor resolución
|
|
||||||
|
|
||||||
### 6.2 Indicadores de Estado Visuales (LED RGB)
|
|
||||||
|
|
||||||
| Color | Estado del sistema |
|
|
||||||
| ------------------ | ----------------------------- |
|
|
||||||
| 🟡 Amarillo | Sistema en espera (0%) |
|
|
||||||
| 🟢 Verde | Motor girando adelante |
|
|
||||||
| 🔴 Rojo | Motor girando en reversa |
|
|
||||||
| 🔵 Azul (parpadeo) | Cambio de dirección / frenado |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Limitaciones Técnicas Actuales
|
|
||||||
|
|
||||||
* **D3 / D8:** Pines sensibles al arranque por resistencias internas
|
|
||||||
* **PWM en D0:** Frecuencia no estándar, compensada por software
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Desarrollado por:** Marco Gallegos
|
|
||||||
|
|||||||
253
drill_vanity.ino
Normal file
253
drill_vanity.ino
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Proyecto: Control de Motor DC - Consola Digital v1.0
|
||||||
|
* Archivo: drill_vanity.ino
|
||||||
|
* Autor: Marco Gallegos
|
||||||
|
* Hardware: ESP8266 (HW-364A), DRV8871, OLED SSD1306, Encoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
|
||||||
|
// --- DEFINICIÓN DE PINES ---
|
||||||
|
// Nota: Usamos la notación Dx del NodeMCU para claridad, mapeada a GPIO
|
||||||
|
#define PIN_CON 0 // D3 (GPIO0) - Adelante / Confirmar (Active LOW)
|
||||||
|
#define PIN_SDA 4 // D2 (GPIO4) - I2C Data
|
||||||
|
#define PIN_SCL 5 // D1 (GPIO5) - I2C Clock
|
||||||
|
#define PIN_PSH 13 // D7 (GPIO13) - Botón Encoder (Start/Stop)
|
||||||
|
#define PIN_RTA 14 // D5 (GPIO14) - Encoder A
|
||||||
|
#define PIN_TRB 12 // D6 (GPIO12) - Encoder B
|
||||||
|
#define PIN_BAK 15 // D8 (GPIO15) - Atrás / Reversa (Active LOW)
|
||||||
|
#define PIN_IN1 16 // D0 (GPIO16) - PWM A
|
||||||
|
#define PIN_IN2 2 // D4 (GPIO2) - PWM B
|
||||||
|
|
||||||
|
// --- CONFIGURACIÓN OLED ---
|
||||||
|
#define SCREEN_WIDTH 128
|
||||||
|
#define SCREEN_HEIGHT 64
|
||||||
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
|
||||||
|
|
||||||
|
// --- MÁQUINA DE ESTADOS ---
|
||||||
|
enum SystemState {
|
||||||
|
WAITING_START, // Sistema armado, motor bloqueado
|
||||||
|
SELECT_DIR, // Esperando selección de sentido
|
||||||
|
RUNNING, // Motor operando
|
||||||
|
CHANGING_DIR // Transición de seguridad
|
||||||
|
};
|
||||||
|
|
||||||
|
SystemState currentState = WAITING_START;
|
||||||
|
bool directionForward = true; // true = Adelante, false = Atrás
|
||||||
|
|
||||||
|
// --- VARIABLES DE CONTROL MOTOR ---
|
||||||
|
int targetSpeed = 0; // Velocidad deseada (0-255)
|
||||||
|
float currentSpeed = 0; // Velocidad real (Rampa)
|
||||||
|
const float RAMP_STEP = 0.8; // Ajuste de suavidad (menor = más suave)
|
||||||
|
unsigned long lastRampTime = 0;
|
||||||
|
const int RAMP_INTERVAL = 5; // ms
|
||||||
|
|
||||||
|
// --- VARIABLES ENCODER ---
|
||||||
|
volatile int encoderValue = 0;
|
||||||
|
volatile unsigned long lastInterruptTime = 0;
|
||||||
|
unsigned long lastEncoderChangeTime = 0;
|
||||||
|
|
||||||
|
// --- DEBOUNCE BOTONES ---
|
||||||
|
unsigned long lastDebounceTime = 0;
|
||||||
|
const int DEBOUNCE_DELAY = 200;
|
||||||
|
|
||||||
|
// --- ISR (Interrupción Encoder) ---
|
||||||
|
ICACHE_RAM_ATTR void handleEncoder() {
|
||||||
|
unsigned long interruptTime = millis();
|
||||||
|
if (interruptTime - lastInterruptTime > 5) {
|
||||||
|
if (digitalRead(PIN_RTA) == digitalRead(PIN_TRB)) {
|
||||||
|
encoderValue--;
|
||||||
|
} else {
|
||||||
|
encoderValue++;
|
||||||
|
}
|
||||||
|
lastInterruptTime = interruptTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Configuración de Pines
|
||||||
|
// D3 y D8 son pines de BOOT. Se configuran INPUT_PULLUP en setup,
|
||||||
|
// pero el hardware debe asegurar sus estados correctos al encender.
|
||||||
|
pinMode(PIN_CON, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_BAK, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_PSH, INPUT_PULLUP);
|
||||||
|
|
||||||
|
pinMode(PIN_RTA, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_TRB, INPUT_PULLUP);
|
||||||
|
|
||||||
|
pinMode(PIN_IN1, OUTPUT);
|
||||||
|
pinMode(PIN_IN2, OUTPUT);
|
||||||
|
|
||||||
|
// Motor apagado al inicio
|
||||||
|
digitalWrite(PIN_IN1, LOW);
|
||||||
|
digitalWrite(PIN_IN2, LOW);
|
||||||
|
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_RTA), handleEncoder, CHANGE);
|
||||||
|
|
||||||
|
// Inicializar OLED
|
||||||
|
Wire.begin(PIN_SDA, PIN_SCL);
|
||||||
|
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
|
||||||
|
Serial.println(F("Error OLED"));
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setTextColor(SSD1306_WHITE);
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
handleStateMachine();
|
||||||
|
updateMotorOutput();
|
||||||
|
updateDisplay();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleStateMachine() {
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
bool btnCon = (digitalRead(PIN_CON) == LOW);
|
||||||
|
bool btnBak = (digitalRead(PIN_BAK) == LOW);
|
||||||
|
bool btnPsh = (digitalRead(PIN_PSH) == LOW);
|
||||||
|
|
||||||
|
// Filtro de rebotes
|
||||||
|
if ((btnCon || btnBak || btnPsh) && (now - lastDebounceTime < DEBOUNCE_DELAY)) return;
|
||||||
|
if (btnCon || btnBak || btnPsh) lastDebounceTime = now;
|
||||||
|
|
||||||
|
switch (currentState) {
|
||||||
|
case WAITING_START:
|
||||||
|
targetSpeed = 0;
|
||||||
|
currentSpeed = 0;
|
||||||
|
if (btnPsh) currentState = SELECT_DIR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SELECT_DIR:
|
||||||
|
if (btnCon) {
|
||||||
|
directionForward = true;
|
||||||
|
targetSpeed = 60; // Arranca suave
|
||||||
|
currentState = RUNNING;
|
||||||
|
} else if (btnBak) {
|
||||||
|
directionForward = false;
|
||||||
|
targetSpeed = 60;
|
||||||
|
currentState = RUNNING;
|
||||||
|
} else if (btnPsh) {
|
||||||
|
currentState = WAITING_START; // Cancelar
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNNING:
|
||||||
|
// Control de velocidad con encoder
|
||||||
|
if (encoderValue != 0) {
|
||||||
|
int change = encoderValue;
|
||||||
|
// Aceleración adaptativa según velocidad de giro del encoder
|
||||||
|
int step = (millis() - lastEncoderChangeTime < 50) ? 10 : 2;
|
||||||
|
|
||||||
|
targetSpeed += (change * step);
|
||||||
|
targetSpeed = constrain(targetSpeed, 0, 255);
|
||||||
|
encoderValue = 0;
|
||||||
|
lastEncoderChangeTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parada
|
||||||
|
if (btnPsh) {
|
||||||
|
targetSpeed = 0;
|
||||||
|
if (currentSpeed < 10) currentState = WAITING_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambio de sentido "al vuelo"
|
||||||
|
if ((directionForward && btnBak) || (!directionForward && btnCon)) {
|
||||||
|
currentState = CHANGING_DIR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHANGING_DIR:
|
||||||
|
targetSpeed = 0;
|
||||||
|
// Esperar a que el motor se detenga casi por completo
|
||||||
|
if (currentSpeed <= 5) {
|
||||||
|
delay(300); // Pequeña pausa mecánica
|
||||||
|
directionForward = !directionForward;
|
||||||
|
currentState = RUNNING;
|
||||||
|
targetSpeed = 60;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateMotorOutput() {
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
// Lógica de Rampa
|
||||||
|
if (now - lastRampTime >= RAMP_INTERVAL) {
|
||||||
|
if (currentSpeed < targetSpeed) {
|
||||||
|
currentSpeed += RAMP_STEP;
|
||||||
|
if (currentSpeed > targetSpeed) currentSpeed = targetSpeed;
|
||||||
|
} else if (currentSpeed > targetSpeed) {
|
||||||
|
currentSpeed -= RAMP_STEP;
|
||||||
|
if (currentSpeed < targetSpeed) currentSpeed = targetSpeed;
|
||||||
|
}
|
||||||
|
lastRampTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pwmOutput = (int)currentSpeed;
|
||||||
|
|
||||||
|
if (currentState == WAITING_START) {
|
||||||
|
digitalWrite(PIN_IN1, LOW);
|
||||||
|
digitalWrite(PIN_IN2, LOW);
|
||||||
|
} else {
|
||||||
|
// DRV8871 Control
|
||||||
|
if (directionForward) {
|
||||||
|
analogWrite(PIN_IN1, pwmOutput);
|
||||||
|
digitalWrite(PIN_IN2, LOW);
|
||||||
|
} else {
|
||||||
|
digitalWrite(PIN_IN1, LOW);
|
||||||
|
analogWrite(PIN_IN2, pwmOutput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateDisplay() {
|
||||||
|
static unsigned long lastDisp = 0;
|
||||||
|
if (millis() - lastDisp < 100) return;
|
||||||
|
lastDisp = millis();
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(0, 0);
|
||||||
|
|
||||||
|
switch (currentState) {
|
||||||
|
case WAITING_START:
|
||||||
|
display.println(F(">> SISTEMA LISTO <<"));
|
||||||
|
display.setCursor(25, 25);
|
||||||
|
display.setTextSize(2);
|
||||||
|
display.print(F("PULSAR"));
|
||||||
|
display.setCursor(35, 45);
|
||||||
|
display.print(F("START"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SELECT_DIR:
|
||||||
|
display.println(F(" SELECCIONAR GIRO"));
|
||||||
|
display.setCursor(10, 30);
|
||||||
|
display.setTextSize(2);
|
||||||
|
display.print(F("<< O >>"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RUNNING:
|
||||||
|
case CHANGING_DIR:
|
||||||
|
display.print(currentState == CHANGING_DIR ? F("! INVIRTIENDO !") : (directionForward ? F("GIRO: ADELANTE >") : F("GIRO: < ATRAS")));
|
||||||
|
|
||||||
|
display.setTextSize(3);
|
||||||
|
int pct = map((int)currentSpeed, 0, 255, 0, 100);
|
||||||
|
display.setCursor(35, 20);
|
||||||
|
display.print(pct);
|
||||||
|
display.setTextSize(2);
|
||||||
|
display.print(F("%"));
|
||||||
|
|
||||||
|
display.drawRect(5, 58, 118, 6, SSD1306_WHITE);
|
||||||
|
display.fillRect(7, 60, map(pct,0,100,0,114), 2, SSD1306_WHITE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user