Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Zumo32u4 motors don't drive, or don't drive the right way

Hi, for school we need to program a Zumo32u4 robot. Currently we’re trying to get the robot to drive, but after fully initiating the timer 1 according to the datasheet, our knowledge of microcontrollers, our experience with the Atmega328p and using the zumo library as an example, it doesn’t seem to work. I’ll share the code we have made with you guys:

void initTimer1PWM(){
  //TCCR1A = (1 << COM1A1) | (1 << WGM10);
  //ICR1 = 400;
  //TCCR1B = (1 << WGM12);
  TCCR1A = 0b10100000;
  TCCR1B = 0b00010001;
  ICR1 = 400;
  OCR1A = 0;
  OCR1B = 0;

}

void setRightSpeed(int16_t speed){
    initTimer1PWM();
   
    int reverse = 0;
   
    if (speed < 0)
    {
        speed = -speed; // Make speed a positive quantity.
        reverse = 1;    // Preserve the direction.
    }
    if (speed > 400)    // Max PWM duty cycle.
    {
        speed = 400;
    }
   
    if(reverse==1){
        PORTB = (1<<PORTB1);
    }
    if(reverse==0){
        PORTB = ~(1<<PORTB1);
    }
    OCR1A = speed;
}

This is pretty much the Zumo library code for the motors copied and pasted, then made to work without the rest of the library. I didn’t include setLeftSpeed as it’s the same, but with OCR1B and using PORTB2 for direction. The resulting behavior is that the motor runs at a total max speed, no speed control, as well as some direction problems. If we set up the right motor only then that one will run at full speed forward or backward like it should, but the other motor will also run but in the opposite direction of the other one. Same result if we set up the left motor but then reversed, the left motor drives forward while the right motor backwards. This is not supposed to happen, the expected result is that only one motor turns on at all, and the speed control should work.

If you think the direction problem is a bitshifting problem, if we use

PORTB |= (1 << PORTB1) 
PORTB &=  ~(1 << PORTB1)

the whole thing just refuses to drive at all.
Our teacher has looked at it, he doesn’t know what to do. A friend whose thesis is about microcontrollers doesn’t know what’s wrong. We’re at a total loss. It would be amazing if anyone here could find the problem.
btw, we’re not allowed to directly use the Zumo library or any library for that matter except the standard AVR ones, just so you know.

Much thanks in advance!

Hello.

I moved your post to our Robots subforum, which seemed more appropriate.

To rule out any problems with the hardware itself, can you confirm that the MotorTest sketch in the Zumo 32U4 Arduino library works as expected on your Zumo 32U4 robot?

Did you set the data direction register for port B (DDRB)? By default, DDRB is initialized to 0x00, acting as inputs. The PWM and DIR pins for the left and right motors are set to output low at the top of Zumo32U4Motors::init2() in Zumo32U4Motors.cpp, which you can see here.

You are constantly reinitializing timer1 every time you call initTimer1PWM() in your speed function(s), which sets your current speed settings back to 0, and this could be a problem if you are calling setRightSpeed() in a tight loop. Instead of calling initTimer1PWM() in your speed functions, you can call it from setup(). Could you also post the rest of your program so we can see if there are any other issues there? (Note that even though our library calls init() from the speed functions, there is a check inside init() so that it only performs the initialization the first time it is called; the actual initialization is done by init2().)

The way you are setting the PORTB register in your code will absolutely have some unintended consequences. If you did not already know, PORTB = (1<<PORTB1); will set PB1 to 1 and all other seven bits in PORTB to 0. When setting specific bits in the register, using bitwise OR and AND is necessary so that you are not changing the other bit values in the register and affecting other pins. You should use PORTB |= (1 << PORTB1) and PORTB &= ~(1 << PORTB1) for changing the DIR pin value for the right motor. (Even though doing it the right way seemed to make things worse for you before, that might have been due to other issues in your code.)

- Amanda