brianinnes / vPiP

A python library with accompanying Arduino code to drive a vertical plotter from a Raspberry Pi. This project is targeted to drive the driver board created by makeBournemouth, but will work with any system capable of running Python and connecting to an Arduino/Genuino to drive the stepper motors
https://github.com/brianinnes/vPiP/wiki
Apache License 2.0
16 stars 11 forks source link

Arduino Motorshield v2.3 #8

Closed 5p4m3r closed 8 years ago

5p4m3r commented 8 years ago

Hi, I am trying to get your stepperdriver sketch to work with the arduino motorshield v2.3. and i am stuck. Obviously I am missing something very basic, but since i am new to python and arduino so i should start asking. I hope it is the right spot if not just point me to the right direction.

so here is my sketch:

//ADAFRUIT_MOTORSHIELD_V2.3

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <Adafruit_PWMServoDriver.h>
#include <AccelStepper.h>

const int stepType = MICROSTEP;

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
Adafruit_StepperMotor *afMotorAleft = AFMS.getStepper(200, 1); //left M1 M2
Adafruit_StepperMotor *afMotorBright = AFMS.getStepper(200, 2); //right M3 M4

void forwarda() { afMotorAleft->onestep(FORWARD, stepType); }
void backwarda() { afMotorAleft->onestep(BACKWARD, stepType); }
void forwardb() { afMotorBright->onestep(FORWARD, stepType); }
void backwardb() { afMotorBright->onestep(BACKWARD, stepType); }
AccelStepper motorA(forwarda, backwarda);
AccelStepper motorB(forwardb, backwardb);

// comment out to disable PENUP support
#define ENABLE_PENUP

// Constants and global variables
// --------------------------------------
const int LED_PINS_COUNT = 4;
const int LED_PINS[LED_PINS_COUNT] = {
  10,11,12,13}; // the pins of all of the leds, first 3 are status lights, 4th is receive indicator

#ifdef ENABLE_PENUP
#include <Servo.h>
Servo penUpServo;
char penTransitionDirection; // -1, 0, 1
const long PENUP_TRANSITION_US = 524288; // time to go from pen up to down, or down to up
const int PENUP_TRANSITION_US_LOG = 19; // 2^19 = 524288
const long PENUP_COOLDOWN_US = 1250000;
const long PENUP_ANGLE = 170;
const long PENDOWN_ANGLE = 85;
#endif

const unsigned int TIME_SLICE_US = 2048; // number of microseconds per time step
const unsigned int TIME_SLICE_US_LOG = 11; // log base 2 of TIME_SLICE_US
const unsigned int POS_FACTOR = 8; // fixed point factor each position is multiplied by
const unsigned int POS_FACTOR_LOG = 3; // log base 2 of POS_FACTOR, used after multiplying two fixed point numbers together

const char RESET_COMMAND = 0x80; // -128, (128) command to reset
const char PENUP_COMMAND = 0x81; // -127, (129) command to lift pen
const char PENDOWN_COMMAND = 0x7F; // 127,(127) command to lower pen

const unsigned int MOVE_DATA_CAPACITY = 1024;
char moveData[MOVE_DATA_CAPACITY]; // buffer of move data, circular buffer
unsigned int moveDataStart = 0; // where data is currently being read from
unsigned int moveDataLength = 0; // the number of items in the moveDataBuffer
unsigned int moveDataRequestPending = 0; // number of bytes requested

char leftDelta, rightDelta; // delta in the current slice
long leftStartPos, rightStartPos; // start position for this slice
long leftCurPos, rightCurPos; // current position of the spools

unsigned long curTime; // current time in microseconds
unsigned long sliceStartTime; // start of current slice in microseconds

// setup
// --------------------------------------
void setup() {
  Serial.begin(57600);
  Serial.setTimeout(0);

//ADAFRUIT_MOTORSHIELD_V2.3
  AFMS.begin();  // create with the default frequency 1.6KHz

  // setup pins
  for(int ledIndex = 0; ledIndex < LED_PINS_COUNT; ledIndex++) {
    pinMode(LED_PINS[ledIndex], OUTPUT);
    digitalWrite(LED_PINS[ledIndex], HIGH);
  }

#ifdef ENABLE_PENUP
  penUpServo.attach(9);
  penUpServo.write(PENUP_ANGLE);
  delay(1000);
  penUpServo.write(PENDOWN_ANGLE);
  delay(1000);
  penUpServo.write(PENUP_ANGLE);
#endif  

  ResetMovementVariables();

  delay(500);
  UpdateReceiveLed(false);
  UpdateStatusLeds(0);
}

