API Modules

The core API python modules are found in the yrk subfolder.

yrk.adc

This module provides functions for reading from the ADS7830 8-bit Analog:Digital Converter. 8-bit raw values can be read using the read_adc function and these values can be converted to distance measurements for various Sharp IR distance sensors based on look-up table values using the get_model_value function.

The ADC has 8 input channels. Channels 0-5 are broken out on the PCB to 3-pin JST-PH headers. +5V[aux] is the uppermost pin, GND in middle and V_sense at the bottom. The ADC is set to range from 0V [0] to 2.50V [255], approx 0.01V/scale. Using the 2y0a21 or 2y0a41 sensor models for the

GP2Y0A21YK0F distance sensor [10 - 80cm] https://global.sharp/products/device/lineup/data/pdf/datasheet/gp2y0a21yk_e.pdf

GP2Y0A41SK0F distance sensor [4 - 30cm] https://global.sharp/products/device/lineup/data/pdf/datasheet/gp2y0a41sk_e.pdf

ADC channel six is connected to the potentiometer at the top-left of the board. This will produce a raw output of 255-0 as it is turned clockwise. Using the inv_pct sensor model will convert this from 0 - 100.0 %. ADC channel 7 is connected to the left auxiliary ADC pin, GND to the right. These pins are 2mm pitch [jumpers leads are available to convert to 0.1” pitch].

yrk.adc.get_model_value(raw_value, sensor_model)

A function that converts a raw ADC value to distance for Sharp IR sensor

Args:

raw_value (int): The 8-bit raw ADC value [eg from read_adc()] sensor_model (str): The sensor model to use. ‘2y0a21’ or ‘2y0a41’ are valid sensors; other options are ‘voltage’,’raw’ and ‘inv_pct’

Returns:

float: Converted distance in mm based on look-up tables

yrk.adc.read_adc(channel)

A function that reads the raw 8-bit value [8-bit] from given channel of ADC

Args:

channel (int): The ADC channel to read from [0-7]. 6 is potentiometer on YRL040.

Returns:

int: ADC value [range 0-255]

yrk.audio

The YRL040 PCB contains a TPA2005 class-D 1.4W mono audio amplifier. The audio output from the Raspberry Pi is sent as a PWM signal over GPIO pin 12 and a logic-high on GPIO pin 16 enables the amplifier. PWM audio is relatively poor in audio quality and inherently noisy, so it is generally preferable to disable the output when audio is not being played.

The audio module is designed to run continuously and uses a seperate execution thread to process a queue of stored audio commands. The audio setup is started by calling the setup_audio function. To add a sound to the playback queue either play_audio_file, which plays a .mp3 or .wav file, or say, which uses the espeak program to read a message.

TPA2005 Data Sheet: https://www.ti.com/lit/ds/symlink/tpa2005d1.pdf

yrk.audio.audio_queue_thread()

Thread loop for handling queued audio files

yrk.audio.kill_audio()

Function to kill all running audio processes

yrk.audio.mute()

This function mutes the audio output

yrk.audio.play_audio_file(file)

Function to add an audio file to the audio Queue

Args:

file (str): The filename for the [.mp3] or [.wav] audio file

yrk.audio.say(message)

Function to add a spoken message to the audio Queue

Args:

message (str): The message to read out [using e-speak]

yrk.audio.say_ip()

This function will speak IP address using hostname subprocess and stored audio files

yrk.audio.set_volume(volume)

A function that sets the [PWM] volume output

Args:

volume (int): The percentage volume [0-100]

yrk.audio.setup_audio()

Function to setup the audio system: sets volume, mutes output, starts thread

yrk.audio.start_audio_thread()

Function to start the audio thread

yrk.audio.unmute()

This function unmutes the audio output.

Note that audio out uses PWM GPIO which is inherently noisy, CPU activity noise should be expected when audio is unmuted. Where possible, use of the play_audio_file() function and queue system is recommended as this mutes audio when the queue is empty

