0

Running stepper motors simultaneously using the Adafruit Mot
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Tue May 15, 2018 6:59 am

I have tried using and if-statement, with greenLEDstate == LOW && redLEDstate == LOW, to reset the position,

Why are you using that state to reset the position? Take another look at your description of the problem:

How do I make the stepper run every time, I put my hand in front of the sensor? :)

The sensor is the condition that should trigger your reset.

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Wed May 16, 2018 12:29 pm

Using the sensor to trigger the reset works! :D

But my steppers are turning really slow I have tried implementing the following code:
Code: Select all | TOGGLE FULL SIZE
TWBR = ((F_CPU /400000l) - 16) / 2;
, but it only speeds up the stepping process a tiny bit? I have also tried using different values for speed and acceleration, but nothing dramatic is happening. I am using three 5V 28BYJ-48 DC steppers. They should be able to run faster.

My power supply is still a 5V, 1000mA DC supply.

Code: Select all | TOGGLE FULL SIZE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL /////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Below are the needed libraries imported into the document ready to use in the script

    #include <Wire.h>                                                             // wire library used for I2C
    #include <AccelStepper.h>                                                     // step library used for steppers
    #include <Adafruit_MotorShield.h>                                             // motor library used for steppers

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Some global variables available anywhere in the program
   
    // Digital pins used to make the RGB LED light up
    const int redPin = 3;                                                         // red RGB LED on pin 3
    const int greenPin = 5;                                                       // green RGB LED on pin 5
    const int bluePin = 6;                                                        // blue RGB LED on pin 6

    // Digital pins used to messure the distance for the sensor
    const int trigPin = 11;                                                       // trigger pin 11 on sensor
    const int echoPin = 12;                                                       // echo pin 12 on sensor

    // Long variable that holds the information about the distance messured
    long duration, distance;

    // Booleans used for the LED statements
    bool redLEDstate = LOW;                                                       // state of LED output
    bool greenLEDstate = LOW;                                                     // state of LED output
    bool blueLEDstate = LOW;                                                      // state of LED output

    // Last phase change time (in milliseconds)
    uint32_t lastChange = 0;                                                      // change value default 0

    // Variables used to fade the blue LED up and down
    int value;                                                                    // variable in fading sequence
    long times = 0;                                                               // variable in fading sequence

    int periode = 2000;                                                           // fading period
    int displace = 500;                                                           // fading displace

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   
    // createa the motor shield object with specified I2C addresses
    Adafruit_MotorShield AFMSbot(0x61);                                           // rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60);                                           // default address, no jumpers

    // On the top shield, connect two steppers, each with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(513, 2);

    // On the bottom shield, connect one stepper with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2)
    Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(513, 1);
   

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// WRAPPERS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // change these to DOUBLE or INTERLEAVE or MICROSTEP!

    void forwardstep1() {                                                         // wrappers for the first motor!
     
      myStepper1->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() { 
      myStepper1->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep2() {                                                         // wrappers for the second motor!
      myStepper2->onestep(FORWARD, DOUBLE);
    }
    void backwardstep2() { 
      myStepper2->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep3() {                                                         // wrappers for the third motor!
      myStepper3->onestep(FORWARD, DOUBLE);
    }
    void backwardstep3() { 
      myStepper3->onestep(BACKWARD, DOUBLE);
    }

    // Now we'll wrap the 3 steppers in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);
    AccelStepper stepper2(forwardstep2, backwardstep2);
    AccelStepper stepper3(forwardstep3, backwardstep3);
   
   
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // Set up communicatoin to serial monitor
      Serial.begin(9600);                                                         // baud rate for communication

      // Pin modes for RGB LED strip
      pinMode(redPin, OUTPUT);                                                    // pin 3 output
      pinMode(greenPin, OUTPUT);                                                  // pin 5 output
      pinMode(bluePin, OUTPUT);                                                   // pin 6 output

      // Pin modes for ultrasonic sensor
      pinMode(trigPin, OUTPUT);                                                   // pin 11 output
      pinMode(echoPin, INPUT);                                                    // pin 12 input

      // sets frequancy on the V2 shields to 1.6 kHz (default)
      AFMSbot.begin();                                                            // start the bottom shield
      AFMStop.begin();                                                            // start the top shield
     
      // steppers configuration for speed - max speed 500 rpm
      // steppers configuration for acceleration

      stepper1.setMaxSpeed(500.0);
      stepper1.setAcceleration(100.0);

      stepper2.setMaxSpeed(500.0);
      stepper2.setAcceleration(100.0);
 
      stepper3.setMaxSpeed(500.0);
      stepper3.setAcceleration(100.0);

      // change the I2C clock to 400KHz insted of 100KHz
      // to optimize communication and speed of steppers
      TWBR = ((F_CPU /400000l) - 16) / 2;
           
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop(){

      // Trigger ultrasonic 'ping'
      digitalWrite(trigPin, LOW); 
      digitalWrite(trigPin, HIGH);
      digitalWrite(trigPin, LOW);

      // Calcualte distance from echo time
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
     
      distance = (duration/2) / 29.1;

      // Green LED sequence (#1)
     
      if (distance < 5)                                                           // something is in range
      {
        if ((greenLEDstate == LOW) && (blueLEDstate == HIGH))                     // green LED is currently OFF and blue is on
        {
          greenLEDstate = HIGH;                                                   // turn it on green LED
          lastChange = millis();                                                  // remember the time

          stepper1.setCurrentPosition(0);                                         // resets the stepper 1 position to 0
          stepper2.setCurrentPosition(0);                                         // resets the stepper 2 position to 0
          stepper3.setCurrentPosition(0);                                         // resets the stepper 3 position to 0
        }
      }

      // Yellow LED sequence
     
      if ((greenLEDstate == HIGH) && (millis() - lastChange > 1000))              // LED has been ON for more than 1 second
      {                                                                       
        greenLEDstate = HIGH;                                                     // after 1 second the green LED is still on 
        redLEDstate = HIGH;                                                       // and the red LED also turns on (combined yellow LED)
      }

      // Green LED sequence (#2)
     
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH) && (millis() - lastChange > 15000))         // red and green LED has been ON for more than 14 additional seconds
      {
        greenLEDstate = HIGH;                                                     // green stays on while
        redLEDstate = LOW;                                                        // red LED turns off
       
        myStepper1->release();
        myStepper2->release();
        myStepper3->release();
      }

      if ((greenLEDstate == HIGH) && (millis() - lastChange > 16000))             // green LED has been ON for more than 1 additional second
      {
        greenLEDstate = LOW;                                                      // so turn it off
      }

      // Blue LED sequence

      if (distance > 5)                                                           // nothing is in range
      {
        blueLEDstate = HIGH;                                                      // if nothing is in range blue LED lights up

        times = millis();                                                         // time used to calculate fading sequence
        value = 128 + 127 * cos(2*PI / periode * times);                          // fading seguence calculated
       
        if (greenLEDstate == HIGH)                                                // if nothing is there but the green LED is on, the blue should be off
        {
          blueLEDstate = LOW;                                                     // the blue turns off
          value = 0;                                                              // sets value to 0 to deactivate fading
        }
      }

      // Stepper sequence

      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH))                       // green and red LED is high: move steppers
      {
        stepper1.moveTo(1024);
        stepper3.moveTo(-1024/2);
      }

      if (stepper1.currentPosition() == 1024/2)
      {
        stepper2.moveTo(1024/2);
      }

      // Update the LED to match the current state;
      digitalWrite(greenPin, greenLEDstate);                                      // green LED on if state is active
      digitalWrite(redPin, redLEDstate);                                          // red LED on if state is active
      analogWrite(bluePin, value);                                                // blue LED fade up and down

      stepper1.run();                                                             // run stepper 1
      stepper2.run();                                                             // run stepper 2
      stepper3.run();                                                             // run stepper 3
     
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Wed May 16, 2018 12:40 pm

