k3ng / k3ng_rotator_controller

K3NG Arduino Amateur Radio Rotator Controller
http://blog.radioartisan.com/yaesu-rotator-computer-serial-interface/
GNU General Public License v3.0
174 stars 125 forks source link

Feature Request: Support AdaFruit Motorshield v2.3 w/ NEMA 17 Steppers #77

Open Lutraphobia opened 4 years ago

Lutraphobia commented 4 years ago

I am collaborating with K6VUG on an Arduino (Uno/Mega) build with the Adafruit MotorShield (my ver 2.3) driving two Nema 17 HS4401S.

His Sketch works great. Since it's a bare bones solution I'd like to eventually add ability to use a display and LM303 Magnetometer, etc.

However, after coming across this project, he was ok with me reaching out to see if a port of his code was possible. It would be great to assist others with this setup since there are so many more features.

Here is Umesh's (K6VUG) working code for the steppers and shield with EasyComm commands. How would I incorporate this into K3NG? I've tried but it will probably take me months to integrate with my limited abilities.

All credits go to UMESH/K6VUG and a huge thanks to him for helping me get up and running with his code.

Thanks! -Walt / WA7ZYW

// Includes for Adafruit Motor Shield V2 and stepper motors

include

include

include

include "utility/Adafruit_MS_PWMServoDriver.h"

// Constants for Adafruit Motor Shield V2 and stepper motors

define SPEED_DEFAULT 1000.0

define ACCEL_DEFAULT 1000.0

define STEP_TYPE SINGLE // can be changed to DOUBLE or INTERLEAVE or MICROSTEP

define STEPS_360 200 // as specified in stepper specifications

define CCW_MOTOR_AZ false // set this to true if clockwise command moves rotor anti-clockwise

define CCW_MOTOR_EL false // set this to true if clockwise command moves rotor anti-clockwise

// ---------------------------- AdaFruit Shield Initialisation ----------------------------

////Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree) to the top shield Adafruit_StepperMotor myStepper1 = AFMStop.getStepper(STEPS_360, 1); Adafruit_StepperMotor myStepper2 = AFMStop.getStepper(STEPS_360, 2);

// create wrappers for the motors! void forwardstep1() { myStepper1->onestep(FORWARD, STEP_TYPE); }

void backwardstep1() { myStepper1->onestep(BACKWARD, STEP_TYPE); }

void forwardstep2() { myStepper2->onestep(FORWARD, STEP_TYPE); }

void backwardstep2() { myStepper2->onestep(BACKWARD, STEP_TYPE); }

// create AccelStepper objects AccelStepper stepper1(forwardstep1, backwardstep1); AccelStepper stepper2(forwardstep2, backwardstep2);

// ----------------------------------------------------------------------------------------

