Raspberry Pi - Qwiic and pigpio

Some years back pigpio / pigpiod was included with the Raspbian Desktop install. I have used it to do PWM on a Robot for WiFi control and most recently connected a Redboard Turbo by UART to a remote RPi. I use the Python portions but there is also a C++ library. This give local and remote access to all the gpio functions including I2C and SPI. As I am a mechanic with mechanical design training and not a programmer I used example code for my I2C test and picked the Qwiic Joystick because I have 2 of them and they are simple. The first bunch of code was saved as the first line says. It is all the functions to use the Joystick. The other is a test program using 1 or 2 remote RPis, more could be added. The second bunch of code could be run on an X86 system according to the pigpio web site.

I am working on converting other Qwiic programming to pigpio, I will take any help I can. I also think this could help sales of Qwiic sensors as one program can read from several sensors with little effort once the function code is working. This is also a way to do a Python module without having to ‘install’ anything.

Dale

# QWiic_Joystick_Functions.py
# Jan 2020
# by Dale Bartel
#
# Definitions and functions for the Sparkfub QWiic Joystick
#
# make sure pigpio is imported and started in the calling program
# Make sure gpiod is running on target
#  do sudo pigpiod  in a terminal

# > > > > > Definitions < < < < <

QWiic_Joystick_Addr = 0x20  # default I2C Address

# Joystick registers
Joystick_ID = 0x00
Joystick_Version1 = 0x01
Joystick_Version2 = 0x02
Joystick_X_MSB = 0x03
Joystick_X_LSB = 0x04
Joystick_Y_MSB = 0x05
Joystick_Y_LSB = 0x06
Joystick_Button = 0x07
Joystick_Status = 0x08          # 1 = Button clicked
Joystick_I2C_Lock = 0x09
Joystick_Change_Address = 0x0A 

# > > > > > List of functions < < < < <

# Initializes the I2C connection for a specifid RPi
# Returns false if board is not detected, object handle otherwise
def begin(RPi, i2c_bus, i2c_Address):
    handle = RPi.i2c_open(i2c_bus, i2c_Address)
    return handle

# Returns 1 if Button was pressed between reads of .getButton() or .checkButton()
# the register is then cleared after read.
def check_button(RPi, handle):
    Status = RPi.i2c_read_byte_data(handle, Joystick_Status)    # read Status
    RPi.i2c_write_byte_data(handle, Joystick_Status, 0x00)  # clear Status
    if Status > 1:
        return 1  # 1 if new press or 0 if not
    else:
        return 0

# Returns 0 Button is currently being pressed
def get_button(RPi, handle):
    Button = RPi.i2c_read_byte_data(handle, Joystick_Button)
    if Button > 0:
        return 0  # Button not pressed
    else:
        return 1  # Button pressed

# Returns the 10-bit int ADC value of the Joystick horizontal position
def get_horizontal(RPi, handle):
    msb = RPi.i2c_read_byte_data(handle, Joystick_X_MSB)
    lsb = RPi.i2c_read_byte_data(handle, Joystick_X_LSB)
    return int(((msb * 256) + lsb) / 64)  # need to combine msb with lsb

# Returns the 10-bit int ADC value of the Joystick vertical position
def get_vertical(RPi, handle):
    msb = RPi.i2c_read_byte_data(handle, Joystick_Y_MSB)
    lsb = RPi.i2c_read_byte_data(handle, Joystick_Y_LSB)
    return int(((msb * 256) + lsb) / 64)  # need to combine msb and lsb

# Returns a string of the firmware Version number
def get_version(RPi, handle):
    v1 = RPi.i2c_read_byte_data(handle, Joystick_Version1)  # string major
    v2 = RPi.i2c_read_byte_data(handle, Joystick_Version2)  # string minor
    return "v " + str(v1) + "." + str(v2)

'''
# NOT TESTED
# Change the I2C Address of this Address to newAddress
def set_I2C_Address(RPi, handle, newAddress):    
if 8 <= newAddress && newAddress <= 119:
    RPi.i2c_write_byte_data(handle, Joystick_I2C_Lock,0x13 )
    RPi.i2c_write_byte_data(handle, Joystick_Change_Address, newAddress)
    QWiic_Joystick_Addr = newAddress
    RPi.i2c_close(handle)                                # Close the old handle
    handle = RPi.i2c_open(i2c_bus, QWiic_Joystick_Addr)  # Open a new handle
    return handle                          
else:
    return -1                                            # Error
'''

Test program follows.

# QWiic_2_Joystick_test.py
# Jan 2020
# by Dale Bartel
#
# make sure both files are in the same directory
# Make sure gpiod is running on target
# sudo pigpiod  in a terminal
#
# This was tested with 2 Qwiic Joysticks, one on each of 2 remote RPi

import sys
if sys.version > '3':
    buffer = memoryview

import pigpio
import QWiic_Joystick_Functions as JSF

# Default port is 8888 for remote use
port = 8888

# For use with remote RPi_1
ipAdrs1 = ('xxx.xxx.xxx.xxx')  # use a real IP address

# For use with remote RPi_2
#ipAdrs2 = ('xxx.xxx.xxx.xxx')

# For remote use
pi1 = pigpio.pi(ipAdrs1, port)
#pi2 = pigpio.pi(ipAdrs2, port)

# For Local use
#pi1 = pigpio.pi()

BUS = 1  # which i2c buss

# > > > > > PROGRAM FOLLOWS < < < < <
h1 = JSF.begin(pi1, BUS, JSF.QWiic_Joystick_Addr)

if h1 >= 0:            # Connected OK
    print(JSF.get_version(pi1, h1))
else:
    print('ERROR')
    pi1.i2c_close(h1)  # Closes i2c object h1

if h1 >= 0:
    print('H ', JSF.get_horizontal(pi1, h1))
    print('V ', JSF.get_vertical(pi1, h1))
    print('status ', JSF.check_button(pi1, h1))
    print('button ', JSF.get_button(pi1, h1))

'''
h2 = JSF.begin(pi2, BUS, JSF.QWiic_Joystick_Addr)

if h2 >= 0:            # Connected OK
    print("#2", JSF.get_version(pi2, h2))
else:
    print('ERROR')
    pi1.i2c_close(h2)  # Closes i2c object h2

if h2 >= 0:
    print('H_2 ', JSF.get_horizontal(pi2, h2))
    print('V_2 ', JSF.get_vertical(pi2, h2))
    print('status_2 ', JSF.check_button(pi2, h2))
    print('button_2 ', JSF.get_button(pi2, h2))
'''

# End of program
pi1.i2c_close(h1)      # Closes i2c object h1
#pi2.i2c_close(h2)      # Close i2c object h2
pi1.stop()             # Stops pigpio 1
#pi2.stop()             # Stop pigpio 2