Notifications
Clear all

Arduino with Stepper and LiquidCrystal Issue

Page 7 / 21

Voltage
(@voltage)
Estimable Member
Joined: 11 months ago
Posts: 169
Topic starter  
Posted by: @madmisha

@voltage

Here it is again, just to be sure. I did edit it after posting.

 

//Test of accelstepper with LCD and pot

#include <AccelStepper.h>
#include <LiquidCrystal.h>

//Define pins
int LEFT_PIN = 11;
int STOP_PIN = 2;
int RIGHT_PIN = 3;
int driverPUL = 12;    // PUL- pin
int driverDIR = 13;    // DIR- pin
int spd = A1;     // Potentiometer
bool go = false;  //Is it running
bool dirFor = true; //Direction to go in

AccelStepper stepper(1,driverPUL,driverDIR); // This needs to change in any example(Mode, Pul, Dir)

LiquidCrystal lcd(8,9,4,5,6,7); //Setup LCD

//Interupt Handlers
void formotor (){

  dirFor = true;
  go = true;
  
}

void bacmotor (){

  lcd.setCursor(0,1);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }
  go = true;
  
}

void stpmotor (){

  if(go){
    stepper.stop();
    go = false;
  } else {
    dirFor = !dirFor;
    lcd.setCursor(0,1);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }   
  }  
}


void setup()
{  
   //pinMode(LEFT_PIN, INPUT_PULLUP);
   pinMode(STOP_PIN, INPUT_PULLUP);
   pinMode(RIGHT_PIN, INPUT_PULLUP);

   //attachInterrupt(digitalPinToInterrupt(LEFT_PIN), formotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), bacmotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
   
   //stepper.setPinsInverted(false, true, false);
   stepper.setMaxSpeed(1000);
   stepper.setMinPulseWidth(2.7);

   lcd.begin(16, 2);
   lcd.setCursor(1,0);
   lcd.print("Speed:");
   lcd.setCursor(12,0);
   lcd.print("RPM");
   lcd.setCursor(0,1);
   if(dirFor){
    lcd.print("Right");
   } else {
    lcd.print("Left ");
    }
}

void loop()
{
  int sp_pot = map((analogRead(spd)),0,1023,50,1000);
  if(go == true){
    if(dirFor == true){
      stepper.setSpeed(sp_pot);
    } else {
      stepper.setSpeed((sp_pot*-1));
    }
    stepper.runSpeed();
    lcd.setCursor(7,0);
    lcd.print(sp_pot);
    stepper.runSpeed();
  } else {
    stepper.stop();
  }
}

 

Ok, compiled and tested and it works. There is a few thing about the display I thought I would mention. When I reset the UNO the display reads:

Speed:        RPM

Right

When I run it it shows:

Speed: 1000  RPM

Right 000

And if I push the Left or Start button while it is running it adds some odd stuff:

Speed: 1000   5&  v

Right 000

 

and sometimes the 000 turns into 1000

Thanks,
Voltage


ReplyQuote
MadMisha
(@madmisha)
Reputable Member
Joined: 2 years ago
Posts: 319
 
Posted by: @voltage

No thumps and I can change direction.

That is great!

Posted by: @voltage

The display goes from 0-1000 and although it is not correct, that should be easy to adjust.

It should go 0-1000. it can be mapped to lower if needed but you would loose the granularity. We would need to come up with the formula to get the RPM.

Posted by: @voltage

I did notice a little flicker on the number 6 at one point but don't know if that is just the shield quality or if the refresh rate is too high.

On the LCD? That would probably be the screen.


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 
Posted by: @madmisha

It should go 0-1000. it can be mapped to lower if needed but you would loose the granularity. We would need to come up with the formula to get the RPM.

The speed for the stepper is the number of steps per second. @Voltage has suggested the range 0-15 RPM.

 

To get steps per second, we need to take the requested RPM and multiply it by the gear ratio to get the number of turns that the stepper needs to make to turn the gear's axle once and then multiply that by the number of steps per revolution of the stepper

i.e. steps/second = RPM*gearRatio*stepperStepsPerRev

= RPM * 4.25 * 400

which is 25500 for 15RPM.

Sounds awful, doesn't it !

 

To complete the math, given a specific sp_pot, we can calculate

RPM = sp_pot/4.25/400

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 
Posted by: @voltage

Ok, compiled and tested and it works. There is a few thing about the display I thought I would mention. When I reset the UNO the display reads:

