Skip to content

BBBernsteyn/hello_8angle

Repository files navigation

Unit 8Angle Library for Raspberry Pi Pico

A C library for interfacing the M5Stack Unit 8Angle with the Raspberry Pi Pico using the Pico SDK.

About the M5Stack Unit 8Angle

The Unit 8Angle is an input module featuring 8 adjustable potentiometers, a toggle switch, and 9 individually addressable RGB LEDs (SK6812). It communicates via I2C (default address: 0x43) and is useful for applications requiring multiple analog inputs with visual feedback.

Features

  • Analog Input Reading: Read potentiometer values in 8-bit (0-255) or 12-bit (0-4095) resolution
  • Normalized Values: Corrects hardware quirks where potentiometers don't reach documented maximum values
  • Bulk Operations: Read all potentiometers or set all LEDs efficiently
  • Switch State: Read the digital toggle switch state
  • RGB LED Control: Set individual LED colors with brightness control
  • Device Management: Read firmware version and change I2C address
  • Error Handling: All functions return status codes

Hardware Observations

The library includes corrections for observed hardware behavior:

  • 12-bit readings top out at ~4088-4091 instead of 4095
  • 8-bit readings top out at 254 instead of 255
  • Potentiometer maximum value is at the leftmost physical position

The unit_8angle_get_analog_input_* functions normalize and reverse these values to the full documented range.

API Reference

Status Codes

All functions return a status code:

typedef enum {
    UNIT_8ANGLE_OK = 0,
    UNIT_8ANGLE_I2C_ERROR,
    UNIT_8ANGLE_I2C_TIMEOUT,
    UNIT_8ANGLE_INVALID_INDEX,
    UNIT_8ANGLE_NOT_INITIALIZED
} unit_8angle_status_t;

Initialization

unit_8angle_status_t unit_8angle_init(i2c_inst_t *i2c, uint sda_pin, uint scl_pin, uint baudrate);
bool unit_8angle_is_initialized(void);

Reading Potentiometers

// Single read (normalized values)
unit_8angle_status_t unit_8angle_get_analog_input_12bits(uint8_t index, uint16_t *value);
unit_8angle_status_t unit_8angle_get_analog_input_8bits(uint8_t index, uint8_t *value);

// Bulk read all 8 potentiometers
unit_8angle_status_t unit_8angle_get_all_analog_inputs_12bits(uint16_t values[8]);
unit_8angle_status_t unit_8angle_get_all_analog_inputs_8bits(uint8_t values[8]);

Reading the Switch

unit_8angle_status_t unit_8angle_get_switch_enabled(bool *enabled);

Controlling LEDs

typedef struct Unit8angleLedParams {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t brightness;
} Unit8angleLedParams;

unit_8angle_status_t unit_8angle_set_led_color(uint8_t index, Unit8angleLedParams led_params);
unit_8angle_status_t unit_8angle_reset_led_color(uint8_t index);
unit_8angle_status_t unit_8angle_set_all_leds(Unit8angleLedParams led_params);
unit_8angle_status_t unit_8angle_reset_all_leds(void);

LED indices: 0-7 correspond to each potentiometer, 8 is the center LED.

LED Helper Macros

UNIT_8ANGLE_LED(red, green, blue, brightness)
UNIT_8ANGLE_LED_OFF
UNIT_8ANGLE_LED_RED(brightness)
UNIT_8ANGLE_LED_GREEN(brightness)
UNIT_8ANGLE_LED_BLUE(brightness)
UNIT_8ANGLE_LED_WHITE(brightness)

Device Information

unit_8angle_status_t unit_8angle_get_firmware_version(uint8_t *version);

I2C Address Management

unit_8angle_status_t unit_8angle_change_i2c_address(uint8_t new_addr);
void unit_8angle_set_device_address(uint8_t addr);
uint8_t unit_8angle_get_device_address(void);

Low-level I2C

unit_8angle_status_t unit_8angle_read(uint8_t reg, uint8_t *buffer, uint8_t length);
unit_8angle_status_t unit_8angle_write(uint8_t reg, const uint8_t *buffer, uint8_t length);

Usage Example

#include "pico/stdlib.h"
#include "unit_8angle.h"

int main() {
    stdio_init_all();

    unit_8angle_status_t status = unit_8angle_init(
        i2c_default,
        PICO_DEFAULT_I2C_SDA_PIN,
        PICO_DEFAULT_I2C_SCL_PIN,
        100 * 1000
    );

    if (status != UNIT_8ANGLE_OK) {
        return 1;
    }

    while (true) {
        uint8_t value;
        unit_8angle_get_analog_input_8bits(0, &value);
        unit_8angle_set_led_color(0, UNIT_8ANGLE_LED(value, 0, 255 - value, 50));
    }
}

Known Issues & Recovery

I2C Stall

The Unit 8Angle can enter a stalled state where it stops responding to I2C. A full power cycle — not a Pico software reset — is required to recover. The 8Angle's onboard MCU retains its stalled state through a Pico watchdog reboot because its own VCC is unaffected.

Hardware Recovery: MOSFET Power Switch

Wire a logic-level N-channel MOSFET between the Pico and the 8Angle GND pin. A GPIO output controls the gate, cutting and restoring power programmatically.

MOSFET low-side switch schematic

Part Value Purpose
R1 100 Ω Limits gate current during switching transients
R2 10 kΩ Pull-down — keeps MOSFET off while GPIO is uninitialized at boot
MOSFET N-ch logic-level, Vgs(th) < 2 V (e.g. 2N7002, BSS138, AO3400) Switches 8Angle GND

Logic: GPIO HIGH → MOSFET ON → 8Angle powered. GPIO LOW → MOSFET OFF → power cut.

I2C lines during power cut: VCC stays connected, so the 8Angle's pull-up resistors hold SDA/SCL HIGH (I2C idle state). No backfeed risk. After power is restored, call unit_8angle_init before issuing any I2C commands.

Power Control API

// Call once before unit_8angle_init, passing the GPIO pin driving the MOSFET gate.
void unit_8angle_power_ctrl_init(uint gpio_pin);

// Cut power for off_ms ms, wait UNIT_8ANGLE_POWER_CYCLE_BOOT_MS for boot, then return.
// Caller must call unit_8angle_init afterwards.
void unit_8angle_power_cycle(uint off_ms);

// Returns true if power control was configured via unit_8angle_power_ctrl_init.
bool unit_8angle_power_ctrl_enabled(void);

Defaults (overridable via #define before including the header):

Macro Default Description
UNIT_8ANGLE_POWER_CYCLE_OFF_MS 200 ms Duration power is cut
UNIT_8ANGLE_POWER_CYCLE_BOOT_MS 500 ms Post-restore delay before I2C is ready

Usage — see hello_8angle.c for a complete example. The key pattern:

#define POWER_CTRL_PIN 15

unit_8angle_power_ctrl_init(POWER_CTRL_PIN);
// ... init and main loop with error counting ...
if (err_count >= I2C_ERR_THRESHOLD) {
    unit_8angle_power_cycle(UNIT_8ANGLE_POWER_CYCLE_OFF_MS);
    unit_8angle_init(i2c_default, SDA_PIN, SCL_PIN, 400 * 1000);
    err_count = 0;
}

License

MIT

About

Unit 8Angle Library for Raspberry Pi Pico

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors