/* Stepper Unipolar Advanced - hack AGFA scanner
 * ---------------------------------------------
 *
 * v0003 - standalone device
 *
 * - includes moving in percentages
 *
 * Program to drive a stepper motor coming from an AGFA A4 scanner
 * and meant to prototype a project for commissioned by Hangar. We
 * took the structure from the scanner that supports the motor, added
 * a couple of transistors (IRFZ24N) with 1N4004 power diodes, some 
 * resistors, 3 buttons, and a potentiometer to control speed, direction
 * of movement, etc.
 *
 * Regarding the stepper, it is a bipolar one with 6 wires:
 * 
 * - red and black: power connectors, I have them at 12V and work fine
 * - white and blue: coil 1
 * - red and yellow: coil 2
 *
 * (cleft) 2007 DojoDave, Tobbe, and Aposadas
 * http://www.0j0.org | http://arduino.berlios.de
 *
 * @author: David Cuartielles/Aposadas
 * @date: 18 Aug. 2007
 */

// constants defining the movement
int FORWARD = 2;
int BACKWARD = 1;
int STOP = 0;
int MIN_DELAY = 3;  // This value depends on the tension the motor has to handle
int PERCENTAGE = 5450;  // value read from the test

// variables, timers, etc
int move = 0;
int count = 0;
int count2 = 0;
int delayTime = 500;
int val = 0;
int serialControl = 0; // gives control to the serial port if '1'
int countSteps = 0;

// pins, LEDs, etc
int ledPin = 13;
int statusLed = LOW; 
int motorPins[] = {
  4, 5, 6, 7};
int potPin = 0;
int butPin = 8;
int butPotPin = 9;
int endPin1 = 10;
int endPin2 = 11;  


void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(endPin1, INPUT);
  pinMode(endPin2, INPUT);
  pinMode(butPin, INPUT);
  pinMode(butPotPin, INPUT);
  for (count = 0; count < 4; count++) {
    pinMode(motorPins[count], OUTPUT);
  }
  Serial.println("Ready ...");
}

void moveForward() {
  if ((count2 == 0) || (count2 == 1)) {
    count2 = 16;
  }
  count2>>=1;
  for (count = 3; count >= 0; count--) {
    digitalWrite(motorPins[count], count2>>count&0x01);
  }
  delay(delayTime);
}

void moveBackward() {
  if ((count2 == 0) || (count2 == 1)) {
    count2 = 16;
  }
  count2>>=1;
  for (count = 3; count >= 0; count--) {
    digitalWrite(motorPins[3 - count], count2>>count&0x01);
  }
  delay(delayTime);
}

void stop() {
  for (count = 3; count >= 0; count--) {
    digitalWrite(motorPins[count], LOW);
  }
}

void moveMotor() {
  if (move == FORWARD) {
    moveForward();
  } 
  else if (move == BACKWARD) {
    moveBackward();
  } 
  else {
    //move = STOP, do nothing
    stop();
  } 
}

void testMotorLength() {
  countSteps = 0;
  Serial.println("TESTING MOVEMENT ");
  Serial.println("Please be patient ... ");
  while (digitalRead(endPin1) == LOW) {
    moveForward();
  }
  Serial.print("Changing to ");
  Serial.print("BACKWARDS - delay: ");
  Serial.println(delayTime);
  stop();
  delay(200);
  while (digitalRead(endPin2) == LOW) {
    moveBackward();
    countSteps++;
  }
  stop();
  delay(200);
  Serial.println("TOTAL STEPS IN MOVEMENT ");
  Serial.print("Estimation: ");
  Serial.println(countSteps);
  PERCENTAGE = countSteps;  // callibration of the length
  while (digitalRead(endPin2) == HIGH) {
    moveForward();
  }
  move = STOP;
  moveMotor();
}

void goToCenter() {
  countSteps = 0;
  Serial.println("MOVING TO CENTER ");
  Serial.println("Please be patient ... ");
  while (digitalRead(endPin2) == LOW) {
    moveBackward();
  }
  move = FORWARD;
  moveMotor(127);
  stop();
  delay(200);
  Serial.println("Done ");
  move = STOP;
}