The new version of the Wire library includes a setClock() function that makes it easier to set the i2c clock speed: https://www.arduino.cc/en/Reference/WireSetClock
Some users have had success increasing the clock speed to as much as 1000000 (fast mode plus).

But with >500 steps per revolution, the 28BYJ-48 are not particularly fast motors. They are designed for opening and closing dampers in ventilation systems, so they are not typically run faster then just a few RPM.

It is possible to squeeze a bit more speed out of the system with a bit of library hacking. See this post for details:
viewtopic.php?f=31&t=57041&p=292119

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Wed May 16, 2018 1:33 pm

Changing the clock speed did not seem to change anything - sadly.

I know the steppers can run faster than what I am achieving right now - that is what makes it a bit annoying. :P

I feel like something in my code is jamming the rest of the system to function properly. I tried using setSpeed(500) instead, but did not work either.

Code: Select all | TOGGLE FULL SIZE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL /////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Below are the needed libraries imported into the document ready to use in the script
   
    #include <Wire.h>                                                             // wire library used for I2C
    #include <AccelStepper.h>                                                     // step library used for steppers
    #include <Adafruit_MotorShield.h>                                             // motor library used for steppers

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Some global variables available anywhere in the program
   
    // Digital pins used to make the RGB LED light up
    const int redPin = 3;                                                         // red RGB LED on pin 3
    const int greenPin = 5;                                                       // green RGB LED on pin 5
    const int bluePin = 6;                                                        // blue RGB LED on pin 6

    // Digital pins used to messure the distance for the sensor
    const int trigPin = 11;                                                       // trigger pin 11 on sensor
    const int echoPin = 12;                                                       // echo pin 12 on sensor

    // Long variable that holds the information about the distance messured
    long duration, distance;

    // Booleans used for the LED statements
    bool redLEDstate = LOW;                                                       // state of LED output
    bool greenLEDstate = LOW;                                                     // state of LED output
    bool blueLEDstate = LOW;                                                      // state of LED output

    // Last phase change time (in milliseconds)
    uint32_t lastChange = 0;                                                      // change value default 0

    // Variables used to fade the blue LED up and down
    int value;                                                                    // variable in fading sequence
    long times = 0;                                                               // variable in fading sequence

    int periode = 2000;                                                           // fading period
    int displace = 500;                                                           // fading displace

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   
    // createa the motor shield object with specified I2C addresses
    Adafruit_MotorShield AFMSbot(0x61);                                           // rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60);                                           // default address, no jumpers

    // On the top shield, connect two steppers, each with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(513, 2);

    // On the bottom shield, connect one stepper with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2)
    Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(513, 1);
   

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// WRAPPERS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // change these to DOUBLE or INTERLEAVE or MICROSTEP!

    void forwardstep1() {                                                         // wrappers for the first motor!
      myStepper1->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() { 
      myStepper1->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep2() {                                                         // wrappers for the second motor!
      myStepper2->onestep(FORWARD, DOUBLE);
    }
    void backwardstep2() { 
      myStepper2->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep3() {                                                         // wrappers for the third motor!
      myStepper3->onestep(FORWARD, DOUBLE);
    }
    void backwardstep3() { 
      myStepper3->onestep(BACKWARD, DOUBLE);
    }

    // Now we'll wrap the 3 steppers in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);
    AccelStepper stepper2(forwardstep2, backwardstep2);
    AccelStepper stepper3(forwardstep3, backwardstep3);
   
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // Set up communicatoin to serial monitor
      Serial.begin(9600);                                                         // baud rate for communication

      Wire.begin();
      Wire.setClock(1000000);
           
      // Pin modes for RGB LED strip
      pinMode(redPin, OUTPUT);                                                    // pin 3 output
      pinMode(greenPin, OUTPUT);                                                  // pin 5 output
      pinMode(bluePin, OUTPUT);                                                   // pin 6 output

      // Pin modes for ultrasonic sensor
      pinMode(trigPin, OUTPUT);                                                   // pin 11 output
      pinMode(echoPin, INPUT);                                                    // pin 12 input

      // sets frequancy on the V2 shields to 1.6 kHz (default)
      AFMSbot.begin();                                                            // start the bottom shield
      AFMStop.begin();                                                            // start the top shield
     
      // steppers configuration for speed - max speed 500 rpm
      // steppers configuration for acceleration

      /*
      stepper1.setMaxSpeed(500.0);
      stepper1.setAcceleration(100.0);

      stepper2.setMaxSpeed(500.0);
      stepper2.setAcceleration(100.0);
 
      stepper3.setMaxSpeed(500.0);
      stepper3.setAcceleration(100.0);
      */

      stepper1.setSpeed(500);
      stepper2.setSpeed(500);
      stepper3.setSpeed(500);

      // change the I2C clock to 800KHz insted of 100KHz
      // to optimize communication and speed of steppers
      TWBR = ((F_CPU /800000l) - 16) / 2;
           
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop(){

      // Trigger ultrasonic 'ping'
      digitalWrite(trigPin, LOW); 
      digitalWrite(trigPin, HIGH);
      digitalWrite(trigPin, LOW);

      // Calcualte distance from echo time
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
     
      distance = (duration/2) / 29.1;

      // Green LED sequence (#1)
     
      if (distance < 5)                                                           // something is in range
      {
        if ((greenLEDstate == LOW) && (blueLEDstate == HIGH))                     // green LED is currently OFF and blue is on
        {
          greenLEDstate = HIGH;                                                   // turn it on green LED
          lastChange = millis();                                                  // remember the time

          stepper1.setCurrentPosition(0);                                         // resets the stepper 1 position to 0
          stepper2.setCurrentPosition(0);                                         // resets the stepper 2 position to 0
          stepper3.setCurrentPosition(0);                                         // resets the stepper 3 position to 0
        }
      }

      // Yellow LED sequence
     
      if ((greenLEDstate == HIGH) && (millis() - lastChange > 1000))              // LED has been ON for more than 1 second
      {                                                                       
        greenLEDstate = HIGH;                                                     // after 1 second the green LED is still on 
        redLEDstate = HIGH;                                                       // and the red LED also turns on (combined yellow LED)
      }

      // Green LED sequence (#2)
     
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH) && (millis() - lastChange > 15000))         // red and green LED has been ON for more than 14 additional seconds
      {
        greenLEDstate = HIGH;                                                     // green stays on while
        redLEDstate = LOW;                                                        // red LED turns off

        myStepper1->release();
        myStepper2->release();
        myStepper3->release();
      }

      if ((greenLEDstate == HIGH) && (millis() - lastChange > 16000))             // green LED has been ON for more than 1 additional second
      {
        greenLEDstate = LOW;                                                      // so turn it off
      }

      // Blue LED sequence

      if (distance > 5)                                                           // nothing is in range
      {
        blueLEDstate = HIGH;                                                      // if nothing is in range blue LED lights up

        times = millis();                                                         // time used to calculate fading sequence
        value = 128 + 127 * cos(2*PI / periode * times);                          // fading seguence calculated
       
        if (greenLEDstate == HIGH)                                                // if nothing is there but the green LED is on, the blue should be off
        {
          blueLEDstate = LOW;                                                     // the blue turns off
          value = 0;                                                              // sets value to 0 to deactivate fading
        }
      }

      // Stepper sequence

      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH))                       // green and red LED is high: move steppers
      {
        stepper1.moveTo(1024);
        stepper3.moveTo(1024);
      }

      if (stepper1.currentPosition() == 1024/2)
      {
        stepper2.moveTo(1024);
      }

      // Update the LED to match the current state;
      digitalWrite(greenPin, greenLEDstate);                                      // green LED on if state is active
      digitalWrite(redPin, redLEDstate);                                          // red LED on if state is active
      analogWrite(bluePin, value);                                                // blue LED fade up and down

      stepper1.run();                                                             // run stepper 1
      stepper2.run();                                                             // run stepper 2
      stepper3.run();                                                             // run stepper 3
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Wed May 16, 2018 1:36 pm

