Ciao a tutti!
Sto progettando un banco automatico, utilizzando 3 NEMA 17.
Al momento mi trovo in questa situazione:
Ho scritto il codice per regolare i primi due parametri "Fence" e "Tool".
Con questo codice tutto sembra funzionare:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>
// Pin definitions for Motor 1
#define STEP_PIN_1 5
#define DIR_PIN_1 6
#define ENABLE_PIN_1 7
// Pin definitions for Motor 2
#define STEP_PIN_2 8
#define DIR_PIN_2 9
#define ENABLE_PIN_2 10
// Pin definitions for Motor 3
#define STEP_PIN_3 11
#define DIR_PIN_3 12
#define ENABLE_PIN_3 13
// Encoder and Button Pins
#define ENCODER_PIN_A 2
#define ENCODER_PIN_B 3
#define ENCODER_BUTTON A0
// Endstop Pins
#define ENDSTOP_1 A1
#define ENDSTOP_2 A2
#define ENDSTOP_3 A3
// Motor and movement parameters
const float steps_per_mm = 100.0; // 200 steps = 2 mm
const int motor_steps_per_encoder = 10;
float mm_per_encoder_step = (float)motor_steps_per_encoder / steps_per_mm; // 0.1 mm per encoder step
// Display settings
LiquidCrystal_I2C lcd(0x27, 20, 4);
Encoder encoder(ENCODER_PIN_A, ENCODER_PIN_B);
long encoder_position = 0;
long previous_encoder_position = 0;
float mm_position = 0.0;
float previous_mm_position = 0.0;
int cursor_position = 0; // Cursor for post-movement menu
// State Variables
enum State { MAIN_MENU, SELECT_MM, MOVEMENT, POST_MOVEMENT };
State currentState = MAIN_MENU;
bool isFenceSelected = true; // Default selection
void setupMotor(int stepPin, int dirPin, int enablePin) {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW); // Enable motor driver
}
void moveMotor(int stepPin, int dirPin, float delta_mm) {
int steps = abs(delta_mm) * steps_per_mm;
digitalWrite(dirPin, delta_mm > 0 ? HIGH : LOW);
for (int i = 0; i < steps; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
}
void moveSynchronousMotors(float delta_mm) {
int steps = abs(delta_mm) * steps_per_mm;
bool direction = delta_mm > 0 ? HIGH : LOW;
digitalWrite(DIR_PIN_1, direction);
digitalWrite(DIR_PIN_2, direction);
for (int i = 0; i < steps; i++) {
digitalWrite(STEP_PIN_1, HIGH);
digitalWrite(STEP_PIN_2, HIGH);
delayMicroseconds(1000);
digitalWrite(STEP_PIN_1, LOW);
digitalWrite(STEP_PIN_2, LOW);
delayMicroseconds(1000);
}
}
void displayMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode:");
lcd.setCursor(0, 1);
lcd.print(isFenceSelected ? "> Fence" : " Fence");
lcd.setCursor(0, 2);
lcd.print(isFenceSelected ? " Tool" : "> Tool");
}
void displayMMSelection(const char* mode) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set MM - ");
lcd.print(mode);
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(mm_position);
lcd.print(" mm");
lcd.setCursor(0, 2);
lcd.print("Press to Confirm");
}
void displayPostMovement(const char* mode) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Mode: ");
lcd.print(mode);
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(mm_position);
lcd.print(" mm");
lcd.setCursor(0, 2);
lcd.print(cursor_position == 0 ? "> Change Value" : " Change Value");
lcd.setCursor(0, 3);
lcd.print(cursor_position == 1 ? "> Back to Menu" : " Back to Menu");
}
void setup() {
setupMotor(STEP_PIN_1, DIR_PIN_1, ENABLE_PIN_1);
setupMotor(STEP_PIN_2, DIR_PIN_2, ENABLE_PIN_2);
setupMotor(STEP_PIN_3, DIR_PIN_3, ENABLE_PIN_3);
pinMode(ENCODER_BUTTON, INPUT_PULLUP);
lcd.init();
lcd.backlight();
displayMenu();
}
void loop() {
encoder_position = encoder.read() / 4;
switch (currentState) {
case MAIN_MENU:
if (encoder_position != previous_encoder_position) {
isFenceSelected = !isFenceSelected;
displayMenu();
previous_encoder_position = encoder_position;
}
if (digitalRead(ENCODER_BUTTON) == LOW) {
currentState = SELECT_MM;
displayMMSelection(isFenceSelected ? "Fence" : "Tool");
delay(300);
}
break;
case SELECT_MM:
if (encoder_position != previous_encoder_position) {
mm_position += (encoder_position - previous_encoder_position) * mm_per_encoder_step;
if (mm_position < 0) mm_position = 0;
displayMMSelection(isFenceSelected ? "Fence" : "Tool");
previous_encoder_position = encoder_position;
}
if (digitalRead(ENCODER_BUTTON) == LOW) {
currentState = MOVEMENT;
delay(300);
}
break;
case MOVEMENT:
if (isFenceSelected) {
moveSynchronousMotors(mm_position);
} else {
moveMotor(STEP_PIN_3, DIR_PIN_3, mm_position);
}
currentState = POST_MOVEMENT;
displayPostMovement(isFenceSelected ? "Fence" : "Tool");
break;
case POST_MOVEMENT:
if (encoder_position != previous_encoder_position) {
cursor_position = (encoder_position % 2 + 2) % 2;
displayPostMovement(isFenceSelected ? "Fence" : "Tool");
previous_encoder_position = encoder_position;
}
if (digitalRead(ENCODER_BUTTON) == LOW) {
if (cursor_position == 0) {
currentState = SELECT_MM;
displayMMSelection(isFenceSelected ? "Fence" : "Tool");
} else {
currentState = MAIN_MENU;
displayMenu();
}
delay(300);
}
break;
}
}
Il display mostra correttamente una scelta, tra fence e tool.
Fatta la selezione consente di modificare lo spostamento in decimi di mm.
Fatto lo spostamento permette di tornare al menu principale o di modificare nuovamente la posizione.
Ho provato a questo punto ad "espandere" il menù:
Ora mostra correttamente
Tuttavia ogni volta che faccio una selezione, il tutto va in blocco, continua a lampeggiare il display come se facesse aggiornamenti continui e non mi consente di fare alcuna selezione.

