Welcome! Log In Create A New Profile

Advanced

Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller

Posted by KontinuumReprap 
Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
August 03, 2012 06:25AM
Hi reprappers.

We are building the Kontinuum Reprap, which is basically a reeeeeally big 3d-printer, and it will have a rather heavy y-axis to move around.
We will run the printer off a RAMPS 1.4, and we are hoping to use the fifth motor output that this board has to run an extra stepper for the y-axis movement.
We have two beefy NEMA23 steppers and the idea is that if we run them on separate controllers with separate heat sinks and cooling we can push our machine harder and run it for longer without overheating.

So:
1 stepper for the x-axis ---------------------- (standard)
1 stepper for the extruder ------------------- (standard)
2 steppers on one controller for z --------- (standard)
2 steppers on separate controllers for y - (????)

We are hoping to do this inside the Marlin firmware, without having to pull any extra wiring across the Ramps board.
Does anyone have experience with this?
Is there a simple way to echo an output for one stepper controller to another one?

Thanks.

Jeppe
Kontinuum Prints
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
August 03, 2012 05:20PM
I can't test this here since I use RAMPS 1.2 which lacks the fifth stepper driver, but the basic idea is to go into stepper.cpp of marlin, and look for WRITE(Y_DIR_PIN, WRITE(Y_STEP_PIN, and WRITE(Y_ENABLE_PIN

After every occurrence, you need to add an equivalent command to the E1_DIR_PIN and E1_STEP_PIN. The second half of the command is the value to be written so copy it exactly.
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
August 04, 2012 06:36AM
All you want is to drive a second stepper driver for one axis, isn't it? Why not simply connect STEP, DIR, ENABLE and RESET signals of this axis to both drivers? ATmegas provide digital signals which should be able to service two inputs easily.

This way, both will receive the exact same number of steps at exact the same time, no firmware mess possible. As stepper motors never loose a step (hopefully), this should work for hours. Even if they whould loose steps, a firmware couldn't compensate for that anyways.


Generation 7 Electronics Teacup Firmware RepRap DIY
     
@Andrew
Thanks a lot.
I had a look inside the stepper.cpp file, and there are only two occurences of each command. It seems like exactly the kind of solution I was looking for - Almost too easy to be true, hehe. Is that really all that's needed ?
I will do some testing over the coming days and see what I get out of this.

@Traumflug
I think I see what you are saying.
We have stepstick drivers for our Ramps, and it turns out that the diagram at: [reprap.org] shows the STEP, DIR, ENABLE and RESET pins quite clearly.
What I don't understand is how I am supposed to connect them.
Would I just externally connect the pins on one driver to the pins on the other with wires to get the result I'm looking for ? ?
Hahaha, I guess you can see why I'm hoping to find a software solution . . .

Thanks a lot guys.
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
August 06, 2012 06:23AM
Quote

Would I just externally connect the pins on one driver to the pins on the other with wires to get the result I'm looking for ? ?

Exactly. If you use this fifth driver on the RAMPS, you have to cut the original traces, of course.


Generation 7 Electronics Teacup Firmware RepRap DIY
     
Ok, I have to admit I'm kinda lost here.
I still don't have the Ramps hooked up, so it's all theory for now, but I would like to inform myself a little more before I start experimenting with stepper motors.

Question:
How much of the section containing the " WRITE(Y_DIR_PIN" etc do I have to copy with the "E1_DIR_PIN" adaptations?
And where do I put the repeated section?


Here is the section from the stepper.cpp file, with the two ocurrences of "WRITE(Y_DIR_PIN" etc


if ((out_bits & (1< -1
bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING);
if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
step_events_completed = current_block->step_event_count;
}
old_y_min_endstop = y_min_endstop;
#endif
}
}
else { // +direction
WRITE(Y_DIR_PIN,!INVERT_Y_DIR);
count_direction[Y_AXIS]=1;
CHECK_ENDSTOPS
{
#if Y_MAX_PIN > -1
bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING);
if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
step_events_completed = current_block->step_event_count;
}
old_y_max_endstop = y_max_endstop;
#endif
}
}



As far as I can tell with my very limited knowhow it wouldn't make sense to copy the whole section, just the write command.

So maybe just the part that says:
WRITE(Y_DIR_PIN,INVERT_Y_DIR);
count_direction[Y_AXIS]=-1;
CHECK_ENDSTOPS

Which would then become:
WRITE(E1_DIR_PIN,INVERT_Y_DIR);
count_direction[Y_AXIS]=-1;
CHECK_ENDSTOPS

