Plotter V2 mit Omni Wheels

Hallo Ihr Lieben,

Möchte mir den Plotter V2 nachbauen.
https://www.instructables.com/Omni-Wheel-CNC-Plotter-V2/

Leider bin ich in Sachen Arduino noch nicht so tief drin.

Ich bekomme den Basis Code nicht zum Laufen.
Vielleicht hat wer eine Idee was ich Falsch mache.

Hardware ist ein MEGA 2560 , Ramps 1.5 mit DRV 8825

Theoretisch muss ich nur die " motor definitions" einstellen und dann sollte es laufen.

Aber das Klappt nicht…
aber wieso…

Hoffe das wer lust hat mir zu Helfen oder Eventuell in mein Projekt mit einzusteigen

Habe den Original Code mal Hochgeladen…

/**********************************************************************
  CoreXY PLOTTER
  Code by lingib
  Last update 3 June 2019

  This program controls a three-wheel "omni-wheel CNC plotter".
  ----------
  COPYRIGHT
  ----------
  This code is free software: you can redistribute it and/or
  modify it under the terms of the GNU General Public License as published
  by the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This software is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License. If
  not, see <http://www.gnu.org/licenses/>.
***************************************************************************/

// -------------------------------
// GLOBALS
// -------------------------------

// ----- constants
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105

// ----- Bit set/clear/check/toggle macros
#define SET(x,y) (x |=(1<<y))
#define CLR(x,y) (x &= (~(1<<y)))
#define CHK(x,y) (x & (1<<y))
#define TOG(x,y) (x^=(1<<y))

// ----- motor definitions
#define STEPS_PER_MM 200*8/(58*PI)   //200steps/rev; 8 x microstepping; 58mm dia. wheels
#define NUDGE STEPS_PER_MM*5          //move pen 5mm (change number to suit)
#define STEP1 54                      //arduino ports
#define STEP2 60
#define STEP3 46
#define DIRECTION1 55
#define DIRECTION2 61
#define DIRECTION3 48

/*// ----- motor definitions
#define STEPS_PER_MM 200*8/(58*PI)   //200steps/rev; 8 x microstepping; 58mm dia. wheels
#define NUDGE STEPS_PER_MM*5          //move pen 5mm (change number to suit)
#define STEP1 13                      //arduino ports
#define STEP2 11
#define STEP3 9
#define DIRECTION1 12
#define DIRECTION2 10
#define DIRECTION3 8
*/

#define CW false
#define CCW true
bool ROTATE1;                       // Wheel W1 doesn't rotate in vertical direction
bool DIR1;                          // Wheel W1
bool DIR2;                          // Wheel W2
bool DIR3;                          // Wheel W3

long
PULSE_WIDTH = 2,                    //easydriver step pulse-width (uS)
DELAY = 1000;                       //delay (uS) between motor steps (controls speed)

// ----- plotter definitions
#define BAUD 9600
#define XOFF 0x13                   //pause transmission (19 decimal)
#define XON 0x11                    //resume transmission (17 decimal)
#define PEN 3

float
SCALE_FACTOR = 1.0,                 //drawing scale (1 = 100%)
SCALE_FACTOR_VERT = sqrt(3),        //allow for angled wheels
ARC_MAX = 2.0;                      //maximum arc-length (controls smoothness)

int
/*
   XY plotters only deal in integer steps.
*/
THIS_X = 0,                         //"scaled" x co-ordinate (rounded)
THIS_Y = 0,                         //"scaled" y co-ordinate (rounded)
LAST_X = 0,                         //"scaled" x co-ordinate (rounded)
LAST_Y = 0;                         //"scaled" y co-ordinate (rounded)

// ----- gcode definitions
#define STRING_SIZE 128             //string size

char
BUFFER[STRING_SIZE + 1],
       INPUT_CHAR;

String
INPUT_STRING,
SUB_STRING;

int
INDEX = 0,                        //buffer index
START,                            //used for sub_string extraction
FINISH;

float
X,                                //gcode float values held here
Y,
I,
J;

// -----------------------
// SETUP
// -----------------------
void setup()
{
  // ----- initialise motor1
  pinMode(STEP1, OUTPUT);
  pinMode(DIRECTION1, OUTPUT);
  digitalWrite(DIRECTION1, CW);
  delayMicroseconds(PULSE_WIDTH);
  digitalWrite(STEP1, LOW);

  // ----- initialise motor2
  //pinMode(STEP2, OUTPUT);
  //pinMode(DIRECTION2, OUTPUT);
  pinMode(60, OUTPUT);
  pinMode(61, OUTPUT);
  digitalWrite(DIRECTION2, CW);
  delayMicroseconds(PULSE_WIDTH);
  digitalWrite(STEP2, LOW);

  // ----- initialise motor3
  pinMode(STEP3, OUTPUT);
  pinMode(DIRECTION3, OUTPUT);
  digitalWrite(DIRECTION3, CW);
  delayMicroseconds(PULSE_WIDTH);
  digitalWrite(STEP3, LOW);

  // ----- pen-lift
  pinMode(PEN, OUTPUT);                                       //D3
  TCCR2A = _BV(COM2B1) | _BV(COM2B0) | _BV(WGM20);            //PWM
  TCCR2B = _BV(WGM22) | _BV(CS22) | _BV(CS21) | _BV(CS20);    //div 1024
  OCR2A = 156;                                                //20mS period
  OCR2B = 148;                                                //2mS period (pen-up)

  /*
    The above pen-lift comprises a standard servo which requires a 1 mS pulse
    for pen down, or a 2mS pulse for pen up, with a fixed period of 20mS.

    The Arduino "bit value" macro, #define _BV(x) (1 << x), is used to
    set the Timer2 mode to "phase-correct PWM" with a variable "top-limit".
    In this mode the timer counts up to the value entered into register OCR2A
    then back down to zero.

    The following values were used to obtain a 20mS period at pin D3:
      clock:        16 MHz
    prescaler:      1024
    top-limit (OCR2A):  156
    period:       16MHz/1024/(156*2) = 50Hz (20mS)

    If you enter a value into register OCR2B that is LESS than the value in
    register OCR2A then timer2 will will pass through the value in OCR2B
    twice ... once on the way up ... and once on the way down. The duration
    of the output pulse on pin D3 is the time that the count in OCR2A is
    greater than the value in OCR2B.

    A value of 148 entered into OCR2B creates a 1mS pulse:
    period:       156-148)*20mS/156 = 1mS (pen-up)

    A value of 140 entered into OCR2B creates a 2mS pulse):
    period:     156-140)*20mS/156 = 2mS (pen-down)
  */

  // ----- plotter setup
  memset(BUFFER, '\0', sizeof(BUFFER));     //fill with string terminators
  INPUT_STRING.reserve(STRING_SIZE);
  INPUT_STRING = "";

  // ----- establish serial link
  Serial.begin(BAUD);

  // ----- flush the buffers
  Serial.flush();                           //clear TX buffer
  while (Serial.available()) Serial.read(); //clear RX buffer

  // ----- display commands
  menu();
}