The 'setclock' has to come after the 'begin' calls for the motor shields.

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Wed May 16, 2018 1:48 pm

i tried that but i am still experiencing some jamming, could there be other syntax errors im missing?
Code: Select all | TOGGLE FULL SIZE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL /////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Below are the needed libraries imported into the document ready to use in the script
   
    #include <Wire.h>                                                             // wire library used for I2C
    #include <AccelStepper.h>                                                     // step library used for steppers
    #include <Adafruit_MotorShield.h>                                             // motor library used for steppers

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Some global variables available anywhere in the program
   
    // Digital pins used to make the RGB LED light up
    const int redPin = 3;                                                         // red RGB LED on pin 3
    const int greenPin = 5;                                                       // green RGB LED on pin 5
    const int bluePin = 6;                                                        // blue RGB LED on pin 6

    // Digital pins used to messure the distance for the sensor
    const int trigPin = 11;                                                       // trigger pin 11 on sensor
    const int echoPin = 12;                                                       // echo pin 12 on sensor

    // Long variable that holds the information about the distance messured
    long duration, distance;

    // Booleans used for the LED statements
    bool redLEDstate = LOW;                                                       // state of LED output
    bool greenLEDstate = LOW;                                                     // state of LED output
    bool blueLEDstate = LOW;                                                      // state of LED output

    // Last phase change time (in milliseconds)
    uint32_t lastChange = 0;                                                      // change value default 0

    // Variables used to fade the blue LED up and down
    int value;                                                                    // variable in fading sequence
    long times = 0;                                                               // variable in fading sequence

    int periode = 2000;                                                           // fading period
    int displace = 500;                                                           // fading displace

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   
    // createa the motor shield object with specified I2C addresses
    Adafruit_MotorShield AFMSbot(0x61);                                           // rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60);                                           // default address, no jumpers

    // On the top shield, connect two steppers, each with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(513, 2);

    // On the bottom shield, connect one stepper with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2)
    Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(513, 1);
   

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// WRAPPERS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // change these to DOUBLE or INTERLEAVE or MICROSTEP!

    void forwardstep1() {                                                         // wrappers for the first motor!
      myStepper1->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() { 
      myStepper1->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep2() {                                                         // wrappers for the second motor!
      myStepper2->onestep(FORWARD, DOUBLE);
    }
    void backwardstep2() { 
      myStepper2->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep3() {                                                         // wrappers for the third motor!
      myStepper3->onestep(FORWARD, DOUBLE);
    }
    void backwardstep3() { 
      myStepper3->onestep(BACKWARD, DOUBLE);
    }

    // Now we'll wrap the 3 steppers in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);
    AccelStepper stepper2(forwardstep2, backwardstep2);
    AccelStepper stepper3(forwardstep3, backwardstep3);
   
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // Set up communicatoin to serial monitor
      Serial.begin(9600);                                                         // baud rate for communication
      Wire.begin();
           
      // Pin modes for RGB LED strip
      pinMode(redPin, OUTPUT);                                                    // pin 3 output
      pinMode(greenPin, OUTPUT);                                                  // pin 5 output
      pinMode(bluePin, OUTPUT);                                                   // pin 6 output

      // Pin modes for ultrasonic sensor
      pinMode(trigPin, OUTPUT);                                                   // pin 11 output
      pinMode(echoPin, INPUT);                                                    // pin 12 input

      // sets frequancy on the V2 shields to 1.6 kHz (default)
      AFMSbot.begin();                                                            // start the bottom shield
      AFMStop.begin();                                                            // start the top shield

      Wire.setClock(400000);
     
      // steppers configuration for speed - max speed 500 rpm
      // steppers configuration for acceleration

      /*
      stepper1.setMaxSpeed(500.0);
      stepper1.setAcceleration(100.0);

      stepper2.setMaxSpeed(500.0);
      stepper2.setAcceleration(100.0);
 
      stepper3.setMaxSpeed(500.0);
      stepper3.setAcceleration(100.0);
      */

      stepper1.setSpeed(500);
      stepper2.setSpeed(500);
      stepper3.setSpeed(500);

      // change the I2C clock to 800KHz insted of 100KHz
      // to optimize communication and speed of steppers
      TWBR = ((F_CPU /800000l) - 16) / 2;
           
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop(){

      // Trigger ultrasonic 'ping'
      digitalWrite(trigPin, LOW); 
      digitalWrite(trigPin, HIGH);
      digitalWrite(trigPin, LOW);

      // Calcualte distance from echo time
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
     
      distance = (duration/2) / 29.1;

      // Green LED sequence (#1)
     
      if (distance < 5)                                                           // something is in range
      {
        if ((greenLEDstate == LOW) && (blueLEDstate == HIGH))                     // green LED is currently OFF and blue is on
        {
          greenLEDstate = HIGH;                                                   // turn it on green LED
          lastChange = millis();                                                  // remember the time

          stepper1.setCurrentPosition(0);                                         // resets the stepper 1 position to 0
          stepper2.setCurrentPosition(0);                                         // resets the stepper 2 position to 0
          stepper3.setCurrentPosition(0);                                         // resets the stepper 3 position to 0
        }
      }

      // Yellow LED sequence
     
      if ((greenLEDstate == HIGH) && (millis() - lastChange > 1000))              // LED has been ON for more than 1 second
      {                                                                       
        greenLEDstate = HIGH;                                                     // after 1 second the green LED is still on 
        redLEDstate = HIGH;                                                       // and the red LED also turns on (combined yellow LED)
      }

      // Green LED sequence (#2)
     
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH) && (millis() - lastChange > 15000))         // red and green LED has been ON for more than 14 additional seconds
      {
        greenLEDstate = HIGH;                                                     // green stays on while
        redLEDstate = LOW;                                                        // red LED turns off

        myStepper1->release();
        myStepper2->release();
        myStepper3->release();
      }

      if ((greenLEDstate == HIGH) && (millis() - lastChange > 16000))             // green LED has been ON for more than 1 additional second
      {
        greenLEDstate = LOW;                                                      // so turn it off
      }

      // Blue LED sequence

      if (distance > 5)                                                           // nothing is in range
      {
        blueLEDstate = HIGH;                                                      // if nothing is in range blue LED lights up

        times = millis();                                                         // time used to calculate fading sequence
        value = 128 + 127 * cos(2*PI / periode * times);                          // fading seguence calculated
       
        if (greenLEDstate == HIGH)                                                // if nothing is there but the green LED is on, the blue should be off
        {
          blueLEDstate = LOW;                                                     // the blue turns off
          value = 0;                                                              // sets value to 0 to deactivate fading
        }
      }

      // Stepper sequence

      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH))                       // green and red LED is high: move steppers
      {
        stepper1.moveTo(1024);
        stepper3.moveTo(1024);
      }

      if (stepper1.currentPosition() == 1024/2)
      {
        stepper2.moveTo(1024);
      }

      // Update the LED to match the current state;
      digitalWrite(greenPin, greenLEDstate);                                      // green LED on if state is active
      digitalWrite(redPin, redLEDstate);                                          // red LED on if state is active
      analogWrite(bluePin, value);                                                // blue LED fade up and down

      stepper1.run();                                                             // run stepper 1
      stepper2.run();                                                             // run stepper 2
      stepper3.run();                                                             // run stepper 3
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Wed May 16, 2018 1:55 pm

