Two-dimension stepper control with potentiometers

Hello everyone - first time posting so I apologize for any formatting errors. I am attempting to control two stepper motors with the X and Y axes of a 2-axis joystick. I have a working code for just one axis/motor, shown here:

#define DRIVER_STEP_PIN   2
#define DRIVER_DIR_PIN    3
#define POT_PIN           A0
 
#define DEADZONE 50
#define MIN_DRIVER_PULSE_PERIOD_US  50 //max speed
#define MAX_DRIVER_PULSE_PERIOD_US  3000 //min speed
 
enum Driver_pulse_state_enum {PULSE_IDLE, PULSE_HIGH, PULSE_LOW};
 
unsigned long time_now = 0;
uint16_t driver_pulse_hold_time_us = MIN_DRIVER_PULSE_PERIOD_US/2;
uint8_t driver_pulse_state = PULSE_IDLE;
int normalized_analog_value = 0;
uint8_t idle_flag = 1;
 
void setup() {
    pinMode(DRIVER_STEP_PIN, OUTPUT);
    pinMode(DRIVER_DIR_PIN, OUTPUT);
     
}
 
void loop() {
    normalized_analog_value = analogRead(POT_PIN) - 512;
 
    if(abs(normalized_analog_value)-DEADZONE < 0){
        idle_flag = 1;
    }
    else{
        idle_flag = 0;
    }
 
    driver_pulse_hold_time_us = map(abs(normalized_analog_value), DEADZONE, 512, MAX_DRIVER_PULSE_PERIOD_US, MIN_DRIVER_PULSE_PERIOD_US)/2;
 
    if(!idle_flag && driver_pulse_state == PULSE_IDLE){
        write_pulse_high();
    }
 
    if((micros() - time_now > driver_pulse_hold_time_us) && (driver_pulse_state == PULSE_LOW)){
        write_pulse_high();
    }
 
    if((micros() - time_now > driver_pulse_hold_time_us) && (driver_pulse_state == PULSE_HIGH)){
        write_pulse_low();
    }
}
 
void write_pulse_high(void){
    driver_pulse_state = PULSE_HIGH;
 
    if(normalized_analog_value > 0){
        digitalWrite(DRIVER_DIR_PIN, HIGH);
    }
    else if(normalized_analog_value < 0){
        digitalWrite(DRIVER_DIR_PIN, LOW);
    }
 
    digitalWrite(DRIVER_STEP_PIN, HIGH);
    time_now = micros();
}
 
void write_pulse_low(void){
    digitalWrite(DRIVER_STEP_PIN, LOW);
    time_now = micros();
 
    if(!idle_flag){
        driver_pulse_state = PULSE_LOW;
    }
    else{
        driver_pulse_state = PULSE_IDLE;
    }
}

The problem I'm having is when attempting to modify the code to add the second axis/motor, I get an error while verifying: " 'write_Ypulse_low' was not declared in this scope." Any help would be appreciated.

#define XDRIVER_STEP_PIN   2
#define XDRIVER_DIR_PIN    3
#define XPOT_PIN           A0
#define YDRIVER_STEP_PIN   3
#define YDRIVER_DIR_PIN    4
#define YPOT_PIN           A1

#define XDEADZONE 50
#define XMIN_DRIVER_PULSE_PERIOD_US  50 //max speed
#define XMAX_DRIVER_PULSE_PERIOD_US  3000 //min speed
#define YDEADZONE 50
#define YMIN_DRIVER_PULSE_PERIOD_US  50 //max speed
#define YMAX_DRIVER_PULSE_PERIOD_US  3000 //min speed

enum XDriver_pulse_state_enum {XPULSE_IDLE, XPULSE_HIGH, XPULSE_LOW};
enum YDriver_pulse_state_enum {YPULSE_IDLE, YPULSE_HIGH, YPULSE_LOW};

unsigned long Xtime_now = 0;
unsigned long Ytime_now = 0;
uint16_t Xdriver_pulse_hold_time_us = XMIN_DRIVER_PULSE_PERIOD_US/2;
uint8_t Xdriver_pulse_state = XPULSE_IDLE;
int Xnormalized_analog_value = 0;
uint8_t Xidle_flag = 1;
uint16_t Ydriver_pulse_hold_time_us = YMIN_DRIVER_PULSE_PERIOD_US/2;
uint8_t Ydriver_pulse_state = YPULSE_IDLE;
int Ynormalized_analog_value = 0;
uint8_t Yidle_flag = 1;
 