//--------------------------------------------------------------------------
// MAIN LOOP
//--------------------------------------------------------------------------
void loop() {

  // ----- get the next instruction !!  while (Serial.available()) {
  while (Serial.available()) {
    INPUT_CHAR = (char)Serial.read();         //read character
    Serial.write(INPUT_CHAR);                 //echo character to the screen
    BUFFER[INDEX++] = INPUT_CHAR;             //add char to buffer
    if (INPUT_CHAR == '\n') {                 //check for line feed
      Serial.flush();                         //clear TX buffer
      Serial.write(XOFF);                     //pause transmission
      INPUT_STRING = BUFFER;                  //convert to string
      process(INPUT_STRING);                  //interpret string and perform task
      memset(BUFFER, '\0', sizeof(BUFFER));   //fill buffer with string terminators
      INDEX = 0;                              //point to buffer start
      INPUT_STRING = "";                      //empty string
      Serial.flush();                         //clear TX buffer
      Serial.write(XON);                      //resume transmission
    }
  }
}

//---------------------------------------------------------------------------
// MENU
//---------------------------------------------------------------------------
/*
   The Arduino F() flash macro is used to conserve RAM.
*/
void menu() {
  Serial.println(F(""));
  Serial.println(F("  ------------------------------------------------------"));
  Serial.println(F("                         MENU"));
  Serial.println(F("  ------------------------------------------------------"));
  Serial.println(F("    MENU ............... menu"));
  Serial.println(F("    G00 X## Y## ........ goto XY (pen-up)"));
  Serial.println(F("    G01 X## Y## ........ goto XY (pen-down)"));
  Serial.println(F("    T1 ................. move pen to 0,0"));
  Serial.println(F("    T2 S##.## .......... set drawing Scale (1=100%)"));
  Serial.println(F("    T3 ................. pen up"));
  Serial.println(F("    T4 ................. pen down"));
  Serial.println(F("    T5 ................. test pattern: ABC"));
  Serial.println(F("    T6 ................. test pattern: target"));
  Serial.println(F("    T7 ................. test pattern: radials"));
  Serial.println(F("  ------------------------------------------------------"));
}

