Hallo iedereen, Ik ben nog niet zo lang bezig in arduino en heb deels met behulp van AI een code gemaakt die 2 motoren moet doen bewegen. 1 via een keypad 1 via een 8-bit absolute rotarty encoder, deze laatste is een aangepaste copy van een youtube tutorial. wat ik allemaal al getest hebt? i²c scan is oke, ik zie 3 adressen 0x27 (LCD) 0x20 encoder, 0x21 het keypad, Het keypad wordt juist uitgelezen, mijn encodermapping gemaakt via make_encodermap werkt ook. Als ik een testsketch draai om de encoder te bekijken inerial monitor komen die in volgorde netjes na een binnen, met en testsketch kan ik motoren laten draaien afwisselend links rechts. LCD getest 4 lijnen tekst. Alles samen werkt het niet, het is de bedoeling dat ik 1 motor 1/1 kan laten bewegen met de encoder, en 1 motor heb ik momenteel 4 preset steps in staan, ik heb soft-limits ook. Mijn driver (Leadshine DM542E) instellingen zijn oke, voeding ook oke. De code is niet blokkerend geschreven
//2560 — NIET-BLOKKEREND (fix: expliciete pinMode + sinking pulses)
// LCD 20x4 @0x27 | Keypad PCF8574 @0x21 | ACE128 encoder @0x20 (M2)
// DM542E: PUL+/DIR+/ENA+ = +5V, PUL-/DIR-/ENA- = Arduino pins (sinking pulses)
#include <Wire.h>
#include <AccelStepper.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <PCF8574.h>
#include "ACE128MAP12345678.h"
#include <ACE128.h>
// ===== I2C adressen =====
#define I2C_ADDR_LCD 0x27
#define I2C_ADDR_KPD 0x21
#define I2C_ADDR_ENC_M2 0x20
// ===== DM542E pins =====
#define M1_PUL 2
#define M1_DIR 3
#define M1_ENA 4
#define M2_PUL 5
#define M2_DIR 6
#define M2_ENA 7
// ===== Polariteiten =====
#define ENA_ACTIVE_LOW 1 // LOW = enable (DM542E)
#define STEP_ACTIVE_LOW 1 // sinking: LOW-puls = step
#define DIR_ACTIVE_LOW 0
// ===== Motor/µstep/gear =====
#define MOTOR_FULL_STEPS 200
#define M1_MICROSTEP 16
#define M2_MICROSTEP 16
#define M1_GEAR 5.18f
#define M2_GEAR 1.00f
#define STEPS_PER_REV(micro,gear) ((float)MOTOR_FULL_STEPS*(float)(micro)*(float)(gear))
const float M1_STEPS_PER_REV = STEPS_PER_REV(M1_MICROSTEP, M1_GEAR); // 200*16*5.18
const float M2_STEPS_PER_REV = STEPS_PER_REV(M2_MICROSTEP, M2_GEAR); // 200*16*1 = 3200
// ===== Encoder 1:1 naar M2 =====
const long M2_STEPS_PER_TICK = 25; // 3200 / 128 = 25 exact
// Snelheden
const float M1_MAXSPD = 1200, M1_ACCEL = 600; // keypad → M1
const float M2_MAXSPD = 1500, M2_ACCEL = 200; // encoder → M2
// Soft-limits
long MIN_M1 = -200000, MAX_M1 = 200000;
long MIN_M2 = -200000, MAX_M2 = 200000;
// ===== LCD =====
hd44780_I2Cexp lcd(I2C_ADDR_LCD);
const uint8_t LCD_COLS = 20, LCD_ROWS = 4;
unsigned long tLCD = 0;
const unsigned LCD_PERIOD = 200;
// ===== Keypad (PCF8574) =====
PCF8574 pcfKpd(I2C_ADDR_KPD);
const char keymap[4][4] = {
{'D','C','B','A'},
{'#','9','6','3'},
{'0','8','5','2'},
{'*','7','4','1'}
};
uint8_t KPD_ROWS[4] = {0,1,2,3}; // P0..P3
uint8_t KPD_COLS[4] = {4,5,6,7}; // P4..P7
uint8_t kpdRow = 0;
bool kpdBusy = false;
unsigned long kpdPhaseT = 0;
const unsigned KPD_SETTLE_US = 150;
char kpd_lastKey = 0;
unsigned long kpd_lastEv = 0;
// UI buffer/presets (M1 via keypad)
String ibuf;
const uint8_t IBUF_MAX = 10;
enum PendingType:uint8_t { P_NONE, P_PRESET_A, P_PRESET_B, P_PRESET_C, P_PRESET_D, P_NUMERIC };
PendingType pending = P_NONE;
long pendingSteps = 0;
// ===== Encoder (ACE128) → M2 =====
ACE128 encoderM2(I2C_ADDR_ENC_M2, encoderMap_12345678);
int16_t encM2_last = -1;
unsigned long tENC = 0;
const unsigned ENC_PERIOD = 5;
// ===== Steppers =====
AccelStepper stM1(AccelStepper::DRIVER, M1_PUL, M1_DIR);
AccelStepper stM2(AccelStepper::DRIVER, M2_PUL, M2_DIR);
// ===== ENA =====
bool driversEnabled = false;
inline void hwSetENAPin(uint8_t pin, bool en) {
pinMode(pin, OUTPUT);
digitalWrite(pin, en ? LOW : HIGH); // LOW actief, HIGH inactief
}
inline void armDrivers(bool en) {
if(en == driversEnabled) return;
hwSetENAPin(M1_ENA, en);
hwSetENAPin(M2_ENA, en);
driversEnabled = en;
}
// ===== Helpers =====
inline long clampTarget(uint8_t ax, long t) {
if(ax == 0) {
if(t < MIN_M1) t = MIN_M1;
if(t > MAX_M1) t = MAX_M1;
} else {
if(t < MIN_M2) t = MIN_M2;
if(t > MAX_M2) t = MAX_M2;
}
return t;
}
inline char dirChar(long cur, long tgt) {
if(tgt > cur) return '>';
if(tgt < cur) return '<';
return ' ';
}
// ===== Keypad logic (A/B/C/D/n*) → M1 =====
inline void clearInput() { ibuf.remove(0); }
inline bool addDigit(char k) {
if(ibuf.length() >= IBUF_MAX) return false;
ibuf += k;
return true;
}
inline void setPending(uint8_t t, long s) {
pending = (PendingType)t;
pendingSteps = s;
}
inline void execMoveM1(long tgt) {
tgt = clampTarget(0, tgt);
stM1.moveTo(tgt);
}
inline void onConfirm() {
long tgt = (pending == P_NUMERIC) ? (ibuf.length() ? ibuf.toInt() : 0) : pendingSteps;
Serial.print("Pending type: ");
Serial.println(pending);
Serial.print("Target: ");
Serial.println(tgt);
execMoveM1(tgt);
pending = P_NONE;
pendingSteps = 0;
clearInput();
}
char keypadPoll() {
unsigned long now = micros();
if(!kpdBusy) {
for(int rr = 0; rr < 4; rr++) pcfKpd.write(KPD_ROWS[rr], HIGH); // idle
pcfKpd.write(KPD_ROWS[kpdRow], LOW); // active row
kpdBusy = true;
kpdPhaseT = now;
return 0;
}
if((now - kpdPhaseT) < KPD_SETTLE_US) return 0;
for(int c = 0; c < 4; c++) {
int v = pcfKpd.read(KPD_COLS[c]); // LOW = key
if(v == LOW) {
char k = keymap[kpdRow][c];
unsigned long t = millis();
if(k != kpd_lastKey || (t - kpd_lastEv) > 60) {
kpd_lastKey = k;
kpd_lastEv = t;
kpdRow = (kpdRow + 1) & 3;
kpdBusy = false;
return k;
}
}
}
kpdRow = (kpdRow + 1) & 3;
kpdBusy = false;
if(kpd_lastKey && (millis() - kpd_lastEv) > 120) kpd_lastKey = 0;
return 0;
}
void handleKey(char k) {
if (k >= '0' && k <= '9') { addDigit(k); pending = P_NUMERIC; return; }
if (k == '*') { onConfirm(); return; }
if (k == '#') { clearInput(); pending = P_NONE; pendingSteps = 0; return; }
if (k == 'A') { setPending(P_PRESET_A, 1000); return; }
if (k == 'B') { setPending(P_PRESET_B, 2000); return; }
if (k == 'C') { setPending(P_PRESET_C, 3000); return; }
if (k == 'D') { setPending(P_PRESET_D, 4000); return; }
}
// ===== Encoder → M2 (1:1 exact) =====
void encoderPoll() {
unsigned long now = millis();
if(now - tENC < ENC_PERIOD) return;
tENC = now;
int ang = encoderM2.pos(); // 0..127, -1 bij fout
if(ang < 0) return;
if(encM2_last < 0) { encM2_last = ang; return; }
int d = ang - encM2_last;
if(d > 64) d -= 128;
if(d < -64) d += 128;
if(d != 0) {
encM2_last = ang;
long delta = (long)d * M2_STEPS_PER_TICK; // 25 stappen per tick
long tgt = clampTarget(1, stM2.targetPosition() + delta);
stM2.moveTo(tgt);
}
}
// ===== LCD =====
void lcdInit() {
int s = lcd.begin(LCD_COLS, LCD_ROWS);
(void)s;
lcd.backlight();
lcd.clear();
}
void lcdPoll() {
unsigned long now = millis();
if(now - tLCD < LCD_PERIOD) return;
tLCD = now;
long m1c = stM1.currentPosition(), m1t = stM1.targetPosition();
long m2c = stM2.currentPosition(), m2t = stM2.targetPosition();
lcd.setCursor(0, 0);
lcd.print(F("M1 Pos: "));
lcd.print(m1c);
lcd.print(' ');
lcd.print(dirChar(m1c, m1t));
lcd.print(F(" "));
lcd.setCursor(0, 1);
lcd.print(F("M1 Doel: "));
lcd.print(m1t);
lcd.print(F(" "));
lcd.setCursor(0, 2);
lcd.print(F("M2 Pos: "));
lcd.print(m2c);
lcd.print(' ');
lcd.print(dirChar(m2c, m2t));
lcd.print(F(" "));
lcd.setCursor(0, 3);
lcd.print(F("M2 Doel: "));
lcd.print(m2t);
lcd.print(F(" "));
}
// ===== Expliciete OUTPUT setup voor STEP/DIR =====
void forceOutputIdleLevels() {
pinMode(M1_PUL, OUTPUT);
digitalWrite(M1_PUL, STEP_ACTIVE_LOW ? HIGH : LOW);
pinMode(M1_DIR, OUTPUT);
digitalWrite(M1_DIR, DIR_ACTIVE_LOW ? HIGH : LOW);
pinMode(M2_PUL, OUTPUT);
digitalWrite(M2_PUL, STEP_ACTIVE_LOW ? HIGH : LOW);
pinMode(M2_DIR, OUTPUT);
digitalWrite(M2_DIR, DIR_ACTIVE_LOW ? HIGH : LOW);
}
// ===== Steppers init =====
void setupSteppers() {
stM1.setPinsInverted(DIR_ACTIVE_LOW, STEP_ACTIVE_LOW);
stM2.setPinsInverted(DIR_ACTIVE_LOW, STEP_ACTIVE_LOW);
stM1.setMaxSpeed(M1_MAXSPD);
stM1.setAcceleration(M1_ACCEL);
stM2.setMaxSpeed(M2_MAXSPD);
stM2.setAcceleration(M2_ACCEL);
stM1.setMinPulseWidth(5);
stM2.setMinPulseWidth(5);
stM1.setCurrentPosition(0);
stM2.setCurrentPosition(0);
}
// ===== Setup/loop =====
void setup() {
Wire.begin();
pcfKpd.begin();
for(int r = 0; r < 4; r++) pcfKpd.write(KPD_ROWS[r], HIGH); // rows idle
for(int c = 0; c < 4; c++) pcfKpd.write(KPD_COLS[c], HIGH); // cols pull-up
forceOutputIdleLevels(); // Zet STEP/DIR als OUTPUT + idle-niveaus
setupSteppers();
armDrivers(true); // Drivers AAN tijdens testen
lcdInit();
encoderM2.begin();
encM2_last = -1;
// Test: zet doelposities voor M1 en M2
stM1.moveTo(1000);
stM2.moveTo(1000);
}
void loop() {
if(char k = keypadPoll()) handleKey(k); // keypad → M1
encoderPoll(); // encoder → M2
stM1.run();
stM2.run();
lcdPoll();
}