But then again, why would I want to check the endstops twice...?
Hmmmm . . ? ?

And where do I insert it then, right after the original before the curly brace, or after the whole section?

Edited 1 time(s). Last edit at 08/07/2012 03:52PM by KontinuumReprap.
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
August 08, 2012 04:08AM
> But then again, why would I want to check the
> endstops twice...?

You don't: just replace WRITE(Y_DIR_PIN,...); with WRITE(Y_DIR_PIN,...);WRITE(E1_DIR_PIN,...); , and the same for Y_STEP_PIN and Y_ENABLE_PIN.
@ rebecca.
Cool! Thanks a lot.

When we get everything connected I'll let you all know how it went
Hi all,

sorry that I add a reprap for dummies comment here

could we achiev the same by changing the pins.h
FROM

#if MOTHERBOARD == 33 || MOTHERBOARD == 34

#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define X_MIN_PIN -1 //3
#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable.

#define Y_STEP_PIN 60
#define Y_DIR_PIN 61
#define Y_ENABLE_PIN 56
#define Y_MIN_PIN -1 //14
#define Y_MAX_PIN -1 //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 -1 //19


TO THIS (CHANGED THE Z PINS TO Y PINS- JUST THE LETTER)

#if MOTHERBOARD == 33 || MOTHERBOARD == 34

#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define X_MIN_PIN -1 //3
#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable.

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

#define Y_STEP_PIN 46 <<<<<<
#define Y_DIR_PIN 48 <<<<<<<
#define Y_ENABLE_PIN 62 <<<<<<<
#define Y_MIN_PIN 18 <<<<<<<
#define Y_MAX_PIN -1 //19 <<<<<<<

I assumed that the pins correspond with the connectors on the board


thx

apologies if I add to the (my winking smiley) confusion


Carel
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
September 04, 2012 09:22AM
No it would just use the second definition. You have to find all the places in the code that use the Y pin definitions and duplicate those lines. I.e. whenever it writes to one port it will need to write to two ports with two write statements. See Rebecca's example above.


[www.hydraraptor.blogspot.com]
Hi Nophead

thx for the clear reply, but I am somewhat puzzled by the proposed alternative.

The question is to have 2 Y axis motors why do you change the Y to E? this would just move the driver from Y to E, not duplicate it


Hi Rebecca

can you please give a bit more explanation on how to do this exactly


thx


Carel
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
September 06, 2012 04:11AM
You don't change the Y to E, you add E1 (in a second write) next to Y. (E1 because that's what pins.h calls the spare socket; you could rename it there to Y2 or something if you prefer, but not to just Y as you can't have two with the same name.)
Hi Rebecca

thx for your help here
thsi applies then to stepper cpp and pins.h- right?


if ((out_bits & (1< -1
bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING);
if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
step_events_completed = current_block->step_event_count;
}
old_y_min_endstop = y_min_endstop;
#endif
}
}
else { // +direction
WRITE(Y_DIR_PIN,!INVERT_Y_DIR);WRITE(E1_DIR_PIN,INVERT_E1_DIR);
count_direction[Y_AXIS]=1;
CHECK_ENDSTOPS
{
#if Y_MAX_PIN > -1
bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING);
if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
step_events_completed = current_block->step_event_count;
}
old_y_max_endstop = y_max_endstop;
#endif
}
}


compiling is error free


and pins.h would become:

#define Y_STEP_PIN;E1_STEP_PIN 60
#define Y_DIR_PIN 61
#define Y_ENABLE_PIN;E1_ENABLE_PIN 56
#define Y_MIN_PIN -1 //14
#define Y_MAX_PIN -1 //15

Question- the pin nrs do they correlate with physical pins on the RAMPS?

upon compiling i get this error message:
In file included from cardreader.cpp:1:
Marlin.h:116:5: error: token ";" is not valid in preprocessor expressions


what am I doing wrong here?


thx for helping out

br

carel
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
September 07, 2012 04:51AM
> WRITE(Y_DIR_PIN,!INVERT_Y_DIR);WRITE(E1_DIR_PIN,INVERT_E1_DIR);
Missing ! (negation, i.e. - direction): if the Y has one, the E1 needs to as well.

Also, these two aren't the only places where Y_STEP_PIN, Y_DIR_PIN or Y_ENABLE_PIN is used: don't forget to do the others.

> and pins.h would become:
No: leave pins.h unchanged. (This is where the compile error came from.)

> Question- the pin nrs do they correlate with
> physical pins on the RAMPS?
Yes.
Hi Rebecca,


