-1

Hardware:

What I am attempting to do is send a packet from a Python GUI to an Arduino. The serial communications work as expected. However, the number of rotations that I'm expecting to see fails depending on the Step Size the Driver is set to.

The GUI uses meters as the base unit for Speed, Acceleration, and distance. Right now the GUI sends a separate message for each of those values. As the values are based on meters and the AccelStepper library uses steps, I need to convert the user-defined values so that the AccelStepper library is actually receiving valid information. the conversion is as follows.

revolutions = distance(m) / (2 * PI * Radius(m))
Steps = (revolutions * 360(deg)) / (Stepper Step angle / Step Size value)

The stepper motor has a step angle of .38 deg. The A4988 allows me to adjust the step size value; 1/16, 1/8, 1/4, 1/2, 1.

The motor shaft will be spinning a wheel, that will be pulling on a string, that will wind around the wheel. I understand that this is not an exact way of winding a given distance of string, but this is just a concept for now.

The radius of the wheel is .0762m. If I want to wind 1m of string, that should be 2.09 Revolutions of the shaft of the motor. With the driver set to a Full Step, it only rotates 180deg. The input value is 1978, which at .38 step angle should give a full 2.1 rotations.

If I set the value again to 1m of string, but this time 1/16th step, I get an input value of 31659, which actually rotates the shaft ~2.1 rotations. I can also get 2.1 rotations if I set it to 1/4th step, but the other steps are not rotating properly. Here is my Arduino code.

#include <AccelStepper.h>
#include <math.h>

#ifndef winder_H 
#define winder_H

#define MSGSIZE 7 
#define CMDCNT 11 

#define CW 1 
#define CCW 0 

#define DISABLE 0 
#define ENABLE 1 

#define MOTOR_ENABLE 0
#define MOTOR_DISABLE 1

// Stepper Motor Driver Pinout
#define STEPPER_DIR 13
#define STEPPER_STEP 12
#define STEPPER_MS3 1
#define STEPPER_MS2 0
#define STEPPER_MS1 8
#define STEPPER_ENABLE 7

#define STEP_ANGLE .38
#define RADIUS .0762

bool flag = false;

AccelStepper stepper(AccelStepper::DRIVER, STEPPER_STEP, STEPPER_DIR);

int stepSizeValue = 16;
int distanceValue = 1;
int disPerSecValue = 1;

byte incomingMsg[MSGSIZE];

typedef struct{
    byte cmd;                       // Task that needs to be completed
    byte cmdType;                   // Command Type 0xF1 = set, 0xF2 = Read
    int pin;                        // pin number associated with the command
    int dir;                        // establish input/output for pin OUTPUT = 1, INPUT = 0
    int def;                        // default value for reset
    int state;                      // Enabled = 1, Disabled = 0
} CMDTABLE;

CMDTABLE cmdLookup[CMDCNT] = {

    {0xC0, 0xF1, 0, 0, 1, 1},                              // adjusts motor speed to steps/second 
    {0xC1, 0xF1, 0, 0, 1, 1},                              // adjusts motor acceleration steps/second/second
    {0xC2, 0xF1, 0, 0, 1, 1},                              // adjuusts motor distance to steps
    {0xC3, 0xF2, CLAMP, OUTPUT, 0, 0},                    // Toggle Clamp
    {0xC4, 0xF2, BRAKE1, OUTPUT, 0, 0},                    // Toggle Brake1
    {0xC5, 0xF2, BRAKE2, OUTPUT, 0, 0},                    // Toggle Brake2
    {0xC6, 0xF3, STEPPER_ENABLE, OUTPUT, LOW, LOW},
    {0xC7, 0xF3, LASER_TRIGGER, OUTPUT, LOW, LOW},
    {0xC8, 0xF3, RELAY_ILLUMINATOR, OUTPUT, LOW, LOW},
    {0xC9, 0xF4, STEPPER_DIR, OUTPUT, HIGH, HIGH},
    {0xCA, 0xF4, 0, 0, 0xD1}
};

void commsCheck();
void setDefaults();
long calculateSteps(int distance);
void setStepCount(int distance);
void setAcceleration(int disPerSec);
void setSpeed(int speed);
void setStepSize(int val);
void setSize(int MS1, int MS2, int MS3);
void enablePin(int idx, int val);
void singleStep();

#endif

#include "src/winder.h"

void setup() {
    // 
    Serial.begin(115200);

    pinMode(STEPPER_DIR, OUTPUT);
    pinMode(STEPPER_STEP, OUTPUT);
 
    pinMode(STEPPER_ENABLE, OUTPUT);
    pinMode(STEPPER_MS1, OUTPUT);
    pinMode(STEPPER_MS2, OUTPUT);
    pinMode(STEPPER_MS3, OUTPUT);

    digitalWrite(STEPPER_MS1, HIGH);
    digitalWrite(STEPPER_MS2, HIGH);
    digitalWrite(STEPPER_MS3, HIGH);

    digitalWrite(STEPPER_DIR, CW);   
}

void loop() {
    
    commsCheck();
    singleStep();
}