yrk.core

yrk.display

There is a header on the YRL040 PCB to which an Adafruit PiOLED 128x32 pixel display can be attached, either directly or via a ribbon cable. This module augments the functionality of the Adafruit_SSD1306 library, providing functions to display graphics and text on the display. Bus 5 of the I2C switch is routed (exclusively) to the display header.

The init_display() function should be called once before drawing functions are used to initialise the display (this is done by core.py if being used).

yrk.display.clear()

A function to clear the display

yrk.display.display_image(image)

Function to display a 128x32 pixel PIL image on the display

The display functions use the Python Image Library (Pillow) to store the image bitmaps that are to be displayed. All other drawing functions generate a PIL image then call this function to display the generated image.

Args:

image (PIL image): The 128x32 PIL image

yrk.display.display_image_file(image_filename)

Function to display a 128x32 pixel monochrome PBM image from file on the display

PBM are portable bit-map files; the file size should be 522 bytes (10 bytes header + 512 bytes data). Files can be generated using bitmap editing graphics applications such as Gimp or Adobe Photoshop.

Args:

image_filename (str): The filename for the 128x32 PBM image

yrk.display.display_stats()

Function to display current system stats (IP, cpu load, temperatures, memory usage)

yrk.display.get_ip()

Function to get IP address as a string using hostname system process

yrk.display.init_display() → bool

A function to initialise and clear the display

yrk.display.one_line_text(text)

Function to display one line of 32-pixel high text on display [no wrapping]

Args:

text (str): The message to display [8-chars max to be displayed]

yrk.display.one_line_text_wrapped(text)

Function to display one message of text on display

32-pixel high [1-line] font will be used unless message > 14 characters long, in which case either 16-pixel or 8-pixel high fonts will be used.

Args:

text (str): The message to display [64-chars max to be displayed]

yrk.display.two_line_text(line1_text, line2_text)

Function to display two lines of text on display in 16-pixel high font [no wrapping]

Args:

line1_text (str): The first line of text to display [14-chars max to be displayed] line2_text (str): The first line of text to display [14-chars max to be displayed]

yrk.display.two_line_text_wrapped(line1_text, line2_text)

Function to display two lines of text on display

Where lengths are < 15 characters, 16-pixel font used, else 8-pixel font used

Args:

line1_text (str): The first line of text to display [32-chars max to be displayed] line2_text (str): The first line of text to display [32-chars max to be displayed]

yrk.display.warning(text)

Function to display a warning graphics alongside a text message on display

Args:

text (str): The text message to display (limited to about 8 characters)

yrk.gpio

The YRL040 PCB contains two PCA9555 16-bit GPIO expanders, one is connected to the switches [see switch module], the other provides 8 user GPIO pins on a 0.1” pitch 4x2 header. It also uses 4 GPIO input to detect fault conditions in the four H-bridge motor drivers, and 1 more to provide the motor fault LED output. Another input is used to provide the “kill switch” input, which might be configured to stop all running code etc.

The final pair of GPIO outputs are used to provide an NMOS-driven 5V and 12V switched output. These outputs can be used to turn on a DC load [fused at 1A], but note the negative terminal is not a common ground with the main PCB and should not be connected. This makes the output most suited to drive things such as a buzzer or lamp, or potentially a relay. The 5V output is connected to the 5V_AUX supply [though will be slightly under 5V due to the FET losses]; the 12V is connected to V_IN.

PCA5555 GPIO Expander Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9555.pdf

yrk.gpio.read_user_gpio()

A function to read the input registers of the user GPIO Expander

Returns:

int: 16-bit value indicating user GPIO states.

yrk.gpio.set_motor_fault_led(state)

A function to enable or disable the motor fault LED

Args:

state (bool): Enable or disable the motor fault LED

yrk.gpio.set_switched_output_12V(state)

A function to enable the 12V switched output

Note the PD will actually be a little under Vin. V- is not GND and should not be connected to ground.

Args:

state (bool): Enable or disable the 12V output

yrk.gpio.set_switched_output_5V(state)

A function to enable the 5V switched output

Note the PD will actually be a little under 5V. V- is not GND and should not be connected to ground.

Args:

state (bool): Enable or disable the 5V output

yrk.gpio.setup_user_gpio()

An initialisation function for the PCA9555 GPIO Expander for the user GPIO and motor fault detection

Sets pins IO0_0 : IO0_7 based on values from settings.py Sets pins IO1_0 : IO1_3 as inverted inputs for motor fault detection Sets pins IO1_4 : IO1_6 as outputs [off] for switched outputs and motor fault LED Sets pin IO1_7 as inverted input for kill switch

yrk.gpio.update_switched_gpio_outputs()

Sends i2c command to set the switched outputs based on stored variables

yrk.led

The YRL040 PCB contains a TCA6507 7-way I2C LED driver. This IC is connected to the two RGB LEDs at either corner of the top of the PCB, plus one extra output is routed to the top-left expansion pin at the top of the PCB.

The TCA6507 allows 2 programmable channels of PWM output, allowing blinks and pulse effects to be programmed using a single I2C message. However, as this is limited to 2 channels, full independent RGB control of the LEDs is not possible. To simplify use, this module contains a number of functions to allow programmed single colours and animated effects to be shown on the LEDs.

TCA6507 Data Sheet: https://www.ti.com/lit/ds/symlink/tca6507.pdf

yrk.led.animation(index)

Displays the given animation from body_animations list

Args:

index (int): The body_animations entry to use [range 0-8]

yrk.led.set_brightness(brightness_int)

Sets stored target brightness value to given value

NB Brightness is only changed on next call to set led

Args:

brightness_int (int): The target brightness [range 0-15]

yrk.led.set_colour_pulse(index, speed=4)

Sets both LEDs to pulse, at given speed and colour

Args:

index (int): The solid_colours entry to use [range 0-8] speed (int): The speed of the pulse [range 0-15]

yrk.led.set_colour_solid(index)

Sets both LEDs to solid colour

Args:

index (int): The solid_colours entry to use [range 0-8]

yrk.led.set_left_colour_pulse(index, speed=4)

Sets the left LED to pulse, at given speed and colour

Args:

index (int): The solid_colours entry to use [range 0-8] speed (int): The speed of the pulse [range 0-15]

yrk.led.set_left_colour_solid(index)

Sets the left LED to a solid colour

Args:

index (int): The solid_colours entry to use [range 0-8]

yrk.led.set_right_colour_pulse(index, speed=4)

Sets the right LED to pulse, at given speed and colour

Args:

index (int): The solid_colours entry to use [range 0-8] speed (int): The speed of the pulse [range 0-15]

yrk.led.set_right_colour_solid(index)

Sets the right LED to a solid colour

Args:

index (int): The solid_colours entry to use [range 0-8]

yrk.led.stop_animation()

Stops the animation [by calling animation(0)]

yrk.led.timed_animation(index, time)

Starts a Timer thread to run animation for given duration then stop

Use carefully as no checking is done in the case of repeated calls

Args:

index (int): The body_animations entry to use [range 0-8] time (float): The duration in seconds before calling stop_animation

yrk.motors

The YRL040 PCB contains 4 DRV8830 H-Bridge motor drivers, powered from the 5V_AUX supply. Each driver has an 800mA current limit. It is primarily intended for use with small brushed DC motors such as the 12mm micro-metal gear motors available from a number of suppliers including MFA Como, Pimoroni and Pololu. Motors are connected using the push-level Wago terminals at either side of the YRL040 PCB.