thx for your quick reply, I got stuck with some homing/end stop problems- solved
I saw a similar piece of code in the marlin.h sketch, will start loooking in more detail



br

careland
Hi Rebecca & Nophead

Just to let you know the status

I am now running with 2 y axis motors and 2 drivers

I changed a pololu to have 3 pins upside down soldered in the print and placed in z axis driver location
These are the signal/ enable pins made a connection jumping from the y driver signals to the one in the z axis pololu (my app is a plotter so no z axis motor)

In this way i kept the power, step jumpers etc in use

The boys ar Reprapworld.com where most helpfull with testing and assembly!!

Its quick and dirty but works

Br

Carel
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
October 01, 2012 06:24AM
Quote

I changed a pololu to have 3 pins upside down

Excellent idea!


Generation 7 Electronics Teacup Firmware RepRap DIY
     
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
September 19, 2013 12:44PM
Hello,

I've made the changes suggested and compile and upload without any errors, but the E1 motor still does not echo the Y movement.

I pasted my stepper.cpp below.

Thanks in advance! Chris

/*
stepper.c - stepper motor driver: executes motion plans using stepper motors
Part of Grbl

Copyright (c) 2009-2011 Simen Svale Skogsrud

Grbl 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.

Grbl 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
along with Grbl. If not, see [www.gnu.org].
*/

/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith
and Philipp Tiefenbacher. */

#include "Marlin.h"
#include "stepper.h"
#include "planner.h"
#include "temperature.h"
#include "ultralcd.h"
#include "language.h"
#include "cardreader.h"
#include "speed_lookuptable.h"
#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
#include
#endif


//===========================================================================
//=============================public variables ============================
//===========================================================================
block_t *current_block; // A pointer to the block currently being traced


//===========================================================================
//=============================private variables ============================
//===========================================================================
//static makes it inpossible to be called from outside of this file by extern.!

// Variables used by The Stepper Driver Interrupt
static unsigned char out_bits; // The next stepping-bits to be output
static long counter_x, // Counter variables for the bresenham line tracer
counter_y,
counter_z,
counter_e;
volatile static unsigned long step_events_completed; // The number of step events executed in the current block
#ifdef ADVANCE
static long advance_rate, advance, final_advance = 0;
static long old_advance = 0;
static long e_steps[3];
#endif
static long acceleration_time, deceleration_time;
//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate;
static unsigned short acc_step_rate; // needed for deccelaration start point
static char step_loops;
static unsigned short OCR1A_nominal;
static unsigned short step_loops_nominal;

volatile long endstops_trigsteps[3]={0,0,0};
volatile long endstops_stepsTotal,endstops_stepsDone;
static volatile bool endstop_x_hit=false;
static volatile bool endstop_y_hit=false;
static volatile bool endstop_z_hit=false;
#ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
bool abort_on_endstop_hit = false;
#endif

static bool old_x_min_endstop=false;
static bool old_x_max_endstop=false;
static bool old_y_min_endstop=false;
static bool old_y_max_endstop=false;
static bool old_z_min_endstop=false;
static bool old_z_max_endstop=false;

static bool check_endstops = true;

volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0};
volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};

//===========================================================================
//=============================functions ============================
//===========================================================================

#define CHECK_ENDSTOPS if(check_endstops)

// intRes = intIn1 * intIn2 >> 16
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 24 bit result
#define MultiU16X8toH16(intRes, charIn1, intIn2) \
asm volatile ( \
"clr r26 \n\t" \
"mul %A1, %B2 \n\t" \
"movw %A0, r0 \n\t" \
"mul %A1, %A2 \n\t" \
"add %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"lsr r0 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"clr r1 \n\t" \
: \
"=&r" (intRes) \
: \
"d" (charIn1), \
"d" (intIn2) \
: \
"r26" \
)

// intRes = longIn1 * longIn2 >> 24
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 48bit result
#define MultiU24X24toH16(intRes, longIn1, longIn2) \
asm volatile ( \
"clr r26 \n\t" \
"mul %A1, %B2 \n\t" \
"mov r27, r1 \n\t" \
"mul %B1, %C2 \n\t" \
"movw %A0, r0 \n\t" \
"mul %C1, %C2 \n\t" \
"add %B0, r0 \n\t" \
"mul %C1, %B2 \n\t" \
"add %A0, r0 \n\t" \
"adc %B0, r1 \n\t" \
"mul %A1, %C2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %B1, %B2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %C1, %A2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %B1, %A2 \n\t" \
"add r27, r1 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"lsr r27 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"clr r1 \n\t" \
: \
"=&r" (intRes) \
: \
"d" (longIn1), \
"d" (longIn2) \
: \
"r26" , "r27" \
)

