MobaTools buttons and Acceleration

Hi, Starting to get this to work but having some issues I don't understand. My code below was modified from the example given in MobaTools. I have changed the driver pins for my setup and the stepRev for my setup. Also using buttons that are hooked to 5V with resistor as I need a high signal going to the analog pins.
Using A0 as 0 degrees and A2 as 180. These do as I expected moving about 180 which makes me believe my numbers are close. However, when A1 (90 Degrees) is pressed, it goes from 0 to 45? Then if A2, it does go to 180. While at 180, pressing A1 again it goes from 180 to 135 (-45)? Must be something simple.

Also, I don't understand the meaning of these 2 lines of code?
const byte buttonCnt = sizeof(buttonPins); // number of buttons/positions

MoToButtons myButtons( buttonPins, buttonCnt, 20, 500 );

```cpp
/*  Position a stepper according to buttonpresses
 *  The stepper is connected by means of a step/dir driver
 *  The buttons are connected between pins and GND ( using internal pullups )
 */
 
#include <MobaTools.h>

const int stepRev = 24000;    // steps per revolution ( 1/16 microsteps )
// adjust stepper pins to your needs
const byte dirPin = 2;
const byte stepPin = 3;
const byte enablePin = 8;

// create stepper object
MoToStepper myStepper( stepRev, STEPDIR );

// create button objects
const byte buttonPins[] = { A0,A1,A2,A3,A4 };               // adjust pins to your needs
const long stepperPositions[] = { 0, 90, 180, 270, 360 };   // in degrees, must be same number of elements as buttonPins
const byte buttonCnt = sizeof(buttonPins);                  // number of buttons/positions

MoToButtons myButtons( buttonPins, buttonCnt, 20, 500 );

void setup() {
  myStepper.attach(stepPin, dirPin);
  myStepper.setSpeed( 600 );                   // = 60 rpm
  myStepper.setRampLen( 200 );                        // 100 steps to achive set speed
  myStepper.attachEnable( enablePin, 100, LOW );    // if you want to switch off power when stepper reached position
  // a homing procedure may be needed here
}

void loop() {
  myButtons.processButtons();                // Check buttonstates
  
  for( byte pos= 0; pos<buttonCnt; pos ++ ) {
    if ( myButtons.pressed(pos) ) {
      // Button was pressed, move stepper to the according position
      myStepper.write( stepperPositions[pos] );
    }
  }
}

The answer is here: const byte buttonPins[] = { A0,A1,A2,A3,A4 };
Then lenght of the variable buttonPins is 5. 5 byte.

I don't understand that. Why do you need a high signal going to the pins? The MotoButtons class expects the buttons to be connected between pin and Gnd.

const int stepRev = 24000;    // steps per revolution ( 1/16 microsteps )

What stepper are you using, that it needs 24000 steps per revolution? Is there a gearbox?

myStepper.setSpeed( 600 ); // = 60 rpm
60rpm at 24000 steps / rev means 24000 steps per second. A standard Arduino isn't able to do that. What board are you using?

Edit: I tried your code with 3200 steps per rev. ( 200 steps stepper at 1/16 microsteps ) and with buttons connected to Gnd. It worked as expected.

Thanks for the reply.

  • Arduino Nano
  • Stepperonline 17HS19-16842S-PG5 Gear Ratio 5 to 1
  • DRV8825 driver with expansion bd. Dip switch set to on/off/off

I am using a 5 to1 gear box for the torque needed. (Rotating an 18" 3 lb disk on an 8mm shaft.) With these setting I'm able to get pretty smooth rotation and consistence results from point to point. Current settings of steps, speed, and ramp may need to be tweaked.

I need high signal for the analog pins because I'm only using the buttons as testing. Buttons will be replaced with ACS712 current sensor monitoring devices. When device (tool) is powered on the ACS output will jump up from 500 to > 570+. So, I'm coding for say >550 at the analog inputs to know what degree to move to.

Hope I included enough.
Thanks for any help

If you do so, you cannot use the MoToButtons. This class is only suitable for reading buttons from digital inputs - and it needs the buttons connected to Gnd.

I think your 24000 steps/rev is wrong. A stepper with 200steps/rev and a 5 to 1 gearbox needs 1000 steps per revolution. With 1/16 microsteps you need 16000 steps / rev. A wrong value for steps/rev leads to errors in compulting the angle. And you may need a longer ramp.

Thanks,
I thought the example I modified was yours on GITHUB and used analog pins?

As for the steps I am not sure the document for the dip switch settings is correct. Those were the settings that came close to operating correctly. I adj the steps till it would do a 360 degree rotation.

Thanks for any help
Greg

It uses A0 to A4, but it uses these pins as digital pins. Pins A0 to A5 can be used as analog or as digital pins.

Maybe it looses steps when starting because the ramp is too short. It's better to compute the steps per 360° than do it with try and error.

Thank for the help, I will try to recalculate the steps and adj the Ramp (acceleration). Reading this it looks like the ability to link the degrees to the analog pins is not part of the MotoButtons, but part of MotoStepper? If that's the case, I should be able to set the Analog ports up the other way without MotoButtons?
On some examples of the Railroad turn tables, do they just reply on the steppers to position the table or are there sensors involved?
I am using 1 haleffect sensor for homing, controlled by starting the system up, or doing a reset. I'm wondering if that can be used to checked/adj for position when it travels past it while going to new position?

Thanks

Well, part of MotoStepper is the ability to define a target position as degree. The conversion from degrees to steps is done by the MoToStepper class. To do that correctly it needs to know the number of steps per revolution. This information is given when the object is instantiated:

MoToStepper myStepper( stepRev, STEPDIR );

MoToButtons is designed to link actions to buttons that are connected to digital inputs. You can also use MoToButtons if the digital signals are created by some electronics. But it needs to be digital signal similar to a button signal.
If the actions depend on analog values, you have to do that by yourself.

Both is possible. Usually you have at least one sensor to detect the absolute position of the turntable. If you only have one sensor you need to know how many steps/degrees your positions are apart from the 'homing' sensor. Because of the gear backlash, this usually depends on the direction of rotation too ( and how exactly your positions must be reached ).

I would recommend to do so.

If you are not really using the analogue values, but only have a threshold to determine whether the input is "true" or "false" (i.e. convert an analogue signal into a digital signal), you could also use the callback functionality of MoToButtons, and convert your analogue values to digital values for the MoToButtons class.

OK, looks like I need to start reading some more! In total I will have 8 sensors, so I would have to mix & match analog and digital pins, {A0, A1, A2, A3, A4, D4, D5, D6 }
{0, 45, 90, 135, 180,...........}. I guess that is OK?

Reading the hardware state of the buttons can be done by a usercallback function. This enables designs where the buttons/switches are arranged in a matrix and/or read via a port extender

Not sure I understand how to accomplish this?

What signals will your sensors provide? If you connect them to digital pins, they must provide a digital signal.
NB: if you use a Nano you will have 8 analog inputs ( A0...A7 );

Yes, using a callback function is a bit more complicated, but it's not witchcraft. There is an example where the buttons are read via a callback from digital pins. getHW() is the callback function in this example.
Reading from analogue pins is very similar, but you have decide via a threshold if its HIGH or LOW.

Thanks for all your help. After watching the stepper closely, it has a pretty big back lash issue when changing directions. Possibly need to use a different stepper. Certainly not my only issue, but I may need to rethink design or plan. Really wanted it to be directional and take the shortest direction (CW/CCW). It was doing good when just using a simple pointer for testing. If I have to scrap this design, I think I will try the railroad one with the stepper on the outside turning a gear on disk.

Maybe you could tell a little bit more about your project?

Here is the code for the Test pointer. The description at the top of code is probably the best explanation. Tried to include video of both the test and the full-size project. (I will send them in email) The full-size would have 2.5" hoses connected to the openings. The inside rotor lines up to the tool in use and provides vacuum to remove the saw dust.
More than happy to share any extra.

type```cpp

 //  ********FOR DIAL SETUP TESTING ********

 

