Port manipulation test con MEGA2560

Salve a tutti!

Dal mio robottino, come molti di voi sanno, voglio risposte rapide, quindi devo agire direttamente sui registri e porte. Premetto che, prima di introdurre questo argomento nel mio progetto, il robot funzionava anche se lento nelle risposte, utilizzando le funzioni classiche.

Nel codice riportato sto provando a testare ciò che ho scritto, ma come risultato, non si muove nulla, motori fermi...

//mega2560 port manipulation test
//1x dual motor carrier vnh3sp30 (max 10KHz frequenza PWM) https://www.pololu.com/product/707
//2x motori pololu 350 rpm https://www.pololu.com/product/2823
//batteria 3celle 11.1v 3000mah

/* These are used to read and write to the port registers - see http://www.arduino.cc/en/Reference/PortManipulation 
 I do this to save processing power - see this page for more information: http://www.billporter.info/ready-set-oscillate-the-fastest-way-to-change-arduino-pins/ */
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

/* Left motor */
#define leftPort PORTA
#define leftPortDirection DDRA
#define leftPwmPortDirection DDRL
#define leftA PINA2     // PA2 - pin 24 (2INA on the Pololu motor driver)
#define leftB PINA3     // PA3 - pin 25 (2INB on the Pololu motor driver)
#define leftPWM PINL4   // PL4 - pin 45 (2PWM on the Pololu motor driver)

/* Right motor */
#define rightPort PORTA
#define rightPortDirection DDRA
#define rightPwmPortDirection DDRL
#define rightA PINA0    // PA0 - pin 22 (1INA on the Pololu motor driver)  
#define rightB PINA1    // PA1 - pin 23 (1INB on the Pololu motor driver)   
#define rightPWM PINL5  // PL5 - pin 44 (1PWM on the Pololu motor driver)  

void setup() {

  /* Setup motor pins to output */
  sbi(leftPwmPortDirection,leftPWM);
  sbi(leftPortDirection,leftA);
  sbi(leftPortDirection,leftB);

  sbi(rightPwmPortDirection,rightPWM);
  sbi(rightPortDirection,rightA);
  sbi(rightPortDirection,rightB);  

//Timer5 on mega is a 16-bit timer
 TCCR5A = B00101001; // Phase and frequency correct PWM change at OCR5A
 TCCR5B = B10001;  // System clock
 OCR5A = 800; // 16MHz/10kHz/2=800  prescaler a 1 
 OCR5B = 0; // motori fermi
 OCR5C = 0;
 
}

void loop() {

 setPWM(leftPWM,600);
 setPWM(rightPWM,600);
  
}

void setPWM(uint8_t pin, int dutyCycle) { // dutyCycle is a value between 0-ICR
 if(pin == leftPWM) {
    OCR5BH = (dutyCycle >> 8); 
    OCR5BL = (dutyCycle & 0xFF); 

// datasheet a pag. 135: 'To do a 16-bit write, the high byte must be                                            //written before the low byte. For a 16-bit read, the low byte must  
//be read before the high byte.'

  } else if (pin == rightPWM) {
    OCR5CH = (dutyCycle >> 8);//OCR5C=dutyCycle;
    OCR5CL = (dutyCycle & 0xFF);  
 }
}

ok funziona :slight_smile: :slight_smile:

// PORT TEST CODE

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

enum Command {
  stop,
  forward,
  backward,
  left,
  right,
  imu,
  joystick,
};

void setup() {

  /* Setup motor pins to output */
  sbi(DDRL, PINL4);  //left motor
  sbi(DDRA, PINA2);
  sbi(DDRA, PINA3);

  sbi(DDRL, PINL5);  //right motor
  sbi(DDRA, PINA0);
  sbi(DDRA, PINA1);  

 TCCR5A = B00101001; // Phase and frequency correct PWM change at OCR5A
 TCCR5B = B10001;  // System clock
 OCR5A = 800; // 16MHz/10kHz/2=800  prescaler a 1   (0-799)
 OCR5B = 0; // motors stop  D45
 OCR5C = 0;  //D44
 
}

void loop() {

 setPWM(45,600);
 setPWM(44,600);
 delay(1000);
    moveMotor(left, forward, 200);
    moveMotor(right, backward, 200 * -1); 
}

void setPWM(uint8_t pin, int dutyCycle) { // dutyCycle is a value between 0-ICR
 if(pin == 45) {
//    OCR5B = dutyCycle;
 OCR5BH = (dutyCycle >> 8); 
 OCR5BL = (dutyCycle & 0xFF);
  } else if (pin == 44) {
 //  OCR5C = dutyCycle;
  OCR5CH = (dutyCycle >> 8);
  OCR5CL = (dutyCycle & 0xFF);  
 }
}

void moveMotor(Command motor, Command direction, double speedRaw) { // Speed is a value in percentage 0-100%
  if(speedRaw > 100)
    speedRaw = 100;
  int speed = speedRaw*((double)800)/100; // Scale from 100 to PWMVALUE
  if (motor == left) {
    setPWM(45,speed); // Left motor pwm
    if (direction == forward) {
      cbi(PORTA, PINA2);
      sbi(PORTA, PINA3);
    } 
    else if (direction == backward) {
      sbi(PORTA, PINA2);
      cbi(PORTA, PINA3);
    }
  } 
  else if (motor == right) {
    setPWM(44,speed); // Right motor pwm
    if (direction == forward) {
      cbi(PORTA, PINA0);
      sbi(PORTA, PINA1);
    } 
    else if (direction == backward) {
      sbi(PORTA, PINA0);
      cbi(PORTA, PINA1);
    }
  }
}