// Some useful constants

#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<
//
// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
// first block->accelerate_until step_events_completed, then keeps going at constant speed until
// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
// The slope of acceleration is calculated with the leib ramp alghorithm.

void st_wake_up() {
// TCNT1 = 0;
ENABLE_STEPPER_DRIVER_INTERRUPT();
}

void step_wait(){
for(int8_t i=0; i < 6; i++){
}
}


FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
unsigned short timer;
if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;

if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times
step_rate = (step_rate >> 2)&0x3fff;
step_loops = 4;
}
else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times
step_rate = (step_rate >> 1)&0x7fff;
step_loops = 2;
}
else {
step_loops = 1;
}

if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000);
step_rate -= (F_CPU/500000); // Correct for minimal speed
if(step_rate >= (8*256)){ // higher step rate
unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
unsigned char tmp_step_rate = (step_rate & 0x00ff);
unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);
MultiU16X8toH16(timer, tmp_step_rate, gain);
timer = (unsigned short)pgm_read_word_near(table_address) - timer;
}
else { // lower step rates
unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0];
table_address += ((step_rate)>>1) & 0xfffc;
timer = (unsigned short)pgm_read_word_near(table_address);
timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3);
}
if(timer < 100) { timer = 100; MYSERIAL.print(MSG_STEPPER_TOO_HIGH); MYSERIAL.println(step_rate); }//(20kHz this should never happen)
return timer;
}

// Initializes the trapezoid generator from the current block. Called whenever a new
// block begins.
FORCE_INLINE void trapezoid_generator_reset() {
#ifdef ADVANCE
advance = current_block->initial_advance;
final_advance = current_block->final_advance;
// Do E steps + advance steps
e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
old_advance = advance >>8;
#endif
deceleration_time = 0;
// step_rate to timer interval
OCR1A_nominal = calc_timer(current_block->nominal_rate);
// make a note of the number of step loops required at nominal speed
step_loops_nominal = step_loops;
acc_step_rate = current_block->initial_rate;
acceleration_time = calc_timer(acc_step_rate);
OCR1A = acceleration_time;

// SERIAL_ECHO_START;
// SERIAL_ECHOPGM("advance :");
// SERIAL_ECHO(current_block->advance/256.0);
// SERIAL_ECHOPGM("advance rate :");
// SERIAL_ECHO(current_block->advance_rate/256.0);
// SERIAL_ECHOPGM("initial advance :");
// SERIAL_ECHO(current_block->initial_advance/256.0);
// SERIAL_ECHOPGM("final advance :");
// SERIAL_ECHOLN(current_block->final_advance/256.0);

}

// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
ISR(TIMER1_COMPA_vect)
{
// If there is no current block, attempt to pop one from the buffer
if (current_block == NULL) {
// Anything in the buffer?
current_block = plan_get_current_block();
if (current_block != NULL) {
current_block->busy = true;
trapezoid_generator_reset();
counter_x = -(current_block->step_event_count >> 1);
counter_y = counter_x;
counter_z = counter_x;
counter_e = counter_x;
step_events_completed = 0;

#ifdef Z_LATE_ENABLE
if(current_block->steps_z > 0) {
enable_z();
OCR1A = 2000; //1ms wait
return;
}
#endif

// #ifdef ADVANCE
// e_steps[current_block->active_extruder] = 0;
// #endif
}
else {
OCR1A=2000; // 1kHz.
}
}

if (current_block != NULL) {
// Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt
out_bits = current_block->direction_bits;


// Set the direction bits (X_AXIS=A_AXIS and Y_AXIS=B_AXIS for COREXY)
if((out_bits & (1<active_extruder != 0)
WRITE(X2_DIR_PIN, INVERT_X_DIR);
else
WRITE(X_DIR_PIN, INVERT_X_DIR);
}
#else
WRITE(X_DIR_PIN, INVERT_X_DIR);
#endif
count_direction[X_AXIS]=-1;
}
else{
#ifdef DUAL_X_CARRIAGE
if (extruder_duplication_enabled){
WRITE(X_DIR_PIN, !INVERT_X_DIR);
WRITE(X2_DIR_PIN, !INVERT_X_DIR);
}
else{
if (current_block->active_extruder != 0)
WRITE(X2_DIR_PIN, !INVERT_X_DIR);
else
WRITE(X_DIR_PIN, !INVERT_X_DIR);
}
#else
WRITE(X_DIR_PIN, !INVERT_X_DIR);
#endif
count_direction[X_AXIS]=1;
}
if((out_bits & (1<active_extruder == 0 && X_HOME_DIR == -1)
|| (current_block->active_extruder != 0 && X2_HOME_DIR == -1))
#endif
{
#if defined(X_MIN_PIN) && X_MIN_PIN > -1
bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING);
if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) {
endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
endstop_x_hit=true;
step_events_completed = current_block->step_event_count;
}
old_x_min_endstop = x_min_endstop;
#endif
}
}
}
else { // +direction
CHECK_ENDSTOPS
{
#ifdef DUAL_X_CARRIAGE
// with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
if ((current_block->active_extruder == 0 && X_HOME_DIR == 1)
|| (current_block->active_extruder != 0 && X2_HOME_DIR == 1))
#endif
{
#if defined(X_MAX_PIN) && X_MAX_PIN > -1
bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING);
if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){
endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
endstop_x_hit=true;
step_events_completed = current_block->step_event_count;
}
old_x_max_endstop = x_max_endstop;
#endif
}
}
}