// Reset all movement variables
// --------------------------------------
void ResetMovementVariables()
{
  leftDelta = rightDelta = leftStartPos = rightStartPos = leftCurPos = rightCurPos = 0;
  sliceStartTime = curTime;

#ifdef ENABLE_PENUP
  penTransitionDirection = 0;
  penUpServo.write(PENUP_ANGLE);
#endif  
}

// Main execution loop
// --------------------------------------
void loop() {
  curTime = micros();
  if (curTime < sliceStartTime) { // protect against 70 minute overflow
    sliceStartTime = 0;
  }

  long curSliceTime = curTime - sliceStartTime;

#ifdef ENABLE_PENUP
  if (penTransitionDirection) {
    UpdatePenTransition(curSliceTime);
    if (!penTransitionDirection) {
      sliceStartTime = curTime;
    }
  } else {  
#endif
    // move to next slice if necessary
    while(curSliceTime > TIME_SLICE_US) {
      SetSliceVariables();
      curSliceTime -= TIME_SLICE_US;
      sliceStartTime += TIME_SLICE_US;

#ifdef ENABLE_PENUP 
      if (penTransitionDirection) {
        sliceStartTime = curTime;
        return;
      }
#endif      
    }

    UpdateStepperPins(curSliceTime);
#ifdef ENABLE_PENUP    
  }
#endif  

  ReadSerialMoveData();
  RequestMoreSerialMoveData();
}

// Update stepper pins
// --------------------------------------
void UpdateStepperPins(long curSliceTime) {
  long leftTarget = ((long(leftDelta) * curSliceTime) >> TIME_SLICE_US_LOG) + leftStartPos;
  long rightTarget = ((long(rightDelta) * curSliceTime) >> TIME_SLICE_US_LOG) + rightStartPos;

  int leftSteps = (leftTarget - leftCurPos) >> POS_FACTOR_LOG;
  int rightSteps = (rightTarget - rightCurPos) >> POS_FACTOR_LOG;

  boolean leftPositiveDir = true;
  if (leftSteps < 0) {
    leftPositiveDir = false;
    leftSteps = -leftSteps;
  }
  boolean rightPositiveDir = true;
  if (rightSteps < 0) {
    rightPositiveDir = false;
    rightSteps = -rightSteps;
  }

  do {
    if (leftSteps) {
      forwarda();                        // changed the function
      if (leftPositiveDir) {
        leftCurPos += POS_FACTOR;
      } else {
        leftCurPos -= POS_FACTOR;
      }
      leftSteps--;

      UpdateStatusLeds(leftCurPos >> 13);
    }

    if (rightSteps) {
      forwardb();                        // changed the function
      if (rightPositiveDir) {
        rightCurPos += POS_FACTOR;
      } else {
        rightCurPos -= POS_FACTOR;
      }
      rightSteps--;
    }

    if (leftSteps || rightSteps) {
      delayMicroseconds(50); // delay a small amount of time before refiring the steps to smooth things out
    } else {
      break;
    }
  } while(true);
}

// Update pen position
// --------------------------------------
#ifdef ENABLE_PENUP
void UpdatePenTransition(long curSliceTime) {

  //int targetAngle = ((float)(PENDOWN_ANGLE - PENUP_ANGLE) * ((float)curSliceTime / (float)PENUP_TRANSITION_US)) + PENUP_ANGLE;
  //if (targetAngle > PENDOWN_ANGLE) {
    //targetAngle = PENDOWN_ANGLE;

    if (curSliceTime > PENUP_COOLDOWN_US) {
      penTransitionDirection = 0; // are done moving the pen servo
    }
  //}

  if (penTransitionDirection == 1) {
    //targetAngle = 180 - targetAngle;
    penUpServo.write(PENUP_ANGLE);
  } else if (penTransitionDirection == -1) {
    penUpServo.write(PENDOWN_ANGLE);
  }

  //penUpServo.write(targetAngle);
}
#endif

