Controlling multiple motors with PRU at different frequencies?

Hi,
I was wondering if there is any way I could run more than one motor in parallel using the PRU on Beaglebone Black. The motors have to be run at different frequencies which I think is the challenging part. So far, I have managed to run one motor by bit-banging a GPIO with a PRU. I don’t think I can use this approach for multiple motors.
What would be an elegant way to achieve this?

Thanks,
Adwait

P.S I am using the TI toolchain to compile and run C code on the beaglebone using uio_pruss driver.

Hi Adwait!

Don’t you think you should give us an idea of what kind of motors you’re talking about (stepper, serve, ???).

For bit-banging you don’t need the PRU at all. Several modules can generate PWM output, like PWM modules and CAP modules in the PWMSS, or the TIMER subsystems. libpruio offers easy (but also the most flexible) acces to that capabilities.

Regards

Sorry, forgot to mention that. I’ll be running 2 servo motors and 2 brush-less dc motors.
I am concerned about the fact that all of them will be running at different frequencies and in parallel. So far I can only think of running them one after the other. Is there a way to thread in a PRU?

I’ll have a look at the link you mentioned and see if it helps.

Thanks

On Wed, 7 Jun 2017 21:40:22 +0530, Adwait
<adwaitd@endlessrobotics.com> declaimed the
following:

Sorry, forgot to mention that. I'll be running 2 servo motors and 2
brush-less dc motors.

  From what I've read, most servos don't really care about the frequency
(50Hz nominal in the spec sheets) ignoring the on/off ratio and only
relying on the absolute width of the on-time pulse. [This ignores those
servos that have had the position feedback circuit removed allowing
continuous motion.]

I am concerned about the fact that all of them will be running at
different frequencies and in parallel. So far I can only think of
running them one after the other. Is there a way to thread in a PRU?

  What is the major frame of the multiple frequencies? (That is; starting
from 0, when do all the frequencies align again?). Break that major frame
into minor frames (based on the highest frequency in question * finest
resolution needed to handle PWM). Run a loop with minor frame counter
invoking actions on the proper multiples:

t := clock();
loop
  for counter in 1..minorFrames loop
    handleFastestMotor(counter); -- every "tick"
    if counter mod nextFastestRate = 0 then
      handleNextFastestMotor(counter);
    end if;
    if counter mod thirdFastestRate = 0 then
      handleThirdFastest(counter);
    end if;
    if counter mod slowestMotorRate = 0 then
      handleSlowestMotor(counter);
    end if;
    t := t + minorFrameTime
    if t > clock() then
      kickWatchdog();
      delay until t; -- not a delay /for n/ but a delay /until n/
    end if; -- else minor frame overrun, let watchdog reset system
  end loop;
end loop;

  The various handle*() routines would be responsible for determining if
the pin state should be kept or toggled based on internal counter(s). The
trick is that the slowest processing path (all handlers invoked) has to
come in at less than the minor frame time, so you can delay to keep in
synch.

  Granted, the above is just a loose hypothetical approach.

Last summer I did a project where I programmed the PRUs to provide an 18 channel PWM (12 on one PRU and 6 on the other). Each could have it’s own frequency and duty cycle.

The details are here[1].

Though I think using the PRUs may be overkill for what you need to do. There are several hardware PWM channels on the Bone that don’t need the PRUs.

–Mark

[1] BeagleBoard-exercises/pru/examples/pwm at master · MarkAYoder/BeagleBoard-exercises · GitHub

The reason I wanted to use the PRU was that we need to send a fixed number of pulses to the servo motors. We tried it with the usual PWM channels on the beaglebone and by the time we are done counting the number and disabling the PWM, the servo ends up receiving a few extra pulses and overshooting. Maybe comparing it in a while loop is not such a great idea. If there is a better way that does not involve the use of PRUs, I would readily switch to that.

Also, Mark, a small part I didn’t understand in pru-pwm.asm. Once you load the period and duty cycle in channel, only some should get either enabled or disabled each cycle. How do you decide which ones to set high and low?

Adwait