/*Auto Blast gate project:  for dust collection in wood shop.
  Arduino Nano
  ACS712 current sensor
  DRV8825 stepper driver with expansion card
  Nema 17 stepper/Nema 23
  Halls effect sensor
  Homing routine is run at startup or reset to exstablish stepper position
  Each tool will be monitor by a current sensor and when that analog port exceeds a given threshold
  1. Rotate the stepper to a predetermined position to align ports for that tool.
  2. After the gate is align a digital pin will drive relay to turn on Vacuum system.
      Vacuum will stay on as long as sensor exceed the threshold while tool is running. 
      When tool stops vacuum will continue for 4 seconds to clear remaining dust.
  3. If the same tool is used next, the Stepper will remain in it's current position.
      But the vacuum system should still operate the same.
  4.  currently using buttons to simulate tools and also one ACS712 for testing 
  
  This version disables stepper after movement to keep driver cool */

#include <MobaTools.h>

// defines pins numbers
const int stepPin = 3;
const int dirPin  = 2;
const int enPin  = 8;
const int vacPin = 4;
const int halPin = 6; 
MoToTimer  vacTimer; // for delayed switch off
const long runOnTime = 3000; //time for vac delay adjustable

int ca = 0;  //current angle
int na = 0;  //new angle
int stepPerAngle = 5 / 9; // full step = 1.8 or could have used "*1.8"
int   numstep;
int analogValue = 0;