#ifndef COREXY
if ((out_bits & (1< -1
bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING);
if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) {
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
step_events_completed = current_block->step_event_count;
}
old_y_min_endstop = y_min_endstop;
#endif
}
}
else { // +direction
CHECK_ENDSTOPS
{
#if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING);
if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
step_events_completed = current_block->step_event_count;
}
old_y_max_endstop = y_max_endstop;
#endif
}
}

if ((out_bits & (1< -1
bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) {
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
step_events_completed = current_block->step_event_count;
}
old_z_min_endstop = z_min_endstop;
#endif
}
}
else { // +direction
WRITE(Z_DIR_PIN,!INVERT_Z_DIR);

#ifdef Z_DUAL_STEPPER_DRIVERS
WRITE(Z2_DIR_PIN,!INVERT_Z_DIR);
#endif

count_direction[Z_AXIS]=1;
CHECK_ENDSTOPS
{
#if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) {
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
step_events_completed = current_block->step_event_count;
}
old_z_max_endstop = z_max_endstop;
#endif
}
}

#ifndef ADVANCE
if ((out_bits & (1<steps_e;
if (counter_e > 0) {
counter_e -= current_block->step_event_count;
if ((out_bits & (1<active_extruder]--;
}
else {
e_steps[current_block->active_extruder]++;
}
}
#endif //ADVANCE

counter_x += current_block->steps_x;
if (counter_x > 0) {
#ifdef DUAL_X_CARRIAGE
if (extruder_duplication_enabled){
WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
}
else {
if (current_block->active_extruder != 0)
WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN);
else
WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
}
#else
WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
#endif
counter_x -= current_block->step_event_count;
count_position[X_AXIS]+=count_direction[X_AXIS];
#ifdef DUAL_X_CARRIAGE
if (extruder_duplication_enabled){
WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
}
else {
if (current_block->active_extruder != 0)
WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN);
else
WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
}
#else
WRITE(X_STEP_PIN, INVERT_X_STEP_PIN);
#endif
}

counter_y += current_block->steps_y;
if (counter_y > 0) {
WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN);WRITE(E1_STEP_PIN, !INVERT_Y_STEP_PIN);
counter_y -= current_block->step_event_count;
count_position[Y_AXIS]+=count_direction[Y_AXIS];
WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN);WRITE(E1_STEP_PIN, INVERT_Y_STEP_PIN);
}

counter_z += current_block->steps_z;
if (counter_z > 0) {
WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN);

#ifdef Z_DUAL_STEPPER_DRIVERS
WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN);
#endif

counter_z -= current_block->step_event_count;
count_position[Z_AXIS]+=count_direction[Z_AXIS];
WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN);

#ifdef Z_DUAL_STEPPER_DRIVERS
WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN);
#endif
}

#ifndef ADVANCE
counter_e += current_block->steps_e;
if (counter_e > 0) {
WRITE_E_STEP(!INVERT_E_STEP_PIN);
counter_e -= current_block->step_event_count;
count_position[E_AXIS]+=count_direction[E_AXIS];
WRITE_E_STEP(INVERT_E_STEP_PIN);
}
#endif //!ADVANCE
step_events_completed += 1;
if(step_events_completed >= current_block->step_event_count) break;
}
// Calculare new timer value
unsigned short timer;
unsigned short step_rate;
if (step_events_completed <= (unsigned long int)current_block->accelerate_until) {

MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
acc_step_rate += current_block->initial_rate;

// upper limit
if(acc_step_rate > current_block->nominal_rate)
acc_step_rate = current_block->nominal_rate;

// step_rate to timer interval
timer = calc_timer(acc_step_rate);
OCR1A = timer;
acceleration_time += timer;
#ifdef ADVANCE
for(int8_t i=0; i < step_loops; i++) {
advance += advance_rate;
}
//if(advance > current_block->advance) advance = current_block->advance;
// Do E steps + advance steps
e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
old_advance = advance >>8;

#endif
}
else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);