Speed:        RPM

Right

When I run it it shows:

Speed: 1000  RPM

Right 000

And if I push the Left or Start button while it is running it adds some odd stuff:

Speed: 1000   5&  v

Right 000

 

and sometimes the 000 turns into 1000

I think the problem is that the Right and Left info is printed in different places in the code and on the screen. Remove all code where Left or Right is put on the LCD except for stpmotor.

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 11 months ago
Posts: 169
Topic starter  
Posted by: @will
Posted by: @madmisha

It should go 0-1000. it can be mapped to lower if needed but you would loose the granularity. We would need to come up with the formula to get the RPM.

The speed for the stepper is the number of steps per second. @Voltage has suggested the range 0-15 RPM.

 

To get steps per second, we need to take the requested RPM and multiply it by the gear ratio to get the number of turns that the stepper needs to make to turn the gear's axle once and then multiply that by the number of steps per revolution of the stepper

i.e. steps/second = RPM*gearRatio*stepperStepsPerRev

= RPM * 4.25 * 400

which is 25500 for 15RPM.

Sounds awful, doesn't it !

 

To complete the math, given a specific sp_pot, we can calculate

RPM = sp_pot/4.25/400

Don't forget we need to multiply that by 3 to cover for the chain and sprockets with a 10t and 30t for an added 3:1 reduction. 😋 

 

Thanks,
Voltage


ReplyQuote
MadMisha
(@madmisha)
Reputable Member
Joined: 2 years ago
Posts: 319
 

@will @voltage

Like this? I did some rearranging to make it easier. Or would it be better to use the map of the pot(0-15) for the speed?

 

//Test of accelstepper with LCD and pot

#include <AccelStepper.h>
#include <LiquidCrystal.h>

//Define pins
int LEFT_PIN = 11;
int STOP_PIN = 2;
int RIGHT_PIN = 3;
int driverPUL = 12;    // PUL- pin
int driverDIR = 13;    // DIR- pin
int spd = A1;     // Potentiometer
bool go = false;  //Is it running
bool dirFor = true; //Direction to go in

AccelStepper stepper(1,driverPUL,driverDIR); // This needs to change in any example(Mode, Pul, Dir)

LiquidCrystal lcd(8,9,4,5,6,7); //Setup LCD

//Interupt Handlers
void formotor (){

  dirFor = true;
  go = true;
  
}

void bacmotor (){

  lcd.setCursor(7,0);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }
  go = true;
  
}

void stpmotor (){

  if(go){
    stepper.stop();
    go = false;
  } else {
    dirFor = !dirFor;
    lcd.setCursor(7,0);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }   
  }  
}


void setup()
{  
   //pinMode(LEFT_PIN, INPUT_PULLUP);
   pinMode(STOP_PIN, INPUT_PULLUP);
   pinMode(RIGHT_PIN, INPUT_PULLUP);

   //attachInterrupt(digitalPinToInterrupt(LEFT_PIN), formotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), bacmotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
   
   //stepper.setPinsInverted(false, true, false);
   stepper.setMaxSpeed(1000);
   stepper.setMinPulseWidth(2.7);

   lcd.begin(16, 2);
   lcd.setCursor(1,0);
   lcd.print("Speed:");
   lcd.setCursor(13,0);
   lcd.print("RPM");
   lcd.setCursor(7,0);
   if(dirFor){
    lcd.print("Right");
   } else {
    lcd.print("Left ");
    }
}

void loop()
{
  int sp_pot = map((analogRead(spd)),0,1023,50,1000);
  if(go == true){
    if(dirFor == true){
      stepper.setSpeed(sp_pot);
    } else {
      stepper.setSpeed((sp_pot*-1));
    }
    stepper.runSpeed();
    lcd.setCursor(0,1);
    lcd.print((sp_pot/4.25)/400);
    stepper.runSpeed();
    lcd.setCursor(12,1);
    lcd.print(map(sp_pot, 0, 1000, 0, 15));
    stepper.runSpeed();
  } else {
    stepper.stop();
    lcd.setCursor(0,1);
    lcd.print((sp_pot/4.25)/400);
    lcd.setCursor(12,1);
    lcd.print(map(sp_pot, 0, 1000, 0, 15));
  }
}

Edit: With the *3

 

//Test of accelstepper with LCD and pot

#include <AccelStepper.h>
#include <LiquidCrystal.h>

