Hello everyone,
I´ve some trouble with my project. The aim is that a stepper motor would change its direction by pressing the buttons of my Keypad Shield, but it wouldn´t do it. When I use it without the LCD Keypad Shield, everything is fine, but with it, the motor only moves in one direction.
I use a TB6600 as a driver and a NEMA stepper motor. The code without the LCD is this one
#include <AccelStepper.h>
// Definiere die Anzahl der Mikroschritte pro Vollschritt
const int microsteps = 16;
const int dirPlusPin = 7; // Verwende Pin 7 für die Richtungssteuerung (Dir+)
const int dirMinusPin = 8; // Verwende Pin 8 für die Richtungssteuerung (Dir-)
const int fullStepsPerRevolution = 200;
const int stepsPerRevolution = microsteps * fullStepsPerRevolution;
// Definiere den Schrittmotor-Pin
const int motorPin = 3;
// Initialisiere den Schrittmotor mit den Pins und der Art des Treibers
AccelStepper stepper(AccelStepper::DRIVER, motorPin);
void setup() {
// Setze die Pins für die Richtungssteuerung als Ausgänge
pinMode(dirPlusPin, OUTPUT);
pinMode(dirMinusPin, OUTPUT);
// Setze die maximale Geschwindigkeit und Beschleunigung des Schrittmotors
stepper.setMaxSpeed(2000.0);
stepper.setAcceleration(1000.0);
}
void loop() {
// Setze die Richtung auf vorwärts (Dir+ mit HIGH, Dir- mit LOW verbinden)
digitalWrite(dirPlusPin, HIGH);
digitalWrite(dirMinusPin, LOW);
// Bewege den Schrittmotor im Uhrzeigersinn um 1000 Schritte
stepper.moveTo(500); // Setze die Zielposition
stepper.runToPosition(); // Bewege den Schrittmotor zur Zielposition
delay(3000);
// Setze die Richtung auf rückwärts (Dir+ mit LOW, Dir- mit HIGH verbinden)
digitalWrite(dirPlusPin, LOW);
digitalWrite(dirMinusPin, HIGH);
// Bewege den Schrittmotor gegen den Uhrzeigersinn um 1000 Schritte
stepper.moveTo(-500); // Setze die Zielposition
stepper.runToPosition(); // Bewege den Schrittmotor zur Zielposition
}
And the other code is here:
#include <LiquidCrystal.h>
#include <AccelStepper.h>
/******************************************************
Implementation of Button-Logic, Microsteps of movement
and Menuitems
*******************************************************/
const int microsteps = 16;
const int fullStepsPerRevolution = 200;
const int stepsPerRevolution = microsteps * fullStepsPerRevolution;
const int motorPin = 3;
const int dirPlusPin = 2;
const int dirMinusPin = 1;
AccelStepper stepper(AccelStepper::DRIVER, motorPin);
enum Button {
NONE = 0,
RIGHT = 1,
UP = 2,
DOWN = 3,
LEFT = 4,
SELECT = 5
};
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
struct MenuItem {
String name;
int nextMenu;
void (*displayFunction)();
};
/******************************************************
Overview of the used functions, variables and menustructure
*******************************************************/
// Vorankündigungen der Funktionen
void displayMainMenu();
void displaySubMenuA();
void displaySubMenuB();
void displaySubMenuC();
void displaySubMenuD();
void handleSelectButton();
void displaySubMenuA1();
void displaySubMenuB1();
void displaySubMenuC1();
void displayCurrentMenu();
void setVolume();
void setLengthDiameter();
int readButtons();
void adjustFlowRate(int direction);
float calculateSpeedFromFlowRate(float flowRate);
void setFlowRate();
int selectedSyringeIndex = 0; // Standardmäßig die erste Spritze auswählen
MenuItem menuItems[] = {
{"Main Menu", 0, displayMainMenu},
{"Infuse", 1, displaySubMenuA},
{"Refill", 2, displaySubMenuB},
{"Cycle Mode", 3, displaySubMenuC},
{"Start Infuse", 5, displaySubMenuA1},
{"Start Refill", 6, displaySubMenuB1},
{"Start Cycle Mode", 7, displaySubMenuC1}
};
float currentVolume = 0.0; // Deklariert das aktuelle Volumen und setzt es auf 0.0
float volumePerStep = 1.0;
float length = 0.0; // Neue Variable für Länge
float diameter = 0.0; // Neue Variable für Durchmesser
int currentMenu = 0;
float flowRate = 0.0;
float averageCorrectionFactor(float measuredVolumes[], float setVolumes[], int numSamples);
float volumeParts[8] = {100000.0, 10000.0, 1000.0, 100.0, 10.0, 1.0, 0.1, 0.01};
float calibrationFactor = 5.78;
/******************************************************
Setup and Loop
*******************************************************/
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
stepper.setMaxSpeed(2000.0);
stepper.setAcceleration(1000.0);
displayCurrentMenu();
pinMode(dirPlusPin, OUTPUT);
pinMode(dirMinusPin, OUTPUT);
stepper.setMaxSpeed(2000.0);
stepper.setAcceleration(1000.0);
}
void loop() {
digitalWrite(dirPlusPin, HIGH);
digitalWrite(dirMinusPin, LOW);
int button = readButtons();
switch (button) {
case UP:
handleUpButton();
break;
case DOWN:
handleDownButton();
break;
case SELECT:
handleSelectButton();
break;
case RIGHT:
handleRightButton();
break;
case LEFT:
handleLeftButton();
break;
}
stepper.run();
}
/******************************************************
Handling of the Button cases and Submenus
*******************************************************/
void handleUpButton() {
if (currentMenu != 0 && currentMenu < 5) { // Prüfe via Variable, ob Menu nicht Main oder SubMenu ist
int nextMenu = currentMenu - 1; // Springt ins nächste Menu, indem die Variable um 1 reduziert wird
currentMenu = nextMenu; // setzt das Menu auf das aktuelle Menu
displayCurrentMenu(); // Aktualisiert Bildschirm
} else if(currentMenu == 0){
currentMenu = 4; // Stellt den Weg von Main zu D dar evtl später durch A ersetzen
displayCurrentMenu();
}else if(currentMenu >= 5 && currentMenu <= 8){
}else if (currentMenu == 9){
int nextMenu = currentMenu -1;
currentMenu = nextMenu;
displayCurrentMenu();
// delay(500);
}
else {
currentMenu = 0; // Zurücksetzen ins Main bei Grenzwertüberschreitung
displayCurrentMenu();
}
}
void handleDownButton() {
if (currentMenu != 0 && currentMenu < 5) { // Prüfe via Variable, ob Menu nicht Main oder SubMenu ist
int nextMenu = currentMenu + 1; // Springt ins nächste Menu, indem die Variable um 1 erhöht wird
currentMenu = nextMenu; // setzt das Menu auf das aktuelle Menu
displayCurrentMenu(); // Aktualisiert Bildschirm
} else if(currentMenu == 4){
currentMenu = 0; // Stellt den Weg von D zu Main dar evtl. später durch A ersetzen
displayCurrentMenu();
} else if (currentMenu >= 5 && currentMenu <= 7){
} else if (currentMenu == 8){
int nextMenu = currentMenu +1;
currentMenu = nextMenu;
displayCurrentMenu();
// delay(500);
}
else {
currentMenu = 0; // Zurücksetzen ins Main bei Grenzwertüberschreitung
displayCurrentMenu();
}
}
void handleRightButton() {
if (currentMenu >= 1 && currentMenu <= 4) {
currentMenu += 4;
displayCurrentMenu();
} else if(currentMenu == 5){
delay(5000);
startForwardMotion();
} else if(currentMenu == 6){
startBackwardMotion();
lcd.setCursor(0,1);
lcd.print("Backward motion");
} else if(currentMenu == 8){
setVolume();
} else if(currentMenu == 9){
currentMenu = 12;
displayCurrentMenu();
setFlowRate();
}
}
void handleLeftButton() {
if(currentMenu >= 5 && currentMenu <= 8){
currentMenu = currentMenu - 4;
displayCurrentMenu();
}
}
void handleSelectButton() {
switch (currentMenu) {
case 7: // Start Cycle Mode
cycleMode();
break;
// Hier können weitere Cases für andere Funktionen hinzugefügt werden
}
}
void displayCurrentMenu() {
lcd.clear();
if (currentMenu >= 0 && currentMenu < sizeof(menuItems) / sizeof(menuItems[0])) {
lcd.print(menuItems[currentMenu].name);
}
delay(500);
}
void displayMainMenu() {
lcd.clear();
lcd.print("Main Menu");
}
void displaySubMenuA() {
lcd.clear();
lcd.print("Infuse");
}
void displaySubMenuB() {
lcd.clear();
lcd.print("Refill");
}
void displaySubMenuC() {
lcd.clear();
lcd.print("CycleMode");
}
void displaySubMenuA1() {
lcd.clear();
lcd.print("Start Infuse");
}
void displaySubMenuB1() {
lcd.clear();
lcd.print("Start Refill");
}
/******************************************************
Implementation of Movement-Logic
*******************************************************/
void startForwardMotion() {
digitalWrite(dirPlusPin, HIGH);
digitalWrite(dirMinusPin, LOW);
stepper.setSpeed(2000.0); // Example for Velocity
stepper.moveTo(stepper.currentPosition() + stepsPerRevolution * volumePerStep);
// Führe die Bewegung aus und warte, bis sie abgeschlossen ist
while (stepper.distanceToGo() != 0) {
stepper.run();
}
}
void startBackwardMotion() {
digitalWrite(dirPlusPin, LOW);
digitalWrite(dirMinusPin, HIGH);
stepper.setSpeed(2000.0); // Example for Velocity
stepper.runToNewPosition( stepper.currentPosition()- stepsPerRevolution * volumePerStep);
// Führe die Bewegung aus und warte, bis sie abgeschlossen ist
while (stepper.distanceToGo() != 0) {
stepper.run();
}
}
void cycleMode() {
startForwardMotion(); // Starte die Vorwärtsbewegung
// Warte 5 Sekunden
delay(5000);
startBackwardMotion(); // Starte die Rückwärtsbewegung
}
int readButtons() {
delay(50);
int adc_key_in = analogRead(0);
if (adc_key_in > 1000) return NONE;
else if (adc_key_in < 52) return RIGHT;
else if (adc_key_in < 184) return UP;
else if (adc_key_in < 336) return DOWN;
else if (adc_key_in < 524) return LEFT;
else if (adc_key_in < 828) return SELECT;
return NONE;
}