Skip to content

Latest commit

 

History

History
547 lines (348 loc) · 18.8 KB

REFERENCE.md

File metadata and controls

547 lines (348 loc) · 18.8 KB

Inventor HAT Mini - Library Reference

This is the library reference for the Pimoroni Inventor HAT Mini, a versatile motor, servo and audio driver HAT for Raspberry Pi.

Table of Content

Getting Started

To start coding your Inventor HAT Mini, you will need to add the following lines to the start of your code file.

from inventorhatmini import InventorHATMini
board = InventorHATMini()

This will create a InventorHATMini class called board that will be used in the rest of the examples going forward.

Reading the User Button

Inventor HAT Mini has a single button on top, labelled User. This can be read using the switch_pressed() function. To read this button you would write:

state = board.switch_pressed()

Reading Voltage

Inventor HAT Mini can measure the voltage its motors and servos are being powered by. On an unmodified board this is also the voltage of the Raspberry Pi's 5V output.

The voltage can be measured by calling .read_voltage():

voltage = board.read_voltage()

GPIOs

There are four GPIO pins on Inventor HAT Mini. These can be used as digital outputs, digital inputs, and analog inputs. There is also a special mode where a pair of GPIO pins can be used as rotary encoder inputs.

Setup

To start using a GPIO pin, first import one of the handy constants used to reference them (see GPIO Constants). For example, to use the first GPIO pin:

from inventorhatmini import GPIO_1

Alternatively, if you wish to use all four GPIO pins, NUM_GPIOS can be imported for use within a loop, e.g. for i in range(NUM_GPIOS).

Then you need to import the constants for the pin mode to use. These are on the ioexpander module that Inventor HAT Mini is based on.

# For input
from ioexpander import IN  # or IN_PU of a pull-up is wanted

# For output
from ioexpander import OUT

# For ADC
from ioexpander import ADC

Mode

With the intended constants imported, the mode of a GPIO pin can be set by calling .gpio_pin_mode(gpio, mode):

board.gpio_pin_mode(GPIO_1, <IN or IN_PU or OUT or ADC>)

It is also possible to read the current mode of a GPIO pin by calling .gpio_pin_mode(gpio):

mode = board.gpio_pin_mode(GPIO_1)

As Input or ADC

The current value of an GPIO pin in input or ADC mode can be read by calling .gpio_pin_value(gpio):

value = board.gpio_pin_value(GPIO_1)

If the mode is digital, the value will either be 0 or 1. If the mode is analog, the value will be a voltage from 0.0 to 3.3.

As Output

The current value of a GPIO pin in output mode can be set by calling .gpio_pin_value(gpio, value):

board.gpio_pin_value(GPIO_1, value)

The expected value is either 0 or 1, or True or False.

As Encoder

In addition to the input and output functions of GPIO pins, they can also be paired together to read rotary encoders like those used on dials or for motor feedback. Up to two encoders are supported in this way. This is in addition to the two encoders already in use by the motor connectors.

To start using GPIO pins for an encoder, first import their handy constants:

from inventorhatmini import GPIO_1, GPIO_2

Then on the InventorHATMini class call the function .encoder_from_gpio_pins(channel, gpio_a, gpio_b), where channel is the encoder channel to use from 3 to 4 (1 and 2 are in use by the motor connectors), and gpio_a and gpio_b are the two pins to use. There are also optional parameters for direction, counts_per_rev, and count_microsteps.

CHANNEL = 3
encoder = board.encoder_from_gpio_pins(CHANNEL, GPIO_1, GPIO_2)

This function returns a new Encoder object that uses the specified pins. To use this object, refer to the Encoder object reference.

Motors and Encoders

Inventor HAT Mini two motor outputs with independent control and feedback, enabling differential steering, whereby the speed of one motor can be controlled separately of the other.

Motors, and their encoders, are setup by default when creating a new InventorHATMini object.