void homefunction() {

  // Set motor speed pulse duration
  int pd = 1000;
  int   numstep;
  // Move motor until home position reached
  while (digitalRead(halPin) == 1) {

    digitalWrite(dirPin, LOW);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pd);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(pd);
     
  }
  for (int i=0; i<7; i++){
    digitalWrite(enPin, LOW);
    digitalWrite(dirPin, LOW);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pd);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(pd);
  }
  //(digitalRead(halPin)!=1) {
    //(numstep=25);
    {
    delay(200);
    digitalWrite(enPin, HIGH);
    }
  }




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

  // Sets the 3 pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enPin, OUTPUT);
  pinMode(vacPin, OUTPUT); 
  pinMode(halPin, INPUT);

  //set values for 3 outputs
  digitalWrite(enPin, LOW); 
  digitalWrite(dirPin, HIGH);
  digitalWrite(vacPin, LOW); 

  //home the motor
  homefunction();
 
}

void loop() {
  int n;
 analogValue = 0;
 
  
  // Assign button degrees section
  if      ( analogRead(A0) > 600) {
    analogValue = (analogRead(A0));
    Serial.print("AO = ");
    Serial.println(analogValue);
    na = 0;    
  }

  else if ( analogRead(A1) > 600) {
    analogValue = (analogRead(A1));
    Serial.print("A1 = ");
    Serial.println(analogValue);
    na = 45;    
  }
  
  else if ( analogRead(A2) > 600) {
    analogValue = (analogRead(A2));
    Serial.print("A2 = ");
    Serial.println(analogValue);
    na = 225;
  }
  
  else if ( analogRead(A3) > 600) {   
  analogValue = (analogRead(A3));
    Serial.print("A3 = ");
    Serial.println(analogValue);
    na =270;   
  }
   
// vacuum control section

  if(analogValue > 600 && ca==na) {
    digitalWrite(vacPin, HIGH);
  }

  if ( vacTimer.expired() ) {
    // switch off vac if timer expires
    Serial.println( "Vac = off");
    digitalWrite(vacPin, LOW);
  }

 if (analogValue < 600 && digitalRead( vacPin ) && !vacTimer.running()) {
    // start timer to switch off vac after time
    Serial.println( " start vac run-on-time" );
    vacTimer.setTime( runOnTime );
  }

// this section just determines stepper direction (CW/CCW) and steps
  if ( ca != na ) {

    //1st SCENARIO
  if (na - ca > 0 && na - ca <= 180)
    { digitalWrite(dirPin, HIGH);
      n = ((na - ca) * 5 / 9);
      numstep = n;
      ca = na;     
    }

    //2nd SCENARIO
    else if (ca - na > 0 && ca - na > 180)
    { digitalWrite(dirPin, HIGH);
      n = ((na + 360 - ca) * 5 / 9);
      numstep = n;
      ca = na;
    }

    // 3rd SCENARIO
    else if (na - ca < 0 && na - ca <= 180)
    { digitalWrite(dirPin, LOW);
      n = ((ca - na) * 5 / 9);
      numstep = n;
      ca = na;
    }

    //4th SCENARIO
    else if (na - ca > 0 && na - ca > 180)
    { digitalWrite(dirPin, LOW);
      n = ((ca + 360 - na) * 5 / 9);
      numstep = n;
      ca = na;   
    }
    

   //stepper control and speed

    for (int x = 0; x < numstep; x++) {
      digitalWrite(enPin, LOW);     //enable stepper
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(500);  
      digitalWrite(stepPin, LOW);
      delayMicroseconds(500);
    }     
    
    
    digitalWrite(enPin, HIGH);   //disable stepper,,,,,keeps driver cool
    delay(200);
  }
  
}