//--------------------------------------------------------------------------
// PROCESS
//--------------------------------------------------------------------------
void process(String string) {

  // ----- convert string to upper case
  INPUT_STRING = string;
  INPUT_STRING.toUpperCase();

  // ----------------------------------
  // G00   linear move with pen_up
  // ----------------------------------
  if (INPUT_STRING.startsWith("G00")) {

    // ----- extract X
    START = INPUT_STRING.indexOf('X');
    if (!(START < 0)) {
      FINISH = START + 8;
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 1);
      X = SUB_STRING.toFloat();
    }

    // ----- extract Y
    START = INPUT_STRING.indexOf('Y');
    if (!(START < 0)) {
      FINISH = START + 8;
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 1);
      Y = SUB_STRING.toFloat();
    }

    pen_up();
    move_to(X, Y);
  }

  // ----------------------------------
  // G01   linear move with pen_down
  // ----------------------------------
  if (INPUT_STRING.startsWith("G01")) {

    // ----- extract X
    START = INPUT_STRING.indexOf('X');
    if (!(START < 0)) {
      FINISH = START + 8;
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 1);
      X = SUB_STRING.toFloat();
    }

    // ----- extract Y
    START = INPUT_STRING.indexOf('Y');
    if (!(START < 0)) {
      FINISH = START + 8;
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 1);
      Y = SUB_STRING.toFloat();
    }

    pen_down();
    move_to(X, Y);
  }

  // ----------------------------------
  // G02   clockwise arc with pen_down
  // ----------------------------------
  if (INPUT_STRING.startsWith("G02")) {

    // ----- extract X
    START = INPUT_STRING.indexOf('X');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('X'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      X = SUB_STRING.toFloat();
    }

    // ----- extract Y
    START = INPUT_STRING.indexOf('Y');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('Y'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      Y = SUB_STRING.toFloat();
    }

    // ----- extract I
    START = INPUT_STRING.indexOf('I');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('I'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      I = SUB_STRING.toFloat();
    }

    // ----- extract J
    START = INPUT_STRING.indexOf('J');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('J'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      J = SUB_STRING.toFloat();
    }

    pen_down();
    draw_arc_cw(X, Y, I, J);
  }

  // ------------------------------------------
  // G03   counter-clockwise arc with pen_down
  // ------------------------------------------
  if (INPUT_STRING.startsWith("G03")) {

    // ----- extract X
    START = INPUT_STRING.indexOf('X');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('X'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      X = SUB_STRING.toFloat();
    }

    // ----- extract Y
    START = INPUT_STRING.indexOf('Y');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('Y'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      Y = SUB_STRING.toFloat();
    }

    // ----- extract I
    START = INPUT_STRING.indexOf('I');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('I'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      I = SUB_STRING.toFloat();
    }

    // ----- extract J
    START = INPUT_STRING.indexOf('J');
    if (!(START < 0)) {
      FINISH = INPUT_STRING.indexOf('.', INPUT_STRING.indexOf('J'));
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH + 7);
      J = SUB_STRING.toFloat();
    }

    pen_down();
    draw_arc_ccw(X, Y, I, J);
  }

  // ----------------------------------
  // MENU
  // ----------------------------------
  if (INPUT_STRING.startsWith("MENU")) {
    menu();
  }

  // ----------------------------------
  // T1   position the pen over 0,0
  // ----------------------------------
  if (INPUT_STRING.startsWith("T1")) {

    // ----- variables
    int step;           //loop counter
    int steps = NUDGE;  //steps motor is to rotate

    // ----- instructions
    Serial.println(F(""));
    Serial.println(F("  ----------------------------------------------"));
    Serial.println(F("    Position the pen over the 0,0 co-ordinate:"));
    Serial.println(F("  ----------------------------------------------"));
    Serial.println(F("    X-axis:             Y-axis:"));
    Serial.println(F("   'A'  'S'            'K'  'L'"));
    Serial.println(F("   <-    ->            <-    ->"));
    Serial.println(F("    Exit = 'E'"));

    // ----- flush the buffer
    while (Serial.available() > 0) Serial.read();

    // ----- control motors with 'A', 'S', 'K', and 'L' keys

    char keystroke = ' ';
    while (keystroke != 'E') {  //press 'E' key to exit

      // ----- check for keypress
      if (Serial.available() > 0) {
        keystroke = (char) Serial.read();
      }

      // ----- select task
      switch (keystroke) {
        case 'a':
        case 'A': {
            // ----- rotate motor1 CW
            for (step = 0; step < steps; step++) {
              left();
            }
            keystroke = ' ';    //otherwise motor will continue to rotate
            break;
          }
        case 's':
        case 'S': {
            // ------ rotate motor1 CCW
            for (step = 0; step < steps; step++) {
              right();
            }
            keystroke = ' ';
            break;
          }
        case 'k':
        case 'K': {
            // ----- rotate motor2 CW
            for (step = 0; step < steps; step++) {
              up();
            }
            keystroke = ' ';
            break;
          }
        case 'l':
        case 'L': {
            // ----- rotate motor2 CCW
            for (step = 0; step < steps; step++) {
              down();
            }
            keystroke = ' ';
            break;
          }
        case 'e':
        case 'E': {
            // ----- exit
            Serial.println(F(" "));
            Serial.println(F("  Calibration complete ..."));
            keystroke = 'E';
            break;
          }
        // ----- default for keystroke
        default: {
            break;
          }
      }
    }

    // ----- initialise counters for co-ordinate (0,0)
    THIS_X = 0;                   //current X co-ordinate
    THIS_Y = 0;                   //current Y co-ordinate
    LAST_X = 0;                   //previous X co-ordinate
    LAST_Y = 0;                   //previous Y-co-ordinate
  }

  // ----------------------------------
  // T2   set scale factor
  // ----------------------------------
  if (INPUT_STRING.startsWith("T2")) {
    Serial.println("T2");

    START = INPUT_STRING.indexOf('S');
    if (!(START < 0)) {
      FINISH = START + 6;
      SUB_STRING = INPUT_STRING.substring(START + 1, FINISH);
      SCALE_FACTOR = SUB_STRING.toFloat();
      Serial.print(F("Drawing now ")); Serial.print(SCALE_FACTOR * 100); Serial.println(F("%"));
    }
    else {
      Serial.println(F("Invalid scale factor ... try again. (1 = 100%)"));
    }
  }

  // ----------------------------------
  // T3   pen up
  // ----------------------------------
  if (INPUT_STRING.startsWith("T3")) {
    pen_up();
  }

  // ----------------------------------
  // T4   pen down
  // ----------------------------------
  if (INPUT_STRING.startsWith("T4")) {
    pen_down();
  }

  // ----------------------------------
  // T5   ABC test pattern
  // ----------------------------------
  if (INPUT_STRING.startsWith("T5")) {
    abc();
  }

  // ----------------------------------
  // T6   target test pattern
  // ----------------------------------
  if (INPUT_STRING.startsWith("T6")) {
    target();
  }

  // ----------------------------------
  // T7   radial line test pattern
  // ----------------------------------
  if (INPUT_STRING.startsWith("T7")) {
    radials();
  }
}

// -------------------------------
// MOVE_TO
// -------------------------------
/*
   Assume that our sheet of paper has been
   "scaled" to match the stepping motors.
*/
void move_to(float x, float y) {                        //x,y are absolute co-ordinates

  // ----- apply scale factor
  THIS_X = round(x * STEPS_PER_MM * SCALE_FACTOR);
  THIS_Y = round(y * STEPS_PER_MM * SCALE_FACTOR_VERT * SCALE_FACTOR);  //prescale y axis to compensate for angled wheels
  // ----- draw a line between these "scaled" co-ordinates
  draw_line(LAST_X, LAST_Y, THIS_X, THIS_Y);

  // ----- remember last "scaled" co-ordinate
  LAST_X = THIS_X;
  LAST_Y = THIS_Y;
}

