GPIO and Python on QNX

Much of the Python GPIO API is the same on QNX. Small changes may be needed to existing scripts or libraries; notably, the module for GPIO is named rpi_gpio and can be imported with import rpi_gpio as GPIO. Refer to the QNX rpi_gpio APIs page for the differences between Python's GPIO API and QNX's.

Here are some basic API usages to get started:

Pin numbering

Two modes are available for pin numbering:

  • GPIO.BOARD: Pin numbers follow the physical pin numbering on the board.
  • GPIO.BCM: Pin numbers following the Broadcom SOC channel numbering.

Set your preferred mode as BOARD or BCM:

GPIO.setmode(GPIO.BOARD)
GPIO.setmode(GPIO.BCM) 
Setting up channels

Configure a channel as input or output:

GPIO.setup(channel, GPIO.IN)
GPIO.setup(channel, GPIO.OUT)

You can also set up a channel with pull up or pull down resistor:

GPIO.setup(channel, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(channel, GPIO.IN, GPIO.PUD_DOWN)
Output to a channel

Set the output of a channel to high or low:

GPIO.output(channel, GPIO.HIGH)
GPIO.output(channel, GPIO.LOW)
Read from a channel

Read the input of a channel:

value = GPIO.input(channel)
Clean up

Close the file descriptor of the QNX resource manager:

GPIO.cleanup()
Event detection

Enable event detection for a GPIO input. When an event is detected, you must use a callback function to perform an action.

GPIO.add_event_detect(channel, GPIO.BOTH, callback = myfunction) # Use GPIO,BOTH to detect both rising and falling edge events

Here are a few sample applications to help further your understanding:

Note how the basics of managing the GPIO are the same as with Pi OS.

Is the rpi_gpio module missing some functionality you're expecting? Please let us know by opening an issue!

GPIO processes

There are several key processes that help manage the GPIO. If you experience any trouble, first make sure these are running:

  • rpi_gpio - The GPIO resource manager
  • i2c-bcm2711 - The I2C communication resource manager
  • spi-bcm2711 - The SPI communication resource manager
qnxuser@qnxpi:~$ su root
...
root@qnxpi:~# pidin -p "rpi_gpio" ar
     pid Arguments
  821234 rpi_gpio 

root@qnxpi:~# pidin -p "i2c-bcm2711" ar
     pid Arguments
  801234 i2c-bcm2711 -p0xfe804000 

root@qnxpi:~# pidin -p "spi-bcm2711" ar
     pid Arguments
  860189 spi-bcm2711 -c /system/etc/config/spi/spi.conf 

PWM

PWM (Pulse Width Modulation) allows you to simulate analog voltage levels by rapidly switching a digital pin HIGH and LOW. By adjusting the ratio of HIGH time to LOW time (the duty cycle), you can control the amount of power delivered to a device like an LED or a motor.

The following GPIO pins support hardware PWM:

  • GPIO 12 and GPIO 18 share PWM channel 1.
  • GPIO 13 and GPIO 19 share PWM channel 2.

If both GPIO 13 and 19 are configured for hardware PWM, then they will have the same period and duty cycle.

The QNX rpi_gpio module supports the following PWM modes:

MS mode

Each PWM period starts with the signal HIGH for the duty time, then LOW for the rest of the period. So, if you set a duty cycle of 25%, the signal is HIGH for 25% of the cycle, then LOW for 75%.

You can use the MS mode for servo motors.

PWM mode

The HIGH and LOW phases are spread out across the period. For the same 25% duty cycle as the previous MS mode example, the HIGH/LOW state toggles multiple times per period, but still results in being HIGH for 25% of the time.

You can use the PWM mode for LED brightness control.

PWM APIs

To create a PWM instance:

p = GPIO.PWM(channel, frequency)  # Use channel 12, 18, 13, and 19 for hardware PWM

You can optionally set the PWM mode:

p = GPIO.PWM(channel, frequency, mode) # GPIO.PWM.MODE_PWM or GPIO.PWM.MODE_MS
Note:

If you don't specify mode, it defaults to GPIO.PWM.MODE_MS.

To start PWM:

p.start(dc)   # where dc is the duty cycle (0.0 <= dc <= 100.0)

To change the frequency:

p.ChangeFrequency(freq)   # where freq is the new frequency in Hz

To change the duty cycle:

p.ChangeDutyCycle(dc)  # where 0.0 <= dc <= 100.0

To change the duty cycle using an absolute value:

p.ChangeDutyCycleAbs(dc)  # where 0 <= dc <= 1024

To stop PWM:

p.stop()

SPI

SPI (Serial Peripheral Interface) is a serial communication protocol that enables full-duplex data exchange between a master device and its peripherals through communication wires. These wires are named MISO, MOSI, SCLK, and CS.

While the RPI4 has multiple SPI buses, only SPI0 is exposed by default. The following GPIO pins support the SPI0 bus:

  • GPIO 7 is the CE1 pin.
  • GPIO 8 is the CE0 pin.
  • GPIO 9 is the MISO pin.
  • GPIO 10 is the MOSI pin.
  • GPIO 11 is the SCLK pin.

SPI APIs

Note:

These APIs interact only with the SPI0 bus.

Initialize the SPI interface
GPIO.init_spi(clkdiv)

Where:

  • clkdiv: The divisor to apply to the system clock to produce the SPI bus clock. By default, the reference clock is at 500MHz. So, for example, to get a SPI bus clock of 10MHz, you should specify a value of 50 for clkdiv.
Note:

This API must be called before using the other SPI APIs.

Write data to a device
GPIO.write_spi([data1, data2, ..., dataN])

Where:

  • [data1, data2, ..., dataN]: An array of integers to write to a device. Each integer can be in the range [0,255]. You can write up to 256 bytes in a single call.
Note:

This API only writes to the device connected to the CE0 pin.

Write and Read data to/from a device
response = GPIO.write_read_spi(ce, [inData1, inData2, ..., inDataN], [outData1, outData2, ..., outDataM])

Where:

  • ce: The Chip Enable (CE) line to enable. Set to 0 to enable CE0. Set to 1 to enable CE1.
  • [inData1, inData2, ..., inDataN]: An array of integers to write to a device. Each integer can be in the range [0,255]. You can write up to 256 bytes in a single call.
  • [outData1, outData2, ..., outDataM]: An array that will be populated with bytes read from the device. The amount of data read is equal to the length of the array. The array can have a length of at most 256.
Note:

The length of the outData array must be equal to or less than the length of the inData array. In other words, M <= N must be true.

Sample application

Not available.

I2C

I2C (Inter-Integrated Circuit) is a serial communication protocol that allows multiple devices to communicate with a Raspberry Pi using two wires; SDA (data) and SCL (clock).

The following GPIO pins support I2C:

  • GPIO 2 is the SDA pin.
  • GPIO 3 is the SCL pin.

I2C APIs

Note:

You must execute the following I2C APIs as root.

Before using the the I2C APIs, import the SMBus module using import smbus.

Create a connection to the I2C resource manager:

bus = smbus.SMBus()
bus.open(1)
Note:

The number 1 in the open() argument matches the I2C bus number, as assigned by the resource manager (i.e., /dev/i2c1).

Optionally, you can also create a connection to the resource manager during smbus initialization:

bus = smbus.SMBus(1)

Closes the connection to the I2C resource manager:

bus.close()

Reads a single byte from a device without specifying a register:

value = bus.read_byte(addr)

Writes a single byte to a device without specifying a register:

bus.write_byte(addr, data)

Reads a byte from a specific register of the device:

value = bus.read_byte_data(addr, reg)

Writes a byte to a specific register of the device:

bus.write_byte_data(addr, reg, data) 

Writes multiple bytes starting at a specific register:

bus.write_block_data(addr, reg, [data1, data2, data3, data4])
Page updated: