Notifications
Clear all

Arduino with Stepper and LiquidCrystal Issue

308 Posts
5 Users
12 Likes
15.2 K Views
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  
Posted by: @madmisha

@voltage

I think @will might be onto something but I am not 100% sure if the stepper.h library was meant to be used by that type of driver. I suggest you follow the steps that he has given but if you still don't have a solution, here is a weird mashup of the your code and the example that bill used that I hobbled together. This does not need the stepper.h so that it can be ruled out. It is at least worth a try.

 

 

/*
  Stepper Motor Test Altered/Butchered
  Uses MA860H or similar Stepper Driver Unit
  Has speed control & direction and stop switches
  
  Original: DroneBot Workshop 2019
   https://dronebotworkshop.com 
*/

#include <LiquidCrystal.h>

// Define pins

LiquidCrystal lcd(8,9,4,5,6,7);
// Define our three input button pins
int LEFT_PIN = 11;
int STOP_PIN = 1;
int RIGHT_PIN = 0;
int driverPUL = 2;    // PUL- pin
int driverDIR = 3;    // DIR- pin
int spd = A1;     // Potentiometer
bool go = false;

// Variables

unsigned long previousMillis = 0;

const long interval = 1000;

int pd = 500;       // Pulse Delay period
boolean setdir = LOW; // Set Direction

// Interrupt Handler

void formotor (){

  setdir = HIGH;
  
}

void bacmotor (){

  setdir = LOW;
  
}

void stpmotor (){

  go = false;
  
}


void setup() {

  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);

  lcd.begin(16, 2);
  lcd.setCursor(1,0);
  lcd.print("Speed:");
  lcd.setCursor(12,0);
  lcd.print("RPM");
  
  pinMode (driverPUL, OUTPUT);
  pinMode (driverDIR, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(LEFT_PIN), formotor, FALLING);
  attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), bacmotor, FALLING);
  attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
  
}

void loop() {

    if (go == true){
  
      pd = map((analogRead(spd)),0,1023,2000,50);
      digitalWrite(driverDIR,setdir);
      digitalWrite(driverPUL,HIGH);
      delayMicroseconds(pd);
      digitalWrite(driverPUL,LOW);
      delayMicroseconds(pd);

    } else {
      pd = 0;
      digitalWrite(driverPUL,LOW);
    }

    
    if (millis() - previousMillis >= interval) {

      previousMillis = millis();

      lcd.setCursor(7,0);
      lcd.print(float(float(pd)/float(12)),1);
    }
}

 

 I have never used an int to define a pin but that is what was there. I left out the serial monitor because when you initiate it, it will affect one of the buttons. You should relocate those on pin 0 and 1.

 Writing to the LCD might mess up the flow a little here too. The only way I could see a correction to that being made is to move the If statement for screen update to before the delay and if true, write to screen and delay it less that time and else just delay.

 

Edit: I looked it up. stepper.h is not intended for that. If you want to use an appropriate library try AccelStepper.

Madmish,

  I tried to compile and run this code and nothing happens. Then I added the AccelStepper library and nothing happens. I see you mentioned something about using an int as a pin and leaving out the serial monitor and relocating those on pins 0 and 1. Could you elaborate? I don't seem to understand which wires I need to relocate.

 

 

Thanks,
Voltage


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

I see you mentioned something about using an int as a pin and leaving out the serial monitor and relocating those on pins 0 and 1. Could you elaborate? I don't seem to understand which wires I need to relocate.

That was just a  comment about using int to define a pin. I had never done that but it should work.

 

The pins that are defined as 0 and 1 should be on different pins. That would be the stop and right buttons. Just pick an open pin and change the declaration in the sketch to match.

 

For Accel Stepper to work, you will need to change the AccelStepper object.

 

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

You have to put it into mode 1 so that it knows that you are using a driver. You will need to do this on any example you try from that library.

Here is an example using the Accel Stepper. Change the 1 and 0 pins to what will work for you. I did not include the LCD yet. You can try that after you confirm your setup is working correctly.

 

//Test of accelstepper

#include <AccelStepper.h>

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

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

//Interupt Handlers
void formotor (){

  dirfor = true;
  go = true;
  
}

void bacmotor (){

  dirfor = false;
  go = true;
  
}

void stpmotor (){

  stepper.stop();
  go = false;
  
}


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.setMaxSpeed(1000);
}

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

 


   
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  
Posted by: @madmisha
Posted by: @voltage

I see you mentioned something about using an int as a pin and leaving out the serial monitor and relocating those on pins 0 and 1. Could you elaborate? I don't seem to understand which wires I need to relocate.

That was just a  comment about using int to define a pin. I had never done that but it should work.

 

The pins that are defined as 0 and 1 should be on different pins. That would be the stop and right buttons. Just pick an open pin and change the declaration in the sketch to match.

 

For Accel Stepper to work, you will need to change the AccelStepper object.

 

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

You have to put it into mode 1 so that it knows that you are using a driver. You will need to do this on any example you try from that library.

Here is an example using the Accel Stepper. Change the 1 and 0 pins to what will work for you. I did not include the LCD yet. You can try that after you confirm your setup is working correctly.

 

//Test of accelstepper

#include <AccelStepper.h>

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

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

//Interupt Handlers
void formotor (){

  dirfor = true;
  go = true;
  
}

void bacmotor (){

  dirfor = false;
  go = true;
  
}

void stpmotor (){

  stepper.stop();
  go = false;
  
}


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.setMaxSpeed(1000);
}

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

 

Great. Thanks for the added info and new code to test. I was studying to find out what pins I could move those 2 wires to as some have a squiggly lines and some do not. I found that the ones with the squiggly lines, as a bonus feature, can output pulse width modulated square waves. So I assume I can use any 2 of the available pins 5,6,7,8,9, and 10 correct? I also noticed with the screw shield I can't really see the UNO's numbers so I printed out the image below for a reference. I just put the project off of the kitchen counter as the wife is on the way home from work and I will resume in the AM. I am in Florida but on CST.

Thanks again!

Arduino uno pinout

Thanks,
Voltage


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

o I assume I can use any 2 of the available pins 5,6,7,8,9, and 10 correct?

Remember that your screen needs pins 4-9 and since it is a shield, you will have to stick with that. So unless you have something hooked up that I didn't account for(or plan on using SPI with this project), you have 10-13. Worse case scenario, you could use an analog pin.

Those squiggly lines are the pins that can output PWM signals. That shouldn't matter in this case.


   
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  
Posted by: @madmisha
Posted by: @voltage

o I assume I can use any 2 of the available pins 5,6,7,8,9, and 10 correct?

Remember that your screen needs pins 4-9 and since it is a shield, you will have to stick with that. So unless you have something hooked up that I didn't account for(or plan on using SPI with this project), you have 10-13. Worse case scenario, you could use an analog pin.

Those squiggly lines are the pins that can output PWM signals. That shouldn't matter in this case.

Glad I asked. Pin 11 is in use but 12 and 13 are free. I will use those. 😀 

 

Thanks,
Voltage


   
ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 1 year ago
Posts: 2134
 

@voltage

As discussed offline, i've prepared a variant of the sketch which doesn't require a library for the stepper. It is based on @madmisha's code (from before the accelStepper library use). 

Since you said that speed would never be changed while the motor is already rotating, this version only reads the speed potentiometer and updates the LCD when it is NOT moving. It starts with go=false and waits until the go button is pressed and then rotates continuously (i.e. go=true) until the go button is pressed again (go=false), which then stops rotation and allows the speed to be reset. It may also require a further update to bounce-proof the go button.

Because this thread has a lot of code and tests already suggested, I'd rather wait until you've tried @madmisha's latest suggestions and the dust has settled before bringing in another bunch of code 🙂

Experience is what you get when you don't get what you want.


   
MadMisha reacted
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  
Posted by: @will

@voltage

As discussed offline, i've prepared a variant of the sketch which doesn't require a library for the stepper. It is based on @madmisha's code (from before the accelStepper library use). 

Since you said that speed would never be changed while the motor is already rotating, this version only reads the speed potentiometer and updates the LCD when it is NOT moving. It starts with go=false and waits until the go button is pressed and then rotates continuously (i.e. go=true) until the go button is pressed again (go=false), which then stops rotation and allows the speed to be reset. It may also require a further update to bounce-proof the go button.