// ------------------------------------------------------------------------
// DRAW LINE
// ------------------------------------------------------------------------
/*
  This routine assumes that motor1 controls the x-axis and that motor2 controls
  the y-axis.

  The algorithm automatically maps all "octants" to "octant 0" and
  automatically swaps the XY coordinates if dY is greater than dX. A swap
  flag determines which motor moves for any combination X,Y inputs. The swap
  algorithm is further optimised by realising that dY is always positive
  in quadrants 0,1 and that dX is always positive in "quadrants" 0,3.

  Each intermediate XY co-ordinate is plotted which results in a straight line
*/
void draw_line(int x1, int y1, int x2, int y2) {          //these are "scaled" co-ordinates

  // ----- locals
  int
  x = x1,                               //current "scaled" X-axis position
  y = y1,                               //current "scaled" Y-axis position
  dy,                                   //line slope
  dx,
  slope,
  longest,                              //axis lengths
  shortest,
  maximum,
  error,                                //bresenham thresholds
  threshold;

  // ----- find longest and shortest axis
  dy = y2 - y1;                         //vertical distance
  dx = x2 - x1;                         //horizontal distance
  longest = max(abs(dy), abs(dx));      //longest axis
  shortest = min(abs(dy), abs(dx));     //shortest axis

  // ----- scale Bresenham values by 2*longest
  error = -longest;                     //add offset to so we can test at zero
  threshold = 0;                        //test now done at zero
  maximum = (longest << 1);             //multiply by two
  slope = (shortest << 1);              //multiply by two ... slope equals (shortest*2/longest*2)

  // ----- initialise the swap flag
  /*
     The XY axes are automatically swapped by using "longest" in
     the "for loop". XYswap is used to decode the motors.
  */
  bool XYswap = true;                    //used for motor decoding
  if (abs(dx) >= abs(dy)) XYswap = false;

  // ----- pretend we are always in octant 0
  /*
     The current X-axis and Y-axis positions will now be incremented (decremented) each time
     through the loop. These intermediate steps are parsed to the plot(x,y) function which calculates
     the number of steps required to reach each of these intermediate co-ordinates. This effectively
     linearises the plotter and eliminates unwanted curves.
  */
  for (int i = 0; i < longest; i++) {

    // ----- move left/right along X axis
    if (XYswap) {   //swap
      if (dy < 0) {
        y--;
        down();                         //move pen 1 step down
      } else {
        y++;
        up();                           //move pen 1 step up
      }
    } else {    //no swap
      if (dx < 0) {
        x--;
        left();                         //move pen 1 step left
      } else {
        x++;
        right();                        //move pen 1 step right
      }
    }

    // ----- move up/down Y axis
    error += slope;
    if (error > threshold) {
      error -= maximum;

      // ----- move up/down along Y axis
      if (XYswap) {  //swap
        if (dx < 0) {
          x--;
          left();                         //move pen 1 step left
        } else {
          x++;
          right();                        //move pen 1 step right
        }
      } else {  //no swap
        if (dy < 0) {
          y--;
          down();                         //move pen 1 step down
        } else {
          y++;
          up();                           //move pen 1 step up
        }
      }
    }
  }
}

//--------------------------------------------------------------------
// LEFT()           (move the pen 1 step left)
//--------- -----------------------------------------------------------
void left() {
  ROTATE1 = true;
  DIR1 = CW;
  DIR2 = CCW;
  DIR3 = CCW;
  step_motors();
}

//--------------------------------------------------------------------
// RIGHT()           (move the pen 1 step right)
//--------- -----------------------------------------------------------
void right() {
  ROTATE1 = true;
  DIR1 = CCW;
  DIR2 = CW;
  DIR3 = CW;
  step_motors();
}

//--------------------------------------------------------------------
// UP()               (move the pen 1 step up)
//--------- -----------------------------------------------------------
void up() {
  ROTATE1 = false;
  DIR1 = CW;           // Ignored
  DIR2 = CCW;
  DIR3 = CW;
  step_motors();
}

//--------------------------------------------------------------------
// DOWN()             (move the pen 1 step down)
//--------- -----------------------------------------------------------
void down() {
  ROTATE1 = false;
  DIR1 = CW;           // Ignored
  DIR2 = CW;
  DIR3 = CCW;
  step_motors();
}

//----------------------------------------------------------------------------------------
// STEP MOTORS
//----------------------------------------------------------------------------------------
void step_motors() {

  // ----- locals
  enum {dir3, step3, dir2, step2, dir1, step1};                   //define bit positions
  byte pattern = PORTB;                                           //read current state PORTB

  // ----- set motor directions
  /*
     Change CCW to CW if the robot moves in the wrong direction
  */
  (DIR1 == CCW) ? SET(pattern, dir1) : CLR(pattern, dir1);
  (DIR2 == CCW) ? SET(pattern, dir2) : CLR(pattern, dir2);
  (DIR3 == CCW) ? SET(pattern, dir3) : CLR(pattern, dir3);
  PORTB = pattern;
  delayMicroseconds(PULSE_WIDTH);                                 //wait for direction lines to stabilise

  // ----- create leading edge of step pulse(s)
  (ROTATE1 == true) ? SET(pattern, step1) : CLR(pattern, step1);
  SET(pattern, step2);
  SET(pattern, step3);
  PORTB = pattern;                                                //step the motors
  delayMicroseconds(PULSE_WIDTH);                               //mandatory delay

  // ----- create trailing-edge of step-pulse(s)
  pattern = CLR(pattern, step1);
  pattern = CLR(pattern, step2);
  pattern = CLR(pattern, step3);
  PORTB = pattern;

  // ----- determines plotting speed
  delayMicroseconds(DELAY);
}