//Define pins
int LEFT_PIN = 11;
int STOP_PIN = 2;
int RIGHT_PIN = 3;
int driverPUL = 12;    // PUL- pin
int driverDIR = 13;    // DIR- pin
int spd = A1;     // Potentiometer
bool go = false;  //Is it running
bool dirFor = true; //Direction to go in

AccelStepper stepper(1,driverPUL,driverDIR); // This needs to change in any example(Mode, Pul, Dir)

LiquidCrystal lcd(8,9,4,5,6,7); //Setup LCD

//Interupt Handlers
void formotor (){

  dirFor = true;
  go = true;
  
}

void bacmotor (){

  lcd.setCursor(7,0);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }
  go = true;
  
}

void stpmotor (){

  if(go){
    stepper.stop();
    go = false;
  } else {
    dirFor = !dirFor;
    lcd.setCursor(7,0);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }   
  }  
}


void setup()
{  
   //pinMode(LEFT_PIN, INPUT_PULLUP);
   pinMode(STOP_PIN, INPUT_PULLUP);
   pinMode(RIGHT_PIN, INPUT_PULLUP);

   //attachInterrupt(digitalPinToInterrupt(LEFT_PIN), formotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), bacmotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
   
   //stepper.setPinsInverted(false, true, false);
   stepper.setMaxSpeed(1000);
   stepper.setMinPulseWidth(2.7);

   lcd.begin(16, 2);
   lcd.setCursor(1,0);
   lcd.print("Speed:");
   lcd.setCursor(13,0);
   lcd.print("RPM");
   lcd.setCursor(7,0);
   if(dirFor){
    lcd.print("Right");
   } else {
    lcd.print("Left ");
    }
}

void loop()
{
  int sp_pot = map((analogRead(spd)),0,1023,50,1000);
  if(go == true){
    if(dirFor == true){
      stepper.setSpeed(sp_pot);
    } else {
      stepper.setSpeed((sp_pot*-1));
    }
    stepper.runSpeed();
    lcd.setCursor(0,1);
    lcd.print(((sp_pot/4.25)/400)*3);
    stepper.runSpeed();
    lcd.setCursor(12,1);
    lcd.print(map(sp_pot, 0, 1000, 0, 15));
    stepper.runSpeed();
  } else {
    stepper.stop();
    lcd.setCursor(0,1);
    lcd.print(((sp_pot/4.25)/400)*3);
    lcd.setCursor(12,1);
    lcd.print(map(sp_pot, 0, 1000, 0, 15));
  }
}

 

 


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 

@voltage

 

Good catch, I forgot about the chain !

Zounds 25500*3 = 76500, that's mind-boggling !

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 11 months ago
Posts: 169
Topic starter  
Posted by: @will
Posted by: @voltage

Ok, compiled and tested and it works. There is a few thing about the display I thought I would mention. When I reset the UNO the display reads:

Speed:        RPM

Right

When I run it it shows:

Speed: 1000  RPM

Right 000

And if I push the Left or Start button while it is running it adds some odd stuff:

Speed: 1000   5&  v

Right 000

 

and sometimes the 000 turns into 1000

I think the problem is that the Right and Left info is printed in different places in the code and on the screen. Remove all code where Left or Right is put on the LCD except for stpmotor.

Here are some pics. It only happens to make the extra characters when I press the start (Left) button while it is running. Easy fix: Don't press the start button while it is running. But it can happen. 😯 Pics of display added:

image 1
image 3
image 2
image 5
image 4
image 7
image 6
image 8

 

 

Thanks,
Voltage


ReplyQuote
MadMisha
(@madmisha)
Reputable Member
Joined: 2 years ago
Posts: 319
 

@voltage

Ok, pictures help since I do not have the hardware. It appears that the interrupt sometimes triggers between the set cursor and the print in the loop. I will look at solutions.

 

Edit: How about this? If if messes up, it should correct itself soon after.

 

//Test of accelstepper with LCD and pot

#include <AccelStepper.h>
#include <LiquidCrystal.h>

//Define pins
int LEFT_PIN = 11;
int STOP_PIN = 2;
int RIGHT_PIN = 3;
int driverPUL = 12;    // PUL- pin
int driverDIR = 13;    // DIR- pin
int spd = A1;     // Potentiometer
bool go = false;  //Is it running
bool dirFor = true; //Direction to go in

AccelStepper stepper(1,driverPUL,driverDIR); // This needs to change in any example(Mode, Pul, Dir)