void commsCheck(){

    if(Serial.available() > 0){
        
        int rlen = Serial.readBytes(incomingMsg, MSGSIZE);
        byte cmd = incomingMsg[2];

        int val = incomingMsg[4];

        switch(cmd){
            case 0xC0:{
                setSpeed(val);
                break;
            }
            case 0xC1:{
                setAcceleration(val);
                break;
            }
            case 0xC2:{
                setStepCount(val);
                break;
            }
            case 0xC6:{

                if(val == ENABLE){
                    // enablePin(6, MOTOR_ENABLE);
                    flag = true;
                }
                else{
                    
                    // enablePin(6, MOTOR_DISABLE);
                    flag = false;

                }
                break;
            }
            case 0xC7:{
                enablePin(7, val);
                break;
            }
            case 0xC8:{
                enablePin(8, val);
                break;
            }
            case 0xC9:{
                if (val == CW){
                    
                    enablePin(9, CW);
                    cmdLookup[9].state = CW; 
                }
                else{

                    enablePin(9, CCW);
                    cmdLookup[9].state = CCW; 
                }
                break;
            }
            case 0xCA:{
                setStepSize(val);
                break;
            }
        }
    }
}
   
long calculateSteps(int distance){
    float rev = distance/(2*M_PI* RADIUS);

    long steps = (rev*360)/(STEP_ANGLE/stepSizeValue);

    return steps;
}

void setStepCount(int distance){

    cmdLookup[2].state = distance;

    long steps = calculateSteps(distance);
    Serial.print(steps);
    Serial.print("\n");

    stepper.move(steps);
}

void setAcceleration(int disPerSec){

    cmdLookup[1].state = disPerSec;
    int steps_per_sec = (int) calculateSteps(disPerSec);

    stepper.setAcceleration(steps_per_sec);
}

void setSpeed(int speed){
    cmdLookup[0].state = speed;
    int steps_per_sec = (int) calculateSteps(speed);

    stepper.setMaxSpeed(steps_per_sec);
    stepper.setSpeed(steps_per_sec);
}

void setStepSize(int val){

    int step = 0xD0;

    switch(val){
        case 0xD0:{
            stepSize(HIGH, HIGH, HIGH);
            stepSizeValue = 16;
            break;
        }
        case 0xD1:{
            stepSize(HIGH, HIGH, LOW);
            stepSizeValue = 8;
            step = 0xD1;
            break;
        }
        case 0xD2:{
            stepSize(LOW, HIGH, LOW);
            stepSizeValue = 4;
            step = 0xD2;
            break;
        }
        case 0xD3:{
            stepSize(HIGH, LOW, LOW);
            stepSizeValue = 2;
            step = 0xD3;
            break;
        }
        case 0xD4:{
            stepSize(LOW, LOW, LOW);
            stepSizeValue = 1;
            step = 0xD4;
            break;
        }
    }
    
    setStepCount(distanceValue);
    setAcceleration(disPerSecValue);
    cmdLookup[10].state = step;
}

void stepSize(int MS1, int MS2, int MS3){
    digitalWrite(STEPPER_MS1, MS1);
    digitalWrite(STEPPER_MS2, MS2);
    digitalWrite(STEPPER_MS3, MS3);
}

void enablePin(int idx, int val){

    if (val == ENABLE){

        digitalWrite(cmdLookup[idx].pin, ENABLE);
        cmdLookup[idx].state = ENABLE; 
    }
    else{

        digitalWrite(cmdLookup[idx].pin, DISABLE);
        cmdLookup[idx].state = DISABLE; 
    }
}
   
void singleStep(){

    if(flag == true){

        stepper.enableOutputs();

        stepper.run();

        if (stepper.distanceToGo() == 0){
            flag == false;
            // TODO: need to do a return signal to disable the button. 
        }

    }
    else{
        stepper.disableOutputs();
    }
}

Please post a comment with any other information I might be missing. If this should be in the Arduino site, please let me know.

hcheung
  • 3,377
  • 3
  • 11
  • 23
Michael
  • 174
  • 2
  • 13
  • How do you expect to transfer 1978 in a single byte? – gre_gor Apr 29 '23 at 08:46
  • @gre_gor I don't, my GUI isn't part of this situation. As I stated, the user will provide a distance value in meters. For now, the application will be limited to a range of 0-255, as a limitation of the transfer. The conversion from meters to steps is done on the Arduino side. – Michael Apr 30 '23 at 14:48
  • You seem to have wired micostep signals to the hardware serial pins. – gre_gor Apr 30 '23 at 16:54
  • @gre_gor. So the pins D1(TX) and D0(RX). I shouldn't use those. I should re-wire to other available pins? I didn't think of that. Ok. I can move those over to D14-D19. I'll try that when I get back in to work tomorrow. Thank you! – Michael Apr 30 '23 at 19:28

1 Answers1

0

I'm not entirely sure why, something I will need to figure out, but it was a pin-wiring issue. My original pin wiring was as follows.

// Stepper Motor Driver Pinout
#define STEPPER_DIR 13
#define STEPPER_STEP 12
#define STEPPER_MS3 1
#define STEPPER_MS2 0
#define STEPPER_MS1 8
#define STEPPER_ENABLE 7

As @gre_gor pointed out in the comments, I had pins 0 & 1 wired as double duty. Microstep signals and RX/TX serial communication. I was under the impression that when I set the pin mode within the setup() block.

pinMode(STEPPER_MS1, OUTPUT);
pinMode(STEPPER_MS2, OUTPUT);
pinMode(STEPPER_MS3, OUTPUT);

this would allow me to use these pins as digital pins, vs serial pins.

However, as soon as I re-wired the A4988 pins related to the micro-step signals to three different pins.

#define STEPPER_MS3 A3 
#define STEPPER_MS2 A4 
#define STEPPER_MS1 A5 

I can not control the motor so that the spindle will rotate the exact same number of revolutions on each of the five micro-step modes.

Michael
  • 174
  • 2
  • 13