Not sure what you mean by 'jammng'. But you are trying to do both the setClock() call and the TWBR statement. The last one you do is the one that controls your clock speed.

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Wed May 16, 2018 2:07 pm

Sorry, I meant "jittering", as in the stepper motors does not step consistently and at a much lower pase than I know they can (I tested them with another code to make sure it was not the hardware). I have uploaded the current code in which I am trying to make work and also the test code I used:

Current code:
Code: Select all | TOGGLE FULL SIZE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL /////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Below are the needed libraries imported into the document ready to use in the script
   
    #include <Wire.h>                                                             // wire library used for I2C
    #include <AccelStepper.h>                                                     // step library used for steppers
    #include <Adafruit_MotorShield.h>                                             // motor library used for steppers

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Some global variables available anywhere in the program
   
    // Digital pins used to make the RGB LED light up
    const int redPin = 3;                                                         // red RGB LED on pin 3
    const int greenPin = 5;                                                       // green RGB LED on pin 5
    const int bluePin = 6;                                                        // blue RGB LED on pin 6

    // Digital pins used to messure the distance for the sensor
    const int trigPin = 11;                                                       // trigger pin 11 on sensor
    const int echoPin = 12;                                                       // echo pin 12 on sensor

    // Long variable that holds the information about the distance messured
    long duration, distance;

    // Booleans used for the LED statements
    bool redLEDstate = LOW;                                                       // state of LED output
    bool greenLEDstate = LOW;                                                     // state of LED output
    bool blueLEDstate = LOW;                                                      // state of LED output

    // Last phase change time (in milliseconds)
    uint32_t lastChange = 0;                                                      // change value default 0

    // Variables used to fade the blue LED up and down
    int value;                                                                    // variable in fading sequence
    long times = 0;                                                               // variable in fading sequence

    int periode = 2000;                                                           // fading period
    int displace = 500;                                                           // fading displace

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   
    // createa the motor shield object with specified I2C addresses
    Adafruit_MotorShield AFMSbot(0x61);                                           // rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60);                                           // default address, no jumpers

    // On the top shield, connect two steppers, each with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(513, 2);

    // On the bottom shield, connect one stepper with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2)
    Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(513, 1);
   

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// WRAPPERS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // change these to DOUBLE or INTERLEAVE or MICROSTEP!

    void forwardstep1() {                                                         // wrappers for the first motor!
      myStepper1->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() { 
      myStepper1->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep2() {                                                         // wrappers for the second motor!
      myStepper2->onestep(FORWARD, DOUBLE);
    }
    void backwardstep2() { 
      myStepper2->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep3() {                                                         // wrappers for the third motor!
      myStepper3->onestep(FORWARD, DOUBLE);
    }
    void backwardstep3() { 
      myStepper3->onestep(BACKWARD, DOUBLE);
    }

    // Now we'll wrap the 3 steppers in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);
    AccelStepper stepper2(forwardstep2, backwardstep2);
    AccelStepper stepper3(forwardstep3, backwardstep3);
   
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // Set up communicatoin to serial monitor
      Serial.begin(9600);                                                         // baud rate for communication
      Wire.begin();
           
      // Pin modes for RGB LED strip
      pinMode(redPin, OUTPUT);                                                    // pin 3 output
      pinMode(greenPin, OUTPUT);                                                  // pin 5 output
      pinMode(bluePin, OUTPUT);                                                   // pin 6 output

      // Pin modes for ultrasonic sensor
      pinMode(trigPin, OUTPUT);                                                   // pin 11 output
      pinMode(echoPin, INPUT);                                                    // pin 12 input

      // sets frequancy on the V2 shields to 1.6 kHz (default)
      AFMSbot.begin();                                                            // start the bottom shield
      AFMStop.begin();                                                            // start the top shield

      Wire.setClock(400000);
     
      // steppers configuration for speed - max speed 500 rpm
      // steppers configuration for acceleration

      /*
      stepper1.setMaxSpeed(500.0);
      stepper1.setAcceleration(100.0);

      stepper2.setMaxSpeed(500.0);
      stepper2.setAcceleration(100.0);
 
      stepper3.setMaxSpeed(500.0);
      stepper3.setAcceleration(100.0);
      */

      stepper1.setSpeed(500);
      stepper2.setSpeed(500);
      stepper3.setSpeed(500);

      // change the I2C clock to 800KHz insted of 100KHz
      // to optimize communication and speed of steppers
      // TWBR = ((F_CPU /800000l) - 16) / 2;
           
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop(){

      // Trigger ultrasonic 'ping'
      digitalWrite(trigPin, LOW); 
      digitalWrite(trigPin, HIGH);
      digitalWrite(trigPin, LOW);

      // Calcualte distance from echo time
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
     
      distance = (duration/2) / 29.1;

      // Green LED sequence (#1)
     
      if (distance < 5)                                                           // something is in range
      {
        if ((greenLEDstate == LOW) && (blueLEDstate == HIGH))                     // green LED is currently OFF and blue is on
        {
          greenLEDstate = HIGH;                                                   // turn it on green LED
          lastChange = millis();                                                  // remember the time

          stepper1.setCurrentPosition(0);                                         // resets the stepper 1 position to 0
          stepper2.setCurrentPosition(0);                                         // resets the stepper 2 position to 0
          stepper3.setCurrentPosition(0);                                         // resets the stepper 3 position to 0
        }
      }

      // Yellow LED sequence
     
      if ((greenLEDstate == HIGH) && (millis() - lastChange > 1000))              // LED has been ON for more than 1 second
      {                                                                       
        greenLEDstate = HIGH;                                                     // after 1 second the green LED is still on 
        redLEDstate = HIGH;                                                       // and the red LED also turns on (combined yellow LED)
      }

      // Green LED sequence (#2)
     
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH) && (millis() - lastChange > 15000))         // red and green LED has been ON for more than 14 additional seconds
      {
        greenLEDstate = HIGH;                                                     // green stays on while
        redLEDstate = LOW;                                                        // red LED turns off

        myStepper1->release();
        myStepper2->release();
        myStepper3->release();
      }

      if ((greenLEDstate == HIGH) && (millis() - lastChange > 16000))             // green LED has been ON for more than 1 additional second
      {
        greenLEDstate = LOW;                                                      // so turn it off
      }

      // Blue LED sequence

      if (distance > 5)                                                           // nothing is in range
      {
        blueLEDstate = HIGH;                                                      // if nothing is in range blue LED lights up

        times = millis();                                                         // time used to calculate fading sequence
        value = 128 + 127 * cos(2*PI / periode * times);                          // fading seguence calculated
       
        if (greenLEDstate == HIGH)                                                // if nothing is there but the green LED is on, the blue should be off
        {
          blueLEDstate = LOW;                                                     // the blue turns off
          value = 0;                                                              // sets value to 0 to deactivate fading
        }
      }

      // Stepper sequence

      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH))                       // green and red LED is high: move steppers
      {
        stepper1.moveTo(1024);
        stepper3.moveTo(1024);
      }

      if (stepper1.currentPosition() == 1024/2)
      {
        stepper2.moveTo(1024);
      }

      // Update the LED to match the current state;
      digitalWrite(greenPin, greenLEDstate);                                      // green LED on if state is active
      digitalWrite(redPin, redLEDstate);                                          // red LED on if state is active
      analogWrite(bluePin, value);                                                // blue LED fade up and down

      stepper1.run();                                                             // run stepper 1
      stepper2.run();                                                             // run stepper 2
      stepper3.run();                                                             // run stepper 3
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Test code
Code: Select all | TOGGLE FULL SIZE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL /////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Authors:

    // Oliver Sandholdt Kolmers         Technical University of Denmark (DTU)
    // Maria Væver Olsen                Technical University of Denmark (DTU)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// LIBRARIES /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // below are the needed libraries imported
    // into the document ready to use in the script
   
    #include <Stepper.h>
    #include <Wire.h>
    #include <AccelStepper.h>
    #include <Adafruit_MotorShield.h>
    #include "utility/Adafruit_MS_PWMServoDriver.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /*
    // createa the motor shield object with the default I2C address
    Adafruit_MotorShield AFMS = Adafruit_MotorShield();
   
    // connect two stepper motors with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper_1 = AFMS.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper_2 = AFMS.getStepper(513, 2);
    */


    Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers
   
    Adafruit_StepperMotor *myStepper_1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper_2 = AFMStop.getStepper(513, 2);
    Adafruit_StepperMotor *myStepper_3 = AFMSbot.getStepper(513, 1);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////// DEFINITIONS ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    // defines the digital pins used to make the RGB LED light up
   
    #define redPin 3
    #define greenPin 5
    #define bluePin 6

    // defines the digital pins used to messure the distance for the sensor
   
    #define trigPin 11
    #define echoPin 12

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // create a variable with start value zero used later to fade RGB LED
    int value = 0;

    // create a variable with start value zero used in I2C communication
    int x = 0;

    // create a variable that holds the information about the distance messured
    long duration, distance;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // set up communicatoin to serial monitor
      Serial.begin(9600);

      // start the I2C Bus as Master
      Wire.begin();

      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
     
      pinMode(redPin, OUTPUT);
      pinMode(greenPin, OUTPUT);
      pinMode(bluePin, OUTPUT);

      // sets frequancy on the V2 shield to 1.6 kHz (default)
      // AFMS.begin();

      AFMSbot.begin(); // Start the bottom shield
      AFMStop.begin(); // Start the top shield
     
      // steppers configuration for speed
      // max speed 500 rpm
     
      myStepper_1->setSpeed(500);
      myStepper_2->setSpeed(500);
      myStepper_3->setSpeed(500);


      // change the I2C clock to 800KHz insted of 100KHz:
      // - without = 11,87 sec for full rotation
      // - with = 3,74 sec for full rotation
     
      TWBR = ((F_CPU /400000l) - 16) / 2;
     
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop()
    {

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////// Ultrasonic sensor ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
      // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
     
      digitalWrite(trigPin, LOW);
      delayMicroseconds(5);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
     
      // Read the signal from the sensor: a HIGH pulse whose
      // duration is the time (in microseconds) from the sending
      // of the ping to the reception of its echo off of an object.
     
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
       
      // convert the time into a distance
      distance = (duration/2) / 29.1;
      delay(250);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// If statement //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      // if distance is equal to or less than 10 cm
      // execute the following sequence of code
     
      if(distance <= 10)
      {

        // blinking blue LED to signal
        // that the scan is succesfull
       
        setColor(0, 0, 255);
        delay(250);

        setColor(0, 0, 0);
        delay(250);

        setColor(0, 0, 255);
        delay(250);

        setColor(0, 0, 0);
        delay(250);

        setColor(0, 0, 255);
        delay(250);

        setColor(0, 0, 0);
        delay(250);

        setColor(0, 0, 255);
        delay(250);

        setColor(0, 0, 0);
        delay(250);
       
        // set yellow LED to signal
        // that the process has been initiated
       
        setColor(255, 255, 0);
        delay(250);

        // initiate conveying process
        // using I2C to activate slave
       
        myStepper_1->step(2048, FORWARD, DOUBLE);
        delay(250);

        myStepper_1->step(2048, BACKWARD, DOUBLE);
        delay(250);

        myStepper_1->release();
        delay(250);

   
       
        myStepper_2->step(2048, FORWARD, DOUBLE);
        delay(250);

        myStepper_2->step(2048, BACKWARD, DOUBLE);
        delay(250);

        myStepper_2->release();
        delay(250);



        myStepper_3->step(2048, FORWARD, DOUBLE);
        delay(250);

        myStepper_3->step(2048, FORWARD, DOUBLE);
        delay(250);

        myStepper_3->release();
        delay(250);
       
        // slave activate
        // send trigger signal
       

        /*
        Wire.beginTransmission(9);                      // transmit to device #9
        x = 1;
        Wire.write(x);                                  // sends x
        Wire.endTransmission();                         // stop transmitting
        x = 0;                                          // reset x
        */       
       
        // initiate last color sequence
       
        setColor(0, 0, 0);
        delay(250);

        setColor(0, 255, 0);
        delay(2000);

        setColor(0, 0, 0);
        delay(500);

      }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////// Else if statement ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      // if distance is greater than 10 cm
      // execute the following sequence of code
     
      else if(distance > 11)
      {

        for(value = 25 ; value <= 255; value+=5)        // fade in (from min to max)
        {
          analogWrite(bluePin, value);                  // sets the value (range from 25 to 255)
          delay(30);                                    // waits for 30 milli seconds to see the dimming effect
        }
     
        for(value = 255; value >=25; value-=5)          // fade out (from max to min)
        {
          analogWrite(bluePin, value);                  // sets the value (range from 25 to 255)
          delay(30);                                    // waits for 30 milli seconds to see the dimming effect
        }

      }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////// COLOR FUNCTION //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // This function takes three arguments, one for the brightness of the red, green and blue LEDs.
    // In each case the number will be in the range 0 to 255, where 0 means off and 255 means maximum brightness.
    // The function then calls 'analogWrite' to set the brightness of each LED.
   
    void setColor(int redValue, int greenValue, int blueValue) {
      analogWrite(redPin, redValue);
      analogWrite(greenPin, greenValue);
      analogWrite(bluePin, blueValue);
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Wed May 16, 2018 2:49 pm

You have this in your loop:
Code: Select all | TOGGLE FULL SIZE
      // Trigger ultrasonic 'ping'
      digitalWrite(trigPin, LOW); 
      digitalWrite(trigPin, HIGH);
      digitalWrite(trigPin, LOW);

      // Calcualte distance from echo time
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
     
      distance = (duration/2) / 29.1;

So the motors can't step any faster than you can read from your ultrasonic sensor.

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Thu May 17, 2018 10:58 am

I see! I have replaced the ultrasonic sensor with a simple pushbutton instead, and the motors move much, much smoother and faster now. Thank you!

I am almost done with my setup, but there is maybe a last thing I do not fully understand. When I click the pushbutton the first time I uploade the code to the arduino, the steppers move the right number of steps and at the right time.

But the second time I click the pushbutton, the steppers kinda ignores my if-statements and just starts stepping immediately?

Code: Select all | TOGGLE FULL SIZE
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL //////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Below are the needed libraries imported into the document ready to use in the script
   
    #include <Wire.h>                                                             // wire library for I2C
    #include <AccelStepper.h>                                                     // step library for steppers
    #include <Adafruit_MotorShield.h>                                             // motor library for steppers

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES /////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Some global variables available anywhere in the program
   
    // Digital pins used to make the RGB LED light up
    const int redPin = 3;                                                         // red RGB LED on pin 3
    const int greenPin = 5;                                                       // green RGB LED on pin 5
    const int bluePin = 6;                                                        // blue RGB LED on pin 6

    // Digital pins used to detect button state
    const int buttonPin = 2;                                                      // pushbutton on pin 2
         
    // Booleans used for the LED statements
    bool redLEDstate = LOW;                                                       // state of LED output
    bool greenLEDstate = LOW;                                                     // state of LED output
    bool blueLEDstate = LOW;                                                      // state of LED output

    // ...
    bool buttonState = LOW;                                                       // variable for reading pushbutton
   
    // Last phase change time (in milliseconds)
    uint32_t lastChange = 0;                                                      // change value default 0

    // Variables used to fade the blue LED up and down
    int value;                                                                    // variable in fading sequence
    long times = 0;                                                               // variable in fading sequence

    int periode = 2000;                                                           // fading period
    int displace = 500;                                                           // fading displace

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS //////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   
    // createa the motor shield object with specified I2C addresses
    Adafruit_MotorShield AFMSbot(0x61);                                           // rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60);                                           // default address, no jumpers

    // On the top shield, connect two steppers, each with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(513, 2);

    // On the bottom shield, connect one stepper with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2)
    Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(513, 1);
   

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// WRAPPERS //////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Change these to DOUBLE or INTERLEAVE or MICROSTEP

    void forwardstep1() {                                                         // wrappers for the first motor!
      myStepper1->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() { 
      myStepper1->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep2() {                                                         // wrappers for the second motor!
      myStepper2->onestep(FORWARD, DOUBLE);
    }
    void backwardstep2() { 
      myStepper2->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep3() {                                                         // wrappers for the third motor!
      myStepper3->onestep(FORWARD, DOUBLE);
    }
    void backwardstep3() { 
      myStepper3->onestep(BACKWARD, DOUBLE);
    }

    // Wrapper for the 3 steppers in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);
    AccelStepper stepper2(forwardstep2, backwardstep2);
    AccelStepper stepper3(forwardstep3, backwardstep3);
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP ///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // Set up communicatoin to serial monitor
      Serial.begin(9600);                                                         // baud rate for communication

      // Pin modes for RGB LED strip
      pinMode(redPin, OUTPUT);                                                    // pin 3 output
      pinMode(greenPin, OUTPUT);                                                  // pin 5 output
      pinMode(bluePin, OUTPUT);                                                   // pin 6 output

      // Pin modes for pushbutton                                                 
      pinMode(buttonPin, INPUT);                                                  // pin 2 input
     
      // Sets frequancy on the V2 shields to 1.6 kHz (default)
      AFMSbot.begin();                                                            // start the bottom shield
      AFMStop.begin();                                                            // start the top shield
     
      // Stepper configuration: speed and acceleratoin
      stepper1.setMaxSpeed(600.0);                                                // stepper 1 max speed
      stepper1.setAcceleration(200.0);                                            // stepper 1 acceleration

      stepper2.setMaxSpeed(600.0);                                                // stepper 2 max speed                 
      stepper2.setAcceleration(200.0);                                            // stepper 2 acceleration
 
      stepper3.setMaxSpeed(600.0);                                                // stepper 3 max speed
      stepper3.setAcceleration(200.0);                                            // stepper 3 acceleration

      // Change the I2C clock to 800KHz insted of 100KHz
      TWBR = ((F_CPU /800000l) - 16) / 2;
           
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP ///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop(){

      // Pushbutton used to trigger following sequences
      buttonState = digitalRead(buttonPin);                                       // read pushbutton value and store it

      // Green LED sequence (#1) ////////////////////////////////////////////////////////////////////////////////////////////////
     
      if (buttonState == HIGH)                                                    // pushbutton has been pushed
      {
        if ((greenLEDstate == LOW) && (blueLEDstate == HIGH))                     // green LED is currently off and blue is on
        {
          greenLEDstate = HIGH;                                                   // turn on green LED
          lastChange = millis();                                                  // remember the time

          stepper1.setCurrentPosition(0);                                         // resets the stepper 1 position to 0
          stepper2.setCurrentPosition(0);                                         // resets the stepper 2 position to 0
          stepper3.setCurrentPosition(0);                                         // resets the stepper 3 position to 0
        }
      }

      // Yellow LED sequence ////////////////////////////////////////////////////////////////////////////////////////////////////
     
      if ((greenLEDstate == HIGH) && (millis() - lastChange > 1000))              // LED has been ON for more than 1 second
      {                                                                       
        greenLEDstate = HIGH;                                                     // after 1 second the green LED is still on 
        redLEDstate = HIGH;                                                       // the red LED also turns on
      }

      // Green LED sequence (#2) ////////////////////////////////////////////////////////////////////////////////////////////////
     
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH) && (millis() - lastChange > 15000))         // 14 additional seconds
      {
        greenLEDstate = HIGH;                                                     // green LED stays on
        redLEDstate = LOW;                                                        // red LED turns off
       
        myStepper1->release();                                                    // release current from stepper 1
        myStepper2->release();                                                    // release current from stepper 2
        myStepper3->release();                                                    // release current from stepper 3
      }

      if ((greenLEDstate == HIGH) && (millis() - lastChange > 16000))             // 1 additional second
      {
        greenLEDstate = LOW;                                                      // green LED turn off
      }

      // Blue LED sequence //////////////////////////////////////////////////////////////////////////////////////////////////////

      if (buttonState == LOW)                                                     // pushbutton has not been pushed
      {
        blueLEDstate = HIGH;                                                      // if nothing is in range blue LED lights up

        times = millis();                                                         // time used to calculate fading sequence
        value = 128 + 127 * cos(2*PI / periode * times);                          // fading seguence calculated
       
        if (greenLEDstate == HIGH)                                                // green LED on, blue LED off
        {
          blueLEDstate = LOW;                                                     // the blue turns off
          value = 0;                                                              // sets value to 0 to deactivate fading
        }
      }

      // Stepper sequence ///////////////////////////////////////////////////////////////////////////////////////////////////////

      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH))                       // green and red LED is high: move steppers
      {
        stepper1.moveTo(2048);                                                    // change value for desired direction
        stepper3.moveTo(-2048);                                                   // change value for desired direction
      }

      if (stepper1.currentPosition() == 2048/2)
      {
        stepper2.moveTo(1024);                                                    // change value for desired direction
      }

      // Initiate the different sequences ///////////////////////////////////////////////////////////////////////////////////////
     
      // Update the LED to match the current state;
      digitalWrite(greenPin, greenLEDstate);                                      // green LED on if state is active
      digitalWrite(redPin, redLEDstate);                                          // red LED on if state is active
      analogWrite(bluePin, value);                                                // blue LED fade up and down

      stepper1.run();                                                             // run stepper 1
      stepper2.run();                                                             // run stepper 2
      stepper3.run();                                                             // run stepper 3
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END /////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Thu May 17, 2018 11:42 am

When you call setCurrentPosition(0) the second time around, you still have an active target position from the last moveTo command. So the motors will start moving toward that position.

You can reset the target position to 0 also by calling moveTo(0).
Or you can just call stop() after calling setCurrentPosition(0)
http://www.airspayce.com/mikem/arduino/ ... a76c00aced

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Thu May 17, 2018 12:05 pm

Or you can just call stop() after calling setCurrentPosition(0)


When I try to use the .stop(); function I get the following error message:

'class AccelStepper' has no member named 'stop'


I have also uploaded the code again so you can see where I try to implement it:

Code: Select all | TOGGLE FULL SIZE
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// FUNCTIONAL MODEL //////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Below are the needed libraries imported into the document ready to use in the script
   
    #include <Wire.h>                                                             // wire library for I2C
    #include <AccelStepper.h>                                                     // step library for steppers
    #include <Adafruit_MotorShield.h>                                             // motor library for steppers

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// VARIABLES /////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Some global variables available anywhere in the program
   
    // Digital pins used to make the RGB LED light up
    const int redPin = 3;                                                         // red RGB LED on pin 3
    const int greenPin = 5;                                                       // green RGB LED on pin 5
    const int bluePin = 6;                                                        // blue RGB LED on pin 6

    // Digital pins used to detect button state
    const int buttonPin = 2;                                                      // pushbutton on pin 2
         
    // Booleans used for the LED statements
    bool redLEDstate = LOW;                                                       // state of LED output
    bool greenLEDstate = LOW;                                                     // state of LED output
    bool blueLEDstate = LOW;                                                      // state of LED output

    // ...
    bool buttonState = LOW;                                                       // variable for reading pushbutton
   
    // Last phase change time (in milliseconds)
    uint32_t lastChange = 0;                                                      // change value default 0

    // Variables used to fade the blue LED up and down
    int value;                                                                    // variable in fading sequence
    long times = 0;                                                               // variable in fading sequence

    int periode = 2000;                                                           // fading period
    int displace = 500;                                                           // fading displace

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// OBJECTS //////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   
    // createa the motor shield object with specified I2C addresses
    Adafruit_MotorShield AFMSbot(0x61);                                           // rightmost jumper closed
    Adafruit_MotorShield AFMStop(0x60);                                           // default address, no jumpers

    // On the top shield, connect two steppers, each with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2) and port #2 (M3 and M4)
    Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(513, 1);
    Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(513, 2);

    // On the bottom shield, connect one stepper with 513 steps per revolution (11.25 degree)
    // to motor port #1 (M1 and M2)
    Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(513, 1);
   

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// WRAPPERS //////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // Change these to DOUBLE or INTERLEAVE or MICROSTEP

    void forwardstep1() {                                                         // wrappers for the first motor!
      myStepper1->onestep(FORWARD, DOUBLE);
    }
    void backwardstep1() { 
      myStepper1->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep2() {                                                         // wrappers for the second motor!
      myStepper2->onestep(FORWARD, DOUBLE);
    }
    void backwardstep2() { 
      myStepper2->onestep(BACKWARD, DOUBLE);
    }
   
    void forwardstep3() {                                                         // wrappers for the third motor!
      myStepper3->onestep(FORWARD, DOUBLE);
    }
    void backwardstep3() { 
      myStepper3->onestep(BACKWARD, DOUBLE);
    }

    // Wrapper for the 3 steppers in an AccelStepper object
    AccelStepper stepper1(forwardstep1, backwardstep1);
    AccelStepper stepper2(forwardstep2, backwardstep2);
    AccelStepper stepper3(forwardstep3, backwardstep3);
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////// SETUP ///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {

      // Set up communicatoin to serial monitor
      Serial.begin(9600);                                                         // baud rate for communication

      // Pin modes for RGB LED strip
      pinMode(redPin, OUTPUT);                                                    // pin 3 output
      pinMode(greenPin, OUTPUT);                                                  // pin 5 output
      pinMode(bluePin, OUTPUT);                                                   // pin 6 output

      // Pin modes for pushbutton                                                 
      pinMode(buttonPin, INPUT);                                                  // pin 2 input
     
      // Sets frequancy on the V2 shields to 1.6 kHz (default)
      AFMSbot.begin();                                                            // start the bottom shield
      AFMStop.begin();                                                            // start the top shield
     
      // Stepper configuration: speed and acceleratoin
      stepper1.setMaxSpeed(600.0);                                                // stepper 1 max speed
      stepper1.setAcceleration(200.0);                                            // stepper 1 acceleration

      stepper2.setMaxSpeed(600.0);                                                // stepper 2 max speed                 
      stepper2.setAcceleration(200.0);                                            // stepper 2 acceleration
 
      stepper3.setMaxSpeed(600.0);                                                // stepper 3 max speed
      stepper3.setAcceleration(200.0);                                            // stepper 3 acceleration

      // Change the I2C clock to 800KHz insted of 100KHz
      TWBR = ((F_CPU /800000l) - 16) / 2;
           
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// LOOP ///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop(){

      // Pushbutton used to trigger following sequences
      buttonState = digitalRead(buttonPin);                                       // read pushbutton value and store it

      // Green LED sequence (#1) ////////////////////////////////////////////////////////////////////////////////////////////////
     
      if (buttonState == HIGH)                                                    // pushbutton has been pushed
      {
        if ((greenLEDstate == LOW) && (blueLEDstate == HIGH))                     // green LED is currently off and blue is on
        {
          greenLEDstate = HIGH;                                                   // turn on green LED
          lastChange = millis();                                                  // remember the time

          stepper1.setCurrentPosition(0);                                         // resets the stepper 1 position to 0
          stepper2.setCurrentPosition(0);                                         // resets the stepper 2 position to 0
          stepper3.setCurrentPosition(0);                                         // resets the stepper 3 position to 0

          stepper1.stop();
        }
      }

      // Yellow LED sequence ////////////////////////////////////////////////////////////////////////////////////////////////////
     
      if ((greenLEDstate == HIGH) && (millis() - lastChange > 1000))              // LED has been ON for more than 1 second
      {                                                                       
        greenLEDstate = HIGH;                                                     // after 1 second the green LED is still on 
        redLEDstate = HIGH;                                                       // the red LED also turns on

        stepper1.moveTo(2048);                                                    // change value for desired direction
        stepper3.moveTo(-2048);                                                   // change value for desired direction

        if (stepper1.currentPosition() == 2048/2)
        {
          stepper2.moveTo(1024);                                                  // change value for desired direction
        }
      }

      // Green LED sequence (#2) ////////////////////////////////////////////////////////////////////////////////////////////////
     
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH) && (millis() - lastChange > 15000))         // 14 additional seconds
      {
        greenLEDstate = HIGH;                                                     // green LED stays on
        redLEDstate = LOW;                                                        // red LED turns off
       
        myStepper1->release();                                                    // release current from stepper 1
        myStepper2->release();                                                    // release current from stepper 2
        myStepper3->release();                                                    // release current from stepper 3
      }

      if ((greenLEDstate == HIGH) && (millis() - lastChange > 16000))             // 1 additional second
      {
        greenLEDstate = LOW;                                                      // green LED turn off
      }

      // Blue LED sequence //////////////////////////////////////////////////////////////////////////////////////////////////////

      if (buttonState == LOW)                                                     // pushbutton has not been pushed
      {
        blueLEDstate = HIGH;                                                      // if nothing is in range blue LED lights up

        times = millis();                                                         // time used to calculate fading sequence
        value = 128 + 127 * cos(2*PI / periode * times);                          // fading seguence calculated
       
        if (greenLEDstate == HIGH)                                                // green LED on, blue LED off
        {
          blueLEDstate = LOW;                                                     // the blue turns off
          value = 0;                                                              // sets value to 0 to deactivate fading
        }
      }

      // Stepper sequence ///////////////////////////////////////////////////////////////////////////////////////////////////////

      /*
      if ((greenLEDstate == HIGH) && (redLEDstate == HIGH))                       // green and red LED is high: move steppers
      {
        stepper1.moveTo(2048);                                                    // change value for desired direction
        stepper3.moveTo(-2048);                                                   // change value for desired direction
       
        if (stepper1.currentPosition() == 2048/2)
        {
          stepper2.moveTo(1024);                                                    // change value for desired direction
        }
      }
      */

      // Initiate the different sequences ///////////////////////////////////////////////////////////////////////////////////////
     
      // Update the LED to match the current state;
      digitalWrite(greenPin, greenLEDstate);                                      // green LED on if state is active
      digitalWrite(redPin, redLEDstate);                                          // red LED on if state is active
      analogWrite(bluePin, value);                                                // blue LED fade up and down

      stepper1.run();                                                             // run stepper 1
      stepper2.run();                                                             // run stepper 2
      stepper3.run();                                                             // run stepper 3
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// SCRIPT END /////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Thu May 17, 2018 12:16 pm

I fixed it! I had and outdated version of the library! :D

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Re: Running stepper motors simultaneously using the Adafruit

by adafruit_support_bill on Thu May 17, 2018 12:21 pm

I fixed it! I had and outdated version of the library! :D

That's good to hear. Everything working as planned now?

adafruit_support_bill
 
Posts: 69745
Joined: Sat Feb 07, 2009 10:11 am

Re: Running stepper motors simultaneously using the Adafruit

by kringle on Thu May 17, 2018 12:31 pm

It seems like it! :D Thank you so much for your huge support! Absolutely amazing how quick you are to answer. :)

kringle
 
Posts: 20
Joined: Wed May 09, 2018 10:26 am

Please be positive and constructive with your questions and comments.