The motor driver allows the effective motor voltage [in either direction] to be programmed using an I2C message. It also allows the motor to be put in a coast [high-impendance] or brake [short-circuit] state. The ICs contain fault [over-current and over-temperature] conditions to trigger a logic low output, which is connected the GPIO expander [see gpio].

DRV8830 Data Sheet: https://www.ti.com/lit/ds/symlink/drv8830.pdf

yrk.motors.brake_motor(motor)

Turns on brake mode for given motor

Brake state effectively short-circuits the motor windings, resisting motion. This is different to coast state [high-impendance] which is set by calling set_motor_speed(motor,0)

Args:

motor (int): The motor driver [range 0-3]

yrk.motors.get_brake_state(motor)

Gets current brake state of the given motor driver

Args:

motor (int): The motor driver [range 0-3]

Returns:

bool: True if the motor is in brake [short-circuit] state

yrk.motors.get_motor_speed(motor)

Gets current speed of the given motor driver

Args:

motor (int): The motor driver [range 0-3]

Returns:

float: The target speed of the motor [range -1.0 to 1.0]

yrk.motors.set_motor_speed(motor, speed)

Sets the motor to given speed

Args:

motor (int): The motor driver [range 0-3] speed (float): The target speed for the motor [range -1.0 to 1.0]

yrk.motors.stop_all_motors()

Sets all 4 motor drivers to coast state

yrk.power

The YRL039 PCB provides the main power supplies for the YRK, using a pair of 3A, 5V buck [step-down] converters. These power supplies are controlled by a ATMega328 microcontroller, which also monitors the voltage of the supply plus the voltages and currents of both 5V outputs. The ATMega also monitors the temperature of the PCB and controls a small fan, positioned directly above the CPU of the Raspberry Pi.

This module provides the functions to read the data values from the ATMega microcontroller [using the I2C bus].

yrk.power.get_aux_current()

Returns 5V_AUX current (float) stored on last call of read_all_values

yrk.power.get_aux_voltage()

Returns 5V_AUX voltage (float) stored on last call of read_all_values

yrk.power.get_battery_voltage()

Returns battery voltage (float) stored on last call of read_all_values

yrk.power.get_pcb_temperature()

Returns PCB temperature (float) stored on last call of read_all_values

yrk.power.get_pi_current()

Returns 5V_PI current (float) stored on last call of read_all_values

yrk.power.get_pi_voltage()

Returns 5V_PI voltage (float) stored on last call of read_all_values

yrk.power.read_all_values()

Reads and stores all voltage, current and temperature readings in a single i2c request

yrk.pwm

This module provides functions for controlling the PCA9685 16-channel 12-bit PWM driver, which is primarily intended for use with analog servo motors.

This module has been quickly put relatively quickly to provide functionality for [exclusively for] use with analog servos. If wanted for other purposes it would be worth investigating the existing Adafruit library, which is more polished, but requires circuitpython amongst other libraries and might take a bit of adaptation to work using the switched i2c bus.

PCA9685 Datasheet https://www.nxp.com/docs/en/data-sheet/PCA9685.pdf

yrk.pwm.calculate_nearest_duty_cycle_to_period(period_seconds: float) → int

Calculate the value for raw cycle for a given period

Args:

period_seconds (float): The target on-time in seconds.

Returns:

int: The raw duty cycle value [for use with set_duty_cycle_raw]

yrk.pwm.estimate_on_time(dutycycle_raw: int) → float

Estimate the on-time based on the raw duty cycle value

Args:

dutycycle_raw (int): The target duty-cycle [range 0 - 4095]

Returns:

float: The approximate on-time value in seconds

yrk.pwm.set_duty_cycle(output: int, dutycycle_pct: float)

Sets the duty cycle (on period) of a PWM output as a percentage

Args:

output (int): The servo output to use [range 0-15] dutycycle_pct (float): The percentage [0-100] of on-time

yrk.pwm.set_duty_cycle_raw(output: int, dutycycle_raw: int)