void setupSteppers() { // initialize motor shield initMotorShield(); // initialize motors initMotors(); // initialize current position based on stepper data curAz = stepper1.currentPosition() 360 / STEPS_360; curEl = stepper2.currentPosition() 360 / STEPS_360; }

void loopSteppers() { // move the motors one step towards target position //if ((!stepper1.isRunning()) && (stepper1.distanceToGo() != 0)) { if ((stepper1.distanceToGo() != 0)) { stepper1.run(); //Serial.print(stepper1.distanceToGo()); //Serial.print(","); curAz = stepper1.currentPosition() 360 / STEPS_360; } //if ((!stepper2.isRunning()) && (stepper2.distanceToGo() != 0)) { if ((stepper2.distanceToGo() != 0)) { stepper2.run(); //Serial.print(stepper2.distanceToGo()); //Serial.print(","); curEl = stepper2.currentPosition() 360 / STEPS_360; } }

void initMotorShield() { ////AFMSbot.begin(); // Start the bottom shield AFMStop.begin(); // Start the top shield }

void initMotors() { stepper1.setMaxSpeed(SPEED_DEFAULT); stepper1.setAcceleration(ACCEL_DEFAULT); stepper2.setMaxSpeed(SPEED_DEFAULT); stepper2.setAcceleration(ACCEL_DEFAULT); }

void setNewAz(int pos) { long newAzStep = ((long)pos) * STEPS_360 / 360; stepper1.moveTo(newAzStep); // set new target for stepper motor }

void setNewEl(int pos) { long newElStep = ((long)pos) * STEPS_360 / 360; stepper2.moveTo(newElStep); // set new target for stepper motor }

void stopMotorAz() { ////stepper1.stop(); delay(200); // calculate current position from stepper data curAz = stepper1.currentPosition() * 360 / STEPS_360; }

void stopMotorEl() { ////stepper2.stop(); delay(200); // calculate current position from stepper data curAz = stepper2.currentPosition() * 360 / STEPS_360; }

void setZeroPositions() { stepper1.setCurrentPosition(0); stepper2.setCurrentPosition(0); curAz = 0; newAz = curAz; curEl = 0; newEl = curEl; initMotors(); }

// Sends the current parameters of the azimuth servo back to the PC void printMotorParameters() { Serial.print("Stepper Speed: "); Serial.println(SPEED_DEFAULT); Serial.print("Stepper Accel: "); Serial.println(ACCEL_DEFAULT); Serial.print("Current Azimuth: "); Serial.println(curAz); Serial.print("Current Elevation: "); Serial.println(curEl); }

//////////////////////////////////////////////////////////////////////////////////////

K6VUG SatTrackerIV.zip

Supermagnum commented 3 years ago

I am collaborating with K6VUG on an Arduino (Uno/Mega) build with the Adafruit MotorShield (my ver 2.3) driving two Nema 17 HS4401S.

His Sketch works great. Since it's a bare bones solution I'd like to eventually add ability to use a display and LM303 Magnetometer, etc.

However, after coming across this project, he was ok with me reaching out to see if a port of his code was possible. It would be great to assist others with this setup since there are so many more features.

Here is Umesh's (K6VUG) working code for the steppers and shield with EasyComm commands. How would I incorporate this into K3NG? I've tried but it will probably take me months to integrate with my limited abilities.

All credits go to UMESH/K6VUG and a huge thanks to him for helping me get up and running with his code.

Thanks! -Walt / WA7ZYW

// Includes for Adafruit Motor Shield V2 and stepper motors

include

include

include

include "utility/Adafruit_MS_PWMServoDriver.h"

// Constants for Adafruit Motor Shield V2 and stepper motors

define SPEED_DEFAULT 1000.0

define ACCEL_DEFAULT 1000.0

define STEP_TYPE SINGLE // can be changed to DOUBLE or INTERLEAVE or MICROSTEP

define STEPS_360 200 // as specified in stepper specifications

define CCW_MOTOR_AZ false // set this to true if clockwise command moves rotor anti-clockwise

define CCW_MOTOR_EL false // set this to true if clockwise command moves rotor anti-clockwise

// ---------------------------- AdaFruit Shield Initialisation ----------------------------

////Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree) to the top shield Adafruit_StepperMotor myStepper1 = AFMStop.getStepper(STEPS_360, 1); Adafruit_StepperMotor myStepper2 = AFMStop.getStepper(STEPS_360, 2);

// create wrappers for the motors! void forwardstep1() { myStepper1->onestep(FORWARD, STEP_TYPE); }

void backwardstep1() { myStepper1->onestep(BACKWARD, STEP_TYPE); }

void forwardstep2() { myStepper2->onestep(FORWARD, STEP_TYPE); }

void backwardstep2() { myStepper2->onestep(BACKWARD, STEP_TYPE); }

// create AccelStepper objects AccelStepper stepper1(forwardstep1, backwardstep1); AccelStepper stepper2(forwardstep2, backwardstep2);

// ----------------------------------------------------------------------------------------

void setupSteppers() { // initialize motor shield initMotorShield(); // initialize motors initMotors(); // initialize current position based on stepper data curAz = stepper1.currentPosition() 360 / STEPS_360; curEl = stepper2.currentPosition() 360 / STEPS_360; }

void loopSteppers() { // move the motors one step towards target position //if ((!stepper1.isRunning()) && (stepper1.distanceToGo() != 0)) { if ((stepper1.distanceToGo() != 0)) { stepper1.run(); //Serial.print(stepper1.distanceToGo()); //Serial.print(","); curAz = stepper1.currentPosition() 360 / STEPS_360; } //if ((!stepper2.isRunning()) && (stepper2.distanceToGo() != 0)) { if ((stepper2.distanceToGo() != 0)) { stepper2.run(); //Serial.print(stepper2.distanceToGo()); //Serial.print(","); curEl = stepper2.currentPosition() 360 / STEPS_360; } }

void initMotorShield() { ////AFMSbot.begin(); // Start the bottom shield AFMStop.begin(); // Start the top shield }

void initMotors() { stepper1.setMaxSpeed(SPEED_DEFAULT); stepper1.setAcceleration(ACCEL_DEFAULT); stepper2.setMaxSpeed(SPEED_DEFAULT); stepper2.setAcceleration(ACCEL_DEFAULT); }

void setNewAz(int pos) { long newAzStep = ((long)pos) * STEPS_360 / 360; stepper1.moveTo(newAzStep); // set new target for stepper motor }

void setNewEl(int pos) { long newElStep = ((long)pos) * STEPS_360 / 360; stepper2.moveTo(newElStep); // set new target for stepper motor }

void stopMotorAz() { ////stepper1.stop(); delay(200); // calculate current position from stepper data curAz = stepper1.currentPosition() * 360 / STEPS_360; }

void stopMotorEl() { ////stepper2.stop(); delay(200); // calculate current position from stepper data curAz = stepper2.currentPosition() * 360 / STEPS_360; }

void setZeroPositions() { stepper1.setCurrentPosition(0); stepper2.setCurrentPosition(0); curAz = 0; newAz = curAz; curEl = 0; newEl = curEl; initMotors(); }

// Sends the current parameters of the azimuth servo back to the PC void printMotorParameters() { Serial.print("Stepper Speed: "); Serial.println(SPEED_DEFAULT); Serial.print("Stepper Accel: "); Serial.println(ACCEL_DEFAULT); Serial.print("Current Azimuth: "); Serial.println(curAz); Serial.print("Current Elevation: "); Serial.println(curEl); }

//////////////////////////////////////////////////////////////////////////////////////

K6VUG SatTrackerIV.zip

Very nice! But I think that the code should account for worm gear box ratios like 1:60 as those does not need any form for braking.

Also, for those who need to be able to run BIG stepper motors: PicoBorg Reverse - Dual 5A Motor Controller is the only controller that handles that kind of Amperes. You will need one Picoborg reverse per motor, they communicate using I2C bus.

Lutraphobia commented 3 years ago

Thanks for the feedback!

What I was really hoping for was someone with coding experience could pull this into a testing release and make the changes necessary to enable these features. AFAIK, the latest release doesn't support the motorshield or stepper motors?

Maybe it's more complicated then I thought based on your comments?

Supermagnum commented 3 years ago

Thanks for the feedback!

What I was really hoping for was someone with coding experience could pull this into a testing release and make the changes necessary to enable these features. AFAIK, the latest release doesn't support the motorshield or stepper motors?

Maybe it's more complicated then I thought based on your comments?

My knowledge of programming is severely limited,- but I like the idea and I hope that you succeed as this is a great feature. I really can use it for 2X NEMA 23 steppers.

OH6ETB used steppers in his code, it can be found here: https://github.com/Supermagnum/Pirotator/blob/main/pirotator.py

I think that automatic detection and setup of stepper controllers by scanning the I2C bus could eventually be implemented as some of us may want to use controllers like ThunderBorg or two Diablo boards by Piborg. The Diablo board can drive steppers that require up to 55A !