Go Down

Topic: Problem with high speed motor (Read 485 times) previous topic - next topic

santxo

May 29, 2013, 10:48 am Last Edit: Jun 01, 2013, 07:26 pm by santxo Reason: 1
Hello

I'm trying to make a motor with 12 magnets in the rotor and 3 driving coils, using an incremental encoder and a arduino due.
Until now I have tried several sketchs with no results. I tried interrupts at both channels, hardware quadrature...
The best counting metod so far is the hardware quadrature, but it lose ticks when it reach at 100, 120rpm. With hardware quadrature the resolution of the encoder is 4096ticks per revolution.

This is the hardware quadrature code:

Code: [Select]

const int quad_A = 2;
const int quad_B = 13;
const unsigned int mask_quad_A = digitalPinToBitMask(quad_A);
const unsigned int mask_quad_B = digitalPinToBitMask(quad_B); 

void setup() {
    Serial.begin(115200); 
    delay(100);
   
    // activate peripheral functions for quad pins
    REG_PIOB_PDR = mask_quad_A;     // activate peripheral function (disables all PIO functionality)
    REG_PIOB_ABSR |= mask_quad_A;   // choose peripheral option B   
    REG_PIOB_PDR = mask_quad_B;     // activate peripheral function (disables all PIO functionality)
    REG_PIOB_ABSR |= mask_quad_B;   // choose peripheral option B
   
    // activate clock for TC0
    REG_PMC_PCER0 = (1<<27);
    // select XC0 as clock source and set capture mode
    REG_TC0_CMR0 = 5;
    // activate quadrature encoder and position measure mode, no filters
    REG_TC0_BMR = (1<<9)|(1<<8)|(1<<12);
    // enable the clock (CLKEN=1) and reset the counter (SWTRG=1)
    // SWTRG = 1 necessary to start the clock!!
    REG_TC0_CCR0 = 5;


I use a counter to detect changes in REG_TC0_CV0, and a shooter to open and close the 3 Mosfet circuits. Don't have the last code here, I will post it as soon as possible, but it is something like this:

Code: [Select]

void Loop(){

tick=REG_TC0_CV0;

   if (tick>counter){
      shooter++;
   }

   if (shooter>0 && shooter<113){   //all the positions like this
      digitalWriteDirect(31, HIGH);
   }
   else
   if (shooter>...

   else
       digitalWriteDirect(31, LOW);   // all the transistors off before change coil
       digitalWriteDirect(33, LOW);
       digitalWriteDirect(35, LOW);
   


The digitalWriteDirect code is the next one:

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}


Some suggestion? I'm new in this programing stuff and don't understand it very well. There is a metod to make what I'm doing much more eficiently?

Thanks!

santxo

#1
Jun 01, 2013, 07:21 pm Last Edit: Jun 01, 2013, 07:23 pm by santxo Reason: 1
Hello again

I tried another sketch and have the same result. Can be a encoders problem. I see it lost ticks when it reach at this speed. It doesn't matter if I wanna read 4096 ticks per revolution or 1024. In the first case I use the code posted in the previous post, and in the second only an interrups reading the rising of the channel A. Here is the second code(the numbers in the loop are in accordance to coil position):


Code: [Select]
inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

const int a = 2;
const int z = 10;
volatile int tick=1;
volatile int ticklect=1;

void setup() {
    pinMode(33, OUTPUT);
    pinMode(31, OUTPUT);
    pinMode(35, OUTPUT);
    digitalWrite(31, LOW);
    digitalWrite(35, LOW);
    digitalWrite(33, LOW);
    pinMode(a, INPUT);
    pinMode(z, INPUT);
    digitalWrite(a, LOW);
    digitalWrite(z, LOW);   
    attachInterrupt(z, zrising, RISING);
    attachInterrupt(a, acount, RISING);
   
}   


void loop() {
 
  for (tick==5; tick<23; tick=ticklect){
   digitalWriteDirect(33, LOW);
   digitalWriteDirect(31, LOW);
   digitalWriteDirect(35, HIGH);
  }
 
  for (tick==33; tick<52; tick=ticklect){
   digitalWriteDirect(35, LOW);
   digitalWriteDirect(31, LOW);
   digitalWriteDirect(33, HIGH);
  }
 
  for (tick==61; tick<81; tick=ticklect){
    digitalWriteDirect(35, LOW);
    digitalWriteDirect(33, LOW);
    digitalWriteDirect(31, HIGH);
  }
 
  for (tick==91; tick<109; tick=ticklect){
   digitalWriteDirect(33, LOW);
   digitalWriteDirect(31, LOW);
   digitalWriteDirect(35, HIGH);
  }
 
  for (tick==119; tick<138; tick=ticklect){
   digitalWriteDirect(35, LOW);
   digitalWriteDirect(31, LOW);
   digitalWriteDirect(33, HIGH);
  }
 
  for (tick==147; tick<164; tick=ticklect){
    digitalWriteDirect(35, LOW);
    digitalWriteDirect(33, LOW);
    digitalWriteDirect(31, HIGH);
  }
 
  for (tick==175; tick<195; tick=ticklect){
   digitalWriteDirect(33, LOW);
   digitalWriteDirect(31, LOW);
   digitalWriteDirect(35, HIGH);
  }
 
  for (tick==204; tick<223; tick=ticklect){
   digitalWriteDirect(35, LOW);
   digitalWriteDirect(31, LOW);
   digitalWriteDirect(33, HIGH);
  }
 
  for (tick==232; tick<252; tick=ticklect){
    digitalWriteDirect(35, LOW);
    digitalWriteDirect(33, LOW);
    digitalWriteDirect(31, HIGH);
  }

  if (ticklect==256){
    ticklect=1;
    tick=1;
  }
 
}
 
 
 
 



void zrising() {
    ticklect=1;
     
}

 
void acount(){

  ticklect++;

}



The both codes gives the same speed.
I think the calculation is correct because it start so fast but when arrive at 100-120RPM don't speed up more, and the counter starts to lose tics.
A encoder can seem ok when driving it by hand, but count wrong when it speeds up?
I'm little suprised because it seems that the due can handle this code more than easy. Some suggestion?

Go Up