Sets the raw on-period value for a given PWM output

Args:

output (int): The servo output to use [range 0-15] dutycycle_raw (int): The on-time period [range 0-4095]

yrk.pwm.set_normal_mode()

Disables sleep mode on PWM driver

yrk.pwm.set_prescale_value(psv: int)

Sets the prescale register to set the PWM frequency

PWM frequency approximately equal to 6104 / (psv + 1)

Args:

psv (int): The target prescale register value [range 3-255]

yrk.pwm.set_pwm_frequency(freq: float)

Sets the PWM frequency

The PWM will be set as close as it can be to the requested frequency. It calculates the closest prescale value and calls set_prescale_value with this value. All outputs have the same frequency.

Args:

freq (float): The target frequency in hertz [effective range 24 - 1526]

yrk.pwm.set_sleep_mode()

Enables sleep mode on PWM driver

yrk.settings

yrk.settings.ADC_MODELS = ['voltage', 'voltage', 'voltage', 'voltage', 'voltage', 'voltage', 'inv_pct', 'voltage']

List of model types for the 8 ADC inputs

Sensor type in this list. Should have 8 entries. Note 7th is for potentiometer. Valid models are voltage, pct, inv_pct, raw, 2y0a21 and 2Y0a41

Eg: ADC_MODELS = [‘2y0a21’,‘2y0a41’,’voltage’,’raw’,’raw’,’raw’,’inv_pct’,’raw’]

yrk.settings.AUDIO_VOLUME = 100

Volume to set Alsa mixer to on setup of audio (range 0-100, but 80+ recommended)

yrk.settings.BATTERY_CELLS = 2

Number of Li-Ion or Li-Po cells in battery (2,3 or 4)

Sets the BATTERY_LOW_VOLTAGE, BATTERY_CRITICAL_VOLTAGE and BATTERY_SHUTDOWN_VOLTAGE parameters based on the number of cells described. The values for 2 cell batteries are a little more generous to get decent usable life of of battery, although voltage drop may be too great in high current drain use cases. If using other battery technology (eg Ni-Mh) set values manually within settings.py

yrk.settings.BATTERY_CHECK_PERIOD = 2.0

Period (s) between battery state checks

yrk.settings.BATTERY_CRITICAL_SHUTDOWN = True

If enabled, system will force shutdown when Vbatt<BATTERY_SHUTDOWN_VOLTAGE

yrk.settings.CONSOLE_LOGGING_MODE = 20

Set the Python logging level for console output.

The recommend setting is logging.INFO for deployment and logging.DEBUG for debugging. Cannot be at a lower level than FILE_LOGGING_MODE.

yrk.settings.CPU_CRITICAL_TEMP = 75

CPU critical temperature, recommend ~75C for Pi 4 and ~65C for Pi 3

yrk.settings.CPU_SHUTDOWN_TEMP = 82

CPU shutdown temperature, recommend ~82C for Pi 4 and ~72C for Pi 3

yrk.settings.CPU_WARNING_TEMP = 65

CPU warning temperature, recommend ~65C for Pi 4 and ~60C for Pi 3

yrk.settings.DISPLAY_ROTATED = False

Set to True if the OLED module is rotated to flip image

yrk.settings.ENABLE_BATTERY_MONITOR = True

If enabled yrk-core.py will display visual+audible warnings when battery low

yrk.settings.ENABLE_TEMPERATURE_MONITOR = True

If enabled yrk-core.py will display visual+audible warnings when cpupcb temperature high

yrk.settings.FILE_LOGGING_MODE = 10

Set the Python logging level for saved log files.

The recommend setting is logging.INFO for deployment and logging.DEBUG for debugging

yrk.settings.HAS_DISPLAY = False

Set to True is OLED module is being used

yrk.settings.I2C_5V_BUS = 11

The PWM driver and the Arduino are on the 5V I2C Bus [bus 4 on switch]