Because this thread has a lot of code and tests already suggested, I'd rather wait until you've tried @madmisha's latest suggestions and the dust has settled before bringing in another bunch of code 🙂

Hi Will,

  Sounds good to me. As far as the speed not "needing" to be changed  when the motor is running is just an option I wanted to see if it solves the other issue of the interrupt causing the thump. It is a work around of sorts but may be all I need. The only issue is getting the right speed for the diameter of the part but that is ok with me. I am just learning and that is how I learn. The original author has an update where you can use a foot pedal to control the speed but that can complicate things even more if you already use a foot pedal for the welding input. But I am happy and excited to see what you came up with as it may be 100% the answer once diameters and rpms are established and noted or marked on the control panel. Thanks for all the help. I will be doing the other tests tomorrow with madmisha's latest code and will report back then.

 

Thanks,
Voltage


   
ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 1 year ago
Posts: 2134
 

@voltage

Good, hopefully @madmisha's stuff will work well enough to render mine unneeded.

Experience is what you get when you don't get what you want.


   
ReplyQuote
MadMisha
(@madmisha)
Reputable Member
Joined: 3 years ago
Posts: 346
 

@voltage

Depending on the quality of the potentiometer, you might be getting some variance. Have you thought of just setting it in a digital fashion? If there is an equation that will get you the speed you need, you could just adjust the diameter of the part using buttons or an encoder and it would set the speed based on that. It can still be speed based if you need it to.

All of the sketches here really depend on timing. Accel Stepper needs you keep repeating the run command as many times as possible. So if it does not need to check the potentiometer every loop, buttons or a rotary encoder(rotary encoder is a quick thought and I would have to think more if this one is a good idea, it might not be. Might be better adjusting in the off state) would be better with an interrupt.

 

Edit: I just thought that alternately, you could increase the speed in any direction using the left right buttons you have(as well as starting it in that direction). Pressing it will increase the set speed or decrease it and the stop will reset it to 0. Or instead of resetting it to 0 and it just running the stop command, if it is in the stopped state, start it at the last speed. That way LCD could run from the button interrupt when the change occurred and the loop will solely be running the motor.


   
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  
Posted by: @madmisha
Posted by: @voltage

I see you mentioned something about using an int as a pin and leaving out the serial monitor and relocating those on pins 0 and 1. Could you elaborate? I don't seem to understand which wires I need to relocate.

That was just a  comment about using int to define a pin. I had never done that but it should work.

 

The pins that are defined as 0 and 1 should be on different pins. That would be the stop and right buttons. Just pick an open pin and change the declaration in the sketch to match.

 

For Accel Stepper to work, you will need to change the AccelStepper object.

 

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

You have to put it into mode 1 so that it knows that you are using a driver. You will need to do this on any example you try from that library.

Here is an example using the Accel Stepper. Change the 1 and 0 pins to what will work for you. I did not include the LCD yet. You can try that after you confirm your setup is working correctly.

 

//Test of accelstepper

#include <AccelStepper.h>

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

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

//Interupt Handlers
void formotor (){

  dirfor = true;
  go = true;
  
}

void bacmotor (){

  dirfor = false;
  go = true;
  
}

void stpmotor (){

  stepper.stop();
  go = false;
  
}


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.setMaxSpeed(1000);
}

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

 

Madmisha,

  I have been testing and trying to get this code to work but it doesn't even try to move the stepper. I changed the pins that were 0, and 1 to 12, and 13 and complied the code. Got an error about sp_pot not being defined so I realized that should have been "spd" in the code so I changed all instances of that to "spd" which was the potentiometer on A1. The codes passes the verify and compiles but nothing happens. Any ideas? Here is what I have now:

Edit: I changed the mode here to DRIVER as follows after reading up on it but it did not change anything. And the Pul and Dir are pins 2 and 3.

AccelStepper stepper(1,2,3);

 

 

 

DSCF4089

 

 

#include <AccelStepper.h>
#include <MultiStepper.h>

//Test of accelstepper

#include <AccelStepper.h>

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

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

