Interfaccia controllo Nema17

Grazie a quesa interfaccia porò controllare il motore nema17. Rotella rossa permette di impostare il passo da 1 ad 1/32 l'encoder di sinistra impostiamo il motiplicatore seconda riga dall'alto un click si attiva la modalità modifica il primo digit a sinistra lampeggia e ruotando l'encoder di sinistra possiamo impostare la cifra da 0 a 9, altro click si passa alla cifra subito a destra che inizia a lampeggiare ed è ora modificabie.Con un long press si esce dalla modalità modifica. Encoder di destra ruotando variamo i giri del motore le cifre s'incrementano da destra verso sinistra con un click il motore si arresta rpm = 0, con un long press si cambia la direzione freccia verde a destra altro long press freccia rossa a sinistra.
Per realizzare questa interfaccia ho utilizzato il linguaggio ad oggetti
del C++ di Arduino:
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <EncButton.h>
#include "Blink4.h"
#include "VelDir.h"
#include "Passo.h"
#include "Etich.h"
Adafruit_ST7735 tft(10, 9, 8);
EncButton eval(A0,A1,A2);
EncButton enc(A5, A4, A3);
EncButton pass(12,2,-1);
Blink4* dspDg;
VelDir* velDr;
Passo* setPs;
Etich* etic;
void setup() {
tft.initR(INITR_BLACKTAB);
tft.setRotation(1);
tft.fillScreen(ST77XX_BLACK);
dspDg = new Blink4(90, 40, &tft, &enc);
dspDg->drawAll(true);
velDr = new VelDir(8, 126, &tft, &eval);
velDr->setMax(900);
velDr->draw();
setPs = new Passo(&tft,&pass);
etic = new Etich(&tft);
etic->drawAll();
}
void loop() {
dspDg->update();
setPs->update();
velDr->update();
} |
Notare l'estrema pulizia del codice. Ho utilizzato quattro classi:
- Blink4 - gestisce il moltiplicatore, encoder di sinistra
- VelDir - gestisce il controllodela velocità, la direzione e lo stop delmotore, encoder di destra
- VelDir - iposta il passo da 1 a 1/32
- Etich - visualizza tutte le etichette
Blink4
#pragma once
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <EncButton.h>
#include "DS_Digit18pt7b.h"
class Blink4 {
private:
Adafruit_ST7735* tft;
EncButton* enc;
const GFXfont* font;
int x, y, spz;
int cifre[4];
int xPos[4];
const int blinkInterval = 400;
unsigned long lastBlink = 0;
bool visible = true;
bool inEdit = false;
int pos = 0;
uint16_t color;
uint16_t holdSec;
public:
Blink4(int x, int y, Adafruit_ST7735* display, EncButton* encod )
: x(x), y(y), tft(display), enc(encod), spz(16), font(&DS_Digit18pt7b),
color(0xffff00), holdSec(400)
{
enc->setEncReverse(true);
setLpTm(holdSec);
calcCfr();
calcPos();
}
void setSpaz(int spazio) {
spz = spazio;
calcPos();
}
void setFont(const GFXfont* fnt) {
font = fnt;
}
void setColor(uint32_t hexColor) {
color = hexToColor565(hexColor);
}
uint16_t getValue() {
return cifre[0] * 1000 + cifre[1] * 100 + cifre[2] * 10 + cifre[3];
}
void setLpTm(uint16_t msRit){
enc->setHoldTimeout(msRit);
}
void drawAll(bool allVisible) {
tft->setFont(font);
for (int i = 0; i < 4; i++) {
bool vis = allVisible || (inEdit && i == pos && visible);
drawDigit(i, vis);
}
}
void update() {
enc->tick();
if (enc->click()) {
if (!inEdit) {
inEdit = true;
pos = 0;
visible = true;
lastBlink = millis();
} else {
drawDigit(pos, true);
pos = (pos + 1) % 4;
visible = true;
lastBlink = millis();
}
}
if (enc->hold()) {
inEdit = false;
visible = true;
drawAll(true);
}
if (inEdit) {
bool changed = false;
if (enc->right()) {
drawDigit(pos, false);
cifre[pos] = (cifre[pos] + 1) % 10;
changed = true;
} else if (enc->left()) {
drawDigit(pos, false);
cifre[pos] = (cifre[pos] + 9) % 10;
changed = true;
}
if (changed || millis() - lastBlink >= blinkInterval) {
visible = !visible;
drawDigit(pos, visible);
lastBlink = millis();
}
}
}
private:
void calcPos() {
xPos[0] = x;
for (int i = 1; i < 4; i++) {
xPos[i] = xPos[i - 1] + spz;
}
}
void calcCfr(){
for (int i = 0; i < 4; i++) cifre[i] = 0;
}
uint16_t hexToColor565(uint32_t hexColor) {
uint8_t r = (hexColor >> 16) & 0xFF;
uint8_t g = (hexColor >> 8) & 0xFF;
uint8_t b = hexColor & 0xFF;
return tft->color565(r, g, b); // o tft.color565(...) se non è un puntatore
}
void drawDigit(int p, bool vis) {
tft->setFont(font);
tft->setCursor(xPos[p], y);
tft->setTextColor(vis ? color : ST77XX_BLACK, ST77XX_BLACK);
tft->print(cifre[p]);
}
}; |
VelDir
#pragma once
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <EncButton.h>
#include "DS_Digit36pt7b.h"
class VelDir {
private:
Adafruit_ST7735* tft;
EncButton* enc;
const GFXfont* font;
int x, y;
uint16_t color;
int value = 0;
int maxVal = 1000;
bool dir = true; // true = destra, false = sinistra
uint16_t arrowRightColor = ST77XX_GREEN;
uint16_t arrowLeftColor = ST77XX_RED;
uint16_t bgColor = ST77XX_BLACK;
uint16_t txtColor = ST77XX_YELLOW;
uint32_t holdSec;
bool changed = true;
int valuePrecedente = -9999;
int prevValue = -1;
bool prevDir = !dir;
public:
VelDir(int x, int y, Adafruit_ST7735* display, EncButton* encod)
: x(x), y(y), tft(display), enc(encod), font(&DS_Digit36pt7b),
color(0xffff00), holdSec(400) {
enc->setHoldTimeout(holdSec);
enc->setEncReverse(true);
}
void setFont(const GFXfont* f) { font = f; }
void setColor(uint16_t c) { txtColor = c; }
void setHoldTm(uint32_t ms) { holdSec = ms; enc->setHoldTimeout(holdSec); }
void setMax(int maxV) { maxVal = maxV; }
int getValue() const { return dir ? value : -value; }
bool getDir() const { return dir; }
void draw() {
drawValue();
drawArrow();
changed = false;
}
void update() {
enc->tick();
if (enc->right() && value < maxVal) value++;
if (enc->left() && value > 0) value--;
if (enc->click()) value = 0;
if (enc->hold()) dir = !dir;
if (value != prevValue) {
drawValue();
prevValue = value;
}
if (dir != prevDir) {
drawArrow();
prevDir = dir;
}
}
private:
uint16_t hexToColor565(uint32_t hexColor) {
uint8_t r = (hexColor >> 16) & 0xFF;
uint8_t g = (hexColor >> 8) & 0xFF;
uint8_t b = hexColor & 0xFF;
return tft->color565(r, g, b);
}
void drawArrow() {
int cy = 60;
int size = 14;
// Cancella entrambe le aree prima di ridisegnare
tft->fillRect(8, cy - size - 2, 30, size * 2 + 4, bgColor); // area sinistra
tft->fillRect(122, cy - size - 2, 30, size * 2 + 4, bgColor); // area destra
if (dir) {
// Freccia a DESTRA (verde)
int cx = 136;
tft->fillTriangle(
cx - size, cy - size,
cx - size, cy + size,
cx + size, cy,
arrowRightColor
);
} else {
// Freccia a SINISTRA (rossa)
int cx = 22;
tft->fillTriangle(
cx + size, cy - size,
cx + size, cy + size,
cx - size, cy,
arrowLeftColor
);
}
}
void drawValue() {
static int lastDigits[4] = {-1, -1, -1, -1}; // memorizza cifre precedenti
int digits[4] = {0, 0, 0, 0};
int temp = value;
// Estrae le cifre da destra verso sinistra
for (int i = 3; i >= 0; i--) {
digits[i] = temp % 10;
temp /= 10;
}
tft->setFont(font);
for (int i = 0; i < 4; i++) {
int xPos = 10 + i * 36; // posizioni fisse per font monospazio
if (digits[i] != lastDigits[i]) {
// Cancella la cifra precedente
tft->setTextColor(bgColor, bgColor);
tft->setCursor(xPos, y);
if (lastDigits[i] >= 0) tft->print(lastDigits[i]); // stampa con colore sfondo
// Stampa nuova cifra
tft->setTextColor(txtColor, bgColor);
tft->setCursor(xPos, y);
tft->print(digits[i]);
lastDigits[i] = digits[i];
}
}
}
}; |
Passo
#pragma once
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <EncButton.h>
#include "ARLRDBD10pt7b.h"
class Passo {
private:
Adafruit_ST7735* tft;
EncButton* enc;
int x, y;
const GFXfont* font;
uint16_t textColor;
public:
Passo(Adafruit_ST7735* display, EncButton* encod): tft(display), enc(encod),
font(&ARLRDBD10pt7b){
tft->setFont(font);
enc->setEncReverse(true);
}
void setFont(const GFXfont* newFont) {
if (newFont) {
font = newFont;
tft->setFont(font);
}
}
void setColor(uint32_t hexColor) {
textColor = hexToColor565(hexColor);
tft->setTextColor(textColor);
}
void setCursor(int newX, int newY) {
x = newX;
y = newY;
tft->setCursor(x, y);
}
void draw(const String& text) {
tft->setCursor(x, y);
tft->print(text);
}
void update() {
static int value = 0; // mantiene il valore tra 0 e 5
static int lastValue = -1;
tft->setFont(font);
enc->tick(); // aggiorna lo stato dell'encoder
if (enc->right() && value < 5) {
value++;
} else if (enc->left() && value > 0) {
value--;
}
if (value != lastValue) {
static const char* values[] = { "1", "1/2", "1/4", "1/8", "1/16", "1/32" };
// Cancella il valore precedente scrivendolo in nero
tft->setTextColor(0x0000, 0x0000); // nero su nero
tft->setCursor(98, 14);
tft->print(values[lastValue >= 0 ? lastValue : 0]);
// Scrive il nuovo valore in bianco su sfondo nero
tft->setTextColor(0xFFFF, 0x0000); // giallo su nero
tft->setCursor(98, 14);
tft->print(values[value]);
lastValue = value;
}
}
private:
uint16_t hexToColor565(uint32_t hexColor) {
uint8_t r = (hexColor >> 16) & 0xFF;
uint8_t g = (hexColor >> 8) & 0xFF;
uint8_t b = hexColor & 0xFF;
return tft->color565(r, g, b); // o tft.color565(...) se non è un puntatore
}
}; |
Etich
#pragma once
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include "ARLRDBD8pt7b.h"
#include "ARLRDBD14pt7b.h" // Font di default
class Etich {
private:
Adafruit_ST7735* tft;
int x, y;
const GFXfont* font;
uint16_t textColor;
public:
Etich(Adafruit_ST7735* display): tft(display){
tft->setFont(&ARLRDBD8pt7b);
setColor(0x00ff00);
}
void setFont(const GFXfont* newFont) {
if (newFont) {
font = newFont;
tft->setFont(font);
}
}
void setColor(uint32_t hexColor) {
textColor = hexToColor565(hexColor);
tft->setTextColor(textColor);
}
void setCursor(int newX, int newY) {
x = newX;
y = newY;
tft->setCursor(x, y);
}
void setCenter(int newY, String str) {
y = newY;
// Usa getTextBounds per ottenere le dimensioni del testo
int16_t x1, y1;
uint16_t textWidth = 0, textHeight = 0;
tft->getTextBounds(str.c_str(), 0, 0, &x1, &y1, &textWidth, &textHeight);
// Calcola la posizione orizzontale centrata
int centerX = (tft->width() - textWidth) / 2;
setCursor(centerX, y);
tft->print(str);
}
void draw(const String& text) {
tft->setCursor(x, y);
tft->print(text);
}
void drawAll() {
setCursor(7, 33);
draw("Multiplier:");
setCursor(40, 12);
draw("Passo: ");
setFont(&ARLRDBD14pt7b);
setCursor(50, 68);
draw("RPM");
}
private:
uint16_t hexToColor565(uint32_t hexColor) {
uint8_t r = (hexColor >> 16) & 0xFF;
uint8_t g = (hexColor >> 8) & 0xFF;
uint8_t b = hexColor & 0xFF;
return tft->color565(r, g, b); // o tft.color565(...) se non è un puntatore
}
}; |
|