kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Exposed support for GPIO pins on encoder wheel
rodzic
8966cbf348
commit
653090c89e
|
@ -523,13 +523,35 @@ namespace pimoroni {
|
|||
return divider_good;
|
||||
}
|
||||
|
||||
void IOExpander::set_pwm_period(uint16_t value, bool load) {
|
||||
void IOExpander::set_pwm_period(uint16_t value, bool load, bool wait_for_load) {
|
||||
value &= 0xffff;
|
||||
i2c->reg_write_uint8(address, reg::PWMPL, (uint8_t)(value & 0xff));
|
||||
i2c->reg_write_uint8(address, reg::PWMPH, (uint8_t)(value >> 8));
|
||||
|
||||
if(load)
|
||||
pwm_load();
|
||||
pwm_load(wait_for_load);
|
||||
}
|
||||
|
||||
uint16_t IOExpander::set_pwm_frequency(float frequency, bool load, bool wait_for_load) {
|
||||
uint32_t period = (uint32_t)(CLOCK_FREQ / frequency);
|
||||
if (period / 128 > MAX_PERIOD) {
|
||||
return MAX_PERIOD;
|
||||
}
|
||||
if (period < 2) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
uint8_t divider = 1;
|
||||
while ((period > MAX_PERIOD) && (divider < MAX_DIVIDER)) {
|
||||
period >>= 1;
|
||||
divider <<= 1;
|
||||
}
|
||||
|
||||
period = MIN(period, MAX_PERIOD); // Should be unnecessary because of earlier raised errors, but kept in case
|
||||
set_pwm_control(divider);
|
||||
set_pwm_period((uint16_t)(period - 1), load, wait_for_load);
|
||||
|
||||
return (uint16_t)period;
|
||||
}
|
||||
|
||||
uint8_t IOExpander::get_mode(uint8_t pin) {
|
||||
|
@ -701,7 +723,7 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void IOExpander::output(uint8_t pin, uint16_t value, bool load) {
|
||||
void IOExpander::output(uint8_t pin, uint16_t value, bool load, bool wait_for_load) {
|
||||
if(pin < 1 || pin > NUM_PINS) {
|
||||
printf("Pin should be in range 1-14.");
|
||||
return;
|
||||
|
@ -717,7 +739,7 @@ namespace pimoroni {
|
|||
i2c->reg_write_uint8(address, io_pin.reg_pwml, (uint8_t)(value & 0xff));
|
||||
i2c->reg_write_uint8(address, io_pin.reg_pwmh, (uint8_t)(value >> 8));
|
||||
if(load)
|
||||
pwm_load();
|
||||
pwm_load(wait_for_load);
|
||||
}
|
||||
else {
|
||||
if(value == LOW) {
|
||||
|
|
|
@ -27,6 +27,9 @@ namespace pimoroni {
|
|||
static const uint8_t PIN_MODE_ADC = 0b01010; // ADC, Input-only (high-impedance)
|
||||
|
||||
static const uint32_t RESET_TIMEOUT_MS = 1000;
|
||||
static const uint32_t CLOCK_FREQ = 24000000;
|
||||
static const uint32_t MAX_PERIOD = (1 << 16) - 1;
|
||||
static const uint32_t MAX_DIVIDER = (1 << 7);
|
||||
|
||||
public:
|
||||
static const uint8_t DEFAULT_I2C_ADDRESS = 0x18;
|
||||
|
@ -205,7 +208,8 @@ namespace pimoroni {
|
|||
void pwm_clear(bool wait_for_clear = true);
|
||||
bool pwm_clearing();
|
||||
bool set_pwm_control(uint8_t divider);
|
||||
void set_pwm_period(uint16_t value, bool load = true);
|
||||
void set_pwm_period(uint16_t value, bool load = true, bool wait_for_load = true);
|
||||
uint16_t set_pwm_frequency(float frequency, bool load = true, bool wait_for_load = true);
|
||||
|
||||
uint8_t get_mode(uint8_t pin);
|
||||
void set_mode(uint8_t pin, uint8_t mode, bool schmitt_trigger = false, bool invert = false);
|
||||
|
@ -213,7 +217,7 @@ namespace pimoroni {
|
|||
int16_t input(uint8_t pin, uint32_t adc_timeout = 1);
|
||||
float input_as_voltage(uint8_t pin, uint32_t adc_timeout = 1);
|
||||
|
||||
void output(uint8_t pin, uint16_t value, bool load = true);
|
||||
void output(uint8_t pin, uint16_t value, bool load = true, bool wait_for_load = true);
|
||||
|
||||
void setup_rotary_encoder(uint8_t channel, uint8_t pin_a, uint8_t pin_b, uint8_t pin_c = 0, bool count_microsteps = false);
|
||||
int16_t read_rotary_encoder(uint8_t channel);
|
||||
|
|
|
@ -3,6 +3,6 @@ add_subdirectory(chase_game)
|
|||
add_subdirectory(clock)
|
||||
add_subdirectory(colour_picker)
|
||||
add_subdirectory(encoder)
|
||||
#add_subdirectory(gpio_pwm)
|
||||
add_subdirectory(gpio_pwm)
|
||||
add_subdirectory(led_rainbow)
|
||||
add_subdirectory(stop_watch)
|
|
@ -0,0 +1,13 @@
|
|||
set(OUTPUT_NAME encoderwheel_gpio_pwm)
|
||||
add_executable(${OUTPUT_NAME} gpio_pwm.cpp)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME}
|
||||
pico_stdlib
|
||||
breakout_encoder_wheel
|
||||
)
|
||||
|
||||
# enable usb output
|
||||
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
|
||||
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -0,0 +1,74 @@
|
|||
#include <math.h>
|
||||
#include <string>
|
||||
#include "pimoroni_i2c.hpp"
|
||||
#include "breakout_encoder_wheel.hpp"
|
||||
#include "time.h"
|
||||
|
||||
using namespace pimoroni;
|
||||
using namespace encoderwheel;
|
||||
|
||||
/*
|
||||
Output a sine wave PWM sequence on the Encoder Wheel's side GPIO pins.
|
||||
|
||||
Press the centre button to stop the program.
|
||||
*/
|
||||
|
||||
// Constants
|
||||
constexpr float SPEED = 5.0f; // The speed that the LEDs will cycle at
|
||||
const uint UPDATES = 50; // How many times the LEDs will be updated per second
|
||||
const uint UPDATE_RATE_US = 1000000 / UPDATES;
|
||||
constexpr float FREQUENCY = 1000.0f; // The frequency to run the PWM at
|
||||
|
||||
// Create a new BreakoutEncoderWheel
|
||||
I2C i2c(BOARD::BREAKOUT_GARDEN);
|
||||
BreakoutEncoderWheel wheel(&i2c);
|
||||
|
||||
// Variables
|
||||
float offset = 0.0f;
|
||||
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
// Attempt to initialise the encoder wheel
|
||||
if(wheel.init()) {
|
||||
|
||||
// Set the PWM frequency for the GPIOs
|
||||
uint16_t period = wheel.gpio_pwm_frequency(FREQUENCY);
|
||||
|
||||
// Set the GPIO pins to PWM outputs
|
||||
for(int i = 0; i < NUM_GPIOS; i++) {
|
||||
wheel.gpio_pin_mode(GPIOS[i], IOExpander::PIN_PWM);
|
||||
}
|
||||
|
||||
// Loop forever
|
||||
while(!wheel.pressed(CENTRE)) {
|
||||
// Record the start time of this loop
|
||||
absolute_time_t start_time = get_absolute_time();
|
||||
|
||||
offset += SPEED / 1000.0f;
|
||||
|
||||
// Update all the PWMs
|
||||
for(int i = 0; i < NUM_GPIOS; i++) {
|
||||
float angle = (((float)i / NUM_GPIOS) + offset) * M_PI;
|
||||
uint16_t duty = (uint16_t)(((sinf(angle) / 2.0f) + 0.5f) * period);
|
||||
|
||||
// Set the GPIO pin to the new duty cycle, but do not load it yet
|
||||
wheel.gpio_pin_value(GPIOS[i], duty, false);
|
||||
}
|
||||
|
||||
// Have all the PWMs load at once
|
||||
wheel.gpio_pwm_load();
|
||||
|
||||
// Sleep until the next update, accounting for how long the above operations took to perform
|
||||
sleep_until(delayed_by_us(start_time, UPDATE_RATE_US));
|
||||
}
|
||||
|
||||
// Turn off the PWM outputs
|
||||
for(int i = 0; i < NUM_GPIOS; i++) {
|
||||
wheel.gpio_pin_value(GPIOS[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -190,32 +190,37 @@ namespace encoderwheel {
|
|||
led_ring.update();
|
||||
}
|
||||
|
||||
int BreakoutEncoderWheel::gpio_pin_mode(int gpio) {
|
||||
return 0; // TODO
|
||||
uint8_t BreakoutEncoderWheel::gpio_pin_mode(uint8_t gpio) {
|
||||
assert(gpio < GP7 || gpio > GP9);
|
||||
return ioe.get_mode(gpio);
|
||||
}
|
||||
|
||||
void BreakoutEncoderWheel::gpio_pin_mode(int gpio, int mode) {
|
||||
|
||||
void BreakoutEncoderWheel::gpio_pin_mode(uint8_t gpio, uint8_t mode) {
|
||||
assert(gpio < GP7 || gpio > GP9);
|
||||
ioe.set_mode(gpio, mode);
|
||||
}
|
||||
|
||||
int BreakoutEncoderWheel::gpio_pin_value(int gpio) {
|
||||
return 0; // TODO
|
||||
int16_t BreakoutEncoderWheel::gpio_pin_value(uint8_t gpio) {
|
||||
assert(gpio < GP7 || gpio > GP9);
|
||||
return ioe.input(gpio);
|
||||
}
|
||||
|
||||
float BreakoutEncoderWheel::gpio_pin_value_as_voltage(int gpio) {
|
||||
return 0; // TODO
|
||||
float BreakoutEncoderWheel::gpio_pin_value_as_voltage(uint8_t gpio) {
|
||||
assert(gpio < GP7 || gpio > GP9);
|
||||
return ioe.input_as_voltage(gpio);
|
||||
}
|
||||
|
||||
void BreakoutEncoderWheel::gpio_pin_value(int gpio, int value, bool load, bool wait_for_load) {
|
||||
|
||||
void BreakoutEncoderWheel::gpio_pin_value(uint8_t gpio, uint16_t value, bool load, bool wait_for_load) {
|
||||
assert(gpio < GP7 || gpio > GP9);
|
||||
ioe.output(gpio, value, load, wait_for_load);
|
||||
}
|
||||
|
||||
void BreakoutEncoderWheel::gpio_pwm_load(bool wait_for_load) {
|
||||
|
||||
ioe.pwm_load(wait_for_load);
|
||||
}
|
||||
|
||||
int BreakoutEncoderWheel::gpio_pwm_frequency(float frequency, bool load, bool wait_for_load) {
|
||||
return 0; // TODO
|
||||
return ioe.set_pwm_frequency(frequency, load, wait_for_load);
|
||||
}
|
||||
|
||||
void BreakoutEncoderWheel::take_encoder_reading() {
|
||||
|
|
|
@ -41,17 +41,17 @@ namespace encoderwheel {
|
|||
static const uint32_t DEFAULT_TIMEOUT = 1;
|
||||
|
||||
private:
|
||||
static const uint8_t ENC_CHANNEL = 1;
|
||||
static const uint8_t ENC_TERM_A = 3;
|
||||
static const uint8_t ENC_TERM_B = 12;
|
||||
static const uint8_t ENC_COUNTS_PER_REV = 24;
|
||||
static const uint8_t ENC_COUNT_DIVIDER = 2;
|
||||
static const uint8_t ENC_CHANNEL = 1;
|
||||
static const uint8_t ENC_TERM_A = 3;
|
||||
static const uint8_t ENC_TERM_B = 12;
|
||||
static const uint8_t ENC_COUNTS_PER_REV = 24;
|
||||
static const uint8_t ENC_COUNT_DIVIDER = 2;
|
||||
|
||||
static const uint8_t SW_UP = 13;
|
||||
static const uint8_t SW_DOWN = 4;
|
||||
static const uint8_t SW_LEFT = 11;
|
||||
static const uint8_t SW_RIGHT = 2;
|
||||
static const uint8_t SW_CENTRE = 1;
|
||||
static const uint8_t SW_UP = 13;
|
||||
static const uint8_t SW_DOWN = 4;
|
||||
static const uint8_t SW_LEFT = 11;
|
||||
static const uint8_t SW_RIGHT = 2;
|
||||
static const uint8_t SW_CENTRE = 1;
|
||||
|
||||
// This wonderful lookup table maps the LEDs on the encoder wheel
|
||||
// from their 3x24 (remember, they're RGB) configuration to
|
||||
|
@ -146,12 +146,12 @@ namespace encoderwheel {
|
|||
void clear();
|
||||
void show();
|
||||
|
||||
int gpio_pin_mode(int gpio);
|
||||
void gpio_pin_mode(int gpio, int mode);
|
||||
int gpio_pin_value(int gpio);
|
||||
float gpio_pin_value_as_voltage(int gpio);
|
||||
void gpio_pin_value(int gpio, int value, bool load = true, bool wait_for_load = false);
|
||||
void gpio_pwm_load(bool wait_for_load = false);
|
||||
uint8_t gpio_pin_mode(uint8_t gpio);
|
||||
void gpio_pin_mode(uint8_t gpio, uint8_t mode);
|
||||
int16_t gpio_pin_value(uint8_t gpio);
|
||||
float gpio_pin_value_as_voltage(uint8_t gpio);
|
||||
void gpio_pin_value(uint8_t gpio, uint16_t value, bool load = true, bool wait_for_load = false);
|
||||
void gpio_pwm_load(bool wait_for_load = true);
|
||||
int gpio_pwm_frequency(float frequency, bool load = true, bool wait_for_load = false);
|
||||
|
||||
private:
|
||||
|
|
Ładowanie…
Reference in New Issue