Wednesday, January 5, 2011

Encoders & Cycles

Tonight(or better say this morning at 4:00 a.m.) I managed to make a code to finally count the cycles(it takes around 70 cycles for a motor to screw totally open) that the light fork encoder on this foot counts. This code is an alpha version which monitors just one of the DC motors(the one in the middle, motor with index "1" in the code). 
The challenge to discus here is a limitation in Arduino which I have discussed in my previous post here(few external interruption on Arduino ). Most Arduino boards, so do mine, have just two external interruptions and this makes me not to use this method(which looks to be a perfect one) to monitor the changes on the pins received from the motor driver(changes in A & B state from Motor driver which tells us about the current position of the DC motor connected to it). With external interruptions out of the picture the only way that I came to is to solve this with a software trick. I tried to monitor the changes sent from the encoder which is connected to a moving motors as fast as I can. This is done by placing readFromEncoder() method in loop() method which repeats pretty fast and up to now has given satisfactory results. Check the code down here :




// Encoders inputs
byte pinEncA[] = {7,5,3}; // digital inputs
byte pinEncB[] = {6,4,2}; // digital inputs

// MOTOR OUTPUTS
// digital output, controls direction for motor nr. [x]
byte pinDir[] = {13,8,12}; 
// analog output, controls motor speed, nr. [x]
byte pinPwm[] = {10,11,9}; 

//Global variables
int readValue;
int pwmValue;
int motorDir;
int cycle;

boolean f = false, b = false, r = false, l = false;
byte cycleCounter;
byte cycleCounterOld;

void setup(){
  Serial.begin(9600);
  Serial.println("WELCOME TO C1S0");  
  for (int i=0; i < 3; i++){
    pinMode(pinDir[i], OUTPUT);
    pinMode(pinPwm[i], OUTPUT);
    //in case, just to be sure ...
    digitalWrite(pinPwm[i], LOW);
    //in case, just to be sure ...
    digitalWrite(pinDir[i], LOW); 
    pinMode(pinEncA[i], INPUT);
    pinMode(pinEncB[i], INPUT);
  }//end of for
}//end of setup()

void loop(){

//  digitalWrite(pinDir[2], LOW);
//  digitalWrite(pinPwm[2], HIGH);
//  Serial.println("...");
  //if ( Serial.available() > 0 )
    commandCenter();
    readFromEncoder();
    //Serial.print("cycle: ");
    //Serial.println(cycle);
}//end of loop

void commandCenter(){
  //variables
  int temp = 0;
//  while (Serial.available() < 0)
//    ;
  if ( Serial.available() > 0 ){
    readValue = Serial.read();
    switch (readValue){
      case 102 ://f -> forward
        Serial.println("*** Forward ***");
        digitalWrite(pinDir[1], LOW);
        digitalWrite(pinPwm[1], HIGH);
        f = true;
        b = false;
        l = false;
        r = false;
        break;
      case 98 ://b -> back
        Serial.println("*** Backward ***");
        digitalWrite(pinDir[1], HIGH);
        digitalWrite(pinPwm[1], HIGH);
        f = false;
        b = true;
        l = false;
        r = false;        
        break;
      case 108 ://l -> left
        Serial.println("*** Left ***");
        digitalWrite(pinDir[2], LOW);
        digitalWrite(pinPwm[2], HIGH);
        f = false;
        b = false;
        l = true;
        r = false;        
        break;        
      case 114 ://r -> right
        Serial.println("*** Right ***");
        digitalWrite(pinDir[0], LOW);
        digitalWrite(pinPwm[0], HIGH);
        f = false;
        b = false;
        l = false;
        r = true;
        break;
      case 82 : //R->RESET
        Serial.println("*** Resetting ***");
        for (int i=0; i < 3; i++){
          //Setting all PWM's to LOW
          digitalWrite(pinPwm[i], LOW);
        }//end of for
        f = false;
        b = false;
        l = false;
        r = false;
        break;
    }//end of switch  
  } 
}//end of commandCenter

int angleCount;

void readFromEncoder(){
  int A;
  int B;

  A = digitalRead(pinEncA[1]);
  B = digitalRead(pinEncB[1]);
  digitalWrite(13, A);

  if ( (A==LOW) && (B==LOW) )
    cycleCounter = 0;
  else if ( (A==LOW) && (B==HIGH) )
    cycleCounter = 1;
  else if ( (A==HIGH) && (B==HIGH) )
    cycleCounter = 2;
  else if ( (A==HIGH) && (B==LOW) )
    cycleCounter = 3;

  switch(cycleCounter)
  {
  case 0:
    if ( cycleCounterOld == 1)
      angleCount--;
    else if ( cycleCounterOld == 3){
      angleCount++;
      Serial.print("cycle: ");
      Serial.println(cycle);
      cycle--;
    }
    else if ( cycleCounterOld == 2){
        Serial.println("Error reading from Encoder");
        Serial.println("cycleCounter");
        Serial.println(cycleCounter);
        Serial.println("cycleCounterOld");
        Serial.println(cycleCounterOld);
    }
    break;  

  case 1:
    if ( cycleCounterOld == 2)
      angleCount--;
    else if ( cycleCounterOld == 0)
      angleCount++;
    else if ( cycleCounterOld == 3){
        Serial.println("Error reading from Encoder");
        Serial.println("cycleCounter");
        Serial.println(cycleCounter);
        Serial.println("cycleCounterOld");
        Serial.println(cycleCounterOld);
    }
    break;  

  case 2:
    if ( cycleCounterOld == 3)
      angleCount--;
    else if ( cycleCounterOld == 1)
      angleCount++;
    else if ( cycleCounterOld == 0){
        Serial.println("Error reading from Encoder");
        Serial.println("cycleCounter");
        Serial.println(cycleCounter);
        Serial.println("cycleCounterOld");
        Serial.println(cycleCounterOld);
    }
    break;  

  case 3:
    if ( cycleCounterOld == 0){
      angleCount--;
      Serial.print("cycle: ");
      Serial.println(cycle);
      cycle++;
    }
    else if ( cycleCounterOld == 2)
      angleCount++;
    else if ( cycleCounterOld == 1){
        Serial.println("Error reading from Encoder");
        Serial.println("cycleCounter");
        Serial.println(cycleCounter);
        Serial.println("cycleCounterOld");
        Serial.println(cycleCounterOld);
    }
    break;            
  }
  cycleCounterOld = cycleCounter;
}





The plan a head is to make a complete Arduino code that monitors all three motors and connect it to a Java code. Java code can communicate with Arudino through serial communication and monitors all the three motors, being able to report the current cycle that the motor is right now at.

No comments:

Post a Comment