void setup() {
    pinMode(XDRIVER_STEP_PIN, OUTPUT);
    pinMode(XDRIVER_DIR_PIN, OUTPUT);
    pinMode(YDRIVER_STEP_PIN, OUTPUT);
    pinMode(YDRIVER_DIR_PIN, OUTPUT);
  
}

void loop() {
    Xnormalized_analog_value = analogRead(XPOT_PIN) - 512;
 
    if(abs(Xnormalized_analog_value)-XDEADZONE < 0){
        Xidle_flag = 1;
    }
    else{
        Xidle_flag = 0;
    }
    Ynormalized_analog_value = analogRead(YPOT_PIN) - 512;
 
    if(abs(Ynormalized_analog_value)-YDEADZONE < 0){
        Yidle_flag = 1;
    }
    else{
        Yidle_flag = 0;
    }
    Xdriver_pulse_hold_time_us = map(abs(Xnormalized_analog_value), XDEADZONE, 512, XMAX_DRIVER_PULSE_PERIOD_US, XMIN_DRIVER_PULSE_PERIOD_US)/2;
 
    if(!Xidle_flag && Xdriver_pulse_state == XPULSE_IDLE){
        write_Xpulse_high();
    }
 
    if((micros() - Xtime_now > Xdriver_pulse_hold_time_us) && (Xdriver_pulse_state == XPULSE_LOW)){
        write_Xpulse_high();
    }
 
    if((micros() - Xtime_now > Xdriver_pulse_hold_time_us) && (Xdriver_pulse_state == XPULSE_HIGH)){
        write_Xpulse_low();
    }
    Ydriver_pulse_hold_time_us = map(abs(Ynormalized_analog_value), YDEADZONE, 512, YMAX_DRIVER_PULSE_PERIOD_US, YMIN_DRIVER_PULSE_PERIOD_US)/2;

    if(!Yidle_flag && Ydriver_pulse_state == YPULSE_IDLE){
        write_Ypulse_high();
    }

    if((micros() - Ytime_now > Ydriver_pulse_hold_time_us) && (Ydriver_pulse_state == YPULSE_LOW)){
        write_Ypulse_high();
    }
 
    if((micros() - Ytime_now > Ydriver_pulse_hold_time_us) && (Ydriver_pulse_state == YPULSE_HIGH)){
        write_Ypulse_low();
    }
}
 
void write_Xpulse_high(void){
    Xdriver_pulse_state = XPULSE_HIGH;
 
    if(Xnormalized_analog_value > 0){
        digitalWrite(XDRIVER_DIR_PIN, HIGH);
    }
    else if(Xnormalized_analog_value < 0){
        digitalWrite(XDRIVER_DIR_PIN, LOW);
    }
 
    digitalWrite(XDRIVER_STEP_PIN, HIGH);
    Xtime_now = micros();
}
void write_Ypulse_high(void){
    Ydriver_pulse_state = YPULSE_HIGH;
 
    if(Ynormalized_analog_value > 0){
        digitalWrite(YDRIVER_DIR_PIN, HIGH);
    }
    else if(Ynormalized_analog_value < 0){
        digitalWrite(YDRIVER_DIR_PIN, LOW);
    }
 
    digitalWrite(YDRIVER_STEP_PIN, HIGH);
    Ytime_now = micros();
}

void write_Xpulse_low(void){
    digitalWrite(XDRIVER_STEP_PIN, LOW);
    Xtime_now = micros();
 
    if(!Xidle_flag){
        Xdriver_pulse_state = XPULSE_LOW;
    }
    else{
        Xdriver_pulse_state = XPULSE_IDLE;
    }
void write_Ypulse_low(void){
    digitalWrite(YDRIVER_STEP_PIN, LOW);
    Ytime_now = micros();
 
    if(!Yidle_flag){
        Ydriver_pulse_state = YPULSE_LOW;
    }
    else{
        Ydriver_pulse_state = YPULSE_IDLE;
    }

Take a deep breath, edit your post, delete all the code blocks, and re-post them with [code tags] around the code.

It will format better, and we’re more likely to read it.

Welcome to the forum.

Sorry about that, thank you for the help. I have edited the post.

Cheers, we were all new one time!

no closing brace

copy&paste is often plagued with problems

consider

struct Axis {
    const char     *desc;

    int             zero;
    int             dead;
    int             potMax;

    byte            potPin;
    byte            dirPin;
    byte            stepPin;

    unsigned long   usecMin;
    unsigned long   usecMax;

    unsigned long   usecLst;
    int             period;
};

#define MyHW
#ifdef MyHW
Axis axis [] = {
    { "x", 512,  10,  20, A0, 13, 12,  100000, 1000000L },
    { "y", 200, 100, 800, A2, 10, 11, 100000, 1000000L },
};

#else
# define DRIVER_STEP_PIN   2
# define DRIVER_DIR_PIN    3
Axis axis [] = {
    { "x", 512,  10, A0,  3,  2,  50, 3000 },
    { "y", 512, 500, A1,  5,  4,  50, 3000 },
};
#endif

#define N_AXIS  2

unsigned long  usec      = millis ();
char           s[80];

// -----------------------------------------------------------------------------
void
operate (
    Axis *p )
{
    int pot = analogRead (p->potPin) - p->zero;

    digitalWrite (p->dirPin, 0 < pot);

    int   delta;
    delta = abs (pot) - p->dead;
    delta = 0 > delta ? 0 : delta;

    unsigned long period = map (delta, 0, p->potMax, p->usecMax, p->usecMin);

    sprintf (s, " axis %s, pot %5d, del %3d, per %6ld",
            p->desc, pot, delta, period );
    Serial.print (s);

    if (delta && (usec - p->usecLst) > period)  {
        p->usecLst = usec;
        digitalWrite (p->stepPin, ! digitalRead (p->stepPin));
    }
}

// -----------------------------------------------------------------------------
void
loop ()
{
    usec      = micros ();

    operate (& axis [0]);
    operate (& axis [1]);
    Serial.println ();
}

// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);

    Axis *p = axis;
    for (unsigned n = 0; n < N_AXIS; n++, p++)  {
        pinMode (p->dirPin,  OUTPUT);
        pinMode (p->stepPin, OUTPUT);
    }
}

Thank you for the help everyone. I added the missing braces like johnerrington suggested and was able to get everything working, however I'm having one other problem. For one of the two axes, the motor runs very slow and changing #define YMAX_DRIVER_PULSE_PERIOD_US doesn't seem to affect it. I'm having trouble understanding why, since the code is the same for each axis.

Please show your current sketch.

Sure, here it is:

#define XDRIVER_STEP_PIN   2
#define XDRIVER_DIR_PIN    3
#define XPOT_PIN           A0
#define YDRIVER_STEP_PIN   4
#define YDRIVER_DIR_PIN    5
#define YPOT_PIN           A1

#define XDEADZONE 50
#define XMIN_DRIVER_PULSE_PERIOD_US  50 //max speed
#define XMAX_DRIVER_PULSE_PERIOD_US  3000 //min speed
#define YDEADZONE 50
#define YMIN_DRIVER_PULSE_PERIOD_US  50 //max speed
#define YMAX_DRIVER_PULSE_PERIOD_US  3000 //min speed

enum XDriver_pulse_state_enum {XPULSE_IDLE, XPULSE_HIGH, XPULSE_LOW};
enum YDriver_pulse_state_enum {YPULSE_IDLE, YPULSE_HIGH, YPULSE_LOW};

unsigned long Xtime_now = 0;
unsigned long Ytime_now = 0;
uint16_t Xdriver_pulse_hold_time_us = XMIN_DRIVER_PULSE_PERIOD_US/2;
uint8_t Xdriver_pulse_state = XPULSE_IDLE;
int Xnormalized_analog_value = 0;
uint8_t Xidle_flag = 1;
uint16_t Ydriver_pulse_hold_time_us = YMIN_DRIVER_PULSE_PERIOD_US/2;
uint8_t Ydriver_pulse_state = YPULSE_IDLE;
int Ynormalized_analog_value = 0;
uint8_t Yidle_flag = 1;
 
void setup() {
    pinMode(XDRIVER_STEP_PIN, OUTPUT);
    pinMode(XDRIVER_DIR_PIN, OUTPUT);
    pinMode(YDRIVER_STEP_PIN, OUTPUT);
    pinMode(YDRIVER_DIR_PIN, OUTPUT);
  
}

void loop() {
    Xnormalized_analog_value = analogRead(XPOT_PIN) - 512;
 
    if(abs(Xnormalized_analog_value)-XDEADZONE < 0){
        Xidle_flag = 1;
    }
    else{
        Xidle_flag = 0;
    }
    Ynormalized_analog_value = analogRead(YPOT_PIN) - 512;
 
    if(abs(Ynormalized_analog_value)-YDEADZONE < 0){
        Yidle_flag = 1;
    }
    else{
        Yidle_flag = 0;
    }
    Xdriver_pulse_hold_time_us = map(abs(Xnormalized_analog_value), XDEADZONE, 512, XMAX_DRIVER_PULSE_PERIOD_US, XMIN_DRIVER_PULSE_PERIOD_US)/2;
 
    if(!Xidle_flag && Xdriver_pulse_state == XPULSE_IDLE){
        write_Xpulse_high();
    }
 
    if((micros() - Xtime_now > Xdriver_pulse_hold_time_us) && (Xdriver_pulse_state == XPULSE_LOW)){
        write_Xpulse_high();
    }
 
    if((micros() - Xtime_now > Xdriver_pulse_hold_time_us) && (Xdriver_pulse_state == XPULSE_HIGH)){
        write_Xpulse_low();
    }
    Ydriver_pulse_hold_time_us = map(abs(Ynormalized_analog_value), YDEADZONE, 512, YMAX_DRIVER_PULSE_PERIOD_US, YMIN_DRIVER_PULSE_PERIOD_US)/2;

    if(!Yidle_flag && Ydriver_pulse_state == YPULSE_IDLE){
        write_Ypulse_high();
    }

    if((micros() - Ytime_now > Ydriver_pulse_hold_time_us) && (Ydriver_pulse_state == YPULSE_LOW)){
        write_Ypulse_high();
    }
 
    if((micros() - Ytime_now > Ydriver_pulse_hold_time_us) && (Ydriver_pulse_state == YPULSE_HIGH)){
        write_Ypulse_low();
    }
}
 
void write_Xpulse_high(void){
    Xdriver_pulse_state = XPULSE_HIGH;
 
    if(Xnormalized_analog_value > 0){
        digitalWrite(XDRIVER_DIR_PIN, HIGH);
    }
    else if(Xnormalized_analog_value < 0){
        digitalWrite(XDRIVER_DIR_PIN, LOW);
    }
 
    digitalWrite(XDRIVER_STEP_PIN, HIGH);
    Xtime_now = micros();
}
void write_Ypulse_high(void){
    Ydriver_pulse_state = YPULSE_HIGH;
 
    if(Ynormalized_analog_value > 0){
        digitalWrite(YDRIVER_DIR_PIN, HIGH);
    }
    else if(Ynormalized_analog_value < 0){
        digitalWrite(YDRIVER_DIR_PIN, LOW);
    }
 
    digitalWrite(YDRIVER_STEP_PIN, HIGH);
    Ytime_now = micros();
}

void write_Xpulse_low(void){
    digitalWrite(XDRIVER_STEP_PIN, LOW);
    Xtime_now = micros();
 
    if(!Xidle_flag){
        Xdriver_pulse_state = XPULSE_LOW;
    }
    else{
        Xdriver_pulse_state = XPULSE_IDLE;
    }
}
void write_Ypulse_low(void){
    digitalWrite(YDRIVER_STEP_PIN, LOW);
    Ytime_now = micros();
 
    if(!Yidle_flag){
        Ydriver_pulse_state = YPULSE_LOW;
    }
    else{
        Ydriver_pulse_state = YPULSE_IDLE;
    }
}

I don't see any problem in the code. If you change:

#define XPOT_PIN           A0
#define YPOT_PIN           A1

to

#define XPOT_PIN           A1
#define YPOT_PIN           A0

Does the problem move to the X axis? If so, that would indicate a hardware problem with the pot on A1

I apologize, I misspoke earlier. It's not one axis that runs slower - it's one of the two directions on each axis i.e. moving the joystick up or left will give me full speed on the respective axis, while moving it down or right will give me a slower speed.

Hi,
Do you have a DMM?
Can you please post a schematic diagram of your project, in particular how you have the joysticks connected to power and the controller?
What model controller are you using?

If you have a DMM, can you measure the voltage from each joystick going to the analog inputs, with respect to gnd, and tell us what voltage you get for each when;
Joystick fully in one direction.
Joystick fully in other direction.
Joystick in central position.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

If you accidentally connected the pots to 3.3V instead of 5V that would explain why you don't get the full 0 to 1023 range. Try this test to see (on Serial Monitor) what values you are getting:

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

void loop()
{
  Serial.print(analogRead(A0));
  Serial.print(", ");
  Serial.println(analogRead(A1));
  delay(1000);
}

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