// Update status leds
// --------------------------------------
void UpdateStatusLeds(int value) {
  // output the time to the leds in binary
  digitalWrite(LED_PINS[0], value & 0x1);
  digitalWrite(LED_PINS[1], value & 0x2);
  digitalWrite(LED_PINS[2], value & 0x4);
}

// Update receive leds
// --------------------------------------
void UpdateReceiveLed(boolean value) {
  digitalWrite(LED_PINS[3], value);
}

// Set all variables based on the data currently in the buffer
// --------------------------------------
void SetSliceVariables() {
  // set slice start pos to previous slice start plus previous delta
  leftStartPos = leftStartPos + long(leftDelta);
  rightStartPos = rightStartPos + long(rightDelta);

  if (moveDataLength < 2) {
    leftDelta = rightDelta = 0;
  } else {
    leftDelta = MoveDataGet();
    rightDelta = MoveDataGet();

#ifdef ENABLE_PENUP 
    if (leftDelta == PENUP_COMMAND) {
      leftDelta = rightDelta = 0;
      penTransitionDirection = 1;
    } else if (leftDelta == PENDOWN_COMMAND) {
      leftDelta = rightDelta = 0;
      penTransitionDirection = -1;
    }
#else
    if (leftDelta == PENUP_COMMAND || leftDelta == PENDOWN_COMMAND) {
       leftDelta = rightDelta = 0;
    }
#endif    
  }
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

// Stop everything and blink the status led value times
// --------------------------------------
void Blink(char value) {
 int counts = value;
  if (counts<0) counts=-counts;

  UpdateReceiveLed(false);
  for(int i=0;i<counts;i++) {
   delay(1000);
   UpdateReceiveLed(true);
   delay(1000);
   UpdateReceiveLed(false);

  }
  delay(100000);
}

// Read serial data if its available
// --------------------------------------
void ReadSerialMoveData() {     

  if(Serial.available()) {
    char value = Serial.read();

    // Check if this value is the sentinel reset value
    if (value == RESET_COMMAND) {
      ResetMovementVariables();
      moveDataRequestPending = 0;
      moveDataLength = 0;
      UpdateReceiveLed(false);
      return;
    }

    MoveDataPut(value);
    moveDataRequestPending--;

    if (!moveDataRequestPending) {
      UpdateReceiveLed(false);
    }
  }
}

// Put a value onto the end of the move data buffer
// --------------------------------------
void MoveDataPut(char value) {
  int writePosition = moveDataStart + moveDataLength;
  if (writePosition >= MOVE_DATA_CAPACITY) {
    writePosition = writePosition - MOVE_DATA_CAPACITY;
  }

  moveData[writePosition] = value;

  if (moveDataLength == MOVE_DATA_CAPACITY) { // full, overwrite existing data
    moveDataStart++;
    if (moveDataStart == MOVE_DATA_CAPACITY) {
      moveDataStart = 0;
    }
  } 
  else {
    moveDataLength++;
  }
}

// Return a piece of data sitting in the moveData buffer, removing it from the buffer
// --------------------------------------
char MoveDataGet() {
  if (moveDataLength == 0) {
    return 0;
  }

  char result = moveData[moveDataStart];
  moveDataStart++;
  if (moveDataStart == MOVE_DATA_CAPACITY) {
    moveDataStart = 0;
  }
  moveDataLength--;

  return result;
}

// Return the amount of data sitting in the moveData buffer
// --------------------------------------
void RequestMoreSerialMoveData() {
  if (moveDataRequestPending > 0 || MOVE_DATA_CAPACITY - moveDataLength < 128)
    return;

  // request 128 bytes of data
  Serial.write(128);
  moveDataRequestPending = 128;
  UpdateReceiveLed(true);
}

`

so actually the only thing I did was adding the missing libaries, changing the servo pin to 9 and update the step function.

in all honesty i have no clue what I am doing so any pointers into the right direction would be really nice.

cheers

and how can i label this as a question?

brianinnes commented 8 years ago

This is not a bug in the project code, so I am closing the issue. I've not got a motor shield, but a quick web search shows it uses pins D12 & D13 for the direction control and D3 and D11 for the steps. Your sketch configures the LED pins as 10, 11, 12 and 13 which will conflict with the motor control pins?