//Interupt Handlers
void formotor (){

  dirFor = true;
  go = true;
  
}

void bacmotor (){

  dirFor = false;
  go = true;
  
}

void stpmotor (){

  stepper.stop();
  go = false;
  
}


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.setMaxSpeed(1000);
}

void loop()
{  
  if(go == true){
    spd = map((analogRead(spd)),0,1023,2000,50);
    if(dirFor == true){
      stepper.setSpeed(spd);
    } else {
      stepper.setSpeed((spd*-1));
    }
    stepper.runSpeed();
  } else {
    stepper.stop();
  }
}

 

Thanks,
Voltage


   
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  

So I kept thinking my problem would be with the

AccelStepper stepper(1,2,3);

But a 1 in the first position seemed correct and I tried using "DRIVER" but no change. I am using only 2 pins to the stepper driver as shown in the info below. I reloaded my previous code and after reassigning the 2 pins I changed it works as before.

Symbolic names for number of pins. Use this in the pins argument the AccelStepper constructor to provide a symbolic name for the number of pins to use.

Enumerator:
FUNCTION 

Use the functional interface, implementing your own driver functions (internal use only)

DRIVER 

Stepper Driver, 2 driver pins required.

FULL2WIRE 

2 wire stepper, 2 motor pins required

FULL3WIRE 

3 wire stepper, such as HDD spindle, 3 motor pins required

FULL4WIRE 

4 wire full stepper, 4 motor pins required

HALF3WIRE 

3 wire half stepper, such as HDD spindle, 3 motor pins required

HALF4WIRE 

4 wire half stepper, 4 motor pins required

Thanks,
Voltage


   
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  
Posted by: @madmisha

@voltage

Depending on the quality of the potentiometer, you might be getting some variance. Have you thought of just setting it in a digital fashion? If there is an equation that will get you the speed you need, you could just adjust the diameter of the part using buttons or an encoder and it would set the speed based on that. It can still be speed based if you need it to.

All of the sketches here really depend on timing. Accel Stepper needs you keep repeating the run command as many times as possible. So if it does not need to check the potentiometer every loop, buttons or a rotary encoder(rotary encoder is a quick thought and I would have to think more if this one is a good idea, it might not be. Might be better adjusting in the off state) would be better with an interrupt.

 

Edit: I just thought that alternately, you could increase the speed in any direction using the left right buttons you have(as well as starting it in that direction). Pressing it will increase the set speed or decrease it and the stop will reset it to 0. Or instead of resetting it to 0 and it just running the stop command, if it is in the stopped state, start it at the last speed. That way LCD could run from the button interrupt when the change occurred and the loop will solely be running the motor.

Madmisha,

  I am using a Bourns 10K 1 turn Pot (280 degree) but I like the digital button idea as it sounds doable with inexpensive parts. As far as a formula I use a piece of tape with 1/8 increments and dial the speed in by counting 1,001, 1,002, 1,003, etc and if the torch tip matches then it is in the ball park and maybe a minor adjustment will be needed dependent on other factors such as thickness, heat, filler diameter etc. The fomula is something like InchesPerMinute\Pi * DiameterOfPart.

I am all ears on the last comment you added but first I need to get it running. 🙂

 

Thanks,
Voltage


   
ReplyQuote
Will
 Will
(@will)
Noble Member
Joined: 1 year ago
Posts: 2134
 

@voltage

 

Since it appears that the latest code doesn't completely fix the problem, here is another code set to test.

As discussed, you need to use the pot to set the speed before pressing the go button and then press the go button again to stop.

I have arbitrarily set the speed range from .1 RPM to 3 RPM. I think this is a reasonable speed range for the intended purpose, but please correct me if I'm wrong. I have included delays for RPM values from .1 to 10.

I switched the pins from 1 and 0 to 12 and 13. Please make sure that I guessed correctly or modify the code to match your pin use.

The pulse delay to speed calculation is documented in the comments section. Please check it over to make sure that I haven't oopsed the formula.

I'd appreciate it if @madmisha would check out the code as well to see if more improvements can be made or to point out any errors - thanks.