To start using a motor, first import one of the handy constants used to reference them (see Motor Constants). For example, to use the first motor:

from inventorhatmini import MOTOR_A

From there the motor and encoder can be accessed by the following board variables:

# Access a motor and its encoder
motor = board.motors[MOTOR_A]
encoder = board.encoders[MOTOR_A]

These give you access to objects that handle the motor and encoder functionality. For details of what can be done with them, check out their respective documentation pages:

Enabling and Disabling

The motor outputs of Inventor HAT Mini can be enabled and disabled at any time by calling .enable_motors() and .disable_motors(). These functions call both motor's respective .enable() and .disable() functions.

Reading Motor Current

The current draw of each motor output can be measured by calling .read_motor_current(motor), where motor is either MOTOR_A or MOTOR_B:

current = board.read_motor_current(MOTOR_A)

The returned value is the current in amps (A).

Skipping Initialisation

For some projects the automatic initialisation of motors and their encoders may not be wanted. For example if you instead wanted to use the motor outputs to drive another kind of inductive load.

To allow for this, the parameter init_motors=False can be added when creating the InventorHATMini object.

board = InventorHATMini(init_motors=False)

This leaves board.motors and board.encoders set to None, letting you to use those board pins for any other purpose by accessing functions on the io expander directly with board.ioe.

The io expander pins available after this are:

  • board.IOE_MOTOR_A_PINS = (20, 19)
  • board.IOE_MOTOR_B_PINS = (16, 15)
  • board.IOE_ENCODER_A_PINS = (3, 4)
  • board.IOE_ENCODER_B_PINS = (26, 1)

For example, heres how to have one of the encoder pins as an output and set it high:

board.ioe.set_mode(board.IOE_ENCODER_A_PINS[0], OUT)
board.ioe.output(board.IOE_ENCODER_A_PINS[0], True)

For more details of what can be done directly with the io expander, visit its library reference.

Servos

Inventor HAT Mini has four servo outputs. These are setup by default when creating a new InventorHATMini object.

To start using a servo, first import one of the handy constants used to reference them (see Servo Constants). For example, to use the first servo:

from inventorhatmini import SERVO_1

From there the servo can be accessed by the following board variables:

# Access a servo
servo = board.servos[SERVO_1]

This gives you access to an object that handle the servo functionality. For details of what can be done with it, check out its documentation page:

Skipping Initialisation

For some projects the automatic initialisation of servos may not be wanted. For example if you instead wanted to use the servo outputs to drive another kind of PWM device.

To allow for this, the parameter init_servos=False can be added when creating the InventorHATMini object.

board = InventorHATMini(init_servos=False)

This leaves board.servos set to None, letting you to use those board pins for any other purpose using the functions described in the next sections or by accessing functions on the io expander directly with board.ioe.

The io expander pins available after this are:

  • board.IOE_SERVO_PINS = (23, 24, 25, 22)

As GPIOs

With servos uninitialised, the servo pins can be interacted with like regular GPIO pins (see GPIOs), using the functions .servo_pin_mode() and .servo_pin_value(). The one exception to this is that these pins are not ADC capable.

To use a servo pin as an input:

# Initialise InventorHATMini without servos
board = InventorHATMini(init_servos=False)

# Setup the servo pin as an input
board.servo_pin_mode(SERVO_1, IN)  # or IN_PU of a pull-up is wanted

# Read the value of the servo pin
value = board.servo_pin_value(SERVO_1)

To use a servo pin as an output:

# Initialise InventorHATMini without servos
board = InventorHATMini(init_servos=False)

# Setup the servo pin as an output
board.servo_pin_mode(SERVO_1, OUT)

# Read the servo pin to high
board.servo_pin_value(i, True)

As PWM

To support their use with servos, the servo pins accept the PWM pin mode. This constant can be imported from the ioexpander module, and passed into the .servo_pin_mode() function.

The frequency of the PWM signal can then be configured by calling .servo_pin_frequency(), which accepts a servo index and the frequency (in Hz).

Finally, the duty cycle of the PWM signal can be set by calling .servo_pin_value() and providing it with a value between 0.0 and 1.0.

Below is an example of setting a servo pin to output a 25KHz signal with a 50% duty cycle:

from ioexpander import PWM
from inventorhatmini import InventorHATMini, SERVO_1

# Initialise InventorHATMini without servos
board = InventorHATMini(init_servos=False)

# Setup the servo pin as a PWM output
board.servo_pin_mode(SERVO_1, PWM)

# Set the servo pin's frequency to 25KHz
board.servo_pin_frequency(SERVO_1, 25000)

# Output a 50% duty cycle square wave
board.servo_pin_value(SERVO_1, 0.5)

Delayed Loading

By default, changes to a servo pin's frequency or value are applied immediately. However, sometimes this may not be wanted, and instead you want all pins to receive updated parameters at the same time, regardless of how long the code ran that calculated the update.

For this purpose, .servo_pin_frequency() and .servo_pin_value() include an optional parameter load, which by default is True. To avoid this "loading" include load=False in the relevant function calls. Then either the last call can include load=True, or a specific call to .servo_pin_load() can be made.

In addition, any function that performs a load, including the .servo_pin_load() function, can be made to wait until the new PWM value has been sent out of the pins. By default this is disabled, but can be enabled by including wait_for_load=True in the relevant function calls.

Limitations

Inventor HAT Mini has limitations on which PWM signals can be controlled independently. For the servo pins, this means that Servo 1 and 2 must share the same frequency, and similarly for Servo 3 and 4.

Keep this in mind if changing the frequency of one, as the other will not automatically know about the change, resulting in unexpected duty cycle outputs.

As Motor

As an extension of the general PWM support of the servo pins, they can also be paired together to output signals for controlling DC motors (via a standalone driver IC) in the same way as Inventor HAT Mini's onboard motor connectors are driven. Up to two motors are supported.

To start using servo pins for a motor, first import their handy constants:

from inventorhatmini import SERVO_1, SERVO_2

Then on the InventorHATMini class call the function .motor_from_servo_pins(servo_p, servo_n), where servo_p and servo_n are the positive and negative output pins to use. There are also optional parameters for direction, speed_scale, zeropoint, deadzone, freq, and mode:

motor = board.motor_from_servo_pins(SERVO_1, SERVO_2)

This function returns a new Motor object that uses the specified pins. To use this object, refer to the Motor object reference.

RGB LEDs

There are 8 independently addressable RGB LEDs on Inventor HAT Mini, positioned nearby the four servo and four GPIO pins. These LEDs are automatically initialised when creating a new InventorHATMini object and can be accessed using the following variable:

# Access the RGB LEDs
leds = board.leds

For details of what can be done with this object, check out its documentation page:

Audio

Inventor HAT Mini features an onboard I2S audio amplifier, letting it play any sounds created by your Raspberry Pi, from any source, be it a web browser, music player, or from code.

There are many ways sound can be created from code, some examples of which can be found in examples/audio.

Muting and Unmuting

The audio output of Inventor HAT Mini can be muted at any time by calling .mute_audio(). Similarly, the audio output can be unmuted by calling .unmute_audio().

Additionally, when creating a new InventorHATMini object, the starting audio output state can be specified by providing either start_muted=True or start_muted=False. The default is False.

Watchdog Timer

Inventor HAT Mini features an onboard Watchdog timer, that can be used to turn off motor and servo outputs in the event of an issue with your code that stops it communicating with the board.

This is especially useful if you are creating a driving robot, to stop it from driving off uncontrolled!

To see an example of the Watchdog timer in action, visit examples/extras/watchdog_reset.py.

Configuring

To start using the watchdog timer, first it's duration needs to be set. This is done using the .set_watchdog_control() function, which accepts one of the following multiple of 2 clock divider values:

Clock Divider Time-Out
1 6.40ms
2 -
4 25.6ms
8 51.2ms
16 102.4ms
32 204.8ms
64 409.6ms
128 819.2ms
256 1.638s

For example, here is how to set the watchdog to the longest time-out:

board.set_watchdog_control(256)

Activating

Once configured, the watchdog can be activated by calling:

board.activate_watchdog()

There is now limited time (1.638 seconds in this example) to communicate with the Inventor HAT Mini before the watchdog timer reaches zero and resets the board!

The active state of the watchdog timer can be checked by calling .is_watchdog_active().

Feeding

To prevent the watchdog time from reaching zero, your code needs to "feed" the watchdog regularly. This is done by calling:

board.feed_watchdog()

This will return the watchdog timer back up to the original value it was at when activated.

Deactivating

If your code reaches a point where you know it will take longer than the time set, or you otherwise no longer need the watchdog, it can be deactivated by calling:

board.deactivate_watchdog()

Handling a Time-Out

If the watchdog does reset your Inventor HAT Mini whilst your code is running, it is possible to check for this by calling .watchdog_timeout_occurred(), then handle the event. The InventorHATMini class has a .reinit() function intended for this exact case:

if board.watchdog_timeout_occurred():
  board.reinit()

There is also .clear_watchdog_timeout() that should be called if you wanted to configure Inventor HAT Mini without calling .reinit().

Function Reference

Here is the complete list of functions available on the InventorHATMini class:

InventorHATMini(address=0x17, motor_gear_ratio=50, init_motors=True, init_servos=True, init_leds=True, start_muted=False)
reinit()
switch_pressed()
enable_motors()
disable_motors()
read_voltage()
read_motor_current(motor)
mute_audio()
unmute_audio()
gpio_pin_mode(gpio)
gpio_pin_mode(gpio, mode)
gpio_pin_value(gpio)
gpio_pin_value(gpio, value)
servo_pin_mode(servo)
servo_pin_mode(servo, mode)
servo_pin_value(servo)
servo_pin_value(servo, mode, load=True, wait_for_load=False)
servo_pin_load(servo, wait_for_load=True)
servo_pin_frequency(servo, frequency, load=True, wait_for_load=True)
encoder_from_gpio_pins(channel, gpio_a, gpio_b, direction=NORMAL_DIR, counts_per_rev=ROTARY_CPR, count_microsteps=False)
motor_from_servo_pins(servo_p, servo_n, direction=NORMAL_DIR, speed_scale=DEFAULT_SPEED_SCALE, zeropoint=DEFAULT_ZEROPOINT, deadzone=DEFAULT_DEADZONE, freq=DEFAULT_FREQUENCY, mode=DEFAULT_DECAY_MODE)
activate_watchdog()
deactivate_watchdog()
feed_watchdog()
watchdog_timeout_occurred()
clear_watchdog_timeout()
is_watchdog_active()
set_watchdog_control(divider)

Constants Reference

Here is the complete list of constants on the inventorhatmini module:

Motor Constants

  • MOTOR_A = 0
  • MOTOR_B = 1

Servo Constants

  • SERVO_1 = 0
  • SERVO_2 = 1
  • SERVO_3 = 2
  • SERVO_4 = 3

GPIO Constants

  • GPIO_1 = 0
  • GPIO_2 = 1
  • GPIO_3 = 2
  • GPIO_4 = 3

LED Constants

  • LED_SERVO_1 = 0
  • LED_SERVO_2 = 1
  • LED_SERVO_3 = 2
  • LED_SERVO_4 = 3
  • LED_GPIO_1 = 4
  • LED_GPIO_2 = 5
  • LED_GPIO_3 = 6
  • LED_GPIO_4 = 7

Count Constants

  • NUM_MOTORS = 2
  • NUM_SERVOS = 4
  • NUM_GPIOS = 4
  • NUM_LEDS = 8