Go Down

Topic: Accelstepper Libraray + PING))) Sensors + Metro Library= Cross-talk? (Read 199 times) previous topic - next topic

Bigrob55

Good day all,

Hopefully this is the correct location to post this request for guidance with my robot.

So far i have been very happy using the Adafruit Motorshield v2.3 to drive two stepper motors with the AccelStepper library on my Arduino Mega 2560.

My short term goal is to be able to have the Stepper motors accelerate/run smoothly and without interruption, as the sonar sensors fire and measure distances independently.

To accomplish this i turned to the Metro Library thinking i could separate the two and have time do separate work, without using the delay(); function.




The issue I am facing arises when I try to incorporate two Parallax PING))) sensors into the mix, as the sonar sensors fire, the stepper motors "tick" during rotation every 500 milliseconds in sync with the timing of the sonars.

To reiterate; the steppers do work as commanded, and if i were to tell the sonar sensors not to fire at all, the steppers move smoothly as commanded without any jitters.

I suspect my problem is either due to my lack of knowledge of how the timers work on Arduino, and/or perhaps a limitation of the Metro library.

If it is a timer issue, is there a way to tell the NewPing library to use a different timer on the Mega?

I am open to any suggestions that you folks may have.

All the best,
Bigrob

Here is the code thus far:
Code: [Select]

#include <Wire.h>
#include <Metro.h>
#include <NewPing.h>
#include <AccelStepper.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

#define SONAR_NUM     2 // Number of sensors.
#define LEFT_PING_PIN 7 // Arduino pin tied to echo pin on the left ultrasonic sensor.
#define RIGHT_PING_PIN 8 // Arduino pin tied to echo pin on the right ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing leftSonar(LEFT_PING_PIN, LEFT_PING_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
NewPing rightSonar(RIGHT_PING_PIN, RIGHT_PING_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

////////////////////////////////////////////////////////////////////////////////////////////////

// Connect two steppers with 200 steps per revolution (1.8 degree)
Adafruit_MotorShield adafruitMotorShield(0x60); // Default address, no jumpers
Adafruit_StepperMotor *myrightStepper = adafruitMotorShield.getStepper(200, 1);
Adafruit_StepperMotor *myleftStepper = adafruitMotorShield.getStepper(200, 2);

////////////////////////////////////////////////////////////////////////////////////////////////
// wrappers for the first motor!
void forwardstep1() { 
  myrightStepper->onestep(FORWARD, SINGLE);
}
void backwardstep1() { 
  myrightStepper->onestep(BACKWARD, SINGLE);
}
// wrappers for the second motor!
void forwardstep2() { 
  myleftStepper->onestep(FORWARD, SINGLE);
}
void backwardstep2() { 
  myleftStepper->onestep(BACKWARD, SINGLE);
}

// Now we'll wrap the steppers in an AccelStepper object
AccelStepper rightStepper(forwardstep1, backwardstep1);
AccelStepper leftStepper(forwardstep2, backwardstep2);

////////////////////////////////////////////////////////////////////////////////////////////////

// Create variables to hold the component refresh flags
int flag0 = HIGH; // fire sonar
int flag1 = HIGH; // change stepper speed
int flag2 = HIGH; // print data
int flag3 = HIGH; // Clear terminal window
int flag4 = HIGH; // Run Steppers

// Create metro object and set the interval to 500 milliseconds (0.500 seconds).
Metro sonarRate = Metro(500);
Metro motorSpeedUpdate = Metro(3000);
Metro printDataTimer = Metro(20000);
Metro clearTerminalTimer = Metro(520);
Metro runStepperTimer = Metro(0);

// =============================================== BEGIN SETUP ===============================================
void setup()
{
  adafruitMotorShield.begin(); // Start the stepper shield

  rightStepper.setMaxSpeed(10.0);
  rightStepper.setAcceleration(20.0);
  rightStepper.move(2000);

  leftStepper.setMaxSpeed(10.0);
  leftStepper.setAcceleration(20.0);
  leftStepper.move(2000);
 
  Serial.begin(9600); // Open serial monitor at 9600 baud.
 
  Serial.println(" *-= R.A.S. BOT II =-* ");
  Serial.println("");
 
}
// =============================================== END SETUP ===============================================




// =============================================== BEGIN LOOP ===============================================
void loop()
{

 
    if (sonarRate.check() == 1) { // check if the metro has passed its interval .
    if (flag0==HIGH)  flag0=LOW;
    else flag0=HIGH;
    fireSonar();
    }

    if (motorSpeedUpdate.check() == 1) { // check if the metro has passed its interval .
    if (flag1==HIGH)  flag1=LOW;
    else flag1=HIGH;
    changeMotorSpeed();
    }

    if (printDataTimer.check() == 1) { // check if the metro has passed its interval .
    if (flag2==HIGH)  flag2=LOW;
    else flag2=HIGH;
    printData();
    }

    if (clearTerminalTimer.check() == 1) { // check if the metro has passed its interval .
    if (flag3==HIGH)  flag3=LOW;
    else flag3=HIGH;
   // clearTerminal();
    }

    if (runStepperTimer.check() == 1) { // check if the metro has passed its interval .
    if (flag4==HIGH)  flag4=LOW;
    else flag4=HIGH;
    runSteppers();
    }

 }
// =============================================== END LOOP ===============================================


///////////////////////////////////////////////////
void runSteppers()

  rightStepper.run();
  leftStepper.run();
}