// move the motor a percentage expressed as a byte 0..255 (0-100%)
void moveMotor(int percentage) {
  int timer = 0;
  while (timer < (percentage * (PERCENTAGE / 255))) {
    if (move == FORWARD) {
      moveForward();
    } 
    else if (move == BACKWARD) {
      moveBackward();
    } 
    else {
      //move = STOP, do nothing
      stop();
    }
    timer++; 
  }
}


// move the motor during some miliseconds
/*void moveMotor(int time) {
  int timer = millis();
  while (millis() - timer < time) {
    if (move == FORWARD) {
      moveForward();
    } 
    else if (move == BACKWARD) {
      moveBackward();
    } 
    else {
      //move = STOP, do nothing
      stop();
    } 
  }
}*/

void loop() {
  if (serialControl == 0) {
    delayTime = 1023 - analogRead(potPin);
    if (delayTime < MIN_DELAY) delayTime = MIN_DELAY;
    if (digitalRead(butPin) == LOW) {
      stop();
      delay(200);
      if (move == FORWARD) {
        move = BACKWARD;
        Serial.println("Button Pressed");
        Serial.println("Changing to ** ");
        Serial.print("BACKWARDS - delay: ");
        Serial.println(delayTime);
      }
      else {
        move = FORWARD;
        Serial.println("Button Pressed");
        Serial.println("Changing to ** ");
        Serial.print("FORWARDS - delay: ");
        Serial.println(delayTime);
      }
    }
    if (digitalRead(butPotPin == HIGH)) {
      stop();
    }
  }

  // controlling the end of the movements
  if (digitalRead(endPin1) == HIGH) {
    stop();
    delay(200);
    if (move == FORWARD) move = BACKWARD;
    Serial.println("END OF MOVEMENT ");
    Serial.println("Changing to ** ");
    Serial.print("BACKWARDS - delay: ");
    Serial.println(delayTime);
    while (digitalRead(endPin1) == HIGH) {
      moveBackward();
    }
  }
  if (digitalRead(endPin2) == HIGH) {
    stop();
    delay(200);
    if (move == BACKWARD) move = FORWARD;
    Serial.println("END OF MOVEMENT ");
    Serial.println("Changing to ** ");
    Serial.print("FORWARDS - delay: ");
    Serial.println(delayTime);
    while (digitalRead(endPin2) == HIGH) {
      moveForward();
    }
  }

  // Serial control
  if (Serial.available()){
    val = Serial.read();
    if (val == 'X') {
      if (serialControl == 0) serialControl = 1;
      else serialControl = 0;
      if (serialControl) Serial.println("Serial Control - active!");
      else Serial.println("Serial Control - not armed!");
    }
    if (serialControl) {
      if (val == 'A') {
        //moveForward();
        Serial.print("FORWARDS - delay: ");
        Serial.println(delayTime);
        move = FORWARD;
      } 
      else if (val == 'D') {
        //moveBackward();
        Serial.print("BACKWARDS - delay: ");
        Serial.println(delayTime);
        move = BACKWARD;
      } 
      else if (val == 'S') {
        Serial.print("STOP - delay: ");
        Serial.println(delayTime);
        move = STOP;
      } 
      else if (val == '+') {
        if (delayTime > 100) delayTime += 100; // move faster the lower the value from the potentiometer
        else if (delayTime > 10) delayTime += 10; // move faster the lower the value from the potentiometer
        else delayTime += 1;
        if (delayTime > 1000) delayTime = 1000;
        Serial.print("delay: ");
        Serial.println(delayTime);
      } 
      else if (val == '-') {
        if (delayTime > 100) delayTime -= 100; // move faster the lower the value from the potentiometer
        else if (delayTime > 10) delayTime -= 10; // move faster the lower the value from the potentiometer
        else delayTime -= 1;
        if (delayTime < MIN_DELAY) delayTime = MIN_DELAY;  // MAX SPEED AT DELAY=2!! 20070818
        Serial.print("delay: ");
        Serial.println(delayTime);
      } 
      else if (val == 'R') {
        delayTime = 500; // move faster the lower the value from the potentiometer
        Serial.print("reset delay: ");
        Serial.println(delayTime);
      } 
      else if (val == 'T') {
        testMotorLength();
      } 
      else if (val == 'C') {
        goToCenter();
      } 
      else {
        // do nothing
      }
    }
  }
  moveMotor();
}