//----------------------------------------------------------------------------
// DRAW ARC CLOCKWISE (G02)
//----------------------------------------------------------------------------
void draw_arc_cw(float x, float y, float i, float j) {

  // ----- inkscape sometimes produces some crazy values for i,j
  if ((i < -100) || (i > 100) || (j < -100) || (j > 100)) {
    move_to(x, y);
  } else {

    // ----- variables
    float
    thisX = LAST_X / (STEPS_PER_MM * SCALE_FACTOR), //current unscaled X co-ordinate
    thisY = LAST_Y / (STEPS_PER_MM * SCALE_FACTOR_VERT * SCALE_FACTOR), //current unscaled Y co-ordinate
    nextX = x,                    //next X co-ordinate
    nextY = y,                    //next Y co-ordinate
    newX,                         //interpolated X co-ordinate
    newY,                         //interpolated Y co-ordinate
    I = i,                        //horizontal distance thisX from circle center
    J = j,                        //vertical distance thisY from circle center
    circleX = thisX + I,          //circle X co-ordinate
    circleY = thisY + J,          //circle Y co-ordinate
    delta_x,                      //horizontal distance between thisX and nextX
    delta_y,                      //vertical distance between thisY and nextY
    chord,                        //line_length between lastXY and nextXY
    radius,                       //circle radius
    alpha,                        //interior angle of arc
    beta,                         //fraction of alpha
    arc,                          //subtended by alpha
    current_angle,                //measured CCW from 3 o'clock
    next_angle;                   //measured CCW from 3 o'clock

    // ----- calculate arc
    delta_x = thisX - nextX;
    delta_y = thisY - nextY;
    chord = sqrt(delta_x * delta_x + delta_y * delta_y);
    radius = sqrt(I * I + J * J);
    alpha = 2 * asin(chord / (2 * radius)); //see construction lines
    arc = alpha * radius;         //radians

    // ----- sub-divide alpha
    int segments = 1;
    if (arc > ARC_MAX) {
      segments = (int)(arc / ARC_MAX);
      beta = alpha / segments;
    } else {
      beta = alpha;
    }

    // ----- calculate current angle
    /*
      atan2() angles between 0 and PI are CCW +ve from 3 o'clock.
      atan2() angles between 2*PI and PI are CW -ve relative to 3 o'clock
    */
    current_angle = atan2(-J, -I);
    if (current_angle <= 0) current_angle += 2 * PI;        //angles now 360..0 degrees CW

    // ----- plot intermediate CW co-ordinates
    next_angle = current_angle;                             //initialise angle
    for (int segment = 1; segment < segments; segment++) {
      next_angle -= beta;                                   //move CW around circle
      if (next_angle < 0) next_angle += 2 * PI;             //check if angle crosses zero
      newX = circleX + radius * cos(next_angle);            //standard circle formula
      newY = circleY + radius * sin(next_angle);
      move_to(newX, newY);
    }

    // ----- draw final line
    move_to(nextX, nextY);
  }
}

//----------------------------------------------------------------------------
// DRAW ARC COUNTER-CLOCKWISE (G03)
//----------------------------------------------------------------------------
/*
   We know the start and finish co-ordinates which allows us to calculate the
   chord length. We can also calculate the radius using the biarc I,J values.
   If we bisect the chord the center angle becomes 2*asin(chord/(2*radius)).
   The arc length may now be calculated using the formula arc_length = radius*angle.
*/
void draw_arc_ccw(float x, float y, float i, float j) {

  // ----- inkscape sometimes produces some crazy values for i,j
  if ((i < -100) || (i > 100) || (j < -100) || (j > 100)) {
    move_to(x, y);
  } else {

    // ----- variables
    float
    thisX = LAST_X / (STEPS_PER_MM * SCALE_FACTOR), //current unscaled X co-ordinate
    thisY = LAST_Y / (STEPS_PER_MM * SCALE_FACTOR_VERT * SCALE_FACTOR), //current unscaled Y co-ordinate
    nextX = x,                      //next X co-ordinate
    nextY = y,                      //next Y co-ordinate
    newX,                           //interpolated X co-ordinate
    newY,                           //interpolated Y co-ordinate
    I = i,                          //horizontal distance thisX from circle center
    J = j,                          //vertical distance thisY from circle center
    circleX = thisX + I,            //circle X co-ordinate
    circleY = thisY + J,            //circle Y co-ordinate
    delta_x,                        //horizontal distance between thisX and nextX
    delta_y,                        //vertical distance between thisY and nextY
    chord,                          //line_length between lastXY and nextXY
    radius,                         //circle radius
    alpha,                          //interior angle of arc
    beta,                           //fraction of alpha
    arc,                            //subtended by alpha
    current_angle,                  //measured CCW from 3 o'clock
    next_angle;                     //measured CCW from 3 o'clock

    // ----- calculate arc
    delta_x = thisX - nextX;
    delta_y = thisY - nextY;
    chord = sqrt(delta_x * delta_x + delta_y * delta_y);
    radius = sqrt(I * I + J * J);
    alpha = 2 * asin(chord / (2 * radius));     //see construction lines
    arc = alpha * radius;                       //radians

    // ----- sub-divide alpha
    int segments = 1;
    if (arc > ARC_MAX) {
      segments = (int)(arc / ARC_MAX);
      beta = alpha / segments;
    } else {
      beta = alpha;
    }

    // ----- calculate current angle
    /*
        tan2() angles between 0 and PI are CCW +ve from 3 o'clock.
        atan2() angles between 2*PI and PI are CW -ve relative to 3 o'clock
    */
    current_angle = atan2(-J, -I);
    if (current_angle <= 0) current_angle += 2 * PI;        //angles now 360..0 degrees CW

    // ----- plot intermediate CCW co-ordinates
    next_angle = current_angle;                             //initialise angle
    for (int segment = 1; segment < segments; segment++) {
      next_angle += beta;                                   //move CCW around circle
      if (next_angle > 2 * PI) next_angle -= 2 * PI;        //check if angle crosses zero
      newX = circleX + radius * cos(next_angle);            //standard circle formula
      newY = circleY + radius * sin(next_angle);
      move_to(newX, newY);
    }

    // ----- draw final line
    move_to(nextX, nextY);
  }
}