In aggiunta le funzioni che prima funzionavano e mi consentivano di fare gli aggiustamenti di posizione non sono più disponibili.
L'idea era quella di espandere il menu per aggiungere pian piano funzioni, ma ora non riesco a venirne fuori...
Questo il codice che non riesco a far funzionare:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>
// Pin definitions for Motor 1
#define STEP_PIN_1 5
#define DIR_PIN_1 6
#define ENABLE_PIN_1 7
// Pin definitions for Motor 2
#define STEP_PIN_2 8
#define DIR_PIN_2 9
#define ENABLE_PIN_2 10
// Pin definitions for Motor 3
#define STEP_PIN_3 11
#define DIR_PIN_3 12
#define ENABLE_PIN_3 13
// Encoder and Button Pins
#define ENCODER_PIN_A 2
#define ENCODER_PIN_B 3
#define ENCODER_BUTTON A0
// Endstop Pins
#define ENDSTOP_1 A1
#define ENDSTOP_2 A2
#define ENDSTOP_3 A3
// Motor and movement parameters
const float steps_per_mm = 100.0; // 200 steps = 2 mm
const int motor_steps_per_encoder = 10;
float mm_per_encoder_step = (float)motor_steps_per_encoder / steps_per_mm; // 0.1 mm per encoder step
// Display settings
LiquidCrystal_I2C lcd(0x27, 20, 4);
Encoder encoder(ENCODER_PIN_A, ENCODER_PIN_B);
long encoder_position = 0;
long previous_encoder_position = 0;
float mm_position = 0.0;
float previous_mm_position = 0.0;
int cursor_position = 0; // Cursor for post-movement menu
// State Variables
enum State { MAIN_MENU, ZERO_CALIBRATION, FENCE_TOOL_MENU, SELECT_MM, MOVEMENT, POST_MOVEMENT };
State currentState = MAIN_MENU;
bool isFenceSelected = true; // Default selection
void setupMotor(int stepPin, int dirPin, int enablePin) {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW); // Enable motor driver
}
void moveMotor(int stepPin, int dirPin, float delta_mm) {
int steps = abs(delta_mm) * steps_per_mm;
digitalWrite(dirPin, delta_mm > 0 ? HIGH : LOW);
for (int i = 0; i < steps; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
}
void moveSynchronousMotors(float delta_mm) {
int steps = abs(delta_mm) * steps_per_mm;
bool direction = delta_mm > 0 ? HIGH : LOW;
digitalWrite(DIR_PIN_1, direction);
digitalWrite(DIR_PIN_2, direction);
for (int i = 0; i < steps; i++) {
digitalWrite(STEP_PIN_1, HIGH);
digitalWrite(STEP_PIN_2, HIGH);
delayMicroseconds(1000);
digitalWrite(STEP_PIN_1, LOW);
digitalWrite(STEP_PIN_2, LOW);
delayMicroseconds(1000);
}
}
void displayMainMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Welcome!");
lcd.setCursor(0, 1);
lcd.print(cursor_position == 0 ? "> Zero Calibration" : " Zero Calibration");
lcd.setCursor(0, 2);
lcd.print(cursor_position == 1 ? "> Fence & Tool" : " Fence & Tool");
lcd.setCursor(0, 3);
lcd.print(cursor_position == 2 ? "> Apps" : " Apps");
}
void displayFenceToolMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Fence & Tool Menu");
lcd.setCursor(0, 1);
lcd.print(isFenceSelected ? "> Fence" : " Fence");
lcd.setCursor(0, 2);
lcd.print(isFenceSelected ? " Tool" : "> Tool");
}
void displayMMSelection(const char* mode) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set MM - Mode:");
lcd.print(mode);
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(mm_position);
lcd.print(" mm");
lcd.setCursor(0, 2);
lcd.print("Press to Confirm");
}
void displayPostMovement(const char* mode) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Mode: ");
lcd.print(mode);
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(mm_position);
lcd.print(" mm");
lcd.setCursor(0, 2);
lcd.print(cursor_position == 0 ? "> Change Value" : " Change Value");
lcd.setCursor(0, 3);
lcd.print(cursor_position == 1 ? "> Back to Menu" : " Back to Menu");
}
void setup() {
setupMotor(STEP_PIN_1, DIR_PIN_1, ENABLE_PIN_1);
setupMotor(STEP_PIN_2, DIR_PIN_2, ENABLE_PIN_2);
setupMotor(STEP_PIN_3, DIR_PIN_3, ENABLE_PIN_3);
pinMode(ENCODER_BUTTON, INPUT_PULLUP);
lcd.init();
lcd.backlight();
displayMainMenu();
}
void loop() {
encoder_position = encoder.read() / 4;
switch (currentState) {
case MAIN_MENU:
if (encoder_position != previous_encoder_position) {
cursor_position = (encoder_position % 3 + 3) % 3;
displayMainMenu();
previous_encoder_position = encoder_position;
}
if (digitalRead(ENCODER_BUTTON) == LOW) {
if (cursor_position == 0) currentState = ZERO_CALIBRATION;
else if (cursor_position == 1) currentState = FENCE_TOOL_MENU;
else if (cursor_position == 2) currentState = MAIN_MENU;
delay(300);
}
break;
case ZERO_CALIBRATION:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Zero Calibration");
lcd.setCursor(0, 1);
lcd.print("> Back to Menu");
if (digitalRead(ENCODER_BUTTON) == LOW) {
currentState = MAIN_MENU;
delay(300);
}
break;
case FENCE_TOOL_MENU:
displayFenceToolMenu();
if (digitalRead(ENCODER_BUTTON) == LOW) {
currentState = SELECT_MM;
delay(300);
}
break;
}
}
Sto utilizzando un display 4x20 ed un encoder ky-040 per effettuare le selezioni e spostarmi nel menu. Nel codice precedente, correttamente permetteva di aumentare il valore in decimi di mm dove richiesto, una volta effettuato il movimento, nuovamente veniva utilizzato per spostarsi tra le opzioni disponibili.
Spero in un vostro aiuto ![]()
Grazie mille