/*
  Stepper Motor Test Altered/Butchered
  Uses MA860H or similar Stepper Driver Unit
  Has speed control & direction and stop switches
  
  Original: DroneBot Workshop 2019
    https://dronebotworkshop.com  

  Rendered totally unrecognizable by Voltage, MadMisha and Will in
        August, 2021.
*/

#include <LiquidCrystal.h>

// Define our three button pins and the stepper driver pins
int LEFT_PIN = 11;
int STOP_PIN = 12;
int RIGHT_PIN = 13;
int driverPUL = 2;      // PUL- pin
int driverDIR = 3;      // DIR- pin

// Variables
LiquidCrystal lcd(8,9,4,5,6,7);
bool go = false;        // Rotating or stopped
int pd = 500;           // Pulse Delay period
boolean setdir = LOW;   // Set Direction
int stepsPerRevolution = 400;
int spd = A1;           // Potentiometer

// Interrupt Handlers
//
void formotor (){
  setdir = HIGH;
}
//
void bacmotor (){
  setdir = LOW;
}
//
//  If we were going, stop now. If we were stopped, go now
//
void stpmotor (){
  go = !go;
}

//*****************************************************
void setup() {
  // Set pin modes
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
  pinMode (driverPUL, OUTPUT);
  pinMode (driverDIR, OUTPUT);
  
  // LCD initialization
  lcd.begin(16, 2);
  lcd.setCursor(1,0);
  lcd.print("Speed:      RPM");
  
  // Interrupt associations
  attachInterrupt(digitalPinToInterrupt(LEFT_PIN), formotor, FALLING);
  attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), bacmotor, FALLING);
  attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
}

//*****************************************************
//
//      Read the speed potentiometer and generate
//      a reasonable estimate of RPM from it
//      and then display the RPM.
//      Continue doing this until the go button is
//      pushed again.
//
void getNewSpeed() {
  while (!go) {
    pd = map((analogRead(spd)),0,1023,750,25); // Set delay from pot reading
    //
    //   Need to check speed range to set delay range in map above
    //       - 10 RPM is about 8 ms
    //       - 5 RPM is about 15 ms
    //       - 3 RPM is about 25 ms
    //       - 2 RPM is about 38 ms
    //       - 1 RPM is about 75 ms
    //       - .5 RPM is about 150 ms
    //       - .1 RPM is about 750 ms
    //
    //   What range of RPM is required ?
    //
    //    One step = the time spent in the two digitalWrites and the two
    //        delayMicroseconds calls. To get a better estimate of the
    //        time per loop, you can time 1000 steps and then divide that
    //        time by 1000 to get a more precise estimated time per loop.
    //
    //    Here, we assume each digitalWrite takes neglibible time so estimate
    //        time per step = 2*pd (in millis)
    //        stepsPerSecond = 1000 (uSecs) / time per step
    //        RPM = stepsPerSecond * seconds per minute / stepsPerRevolution
    //
    float timePerStep = 2*pd;
    float stepsPerSecond = 1000/timePerStep;
    float RPM = stepsPerSecond * 60 / stepsPerRevolution;
    lcd.setCursor(7,0);
    lcd.print("     "); // Clear area for new speed calculated
    lcd.setCursor(7,0);
    lcd.print(RPM,1);   // Display new speed
    //
    delay(50);     // Wait for LCD to settle
  } 
}

//********************************************************
void loop() {
  if (go) {
    //
    // We're running, take a single step in the current direction
    //
    digitalWrite(driverDIR,setdir);
    digitalWrite(driverPUL,HIGH);
    delay(pd);
    digitalWrite(driverPUL,LOW);
    delay(pd);
  } else {
    //
    //  Not running, try getting a new speed from the user
    //
    getNewSpeed();
  }
}

 

 

Experience is what you get when you don't get what you want.


   
Voltage reacted
ReplyQuote
Voltage
(@voltage)
Estimable Member
Joined: 1 year ago
Posts: 176
Topic starter  

@will

Thanks Will, I will give it a test right now. Fingers crossed. 😀 

 

Edit: I downloaded and verified and compiled but noticed you made an edit so I did it a second time just in case you changed so code. It does not work as the stepper never runs. The readout on the LCD displays from .1-3 RPM so that part works. Maybe it's the same thing where madmisha's code and yours doesn't work? I will see if I can spot anything but I am not the expert. 🙂

 

