Skip to content

Commit 48d6a29

Browse files
authored
Merge pull request #803 from makermelissa/main
Add PWM Support for Jetson Nano
2 parents 60f2f02 + 5030e3d commit 48d6a29

File tree

5 files changed

+169
-2
lines changed

5 files changed

+169
-2
lines changed

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Adafruit-PlatformDetect>=3.53.0
1+
Adafruit-PlatformDetect>=3.62.0
22
Adafruit-PureIO>=1.1.7
33
Jetson.GPIO; platform_machine=='aarch64'
44
RPi.GPIO; platform_machine=='armv7l' or platform_machine=='armv6l' or platform_machine=='aarch64'

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
},
9090
include_package_data=True,
9191
install_requires=[
92-
"Adafruit-PlatformDetect>=3.53.0",
92+
"Adafruit-PlatformDetect>=3.62.0",
9393
"Adafruit-PureIO>=1.1.7",
9494
"pyftdi>=0.40.0",
9595
"adafruit-circuitpython-typing",
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""Custom PWMOut Wrapper for Jetson GPIO PWM Class"""
5+
from RPi import GPIO
6+
7+
GPIO.setmode(GPIO.TEGRA_SOC) # Use BCM pins D4 = GPIO #4
8+
GPIO.setwarnings(True) # shh!
9+
10+
11+
class PWMError(IOError):
12+
"""Base class for PWM errors."""
13+
14+
15+
class PWMOut:
16+
"""Pulse Width Modulation Output Class"""
17+
18+
def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False):
19+
self._pwmpin = None
20+
self._period = 0
21+
self._open(pin, duty_cycle, frequency, variable_frequency)
22+
23+
def __del__(self):
24+
self.deinit()
25+
26+
def __enter__(self):
27+
return self
28+
29+
def __exit__(self, t, value, traceback):
30+
self.deinit()
31+
32+
def _open(self, pin, duty=0, freq=500, variable_frequency=False):
33+
self._pin = pin
34+
GPIO.setup(pin.id, GPIO.OUT, initial=GPIO.HIGH)
35+
self._pwmpin = GPIO.PWM(pin.id, freq)
36+
37+
if variable_frequency:
38+
print("Variable Frequency is not supported, continuing without it...")
39+
40+
# set frequency
41+
self.frequency = freq
42+
# set duty
43+
self.duty_cycle = duty
44+
45+
self.enabled = True
46+
47+
def deinit(self):
48+
"""Deinit the PWM."""
49+
if self._pwmpin is not None:
50+
self._pwmpin.stop()
51+
GPIO.cleanup(self._pin.id)
52+
self._pwmpin = None
53+
54+
def _is_deinited(self):
55+
if self._pwmpin is None:
56+
raise ValueError(
57+
"Object has been deinitialize and can no longer "
58+
"be used. Create a new object."
59+
)
60+
61+
@property
62+
def period(self):
63+
"""Get or set the PWM's output period in seconds.
64+
65+
Raises:
66+
PWMError: if an I/O or OS error occurs.
67+
TypeError: if value type is not int or float.
68+
69+
:type: int, float
70+
"""
71+
return 1.0 / self.frequency
72+
73+
@period.setter
74+
def period(self, period):
75+
if not isinstance(period, (int, float)):
76+
raise TypeError("Invalid period type, should be int or float.")
77+
78+
self.frequency = 1.0 / period
79+
80+
@property
81+
def duty_cycle(self):
82+
"""Get or set the PWM's output duty cycle which is the fraction of
83+
each pulse which is high. 16-bit
84+
85+
Raises:
86+
PWMError: if an I/O or OS error occurs.
87+
TypeError: if value type is not int or float.
88+
ValueError: if value is out of bounds of 0.0 to 1.0.
89+
90+
:type: int, float
91+
"""
92+
return int(self._duty_cycle * 65535)
93+
94+
@duty_cycle.setter
95+
def duty_cycle(self, duty_cycle):
96+
if not isinstance(duty_cycle, (int, float)):
97+
raise TypeError("Invalid duty cycle type, should be int or float.")
98+
99+
if not 0 <= duty_cycle <= 65535:
100+
raise ValueError("Invalid duty cycle value, should be between 0 and 65535")
101+
102+
# convert from 16-bit
103+
duty_cycle /= 65535.0
104+
105+
self._duty_cycle = duty_cycle
106+
self._pwmpin.ChangeDutyCycle(round(self._duty_cycle * 100))
107+
108+
@property
109+
def frequency(self):
110+
"""Get or set the PWM's output frequency in Hertz.
111+
112+
Raises:
113+
PWMError: if an I/O or OS error occurs.
114+
TypeError: if value type is not int or float.
115+
116+
:type: int, float
117+
"""
118+
119+
return self._frequency
120+
121+
@frequency.setter
122+
def frequency(self, frequency):
123+
if not isinstance(frequency, (int, float)):
124+
raise TypeError("Invalid frequency type, should be int or float.")
125+
126+
self._pwmpin.ChangeFrequency(round(frequency))
127+
self._frequency = frequency
128+
129+
@property
130+
def enabled(self):
131+
"""Get or set the PWM's output enabled state.
132+
133+
Raises:
134+
PWMError: if an I/O or OS error occurs.
135+
TypeError: if value type is not bool.
136+
137+
:type: bool
138+
"""
139+
return self._enabled
140+
141+
@enabled.setter
142+
def enabled(self, value):
143+
if not isinstance(value, bool):
144+
raise TypeError("Invalid enabled type, should be string.")
145+
146+
if value:
147+
self._pwmpin.start(round(self._duty_cycle * 100))
148+
else:
149+
self._pwmpin.stop()
150+
151+
self._enabled = value
152+
153+
# String representation
154+
def __str__(self):
155+
return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
156+
self._pin,
157+
self.frequency,
158+
self.duty_cycle,
159+
)

src/adafruit_blinka/microcontroller/tegra/t210/pin.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,9 @@ def cleanup():
135135

136136
# ordered as spiId, sckId, mosiId, misoId
137137
spiPorts = ((0, C02, C00, C01), (1, B06, B04, B05))
138+
139+
# SysFS pwm outputs, pwm channel and pin in first tuple
140+
pwmOuts = (
141+
((0, 0), V00),
142+
((0, 1), E06),
143+
)

src/pwmio.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
4343
elif detector.board.pico_u2if:
4444
from adafruit_blinka.microcontroller.rp2040_u2if.pwmio import PWMOut
45+
if detector.board.any_jetson_board:
46+
from adafruit_blinka.microcontroller.tegra.PWMOut import PWMOut
4547
elif (
4648
detector.board.feather_u2if
4749
or detector.board.feather_can_u2if

0 commit comments

Comments
 (0)