yrk.settings.OLED_BUS = 12

The /dev/i2c_XX bus which the OLED module is attached to

yrk.settings.PCB_CRITICAL_TEMP = 45

PCB critical temperature, recommend ~45C

yrk.settings.PCB_SHUTDOWN_TEMP = 50

PCB forced shutdown temperature, recommend ~50C

yrk.settings.PCB_WARNING_TEMP = 40

PCB warning temperature, recommend ~40C

yrk.settings.PWM_FREQUENCY = 50

PWM (Analog Servo) target frequency in hertz

yrk.settings.RASPBERRY_PI_MODEL = 4

Sets the Raspberry Pi version being used

Set to 4 if using Raspberry Pi 4 (recommended) If set to different value, default BUS values are overwritten with values compatible with the earlier Pis.

yrk.settings.TEMPERATURE_CHECK_PERIOD = 2.0

Period (s) between temperature checks

yrk.settings.TEMPERATURE_CRITICAL_SHUTDOWN = True

If enabled, system will force shutdown when CPU Temp<CPU_SHUTDOWN_TEMP or PCB Temp<PCB_SHUTDOWN_TEMP

yrk.settings.USER_GPIO_INVERTED = 0

Initialisation inversion state for the 8 user GPIO pins [1=Invert input]

yrk.settings.USER_GPIO_MODE = 255

Initialisation mode for the 8 user GPIO pins [1=Input [with pull-up], 0=Output].

yrk.settings.USER_GPIO_OUTPUT_STATE = 0

Initialisation output state for the 8 user GPIO pins

yrk.settings.USE_DIP_FUNCTIONS = True

If True, yrk-core uses DIP 2 for ROS, DIP 3 for DASH server and DIP 4 for DEMO

yrk.settings.USE_DIP_LEDS = True

If true, yrk-core will set DIP LEDs based on program state

yrk.settings.YRL039_ADDRESS = 57

The I2C address for the ATMega on the YRL039 Power Supply Board (could be reprogrammed to different address if needed).

yrk.settings.YRL039_BUS = 14

The /dev/i2c_XX bus the YRL039 Power Supply board’s ATMega is attached to

yrk.settings.YRL040_BUS = 13

The /dev/i2c_XX bus the YRL040 [3.3V] I2C devoices are attached to

yrk.switch

This module contains function for the switch GPIO expander [one of two PCA9555 GPIO expanders on the YRL040 PCB]. The switch module, at the bottom of the YRL040 PCB, contains a 4-way DIP switch with associated LEDs, a 5-way directional switch and 2 push-buttons at either side. The green power LED is also connected to the GPIO expander.

PCA5555 GPIO Expander Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9555.pdf

yrk.switch.read_dip_switch()

A function to read the state of the 4-way DIP switch

Returns:

int: 4-bit value indicating switch states

yrk.switch.read_input_registers()

A function to read the state of the switches at the bottom of the YRL040 PCB

Returns:

int: 11-bit value indicating switch states.

yrk.switch.set_dip_leds(nibble)

A function to set the state of the yellow LEDs above the DIP switch

Args:

nibble (int): A four-bit value indicating the target state of the LEDs

yrk.switch.set_power_green_led(state)

A function to set the state of the green power LED at top of YRL040 PCB

Args:

state (bool): Enable or disable the LED

yrk.switch.setup_switch_gpio()

An initialisation function for the PCA9555 GPIO Expander controlling the switches

Sets pins IO0_0 : IO0_7 and IO1_0 : IO1_2 as inverted inputs [ie 0V = True] Sets pins IO1_3 : IO1_7 as outputs. IO1_3 : IO1_6 are DIP LEDs, IO1_7 is green power LED

yrk.switch.update_switch_gpio_output(new_states)

A function to update the output pins on the PCA9555 GPIO Expander

Args:

new_states (int): A 1-byte value [MSB=1_7, Green LED].

yrk.utils