Servo (PWM) code dropping to bootloader

I’m working on yet another Servo library, and I can, so far, sweep a servo back and forth across its range of motion based on a Timer3 interrupt. It has a fairly simple API and will be able to control as many servos as we have I/O pins.

To use this early version, these 3 files can be built together. Connect your Wixel to USB, and connect VALT to the servo positive (red), GND to servo negative (black), and P2_2 yellow LED to servo signal (white). The servo will sweep from one side to another.

However, after a few sweeps (which take a couple of seconds) the Wixel drops back into bootloader mode, for no reason I can determine.

Can anyone see an obvious reason why it would be doing this? What will cause a Wixel to reset itself and go back to the bootloader? Is something resetting the CPU while P2_2 is held high by the chip?

Code is at GitHub, github.com/jpvlsmv/Wixel-Servo-Lib

Thanks,
–Joe

I wonder if the servo(s) drawing current from VALT cause a brown-out?
if P2_2 is high - that would get you into the boot loader

I’d thought of that, but even when I have the servo disconnected, the Wixel app still dies.

Also, when I power the servo from the +5V from my arduino (connecting their grounds, and having both plugged in via USB – Yes, I know this abuses the TTL “high” level by relying on 3.3V as being seen that way) it also dies.

–Joe

Hello.

What kind of servo are you using? I do not think this is your only problem, but USB power is not meant to power servos and can’t supply the kind of current a typical servo wants to draw.

- Ryan

Hello, Joe.

Thanks for sharing that code with us!

In your code you are calling boardService(), which calls boardStartBootloaderIfNeeded(), defined in board.c:

void boardStartBootloaderIfNeeded()
{
    if (!(P2DIR & (1<<2)))       // If the yellow LED is off...
    {
        delayMicroseconds(10);
        if (P2_2)
        {
            boardStartBootloader();
        }
    }
}

If your interrupt happens to fire during that 10 microsecond delay and it turns the yellow LED on, then the P2_2 bit will read high and boardStartBootloader will be called. Does this make sense?

Here are some possible solutions, any of which would solve this particular problem:

  • Don’t call boardService (currently all it does is call boardStartBootloaderIfNeeded)
  • Use a different I/O line for your servo signal.
  • Instead of using the LED_YELLOW macro, which turns the LED off by setting the pin to be an input, you could set the pin to be an output at the beginning of your program (“P2DIR |= (1<<2);”) and then just write directly to the output (“P2_2 = 1;” or “P2_2 = 0;”) in your ISR.

As Ryan said, you will probably want a better power supply for the servo.

–David

It’s a basic servo that I had laying around from an old R/C car, a “hitec HS-300A”. Since I’m not putting any load on it at the moment, 3.3V from the USB seems to be enough to move the arm around.

I took out the LED_YELLOW() and moved the servo to P0_1, and so far it hasn’t glitched out.

So I’ve learned… don’t fiddle with LED_YELLOW in interrupts.

Once I finish refactoring the servo code and get the API stable, I’ll post an update.

–Joe