View Source grisp_pwm (grisp v2.8.0)

GriSP Pulse Width Modulation (PWM) API.

Pulse Width Modulation (PWM) is used to generate a rectangular wave with a varying duty cycle to control the average power or amplitude delivered. The ARM Cortex-A7 has eight PWM units that can be multiplexed to drive a few different pins.

  1> grisp_pwm:start_driver().
  {device,pwm,grisp_pwm,<0.353.0>,
        #Ref<0.838610995.3080454145.146844>}
  2> grisp_pwm:open(gpio1_8, default, 0.75).
  ok

This creates a rectangular wave on pin gpio1_8 with a 155.5μs cycle time (6.43MHz) and a duty cycle of 75% (see Figure 1).

You can change the duty cycle by setting a new sample:

3> grisp_pwm:set_sample(gpio1_8, 0.5).
ok

If you want to stop using PWM on this pin you can call:

 4> grisp_pwm:close(gpio1_8).
 ok

image Figure 1. Oscilloscope trace with a 0.75 % duty cycle and the default configuration.

Ramp Up Example

Youn can ramp up the duty cycle from 0% to 100% in one second like this:

1> RampSample = fun(X) -> grisp_pwm:set_sample(gpio1_8, (X/100)), timer:sleep(10) end.
#Fun<erl_eval.42.39164016>
2> [RampSample(X) || X <- lists:seq(1, 100)].
[ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,
ok,ok,ok,ok,ok,ok,ok,ok,ok,ok|...]

Sinusoidal Example

You can create a sine wave like this:

1> SinSample = fun(X) -> V = math:sin(math:pi()/2*(X/10))/2+0.5, grisp_pwm:set_sample(gpio1_8, V), timer:sleep(10) end.
#Fun<erl_eval.42.39164016>
2> [SinSample(X) || X <- lists:seq(1, 1000)].
[ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,
ok,ok,ok,ok,ok,ok,ok,ok,ok,ok|...]

Pin Mappings

IDSlotType#Schematic
gpio1_2GPIO1PMOD 1A2X1404.2
gpio1_4GPIO1PMOD 1A4X1404.4
gpio1_8GPIO1PMOD 1A8X1404.8
gpio_2_6GPIO_2/4GenericX1301.6
spi2_7SPI2SPIX1402.7
uart_8UARTUARTX1405.8
uart_9UARTUARTX1405.9
jtag_4JTAGJTAGX1503.4
jtag_8JTAGJTAGX1503.8

Note

This driver might use pins that are also used by other drivers (GPIO, SPI, UART). When opening a pin the PWM driver takes control and configures the multixplexing so the pin is wired to the corresponding PWM unit. When closing the pin the driver will restore the pevious multiplexing setting, handing back control.

Example: grisp_gpio is used to set a pin to high, then grisp_pwm:open/3 is used to drive the pin. After grisp_pwm:close/1 is called, the pin is set to high and grisp_gpio is again in control.

Summary

Functions

Closes a pin.

Opens a pin and sets a configuration and a sample.

Sets a sample to define the duty cycle.

Starts the driver and registers a PWM device.

Types

clock()

-type clock() :: off | ipg_clk | ipg_clk_highfreq | ipg_clk_32k.

config()

-type config() :: default | {prescale(), period()} | {clock(), prescale(), period()}.

period()

-type period() :: <<_:16>>.

pin()

-type pin() :: gpio1_2 | gpio1_4 | gpio1_8 | gpio_2_6 | spi2_7 | uart_8 | uart_9 | jtag_4 | jtag_8.

prescale()

-type prescale() :: 1..4096.

sample()

-type sample() :: <<_:16>> | float().

Functions

close(Pin)

-spec close(pin()) -> ok.

Closes a pin.

open/3

-spec open(pin(), config(), sample()) -> ok | {error, _}.

Opens a pin and sets a configuration and a sample.

Default Config

The default configuratin uses the ipg_clk clock, a prescale of 10 and a period of <<1024:16>>. This results in a 155.5μs cycle time (6.43MHz) and 10bit resolution.

1> grisp_pwm:open(gpio1_8, default, 0.75).
ok

Prescale and Period Config

Here we set the prescaler to 1 (10 times higher frequency than the default) and the period to <<512:16>> (further doubling the frequency and halfing the resolution). The result is a 7,775μs cycle time (128.6MHz) and 9bit resolution.

1> grisp_pwm:open(gpio1_8, {1, <<512:16>>}, 0.5).
ok

Clock, Prescale and Period Config

This sets a low frequency clock and results in a 500ms cycle time (2Hz) and 4bit resolution.

1> grisp_pwm:open(gpio1_8, {ipg_clk_32k, 1, <<16:16>>}, 0.5).
ok

set_sample(Pin, Sample)

-spec set_sample(pin(), sample()) -> ok | {error | _}.

Sets a sample to define the duty cycle.

You can pass a float between 0.0 and 1.0 or a 16bit binary. The binary value must be below or equal to the period (<<1024:16>> by default).

Float Sample

This sets the duty cycle to 25%. This method is independent of the period used.

1> grisp_pwm:set_sample(gpio1_8, 0.25).
ok

Binary Sample

This sets the duty cycle to 25% given a period of <<1024:16>>.

1> grisp_pwm:set_sample(gpio1_8, <<256:16>>).
ok

start_driver()

Starts the driver and registers a PWM device.