port manipulation's #define

Hi everybody,
I'm trying to modify a little example found on the web made for arduino UNO driving a motor with a pololu motor carrier BUT...
I'm not able to understand how can I make things work for my arduino mega2560, I mean, the last three #define are correct, but I can't understand PORTx and DDRx ones. In comments there's my solution. Is this the way?

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

/* Right motor */
#define rightPort PORTC                   //PORTA on mega
#define rightPortDirection DDRC        //DDRA on mega
#define rightPwmPortDirection DDRB  //DDRL on mega

#define rightA PINC4 // PC4 - pin A4 (1INA on the motor driver)          //  D22 on mega  PA0
#define rightB PINC5 // PC5 - pin A5 (1INB on the motor driver)          //  D23 on mega  PA1  
#define rightPWM PINB2 // PB2 - pin 10 - (1PWM on the motor driver)  //  D44 on mega  PL5

and in setup():

  // /* Setup motor pins to output */
  sbi(rightPwmPortDirection,rightPWM);
  sbi(rightPortDirection,rightA);
  sbi(rightPortDirection,rightB);

I'm trying to modify a little example found on the web

Are those snippets taken from the example? Or have you f**ked with them?

If you have f**ked with them, post the original code.

If you haven't f**ked with them, the comments tell you the values and pin numbers to use on the Mega.

Each I/O pin is controlled by an 8-bit 'port' and a bit within that 8-bit 'port'. You can find the mappings for UNO and MEGA here: https://docs.google.com/spreadsheets/d/16MIFE4ITEisEDUBh3H4A7WZga1Sm1Pm-igS3r0A58L8/pub?gid=0

The digitalRead(), digitalWrite() and pinMode() functions may be too slow in some cases and in those cases the solution is to do direct port manipulation.

In your example, the right motor controller is wired:
1INA -> UNO A0 (PORTC bit 4) or MEGA Pin 22 (PORTA bit 0)
1INB -> UNO A1 (PORTC bit 5) or MEGA Pin 23 (PORTA bit 1)
1PWM -> UNO Pin 10 (PORTB bit 2) or MEGA Pin 44 (PORTL bit 5)

You just have to switch the values from the UNO values to the MEGA values.

/* Left motor */
#define leftPort PORTA
#define leftPortDirection DDRA
#define leftPwmPortDirection DDRL
#define leftA PINA2   // PA2- pin 24 ON MEGA (2INA on the Pololu motor driver)
#define leftB PINA3   // PA3- pin25 ON MEGA (2INB on the Pololu motor driver)  
#define leftPWM PINL4 // PL4- pin 45 ON MEGA (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)   


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

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

Can leftPort and rightPort be PORTA both ?
YES, because we are just accessing a register, I think.
The important thing is not to use a pin two times, but can I use a PORTA for both my two motors?

The important thing is not to use a pin two times, but can I use a PORTA for both my two motors?

Since PORTA is a collection of (up to) 8 pins, yes.

I'm driving crazy... everything was OK till I've read about port manipulation... but now motors don't work.. this is port test code... really don't know... :drooling_face:

/* 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);  

 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; // 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);
  } else if (pin == rightPWM) {
    OCR5CH = (dutyCycle >> 8);
    OCR5CL = (dutyCycle & 0xFF);  
 }
}
[/]
// 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);
    }
  }
}

IT WORKS!!!! :slight_smile: :slight_smile:
thanks you all

 delay(1000);

I REALLY do not understand using direct port manipulation for speed and this stupid function in the same sketch.