Megashield + Motor2(NXT) + Flexitimer2 = Bug?

Dear Wayne and Layne support team,

first off all a big big thank you for sharing your great project for free!

However, I have some issues with Motor2 port where I need your support. Let me provide you some more details:

Setup:
SunFounder Mega 2560 R3 ATmega2560-16AU Board
Bricktronics Megashield
External power supply connected to Megashield (9V, 5A max)
NXT motor connected to Motor2 jack

Sofware:
Arduino IDE
The examples provided by BricktronicsMotor library (+dependencies + BricktronicsMegashield library)

Testing
Example: MotorSingle -> configured to use Motor2 -> works fine
Example: MotorPositionControl -> configured to use Motor2 -> works fine
Example: MultipleMotors -> works fine
Example: MotorPositionControlInterrupt -> configured to use Motor2 -> no position control, motor starts to "shake"

I nailed the issue down to the flexitimer library, as soon as the timer gets initialized (FlexiTimer2::set(25, updateMotorInterrupt);), the motor behavior becomes abnormal.

Have you ever seen this issue?

I am currently struggling to nail it down to an hardware or software issue. Any support would be very much appreciated!

Many thanks in advance!

Best regards,
Thorsten

Hello Thorsten, thanks for the nice question. I’m glad you’re enjoying the kits and software!

This is a known bug. Well, not really a “bug” but a hardware limitation. Flexitimer2 breaks the PWM output for Motor 2 on the Bricktronics Megashield. The other five motor ports should work fine.

I’m not sure when you downloaded the Bricktronics libraries, but I added a note about this issue in the latest version of the example: https://github.com/wayneandlayne/BricktronicsMotor/blob/master/examples/MotorPositionControlInterrupt/MotorPositionControlInterruptBricktronicsMegashield/MotorPositionControlInterruptBricktronicsMegashield.ino#L14

// This example uses the FlexiTimer2 library to generate the interrupts, which
// breaks the analogWrite (PWM) output on the following pins:
//      Arduino Mega: Pins 9 and 10
//          On the Bricktronics Megashield, this will only interfere with
//          motor 2, so don't use motor 2 with this FlexiTimer2 library.

The reason this happens is that the FlexiTimer2 library takes over Timer2 (one of a handful of timers in the microcontroller chip), but some pins’ PWM output also need to use Timer2 (Mega’s pins 9 and 10).

Ideally, we could re-work those interrupt-based examples to piggy-back on the existing Timer0 (which is used by the Arduino system for millis() ) to periodically call the motors’ update functions. Something like this might be close:

void setup() 
{ 
  // Timer0 is already used for millis() - we'll just interrupt somewhere
  // in the middle and call the "Compare A" function below
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);

// ... all the other setup() stuff here
}

// This function will be called every millisecond.
// Keep a static char in here to count up to 25 or 50 milliseconds,
// and then call the motors' update() functions.
SIGNAL(TIMER0_COMPA_vect) 
{
  static char count = 0;
  if (++count == 50) {
    // Call each motor's update() function
    count = 0;
  }
}

(From https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers)

You’re welcome to take this TIMER0 code and try to get it working with the MotorPositionControlInterrupt. If not, I can take a look this weekend.

Hi Layne,

thanks a lot for your super fast response and the clarification!

First, I will have a look at it and give it a try by myself. In case I won’t manage… I know where to ask :wink:

Thanks again for your support!

Cheers,
Thorsten

I had some time tonight to take a stab at removing the flexitimer2 library from the MotorPositionControlInterrupt example, with the approach I mentioned above. However I forgot my hardware at the office and don’t have a Megashield and motor to test it out with. The code is in a new branch on github, and here’s the megashield version if you want to give it a try:

https://github.com/wayneandlayne/BricktronicsMotor/blob/feature/remove_flexitimer2/examples/MotorPositionControlInterrupt/MotorPositionControlInterruptBricktronicsMegashield/MotorPositionControlInterruptBricktronicsMegashield.ino

I updated the code in the new branch on github with more and better comments. It seems to be working fine with my Uno + Bricktronics Shield here on my desk. Later today I’ll try the Arduino Mega + Bricktronics Megashield on all six motor ports.

Hi Layne,

thanks a lot for your support!

I tested your updated code with my configuration and first it seems to be fine (all the examples using an interrupt work well). However, in my specific case, I will need to do some more stuff by the interrupt service routine which takes longer than 1 millisecond to process (read motor encoders and publish it via serial communication channel) and would fail.

I took your idea as an input and configured timer5 to throw an interrupt ever 10 millisecond.

Finally, could you please confirm that timer5 isn’t used (under the assumption that 6 motors and 4 ultrasonic sensors are connected to the Megashield)?

Many thanks in advance!

Cheers,
Thorsten

I’d suggest adding code to the ISR to only call the motor’s update() every 50 ms:

ISR(TIMER0_COMPA_vect)
{
    static unsigned char count_ms = 0;
    if (++count_ms == 50)
    {
        m.update();
        // If you have multiple motors, be sure to call all their update
        // functions here in the interrupt handler...
        // m2.update();
        // m3.update();
        // ...
        count_ms = 0;
    }
}

This should mean that the ISR is nice and quick most times it runs, except for every 50th call when it does the motor update call(s). In general you really want to do as little as possible in the interrupts, and do most of your processing in the main loop. Frequently it works best to set a flag from the ISR that you check in your main loop.

On the Arduino Mega Timer 5 is used for PWM output to pins 44, 45, 46, which are not used by the Bricktronics Megashield.