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
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
ID | Slot | Type | # | Schematic |
---|---|---|---|---|
gpio1_2 | GPIO1 | PMOD 1A | 2 | X1404.2 |
gpio1_4 | GPIO1 | PMOD 1A | 4 | X1404.4 |
gpio1_8 | GPIO1 | PMOD 1A | 8 | X1404.8 |
gpio_2_6 | GPIO_2/4 | Generic | X1301.6 | |
spi2_7 | SPI2 | SPI | X1402.7 | |
uart_8 | UART | UART | X1405.8 | |
uart_9 | UART | UART | X1405.9 | |
jtag_4 | JTAG | JTAG | X1503.4 | |
jtag_8 | JTAG | JTAG | X1503.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
-type clock() :: off | ipg_clk | ipg_clk_highfreq | ipg_clk_32k.
-type period() :: <<_:16>>.
-type pin() :: gpio1_2 | gpio1_4 | gpio1_8 | gpio_2_6 | spi2_7 | uart_8 | uart_9 | jtag_4 | jtag_8.
-type prescale() :: 1..4096.
-type sample() :: <<_:16>> | float().
Functions
-spec close(pin()) -> ok.
Closes a pin.
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
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
Starts the driver and registers a PWM device.