LiquidCrystal lcd(8,9,4,5,6,7); //Setup LCD

//Interupt Handlers
void formotor (){

  dirFor = true;
  go = true;
  
}

void bacmotor (){

  lcd.setCursor(7,0);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }
  go = true;
  lcd.setCursor(0,1);
  
}

void stpmotor (){

  if(go){
    stepper.stop();
    go = false;
  } else {
    dirFor = !dirFor;
    lcd.setCursor(7,0);
    if (dirFor){
      lcd.print("Right");
    } else {
      lcd.print("Left ");
    }   
  }  
  lcd.setCursor(0,1);
}


void setup()
{  
   //pinMode(LEFT_PIN, INPUT_PULLUP);
   pinMode(STOP_PIN, INPUT_PULLUP);
   pinMode(RIGHT_PIN, INPUT_PULLUP);

   //attachInterrupt(digitalPinToInterrupt(LEFT_PIN), formotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), bacmotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
   
   //stepper.setPinsInverted(false, true, false);
   stepper.setMaxSpeed(1000);
   stepper.setMinPulseWidth(2.7);

   lcd.begin(16, 2);
   lcd.setCursor(1,0);
   lcd.print("Speed:");
   lcd.setCursor(13,0);
   lcd.print("RPM");
   lcd.setCursor(7,0);
   if(dirFor){
    lcd.print("Right");
   } else {
    lcd.print("Left ");
    }
}

void loop()
{
  int sp_pot = map((analogRead(spd)),0,1023,50,1000);
  if(go == true){
    if(dirFor == true){
      stepper.setSpeed(sp_pot);
    } else {
      stepper.setSpeed((sp_pot*-1));
    }
    stepper.runSpeed();
    lcd.setCursor(0,1);
    lcd.print(((sp_pot/4.25)/400)*3);
    stepper.runSpeed();
    lcd.setCursor(12,1);
    lcd.print(map(sp_pot, 0, 1000, 0, 15));
    stepper.runSpeed();
  } else {
    stepper.stop();
    lcd.setCursor(0,1);
    lcd.print(((sp_pot/4.25)/400)*3);
    lcd.setCursor(12,1);
    lcd.print(map(sp_pot, 0, 1000, 0, 15));
  }
}

 

 


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 

@madmisha

I think that it's better to let the sp_pot in steps/second. Calculating an RPM from that is simple. I think if you mapped from 0-12 you'd only get integer values, so preventing a smooth range of speeds.

Selecting from the range of steps/second gives the maximum precision and continuity in speed.

I'm not sure why you're displaying anything but the RPM  as speed. I doubt if @Voltage would be interested in that since I believe he's only concerned about RPM.

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 

@voltage

Yes, that's because pressing the button causes the direction to be printed without a specified location. That should clear up in the next iteration of the code (or so).

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 

@madmisha

Maybe it's worth moving all of the LCD display commands into a subroutine. That way it'll be easy to update from anywhere and the data will always be placed in the same area.

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
MadMisha
(@madmisha)
Reputable Member
Joined: 2 years ago
Posts: 319
 
Posted by: @will

I'm not sure why you're displaying anything but the RPM  as speed. I doubt if @Voltage would be interested in that since I believe he's only concerned about RPM.

Only because that's what the original had. If we verify that the RPMs are working out correctly, that can always change to a diameter reading.


ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 11 months ago
Posts: 169
Topic starter  

I didn't test the last version but I did the two on the one post above. When the RPM comes down from 15, after you go past 10, the 9 shows up as a 90 and the counts down from 90, 89, 87, etc

 

I will go test the latest version. Be right back...

Edit: I'm back. This last version has all kinds of weird stuff on the display even if I just reset the UNO and change directions with the stop button. Want pics?

 

Also, I like just the RPM as the final output, not speed or diameter. That is the best easiest way and I am used to it.

Thanks,
Voltage


ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 12 months ago
Posts: 1780
 
Posted by: @madmisha
Posted by: @will

I'm not sure why you're displaying anything but the RPM  as speed. I doubt if @Voltage would be interested in that since I believe he's only concerned about RPM.

Only because that's what the original had. If we verify that the RPMs are working out correctly, that can always change to a diameter reading.

OK, I see.

How/where will the diameter be read in ?

I was kidnapped by mimes.
They did unspeakable things to me.


ReplyQuote
Page 7 / 21