Beaglebone: Outputs: Turning a motor

7/1/2017
Andrew B. Wright, Ph. D., SM ’88

Previous Post: Beaglebone: TBD

Next Post: Beaglebone: TBD

I crossed some wires in connecting PWM and fried a beaglebone.  This put my in a cautious frame of mind.  I switched efforts to inputs, including considerable work on the range and identity detection system.  Then, the OS went through a number of revisions, and I switched to the remoteproc interface.

I’m nearly through with all of those other tasks, so I’ll be returning to this task in the next few weeks.


NOTES


2/29/16 …

After frying my previous beaglebone, I’m back to consider how to get the PWM finalized.  I had done some work that I didn’t document.  So, I guess I’m reproducing it.

The Vex motors are not happy with high frequency pwm.  They do not respond above about 1000 Hz.

The PWM needs to be enabled/disabled using some registers that I had previously not known about.  Here’s reproducing this info.

Do NOT use CLKCONFIG (ePWMCLK_EN) to try to turn the PWM on/off.  Once that clock is turned off, it cannot be turned back on from within the PRU.

The CM_PER register (0x44E0 0000) contains three important registers: epwmss0clkctrl (0xcc), epwmss1clkctrl (0xD4), epwmss2clkctrl (0xD8) which have to be set up in order for the pwm to work at all.  These registers can be twiddled to turn the pwm off and on.

In turning the PWM off, it’s nice to also force the module to go low.  This can be done through the ACQTLA/B register.  I need to figure this out again.  Not going to happen tonight given how tired I am.

Another register that has an interesting module is CONTROL_MODULE (0x44E1 0000).  This register has pwmss_ctrl (0x664), which has the bits timebase_clock_enable for pwm 0, 1, 2.  I have not checked it out yet, but it could be a necessary register.

———-

The ARM part of the system, the bit running Linux, should be the easiest way to get started with PWM.  All the values can be set at the command line through adjusting files.  This makes it easy to test and debug before committing to c-code.

There are a number of pwm overlay files in /lib/firmware.  I started with bone_pwm_P9_14-00A0.dtbo.  If you want to see what’s going on under the hood with this file, decompile it with the command dtc -I dtb -O dts bone_pwm_P9_14-00A0.dtbo > bone_pwm_P9_14-00A0.dts so that you can see how to set up a dts file, if you choose to incorporate it into another resource, such as the pru0.

The pwm subsystem became accessible without patches in the kernel version 3.11.  If you type uname -r, you’ll see whether you can use this or not.

Regardless, you can directly access the PWM either from the ARM side by writing the registers directly or from the PRU side.  You still need to reserve the header pin (P9-14, for instance) using the overlay, and you need to set the pinmux into the correct mode.

The trouble that arose with getting the PRU to toggle a gpio will reoccur with any hardware interface.  Getting the overlay file set up, getting the mode correct, figuring out the register addresses, setting all the parameters in those registers to generate the desired signal, and worrying about the latencies associated with accessing resources off-PRU through one of the many memory interconnects.  After all, if you try to update your control values at 1 msec and the output values are not getting out consistently, the system will not be controlled at the 1000 Hz rate that you desire.

There are many tutorials on the interwebs detailing how to access a PWM from Linux.  Alas,  if the kernel wasn’t compiled with a certain flag, the PWM functionality is not available this way.  There’s a kernel module, eHRPWM, to access the PWM functionality, but you have to recompile the kernel to enable it.  That’s a lot of extra effort to generate PWM just to test whether it works or not.  Might as well go to writing the PRU code, since that’s how I’m going to use the PWM.

There are several pins connected to each of the six PWM output signals (PWM0A, PWM0B, PWM1A, PWM1B, PWM2A, PWM2B).  Setting the PWM banging away will put a signal on each pin to which it is connected, assuming the mux for that pin has been set to connect the pin to the PWM module.  So, make sure you only mux those pins that you want to be active.

Once the pin is activated, the PWM can be turned on by writing the following registers …

Set bit 8 of the CLKCONFIG register (ePWMCLK_EN = 1), which enables the clock.

Set bits 15, 14 of TBCTL (FREE_SOFT) to 2h to allow free running of the PWM.

Set bits 5, 4 of TBCTL (SYNCOSEL) to 3h to disable EPWMxSYNCO signal.

Set bits 12-10 of TBCTL (CLKDIV) to 2h to make the prescaler = 4:1. Set bits 9-7 (HSPCLKDIV) to 0 to set the high speed prescaler to 1.  This makes TBCLK = SYSCLKOUT/CLKDIV/HSPCLKDIV.  If SYSCLKOUT = 100MHz, TBCLK = 25 MHz.

Set the other bits to zero (PHSDIR =0, SWFSYNC=0h, PRDLD=0h, PHSEN=0h, CTRMODE=0h). Among other things, these choices set the counter-mode to ‘up-count.’

Set TBPRD = 0xnn.  This is the frequency of the PWM.  It interacts with TBCLK, such that PWMPERIOD = (TBPRD+1)/TBCLK.  If nn = 99, then PWMPERIOD = 100/25 MHz = 4 usec. (confirmed)

The CMPA register is compared against TBCNT register and actions taken based on AQCTLA register.  Setting AQCTLA (CAU=3h,PRD=0h, ZRO=2h) in count-up mode will give a traditional PWM signal.

Duty cycle varies between 0 and TBPRD+1 (100%). (confirmed)

There are many, many other things that the ePWM module can do.  This gives the basic operation, which may be all you need.

For mechanical systems, I’ve always liked a 100kHz frequency.  This puts changes in PWM above most mechanical poles and above hearing frequency, so that PWM switches cannot be heard.  This can be obtained by a prescaler value of 1000 and a TBPRD value of 0.  However, that would give a resolution of the PWM of 1 bit (on-or-off).  Using typical DAC values (powers of 2), TBPRD = 1023 would give a 10 bit resolution.  So, a prescaler of 1 and TBPRD of 1023 would give about 100kHz PWM frequency and allow CMPA to vary between 0 and 1023 (10 bit resolution).

———-

Pins that seem to carry the PWMs without interference (not yet tested) are … P9 – 21 (0B) –  bone_pwm_P9_21-00A0.dtbo, 22 (0A) –  bone_pwm_P9_22-00A0.dtbo, 14 (1A) – bone_pwm_P9_14-00A0.dtbo, 16 (1B) – bone_pwm_P9_16-00A0.dtbo, 28 (ECAPPWM2) – bone_pwm_P9_28-00A0.dtbo, 42 (ECAPPWM0) – bone_pwm_P9_42-00A0.dtbo, and P8 19 (2A) – bone_pwm_P8_19-00A0.dtbo, 13 (2B) – bone_pwm_P8_13-00A0.dtbo.  This gives all the 8 PWMs that are available on the Beaglebone Black.  NOTE:  it seems that ECAPPWM are not the same as what’s in the PWMSS.

————–

The best candidate pins to get PRU0 to output a PWM are P9-29 and P9-31.  On these pins, R30:0 and R30: 1 are mapped, allowing the pin to be toggled as a digital output, to test that the PRU can access the pin through the gpio interface and to test the DTS overlay. Once the pin has been confirmed, the mode can be switch to PWM and the PWM registers can be modified to set up the desired functionality.  Alas, those pins are allocated to the HDMI interface.  If you want to use them for testing, you have to remove the HDMI overlay and add your overlay.  Again, more work than a test that’s supposed to make life easier is worth.

Pins P8.19 and P8.13 carry the PWM signals PWM2A and PWM2B, and these pins are free.  They’re off-PRU as well.

Add the following entries to the overlay file (combine with existing entries):

exclusive-use =”P8.19″,”P8.13″;

fragment@0 {target = <&am33xx_pinmux>;__overlay__ {pruicss_cassy: pinmux_pruicss_cassy{

pinctrl-single,pins = <0x020 0x4 0x024 0x4>;

}; };};

Compile and install the overlay, as before, and test the pins to ensure that they’ve been set into the correct mode. 

From Table 9-10 in the TRM, it can be seen that 44e10820 carries the signal, conf_gpmc_ad8 .  On Table 4-1 of the AM3358 data sheet, gpmc ad8 contains the signals: gpmc_ad8 (0), lcd_data23 (1), mmc1_dat0 (2), mmc2_dat4 (3), ehrpwm2A (4), pr1_mii_mt0_clk(5), gpio0_22 (7). From the Beaglebone SRM, Table 12, Expansion Header P8 pinout, gpmc ad8 is carried on pin 19.  Whew!  That’s how you find all those modes and addresses.

On the PRU, the registers controlling the PWM need to be set.  What are these registers? Where are they?

Chapter 15 of the AM33x TRM contains the description of the Pulse Width Modulation Sub-system (PWMSS).

Table 15-4 indicates some of the registers involved with the PWM: IDVER, SYSCONFIG, CLKCONFIG, CLKSTATUS.

Mainly CLKCONFIG inputs (9: ePWMCLKSTOP_REQ, 8:ePWMCLK_EN) and CLKSTATUS outputs (9: ePWM_CLKSTOP_ACK, 8: ePWM_CLK_EN_ACK).  See Fig. ??? for the schematic representation of these signals.

Figure 15-9 gives a good overview of the ePWM submodules (time base [TB], counter compare [CC], action qualifier [AQ], Dead Band [DB], Chopper [PC],  Trip Zone [TZ]), and Event Trigger [ET]).  The CC module sets frequency and duty cycle, while the others can be bypassed unless their functionality is needed.

Base address is (Table 2-3): ePWM0 (0x4830_0200), ePWM1 (0x4830_2200), ePWM2 (0x4830_4200).

Table 15-57 summarizes all the functions and offsets.

In the Time Base module, TBCTL (0), TBSTS (2), TBPHSHR (4), TBPHS(6), TBCNT (8), TBPRD (A) are the registers controlling the time base.