///////////////////////////////////////////////////
void fireSonar()
{
  leftSonar.ping_in(); // Send ping, get distance in Inches (0 = outside set distance range)
  rightSonar.ping_in(); // Send ping, get distance in Inches (0 = outside set distance range)
   }

///////////////////////////////////////////////////
  void changeMotorSpeed()
  {
  rightStepper.setMaxSpeed(400.0);
  rightStepper.setAcceleration(20.0);
 //rightStepper.move(999);

  leftStepper.setMaxSpeed(400.0);
  leftStepper.setAcceleration(20.0);
  //leftStepper.move(999);   
  } 
 
///////////////////////////////////////////////////
  void printData()
  {
  Serial.print("L Motor Speed: ");
  Serial.print(leftStepper.speed());
 
  Serial.println(); // LINE RETURN
 
  Serial.print("R Motor Speed: ");
  Serial.println(rightStepper.speed());

  Serial.println(); // LINE RETURN

  Serial.print("L Sonar: ");
  Serial.print(leftSonar.ping_in()); // Send ping, get distance in Inches and print result (0 = outside set distance range)
  Serial.print(" in"); // Prints "in" label

  Serial.println(); // LINE RETURN

  Serial.print("R Sonar: ");
  Serial.print(rightSonar.ping_in()); // Send ping, get distance in Inches and print result (0 = outside set distance range)
  Serial.print(" in"); // Prints "in" label

  Serial.println(); // LINE RETURN
  Serial.println(); // LINE RETURN
  }

///////////////////////////////////////////////////
  void clearTerminal()
  {
  Serial.write(27);
  Serial.print("[2J"); // clear screen
  Serial.write(27); // ESC
  Serial.print("[H"); // cursor to home
  }

 // END OF CODE

PaulS

Quote
void forwardstep1() {
  myrightStepper->onestep(FORWARD, SINGLE);
}
void backwardstep1() {
  myrightStepper->onestep(BACKWARD, SINGLE);
}
// wrappers for the second motor!
void forwardstep2() {
  myleftStepper->onestep(FORWARD, SINGLE);
}
void backwardstep2() {
  myleftStepper->onestep(BACKWARD, SINGLE);
}
Pass a stepper instance and a direction to ONE function.

Code: [Select]
// Create metro object and set the interval to 500 milliseconds (0.500 seconds).
Metro sonarRate = Metro(500);
Metro motorSpeedUpdate = Metro(3000);
Metro printDataTimer = Metro(20000);
Metro clearTerminalTimer = Metro(520);
Metro runStepperTimer = Metro(0);

Which one does the comment refer to? What is the sense in having a timer fire ever 0 microsecond/milliseconds/nanoseconds/days/months/years?

Code: [Select]
    if (flag0==HIGH)  flag0=LOW;
    else flag0=HIGH;

Or
Code: [Select]
   flag0 = !flag0;

Code: [Select]
    if (runStepperTimer.check() == 1) { // check if the metro has passed its interval .
    if (flag4==HIGH)  flag4=LOW;
    else flag4=HIGH;
    runSteppers();
    }

The runSteppers() function should be called on EVERY pass through loop().

Bigrob55

PaulS!!

I believe you had helped me before on a different project!


Thank you for the speedy reply and guidance.

I am going to implement your suggestions, and i'll get back to you tonight.


- Cheers

Bigrob55

Alright, i have implemented all the changes you have suggested but one.


I don't understand what you mean by

Quote
Pass a stepper instance and a direction to ONE function.
Can you please elaborate, or provide an example?

- Thank you.

PaulS

Quote
Can you please elaborate, or provide an example?
Code: [Select]
void MoveTheStepper(Adafruit_StepperMotor *pStepper, byte stepDirection)
{
   pStepper->onestep(stepDirection, SINGLE);
}


Code: [Select]
   MoveTheStepper(myrightStepper, FORWARD);

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy