Motoren wil niet bewegen

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();
}

Ik zag een poging tot het gebruik van code tags (bedankt) maar het werkte niet helemaal. Ik heb het gecorrigeerd.

Code tags voor een blok code zijn drie back ticks (```) voor en na het blok. Ze moeten op hun eigen regel staan !!

```
code hier

```

Dit is best een ingewikkelde sketch voor een beginner.
Ziet er ook netjes uit. Ik heb niet alles bekeken, maar ben de beginnersfouten nog niet tegengekomen.
Op welke microcontroller draait dit? Hoeveel geheugen is er run time beschikbaar na compileren?
Beste is om op strategische plekken een Serial.println neer te zetten. Deels om te zien of er delen van de code nooit aan de beurt komen, en deels ook om de waarde van de variabelen die de flow van je code bepalen in te kunnen zien (in jouw geval dus in elk geval k. (Ik zou een langere naam kiezen...
Starten met een werkende sketch en dan 1 voor 1 nieuwe delen toevoegen is ook een goed idee...
Waarom is bijna alles inline? Dit zal veel code genereren (overigens is veel code niet zo vaak een probleem, maar met de UNO R3 kun je er wel tegenaan lopen).

Bedankt voor je reactie

Het is een arduino Mega, waarschijnlijk nog een dan de eerste ik denk dat deze hier waarschijnlijk al een kleine 15 jaar lag te wachten, nu uiteindelijk aan begonnen door dat ik lange tijd werkonbekwaam ben. Ik ben nu opnieuw begonnen en zo zoals je schreef, stap per stap en telkens na een werkend onderdeel neem ik een backup om indoen nodig een fall back te kunnen doen

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.