//---------------------------------------------------------------------------
// PEN_UP
// Raise the pen
// Changing the value in OCR2B changes the pulse-width to the SG-90 servo
//---------------------------------------------------------------------------
void pen_up() {
  OCR2B = 148;                //1mS pulse
  delay(250);                 //give pen-lift time to respond
}

//---------------------------------------------------------------------------
// PEN_DOWN
// Lower the pen
// Changing the value in OCR2B changes the pulse-width to the SG-90 servo
//---------------------------------------------------------------------------
void pen_down() {
  OCR2B = 140;                //2mS pulse
  delay(250);                 //give pen-lift time to respond
}

Eigentlich muss ich nur die PinOuts von meinem Ramps 1.5 eintragen…
So hab ich das verstanden aber leider tut sich NIX :roll_eyes:

Hi, super das du das Forum dafür genutzt hast. ^^ (Ich freu mich über diesen kleinen Erfolg)

Habe jetzt den Link von dir einmal überflogen und mir den Aufbau davon angeguckt.

Ich weiß nicht ob ich das richtig sehe, aber du verwendest ja einen komplett anderen Aufbau, Microcontroller und Motortreiber Ansteuerung. Also wenn ich tippen müsste, würde ich sagen nur die PinOuts ändern reicht nicht.

Hast du dein Problem mit der (Lauten) Motorsteuerung aus dem anderen Thread hier gelöst?

Aber hätte gedacht das ich einfach Steps bekomme.

Wie ich sie dann letztendlich nutze sollte doch keine Rolle spielen oder?

Nein das brummen ist immer noch da schon weniger aber finde die Motoren immer noch sehr laut…

langsam bin ich Verwirrt…

jetzt noch mal eine andere Frage…

Das Ramps 1.5 ist ja Speziell für das MEGA 2560 das hat ja Port Ports bis 54.

Das Ramps 1.5 nutz aber über 60 Teilweise…
wie geht das ?
oder ist damit der Physikalische Port Gemeint und nicht Port…

weil wenn ich mir das Bild von Mega anschaue und dem PinOut des Ramps stimmt da doch was nicht…

oder denke ich gerade Falsch?

// For RAMPS 1.4
#define X_STEP_PIN         54
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38
#define X_MIN_PIN           3
#define X_MAX_PIN           2

#define Y_STEP_PIN         60
#define Y_DIR_PIN          61
#define Y_ENABLE_PIN       56
#define Y_MIN_PIN          14
#define Y_MAX_PIN          15

#define Z_STEP_PIN         46
#define Z_DIR_PIN          48
#define Z_ENABLE_PIN       62
#define Z_MIN_PIN          18
#define Z_MAX_PIN          19

#define E_STEP_PIN         26
#define E_DIR_PIN          28
#define E_ENABLE_PIN       24

#define SDPOWER            -1
#define SDSS               53
#define LED_PIN            13

#define FAN_PIN            9

#define PS_ON_PIN          12
#define KILL_PIN           -1

#define HEATER_0_PIN       10
#define HEATER_1_PIN       8
#define TEMP_0_PIN          13   // ANALOG NUMBERING
#define TEMP_1_PIN          14   // ANALOG NUMBERING

Ich würde an deiner Stelle den Aufbau und die Bauteile aus der Anleitung verwenden damit du nicht ewig lange nach Fehlern suchen musst. Die Teile kosten nicht die Welt. Dann hast du erstmal einen Erfolg und kommst voran.

Im nächsten Schritt kannst du dann überlegen deine Hardware zu verwenden oder nutzt sie für andere Dinge.

Ich weiß nicht wieso du einen Mega verwenden möchtest (späterer Erweiterungen?)

Ist keine Lösung für dein Problem aber evtl. eine Alternative um voran zu kommen. Gerade mit wenig Erfahrung mit Arduino kann man mit den diversen Pins und dessen Konfigurationen schnell durcheinander kommen.

Aber mehr oder weniger nutzt sie ja das selbe nur das sie externe Treiber hat und diese nicht auf das Board steckt…

Und ja es geht um Erweiterungen…
Da ja ein USB Shield verbaut ist und später auch ein Kompass und gyro sensor…

Und je nach dem wie genau das ganze ist kommen auch noch Entfernungs Lichtschranken verbaut die kontrollieren ob er noch auf der Bahn ist…

Viele viele Ideen ob alles realistisch ist weiß ich noch nicht🤣