@Will. When you say the "Go" button I can use either the "Right" or "Left" for that correct? otherwise I only have a "Stop" button.

Thanks,
Voltage


   
ReplyQuote
MadMisha
(@madmisha)
Reputable Member
Joined: 3 years ago
Posts: 346
 

@voltage

That variable should not be spd. That is the pin for the pot. It was a local and adding int before if might have corrected it. It did compile before I sent it so that is odd. Sometimes different computers handle local variable differently. Also, that mapping was for Bills sketch and you could always change it to yours.

 

If you want to also give this a try, I did make a button version. It adds one button and you don't need the pot. We can add the formula later if it does work. I think I thought of everything. Stop button is start and stop. left is decrease, right increase and new button changes direction. I included the LCD on this one and added the direction of travel on the second line of the LCD.

 

//Test of accelstepper with LCD

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

//Define pins
int LEFT_PIN = 11; //Decrease Speed
int STOP_PIN = 1;  //Start and Stop
int RIGHT_PIN = 0;  //Increase Speed
int DIR_PIN = 13;   //Change direction of rotation
int driverPUL = 2;    // PUL- pin
int driverDIR = 3;    // DIR- pin
bool go = false;  //Is it running
bool dirFor = true; //Direction to go in
int rotation = 50; //Speed of rotation
int incChng = 50; //Change in speed to add or minus

AccelStepper stepper(1,2,3); // This needs to change in any example you use(Mode, Pul, Dir)

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

//Interupt Handlers
void formotor (){ //Right Button

  if (go) {
    if(rotation < 1001 - incChng){
      rotation = rotation + incChng;
      if (dirFor){
        stepper.setSpeed(rotation);
      } else {
        stepper.setSpeed(rotation * -1);
      }
      lcd.setCursor(7,0);
      lcd.print(rotation);
      stepper.runSpeed();
    }
        
  } else {
      if(rotation < 1001 - incChng){
        rotation = rotation + incChng;
        lcd.setCursor(7,0);
        lcd.print(rotation);
      }
  }
}

void bacmotor (){  //Left Button

  if (go) {
    if(rotation > incChng){
      rotation = rotation - incChng;
      if (dirFor){
        stepper.setSpeed(rotation);
      } else {
        stepper.setSpeed(rotation * -1);
      }
    lcd.setCursor(7,0);
    lcd.print(rotation);
    stepper.runSpeed(); 
    }
       
  } else {
    if(rotation > incChng){
      rotation = rotation - incChng;
      lcd.setCursor(7,0);
      lcd.print(rotation);
    }
  }
}

void stpmotor (){  //Stop Button

  if (go){
    stepper.stop();
    go = false;
  } else {
    go = true;
    stepper.runSpeed();
  } 
}

void dirmotor (){   //Direction Button

  if(go){
    stepper.stop();
    dirFor = !dirFor;
    lcd.setCursor(0,1);
    if (dirFor){
      lcd.print("Right");
      stepper.setSpeed(rotation);
    } else {
      lcd.print("Left ");
      stepper.setSpeed(rotation * -1);
    }
    delay(100); //Delay to assure stop
    stepper.runSpeed();
    
  } else {
    lcd.setCursor(0,1);
    dirFor = !dirFor;
    if(dirFor){
      stepper.setSpeed(rotation);
      lcd.print("Right");
    } else {
      stepper.setSpeed(rotation * -1);
      lcd.print("Left ");
    }
  }
}


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

   attachInterrupt(digitalPinToInterrupt(RIGHT_PIN), formotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(LEFT_PIN), bacmotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(STOP_PIN), stpmotor, FALLING);
   attachInterrupt(digitalPinToInterrupt(DIR_PIN), dirmotor, FALLING);
   
   stepper.setMaxSpeed(1000);
   stepper.setSpeed(rotation);

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

void loop()
{  
  if(go == true){
    stepper.runSpeed();
  }
}

 

 Can you post the positions of the switches on the driver? The AccelStepper stepper(1,2,3) should be correct. I am curious if it was set up a different way for the other sketch.


   
ReplyQuote
Page 3 / 21