``` or paste code here

Well, now I remember, there was a topic some months ago. I think it's still the same project?
I made a suggestion with MobaTools in that thread, but that's not what you posted above. Didn't it work?

Yes, I believe that was in the Drone Bot forum. Was having trouble with program stopping during the Vacuum delay, The MotoTimer you suggested fixed that as shown in the coding posted. After that I was ready to deal with the full-size project. Requiring more torque than the testing platform, I tried a larger stepper and then a geared one. Reading the info for MobaTools the degree solution looked much simpler and cleaner than my approach.
I have learned much, and many times felt I was in over my head. I'm close, but starting to question my design, steppers, coding, etc.

I also made a suggestion with MoToStepper in that thread. Only the homing function was still missing. Didn't that work?
Of course the homing function could be done with MoToStepper too.

Yes, I added the homing function and it worked well. It's in the code included in the earlier post. Also added code at the end to disable stepper as the driver was heating up while just sitting.
I sent a video to your email. Couldn't get them attached in post due to size. One showed the working button test with homing.

Have made some progress with the big disk rotating correctly. Below is my recent code. Note that

  • Steps per rev is at 16600
  • Change my buttons to ground
  • Change the speed and ramp

Seems to be doing pretty good. Analog A6 and A7 aren't responding but believe it's the Nano BD.

MoToButtons myButtons( buttonPins, buttonCnt, 8,500);

Can you check this line. I still don't understand it. In the example it was 20,500?
Also in the header it refers to internal pullups. is that done in the library? I don't see it anywhere in the coding. Maybe default?

```cpp
 /*  Position a stepper according to buttonpresses
 *  The stepper is connected by means of a step/dir driver  
 *  The buttons are connected between pins and GND ( using internal pullups )
 */
 #define MAX8BUTTONS
#include <MobaTools.h>

const int stepRev = 16600;    // steps per revolution ( 1/16 microsteps )
// adjust stepper pins to your needs
const byte dirPin = 2;
const byte stepPin = 3;
const byte enablePin = 8;

// create stepper object
MoToStepper myStepper( stepRev, STEPDIR );

// create button objects
const byte buttonPins[] = {A0,A1,A2,A3,A4,A5,A6,A7};               // adjust pins to your needs
const long stepperPositions[] = {0, 45, 90, 135, 180, 225, 270, 315};   // in degrees, must be same number of elements as buttonPins
const byte buttonCnt = (8);                  // number of buttons/positions

MoToButtons myButtons( buttonPins, buttonCnt, 8,500);

void setup() {
  myStepper.attach(stepPin, dirPin);
  myStepper.setSpeed( 3000 );                          // = 5 to 1 gearedc
  myStepper.setRampLen(1000 );                        // 1000 steps to achive set speed
  myStepper.attachEnable( enablePin, 100, LOW );    // if you want to switch off power when stepper reached position
  // a homing procedure may be needed here
}

void loop() {
  myButtons.processButtons();                // Check buttonstates
  
  for( byte pos= 0; pos<buttonCnt; pos ++ ) {
    if ( myButtons.pressed(pos) ) {
      // Button was pressed, move stepper to the according position
      myStepper.write( stepperPositions[pos] );
    }
  }
}