Und wenn du den Aufbau modularisierst? Also die forwärtsbewegung (via Stepper) über ein Modul (wie in deiner Vorlage) realisieren, die Sensorik über ein anderes… Etc.
Ich hab meine Stepper Erfahrung nur mit nem raspi gemacht, da hat der raspi nur die Treiber angesteuert als zentrales Element.
Ich mein wenn da am Ende noch n robi ran kommt der muss ja auch angesteuert werden

Ich weiß nicht genau woher Du die Definitionen der Pins hast aber für mich sehen die falsch aus. Habe Dir hier mal eine Schematic angefügt aus denen die Pinbelegung eines Ramps 1.4 (Dein verwendetes Ramps 1.5 unterscheidet sich in der Pinbelegung anscheinend nicht zum Vorgänger. Quelle: Ramps 1.4 vs. 1.5 ) in Verbindung mit einem „Arduino Mega 2560“ klarer werden sollte.

Demnach sollte Deine Motordefinition in etwa so ausschauen:

// ----- motor definitions
#define STEPS_PER_MM 200*8/(58*PI)	//200steps/rev; 8 x microstepping; 58mm dia. wheels
#define NUDGE STEPS_PER_MM*5		//move pen 5mm (change number to suit)
#define STEP1 A0    	//X-STEP	//arduino ports
#define STEP2 A6	//Y-STEP
#define STEP3 D46	//Z-STEP
#define DIRECTION1 A1	//X-DIR
#define DIRECTION2 A7	//Y-DIR
#define DIRECTION3 D48	//Z-DIR

Auf der Schematic sind zwar A4988 Motortreiber aufgelistet aber Deine verwendeten DRV8825 sind ja quasi ein „drop in replacement“ mit identischer Pinbelegung soweit ich das vestanden habe, das sollte demnach also kein Problem sein.

Dabei liegen die Unterschiede des DRV8825 zum A4988 darin:

  • DRV8825 kann 1/32 Microstepping (A4988 kann 1/16)
  • Das Potentiometer zum Strom regulieren ist an einer anderen stelle.
  • Das Verhältnis zwischen der Referenz Spannung und dem Stromlimit ist anders. (Siehe Datasheet)
  • Der DRV8825 braucht einen minimalen Schrittimpulse von 1,9µs im gegensatz zum 1µs des A4988
  • Der DRV8825 kann eine höhere Spannung ab als der A4988 (45 Volt vs. 35 Volt)
  • Der DRV8825 kann ein bisschen mehr Strom ab als der A4988

______________________________________________________________

also die Pin Belegung habe ich von RAMPS 1.4 - RepRap

FSRZV61JWESUX3Q_PlotterV2.ino (43,9 KB)

kann ich so die Signal Zustände von step1 step2 und step3 im Serial Monitor anzeigen lassen??

(ist nur der Auszug der Prozedur)

ich will rausfinden ob auch wirklich gesteppt wird bevor ich mich um die Pins kümmere.


void step_motors()
{
  Serial.println(F("Step_Motors"));
  // ----- locals
  enum {dir3, step3, dir2, step2, dir1, step1};                   //define bit positions
  byte pattern = PORTB;                                           //read current state PORTB

  int LogStep1 ;
  int LogStep2 ;
  int LogStep3;
  int LogDIR1 = digitalRead(dir1);
  int LogDIR2 = digitalRead(dir2);
  int LogDIR3 = digitalRead(dir3);




  // Motor 1
  step1=LogStep1 ;
  Serial.println(F("Step Output 1 "));
  Serial.print(digitalRead(LogStep1));                               // Schreibe den Text in den Monitor
  Serial.println(F(" "));

 
  // Motor 2
  step2=LogStep2 ;
  Serial.println(F("Step Output 2 "));
  Serial.print(digitalRead(LogStep2));                               // Schreibe den Text in den Monitor
  Serial.println(F(" "));

  // Motor 3
  step3=LogStep3 ;
  Serial.println(F("Step Output 3 "));
  Serial.print( digitalRead(LogStep3));                               // Schreibe den Text in den Monitor
  Serial.println(F(" "));

  
  // ----- set motor directions
  /*
     Change CCW to CW if the robot moves in the wrong direction
  */
  (DIR1 == CCW) ? SET(pattern, dir1) : CLR(pattern, dir1);
  (DIR2 == CCW) ? SET(pattern, dir2) : CLR(pattern, dir2);
  (DIR3 == CCW) ? SET(pattern, dir3) : CLR(pattern, dir3);
  PORTB = pattern;
  delayMicroseconds(PULSE_WIDTH);                                 //wait for direction lines to stabilise

  // ----- create leading edge of step pulse(s)
  (ROTATE1 == true) ? SET(pattern, step1) : CLR(pattern, step1);
  SET(pattern, step2);
  SET(pattern, step3);
  PORTB = pattern;                                                //step the motors
  delayMicroseconds(PULSE_WIDTH);                               //mandatory delay

  // ----- create trailing-edge of step-pulse(s)
  pattern = CLR(pattern, step1);
  pattern = CLR(pattern, step2);
  pattern = CLR(pattern, step3);
  PORTB = pattern;



  // Motor 1
  
  Serial.println(F("Step Output 1 "));
  Serial.print(digitalRead(LogStep1));                               // Schreibe den Text in den Monitor
  Serial.println(F(" "));
  
  // Motor 2
 
  Serial.println(F("Step Output 2 "));
  Serial.print(digitalRead(LogStep2));                               // Schreibe den Text in den Monitor
  Serial.println(F(" "));
 
  // Motor 3
 
  Serial.println(F("Step Output 3 "));
  Serial.print(digitalRead(LogStep3));                               // Schreibe den Text in den Monitor
  Serial.println(F(" "));
 

  // ----- determines plotting speed
  delayMicroseconds(DELAY);


}