In the Counter Compare module, CMPCTL (E), CMPAHR(10), CMPA (12), CMPB (14) affect operation.

In the Action Qualifier module, AQCTLA (16), AQCTLB (18), AQSFRC (1A), AQCSFRC (1C) affect operation.

In the Deadband module, DBCTL (1E), DBRED (20), DBFED (22) affect operation.

In the Chopper, PCCTL (3C).

In the Trip Zone, TZSEL (24), TZCTL (28), TZEINT (2A), TZFLG (2C), TZCLR (2E), TZFRC (30).

In the Event Trigger, ETSEL (32), ETPS (34), ETFLG (36), ETCLR (38), ETFRC (3A), affects how interrupts are fired from PWM.

The constant table on the PRU allows access to the PWMs.  C18, C19, C20 point to PWM0, PWM1, PWM2.

———- (below needs a rewrite)

Check to see whether there’s already a gpio directory assigned, ls /sys/class/gpio.  If gpiochip23 exists, then it’s there.  It shouldn’t be.

If you type echo 23 > /sys/class/gpio/export, the gpio23 directory will be created.

Change the pin direction by the command, echo out > /sys/class/gpio/gpio23/direction

Change the state on the pin by, echo 1 > /sys/class/gpio/gpio23/value.  If you scope the pin, it should be reading 3.3V.

Now that you know that P8-13 is where it says it is, you can move on to making it a pwm.

P8-13 seems to be a popular pin to use as PWM.  This pin is mapped to gpio 23. It is a good choice for this test, because an overlay file, bone_pwm_P8_13-00A0.dtbo, already exists in /lib/firmware, saving the effort to create one.

Load the overlay using echo bone_pwm_P8_13 > /sys/devices/bone-capemgr*/slots.

Check the pin using cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep 44e10824. Is it in mode 4?

The different functions on P8-13 (from the AM3358 data sheet) are: gpmc_ad9 (0), lcd_data22(1), mmc1_dat1 (2), mmc2_dat5(3), ehrpwm2B(4), pr1_miii0_col (5), gpio0_23 (7).  So, mode 4 is ehrpwm2B.

In /sys/devices/ocp.?, there is a directory, pwm_test_P8_13.?? (question marks indicate variables based on who knows).

————

 

————

Table 4-3 of the TRM has a PRU-ICSS pin list.  That’s useful if you’re trying to find out what pins might carry what functions.

Table 4-21 has PRU system events. Relevant to the epwm/ecap

Int Number Signal Name Source
46 epwm_intr_intr_pend eHRPWM1
43 epwm_intr_intr_pend eHRPWM0
42 ecap_intr_intr_pend eCAP0
37 epwm_intr_intr_pend eHRPWM2
36 ecap_intr_intr_pend eCAP2
35 ecap_intr_intr_pend eCAP1
15 pr1_ecap_intr_req PRU-ICSS eCAP

————–

There are entries in constant table for PWM.

Entry Number Region pointed to Value
3 PRU-ICSS eCAP 0x00030000
4 PRU-ICSS ePWM 0x00026000
18 eHRPWM1/eCAP1/eQEP1 0x48300000
19 eHRPWM2/eCAP2/eQEP2 0x48302000
20 eHRPWM3/eCAP3/eQEP3 0x48304000

 

CLKCONFIG (ePWMCLKSTOP_REQ , ePWMCLK_EN) and CLKSTATUS (ePWM_CLKSTOP_ACK , ePWM_CLK_EN_ACK ) registers.

Table 15-57 gives the registers in the ePWM module.  There are lots.

————–

Some notes for near future:

Novus robotics cape (Strawson Design)

UCSD Advanced Digital Systems course

Sparkfun parts for Beaglebone (o-botics.org – Ga Tech)

OpenROV

PRU is a growing topic at Embedded Linux Conference.

Sparkfun products of interest:

  1. IR proximity sensor https://www.sparkfun.com/products/12728
  2. TOF range finder https://www.sparkfun.com/products/12785
  3. Distance and gesture sensor https://www.sparkfun.com/products/12780
  4. Lidar lite https://www.sparkfun.com/products/13680

————

Next up … analog input.  Need yaw rate, 3 axis accel, IP pot … total of 5.  Specs say there are up to seven.

After that … encoder interface.  Connect channel A and channel B to two R31 channels on the PRU1.  Use deterministic nature of the PRU at high speed in lieu of capture circuitry.

Could it be … there are audio input and output features to the Beaglebone Black.  The eCAP module might be usable to sample audio signals.  Could use this to enable the tone based identity and distance measurement.

Finally … need to investigate image capture, lidar, sonar, and other distance sensor technologies to expand cassy’s range.

On the arm … need to wire up the bumper switches to dig in.

Need to update the gui to use either bluetooth or ethernet sockets.  Both are available on the iPad, although bluetooth might involve a bit of juggling.

 

Posted in: Robotics

Comments are closed.