if(step_rate > acc_step_rate) { // Check step_rate stays positive
step_rate = current_block->final_rate;
}
else {
step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point.
}

// lower limit
if(step_rate < current_block->final_rate)
step_rate = current_block->final_rate;

// step_rate to timer interval
timer = calc_timer(step_rate);
OCR1A = timer;
deceleration_time += timer;
#ifdef ADVANCE
for(int8_t i=0; i < step_loops; i++) {
advance -= advance_rate;
}
if(advance < final_advance) advance = final_advance;
// Do E steps + advance steps
e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
old_advance = advance >>8;
#endif //ADVANCE
}
else {
OCR1A = OCR1A_nominal;
// ensure we're running at the correct step rate, even if we just came off an acceleration
step_loops = step_loops_nominal;
}

// If current block is finished, reset pointer
if (step_events_completed >= current_block->step_event_count) {
current_block = NULL;
plan_discard_current_block();
}
}
}

#ifdef ADVANCE
unsigned char old_OCR0A;
// Timer interrupt for E. e_steps is set in the main routine;
// Timer 0 is shared with millies
ISR(TIMER0_COMPA_vect)
{
old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz)
OCR0A = old_OCR0A;
// Set E direction (Depends on E direction + advance)
for(unsigned char i=0; i<4;i++) {
if (e_steps[0] != 0) {
WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN);
if (e_steps[0] < 0) {
WRITE(E0_DIR_PIN, INVERT_E0_DIR);
e_steps[0]++;
WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
}
else if (e_steps[0] > 0) {
WRITE(E0_DIR_PIN, !INVERT_E0_DIR);
e_steps[0]--;
WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
}
}
#if EXTRUDERS > 1
if (e_steps[1] != 0) {
WRITE(E1_STEP_PIN, INVERT_E_STEP_PIN);
if (e_steps[1] < 0) {
WRITE(E1_DIR_PIN, INVERT_E1_DIR);
e_steps[1]++;
WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
}
else if (e_steps[1] > 0) {
WRITE(E1_DIR_PIN, !INVERT_E1_DIR);
e_steps[1]--;
WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
}
}
#endif
#if EXTRUDERS > 2
if (e_steps[2] != 0) {
WRITE(E2_STEP_PIN, INVERT_E_STEP_PIN);
if (e_steps[2] < 0) {
WRITE(E2_DIR_PIN, INVERT_E2_DIR);
e_steps[2]++;
WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
}
else if (e_steps[2] > 0) {
WRITE(E2_DIR_PIN, !INVERT_E2_DIR);
e_steps[2]--;
WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
}
}
#endif
}
}
#endif // ADVANCE

void st_init()
{
digipot_init(); //Initialize Digipot Motor Current
microstep_init(); //Initialize Microstepping Pins

//Initialize Dir Pins
#if defined(X_DIR_PIN) && X_DIR_PIN > -1
SET_OUTPUT(X_DIR_PIN);
#endif
#if defined(X2_DIR_PIN) && X2_DIR_PIN > -1
SET_OUTPUT(X2_DIR_PIN);
#endif
#if defined(Y_DIR_PIN) && Y_DIR_PIN > -1
SET_OUTPUT(Y_DIR_PIN);
#endif
#if defined(Z_DIR_PIN) && Z_DIR_PIN > -1
SET_OUTPUT(Z_DIR_PIN);

#if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_DIR_PIN) && (Z2_DIR_PIN > -1)
SET_OUTPUT(Z2_DIR_PIN);
#endif
#endif
#if defined(E0_DIR_PIN) && E0_DIR_PIN > -1
SET_OUTPUT(E0_DIR_PIN);
#endif
#if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1)
SET_OUTPUT(E1_DIR_PIN);
#endif
#if defined(E2_DIR_PIN) && (E2_DIR_PIN > -1)
SET_OUTPUT(E2_DIR_PIN);
#endif

//Initialize Enable Pins - steppers default to disabled.

#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
SET_OUTPUT(X_ENABLE_PIN);
if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
#endif
#if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1
SET_OUTPUT(X2_ENABLE_PIN);
if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH);
#endif
#if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
SET_OUTPUT(Y_ENABLE_PIN);
if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
#endif
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
SET_OUTPUT(Z_ENABLE_PIN);
if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);

#if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_ENABLE_PIN) && (Z2_ENABLE_PIN > -1)
SET_OUTPUT(Z2_ENABLE_PIN);
if(!Z_ENABLE_ON) WRITE(Z2_ENABLE_PIN,HIGH);
#endif
#endif
#if defined(E0_ENABLE_PIN) && (E0_ENABLE_PIN > -1)
SET_OUTPUT(E0_ENABLE_PIN);
if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH);
#endif
#if defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1)
SET_OUTPUT(E1_ENABLE_PIN);
if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH);
#endif
#if defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1)
SET_OUTPUT(E2_ENABLE_PIN);
if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH);
#endif

//endstops and pullups

#if defined(X_MIN_PIN) && X_MIN_PIN > -1
SET_INPUT(X_MIN_PIN);
#ifdef ENDSTOPPULLUP_XMIN
WRITE(X_MIN_PIN,HIGH);
#endif
#endif

#if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
SET_INPUT(Y_MIN_PIN);
#ifdef ENDSTOPPULLUP_YMIN
WRITE(Y_MIN_PIN,HIGH);
#endif
#endif

#if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
SET_INPUT(Z_MIN_PIN);
#ifdef ENDSTOPPULLUP_ZMIN
WRITE(Z_MIN_PIN,HIGH);
#endif
#endif

#if defined(X_MAX_PIN) && X_MAX_PIN > -1
SET_INPUT(X_MAX_PIN);
#ifdef ENDSTOPPULLUP_XMAX
WRITE(X_MAX_PIN,HIGH);
#endif
#endif

#if defined(Y_MAX_PIN) && Y_MAX_PIN > -1
SET_INPUT(Y_MAX_PIN);
#ifdef ENDSTOPPULLUP_YMAX
WRITE(Y_MAX_PIN,HIGH);
#endif
#endif

#if defined(Z_MAX_PIN) && Z_MAX_PIN > -1
SET_INPUT(Z_MAX_PIN);
#ifdef ENDSTOPPULLUP_ZMAX
WRITE(Z_MAX_PIN,HIGH);
#endif
#endif


//Initialize Step Pins
#if defined(X_STEP_PIN) && (X_STEP_PIN > -1)
SET_OUTPUT(X_STEP_PIN);
WRITE(X_STEP_PIN,INVERT_X_STEP_PIN);
disable_x();
#endif
#if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1)
SET_OUTPUT(X2_STEP_PIN);
WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN);
disable_x();
#endif
#if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1)
SET_OUTPUT(Y_STEP_PIN);
WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN);WRITE(E1_STEP_PIN,INVERT_Y_STEP_PIN);
disable_y();
#endif
#if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1)
SET_OUTPUT(Z_STEP_PIN);
WRITE(Z_STEP_PIN,INVERT_Z_STEP_PIN);
#if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_STEP_PIN) && (Z2_STEP_PIN > -1)
SET_OUTPUT(Z2_STEP_PIN);
WRITE(Z2_STEP_PIN,INVERT_Z_STEP_PIN);
#endif
disable_z();
#endif
#if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1)
SET_OUTPUT(E0_STEP_PIN);
WRITE(E0_STEP_PIN,INVERT_E_STEP_PIN);
disable_e0();
#endif
#if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1)
SET_OUTPUT(E1_STEP_PIN);
WRITE(E1_STEP_PIN,INVERT_E_STEP_PIN);
disable_e1();
#endif
#if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1)
SET_OUTPUT(E2_STEP_PIN);
WRITE(E2_STEP_PIN,INVERT_E_STEP_PIN);
disable_e2();
#endif

// waveform generation = 0100 = CTC
TCCR1B &= ~(1< -1
digitalWrite(DIGIPOTSS_PIN,LOW); // take the SS pin low to select the chip
SPI.transfer(address); // send in the address and value via SPI:
SPI.transfer(value);
digitalWrite(DIGIPOTSS_PIN,HIGH); // take the SS pin high to de-select the chip:
//delay(10);
#endif
}

void digipot_init() //Initialize Digipot Motor Current
{
#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT;

SPI.begin();
pinMode(DIGIPOTSS_PIN, OUTPUT);
for(int i=0;i<=4;i++)
//digitalPotWrite(digipot_ch, digipot_motor_current);
digipot_current(i,digipot_motor_current);
#endif
}

void digipot_current(uint8_t driver, int current)
{
#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
const uint8_t digipot_ch[] = DIGIPOT_CHANNELS;
digitalPotWrite(digipot_ch[driver], current);
#endif
}

void microstep_init()
{
#if defined(X_MS1_PIN) && X_MS1_PIN > -1
const uint8_t microstep_modes[] = MICROSTEP_MODES;
pinMode(X_MS2_PIN,OUTPUT);
pinMode(Y_MS2_PIN,OUTPUT);
pinMode(Z_MS2_PIN,OUTPUT);
pinMode(E0_MS2_PIN,OUTPUT);
pinMode(E1_MS2_PIN,OUTPUT);
for(int i=0;i<=4;i++) microstep_mode(i,microstep_modes);
#endif
}

void microstep_ms(uint8_t driver, int8_t ms1, int8_t ms2)
{
if(ms1 > -1) switch(driver)
{
case 0: digitalWrite( X_MS1_PIN,ms1); break;
case 1: digitalWrite( Y_MS1_PIN,ms1); break;
case 2: digitalWrite( Z_MS1_PIN,ms1); break;
case 3: digitalWrite(E0_MS1_PIN,ms1); break;
case 4: digitalWrite(E1_MS1_PIN,ms1); break;
}
if(ms2 > -1) switch(driver)
{
case 0: digitalWrite( X_MS2_PIN,ms2); break;
case 1: digitalWrite( Y_MS2_PIN,ms2); break;
case 2: digitalWrite( Z_MS2_PIN,ms2); break;
case 3: digitalWrite(E0_MS2_PIN,ms2); break;
case 4: digitalWrite(E1_MS2_PIN,ms2); break;
}
}

void microstep_mode(uint8_t driver, uint8_t stepping_mode)
{
switch(stepping_mode)
{
case 1: microstep_ms(driver,MICROSTEP1); break;
case 2: microstep_ms(driver,MICROSTEP2); break;
case 4: microstep_ms(driver,MICROSTEP4); break;
case 8: microstep_ms(driver,MICROSTEP8); break;
case 16: microstep_ms(driver,MICROSTEP16); break;
}
}

void microstep_readings()
{
SERIAL_PROTOCOLPGM("MS1,MS2 Pins\n");
SERIAL_PROTOCOLPGM("X: ");
SERIAL_PROTOCOL( digitalRead(X_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(X_MS2_PIN));
SERIAL_PROTOCOLPGM("Y: ");
SERIAL_PROTOCOL( digitalRead(Y_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(Y_MS2_PIN));
SERIAL_PROTOCOLPGM("Z: ");
SERIAL_PROTOCOL( digitalRead(Z_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(Z_MS2_PIN));
SERIAL_PROTOCOLPGM("E0: ");
SERIAL_PROTOCOL( digitalRead(E0_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(E0_MS2_PIN));
SERIAL_PROTOCOLPGM("E1: ");
SERIAL_PROTOCOL( digitalRead(E1_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(E1_MS2_PIN));
}
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
September 20, 2013 05:13AM
Did you do enable_y() , disable_y() in Marlin.h? Also check that EXTRUDERS is set to 1, to stop the normal 2-extruder code trying to use E1.
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
September 22, 2013 12:04AM
I changed the enable_y() , disable_y() from -1 to 1. Also, checked the extruder.

No change sad smiley
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
November 17, 2013 09:45PM
Quote
cts519chris
I changed the enable_y() , disable_y() from -1 to 1. Also, checked the extruder.

No change sad smiley

Have you made any further progress on this? I'm working on the same issue, needing to recode for two y steppers and have been unable to get it to work... Any help is appreciated
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
January 04, 2014 04:15PM
Repetier Firmware now has the ability to echo motors using unused extruders drivers.

Rebecca.Palmer - I asked if there was a way to do this a while back and didn't get a response. I'd appreciate some help if Marlin can do this too.

Thanks, Chris
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
January 06, 2014 04:12PM
I am also in a similar situation to this.

I have enabled the dual Y steppers and changed all instances of Y2 to E0 (Im not using an extruder).

This has worked, however the Y motor that is connected to E0 will only move 1 way.
Re: Marlin on ramps 1.4 - Echo Y stepper output on the extra stepper controller
April 18, 2015 01:29AM
Okay I got it 90% figured out. It was so simple I feel like a moron. I redefined the E1 pins as Y2. The problem is the motor doesn't move, it stutters. I'm sure this is another stupid thing that I messed up. Anybody have this issue before? It's not inherent to the motor, because it does it with known good motors.
Sorry, only registered users may post in this forum.

Click here to login