´´´

Mir kommt es so vor als wäre das Programm nur halb angepasst.

Oben werden die Pins gesetzt.

#define STEP1 13                      //arduino ports
#define STEP2 11
#define STEP3 9
#define DIRECTION1 12
#define DIRECTION2 10
#define DIRECTION3 8

Wenn man jetzt mal schaut, wo sich diese Werte wiederfinden, dann ist das nur innerhalb der setup()-Funktion. Für die eigentlichen Steps wird PORTB verwendet. Das wären am Arduino Mega 2560 die Pins 19 bis 26. Es macht also irgendwie keinen Sinn das so vorher zu definieren ohne die nicht auch hinterher so zu verwenden. Der Teil müsste dann also noch angepasst werden.

also wenn ich dich richtig verstehe und ich das Programm mit einem Ramps 1.5 nutzen wollen würde
müsste ich das Programm ändern oder nicht das Ramps nutzen sondern externe TreiberStufen.

Ich würd auch eher auf externe Treiber gehen, ist bei der Fehlersuche einfacher

Okay, das Problem liegt in der step_motors() Funktion. Denn die benutzt direkte Bitmanipulationen um die einzelnen Pins zu schalten. Da diese Funktion jedoch für den Arduino UNO* geschrieben wurde und Du einen Arduino Mega 2560 verwendest ist der Code an dieser Stelle nicht kompatibel. Das bedeutet in dem Code den er zum steppen des Motors geschrieben hat verwendet er den Portb des Arduino UNO das bedeutet er kann damit ganz leicht die Pins. 8, 9, 10, 11, 12, 13 auf einmal auf die jeweils richtigen LOW oder HIGH Werte setzen um den Motor einen Schritt weiter zu bewegen, dies ist so aber nicht mit den Digitalen Pins des Mega 2560 möglich da Du ja das Ramps verwendet möchtest und so an die Pins 46, 48, 54, 55, 60, 61 gebunden bist um die Schrittmotoren ansprechen zu können. Diese Pins sind jedoch über die Ports F und L verteilt. Du müsstest nun also die step_motors() Funktion dementsprechend umschreiben um die jeweiligen Bits an der richtigen Stelle in den Ports F und L zu setzen.

Seine genutzte Pinbelegung des Arduino UNOs: (Achtung, nur pseudocode)

#define STEP1 13|PortB5                   //arduino ports
#define STEP2 11|PortB3
#define STEP3 9|PortB1
#define DIRECTION1 12|PortB4
#define DIRECTION2 10|PortB2
#define DIRECTION3 8|PortB0

Deine Pinbelegung des Arduino Mega 2560: (Achtung, nur pseudocode)

#define STEP1 A0|D54|PortF0    		//X-STEP 	//arduino ports
#define STEP2 A6|D60|PortF6		//Y-STEP
#define STEP3 D46|PortL3		//Z-STEP
#define DIRECTION1 A1|D55|PortF1	//X-DIR
#define DIRECTION2 A7|D61|PortF7		//Y-DIR
#define DIRECTION3 D48|PortL1		//Z-DIR

Bitmanipulation des PortB die umgeschrieben werden muss:

void step_motors() {

  // ----- locals
  enum {dir3, step3, dir2, step2, dir1, step1};                   //define bit positions
  byte pattern = PORTB;                                           //read current state PORTB

  // ----- set motor directions
  /*
     Change CCW to CW if the robot moves in the wrong direction
     // ----- Bit set/clear/check/toggle macros
      #define SET(x,y) (x |=(1<<y))
      #define CLR(x,y) (x &= (~(1<<y)))
      #define CHK(x,y) (x & (1<<y))
      #define TOG(x,y) (x^=(1<<y))
  */
  (DIR1 == CCW) ? SET(pattern, dir1) : CLR(pattern, dir1); // (pattern |=(1<<dir1)) ->    (B01000000 (|= 1<<4))
  (DIR2 == CCW) ? SET(pattern, dir2) : CLR(pattern, dir2);
  (DIR3 == CCW) ? SET(pattern, dir3) : CLR(pattern, dir3);
  PORTB = pattern;
  delayMicroseconds(PULSE_WIDTH);                                 //wait for direction lines to stabilise

  // ----- create leading edge of step pulse(s)
  (ROTATE1 == true) ? SET(pattern, step1) : CLR(pattern, step1);
  SET(pattern, step2);
  SET(pattern, step3);
  PORTB = pattern;                                                //step the motors
  delayMicroseconds(PULSE_WIDTH);                               //mandatory delay

  // ----- create trailing-edge of step-pulse(s)
  pattern = CLR(pattern, step1);
  pattern = CLR(pattern, step2);
  pattern = CLR(pattern, step3);
  PORTB = pattern;

  // ----- determines plotting speed
  delayMicroseconds(DELAY);
}

Hier sieht man sehr schön das er alle Pins die er zum steppen der Motoren ansteuern muss über den PortB erreichen kann.

Referenz: Pinlayout des Arduino UNO

Referenz: Pinlayout des Arduino Mega 2560

Hier noch zwei Artikel wie Bitmanipulationen in C so funktionieren:

Jawohl wir Steppen…

Danke an die vielen Hilfen bis hier her…
Jetzt bin ich ein großes Stück weiter… :heart_eyes::heart_eyes::heart_eyes::heart_eyes:

1 Like

Wow @jedi klasse Antwort.

Und @Christoph sehr geil das es geklappt hat, trotzdem unterschiedlichem Aufbau des Projekts.

Wenn man sich live hätte treffen können, wäre es sicher leichter gewesen, aber dafür ist so ein Forum ja da :clap:t3: