1

I'm very new to arduino and have to work on a project for school. We have connected 3 motors (Servo, Stepper (180 degrees) and a DC motor) to an Arduino Uno, Adafruit motorshield and a pcb. With the pcb we were able to record values of the motors individually and use these values to create a playback motion. The code which we got for the playback motion is below (I've already filled in my values for the 3 motors).

This is what I want to do with the motors:

When I press a button I want to 'start' the cycle of motor motions

  1. first the dc motor starts doing the motion based on the chosen values
  2. When this stops after 5 seconds I want the servo motor to do it's motion
  3. When the servo motor is done, I want the stepper motor to start doing the motion based on the chosen values for 5 seconds and then stop.

We were told not to use a delay and someone suggested to use millis() instead of delay() but since I am a beginner I have no idea where to start.

This is the code:

// With this code it is possible to play back recorded motion paths for for motors connected to the Adafruit motorshield

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <Servo.h> // this is a library that allows you to drive servo's.

// variables
int modeChoice = 0;

int buttons = A2;  // the three buttons share an analog pin, resitors provide different levels that point to which button is pressed
int slide = A1;    // the slide is read through one analog pin, resitors provide different levels that point to which slide position is current
int rotation = A0; // the pin for the potentiometer

int buttonPressed = 0; // a variable to remember which button is pressed, it is used to control leds and motion memory position management

int buttonValRaw = 0; // a variable to store the raw analog reading of the buttons pin
int slideValRaw = 0;  // a variable to sore the raw analog reading of the slide pin
int valButton = 0;    // a variable to store the interpreted value, the exact pointer to a button
int valSlide = 0;     // a variable to store the interpreted value, the exact pointer to a slide position
int idleState = 0;    // a variable to toggle the servo idle behavior
int resetMotion = 0;  // a variable to return the arrayPosition to 0 if a button is pushed so that the behaviour starts at the beginning
int motionVar1;       // a variable to hold a motion position
int motionVar2;       // another variable to hold a motion position

int mySensorArray[20];  // an array with 20 slots to store raw potentiometer readings (for filtering)
int sensorArrayPos = 0; // the array position of interest.



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

int servoMotionArray_B1[50] = {95, 95, 95, 95, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // paste your 50 values in between the brackets

int DCMotionArray_B1[50] = {-85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85};

//recorded motions for position implementation
int StepperMotionArray_B1[50] = {-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200};

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




int arrayPosition = 0;

unsigned long mainTimer = 0; // a variable to time recording and playback
int timeBetweenSamples = 100; // the time between samples.

unsigned long debounceTimer = 0; // a variable to control a timer interval for debouncing of the buttons
int lastValButton = 0; // a variable to help debouncing of the buttons
int debounceFlag = 0; // another variabel to help debouncing of the buttons



// Setup motors
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Connect a stepper motor with 16 steps per revolution (2048 positions) to motor port #1 (M1 and M2) -- you need to change this if your stepper is on port #2
Adafruit_StepperMotor *myStepper = AFMS.getStepper(16, 1);
// And connect a DC motor to port M3 -- you need to change this if your DC is on a different port
Adafruit_DCMotor *myMotor = AFMS.getMotor(3);

Servo myservo1;   // servo object (employs the servo library that was included above)

// these are dedicated functions to make the steppermotor move
void forwardstep1() {
  myStepper->onestep(FORWARD, SINGLE);
}
void backwardstep1() {
  myStepper->onestep(BACKWARD, SINGLE);
}

//create aStepper object
AccelStepper aStepper(forwardstep1, backwardstep1); // use functions to step


// setup
void setup() {
  Serial.begin(9600); // start serial communication with 9600 baud rate


  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz

  myservo1.attach(9); // attach servo object to pin 9

  // turn on motor M3
  myMotor->setSpeed(0);
  myMotor->run(RELEASE);

  // setup the stepper
  aStepper.setSpeed(0); // this is used in the 'speed' implementation

  aStepper.setMaxSpeed(200.0); // these are used in the 'position' implementation
  aStepper.setAcceleration(100.0);
  aStepper.moveTo(0);

  // synchronize the first timer cycle -- because the timer is starting at zero it generates negative values in the first 100 miliseconds after starting up when going through the timer cycle, creating potential erratic bahaviour-- giving it a delay at the end of the setup loop will eradicate this behaviour
  delay(1000);
}

void doButtons() {
  if (buttonPressed != 0) {
    return;
  }
  else {
    buttonValRaw = analogRead(buttons);
    valButton = map (buttonValRaw, 49, 605, 0, 5);
    int localButtonVal = valButton;

    if (valButton > 7) {
      return;
    }

    if (debounceFlag == 0) {
      debounceTimer = millis();
      debounceFlag = 1;
    }

    if (debounceTimer < millis() - 20) {

      buttonValRaw = analogRead(buttons);
      valButton = map (buttonValRaw, 49, 605, 0, 5);

      if (valButton == localButtonVal) {
        debounceFlag = 0;

        switch (valButton) {
          case 1:
            buttonPressed = 1;
            break;
          case 2:
            buttonPressed = 2;
            break;
          case 3:
            buttonPressed = 3;
            break;
          default:
            buttonPressed = 0;
            break;
        }
      }
    }
  }
}

void loop() {
  doButtons(); // this uses the buttons from the PCB, if you use your own implementation you need to reprogram this function

  if (mainTimer < millis() - timeBetweenSamples) { // sampling only once per interval.
    mainTimer = millis(); // time is rewritten to current millis starting a new interval.

    if (buttonPressed == 0) { //'idle play'
      if (idleState == 0) {
        motionVar1 = servoMotionArray_B1[arrayPosition];
      }
      else if (idleState == 1){
        motionVar1 = servoMotionArray_B1[arrayPosition];
      }
      motionVar2 = DCMotionArray_B1[arrayPosition];
      myservo1.write(motionVar1);
      if (motionVar2 < 0) {
        myMotor->run(BACKWARD);
        myMotor->setSpeed(abs(motionVar2));
      }
      else if (motionVar2 >= 0) {
        myMotor->run(FORWARD);
        myMotor->setSpeed(motionVar2);
      }
      arrayPosition++;
      if (arrayPosition > 49) {
        arrayPosition = 0;
        idleState = !idleState;
      }
    }

    if (buttonPressed == 1) { //2nd behaviour
      if (resetMotion == 0) {
        arrayPosition = 0;
        resetMotion = 1;
        myMotor->run(RELEASE); // release the DC motor, otherwise it will continue spinning at the last known RPM
      }
      motionVar1 = servoMotionArray_B3[arrayPosition];
      motionVar2 = StepperMotionArray_B1[arrayPosition];
      myservo1.write(motionVar1);
      aStepper.moveTo(motionVar2);
      arrayPosition++;
      if (arrayPosition > 49) {
        arrayPosition = 0;
        buttonPressed = 0;
        resetMotion = 0;
      }
    }
  }



  // one of these needs to be called to make the stepper motor work, comment out the one you do not need (position or speed)
  //aStepper.run(); //stepper position implementation
  aStepper.runSpeed(); //stepper speed implementation

}

1 Answer 1

1

You're almost correct already:

if (millis() - mainTimer >= timeBetweenSamples) {
  mainTimer = millis(); 
  // executing only once per interval.

  ... the action for current arrayPosition ...

  arrayPosition++;
  if (arrayPosition > 49) {
     arrayPosition = 0;
     buttonPressed = 0; // Show ends
  }   
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.