More work on encoder wheel C++, adding reset to ioe

pull/774/head
ZodiusInfuser 2023-05-02 22:55:19 +01:00
rodzic 387df3bd12
commit 1cfae8b5f8
7 zmienionych plików z 137 dodań i 70 usunięć

Wyświetl plik

@ -320,8 +320,21 @@ namespace pimoroni {
Pin::adc(1, 7, 0)} Pin::adc(1, 7, 0)}
{} {}
bool IOExpander::init(bool skipChipIdCheck) { bool IOExpander::init(bool skipChipIdCheck, bool perform_reset) {
bool succeeded = true; if(!skipChipIdCheck) {
uint16_t chip_id = get_chip_id();
if(chip_id != CHIP_ID) {
if(debug) {
printf("Chip ID invalid: %04x expected: %04x\n", chip_id, CHIP_ID);
}
return false;
}
}
// Reset the chip if requested, to put it into a known state
if(perform_reset && !reset()) {
return false;
}
if(interrupt != PIN_UNUSED) { if(interrupt != PIN_UNUSED) {
gpio_set_function(interrupt, GPIO_FUNC_SIO); gpio_set_function(interrupt, GPIO_FUNC_SIO);
@ -331,17 +344,36 @@ namespace pimoroni {
enable_interrupt_out(true); enable_interrupt_out(true);
} }
if(!skipChipIdCheck) { return true;
uint16_t chip_id = get_chip_id(); }
if(chip_id != CHIP_ID) {
if(debug) { uint8_t IOExpander::check_reset() {
printf("Chip ID invalid: %04x expected: %04x\n", chip_id, CHIP_ID); uint8_t user_flash_reg = reg::USER_FLASH;
} uint8_t value;
succeeded = false; if(i2c_write_blocking(i2c->get_i2c(), address, &user_flash_reg, 1, false) == PICO_ERROR_GENERIC) {
return 0x00;
}
if(i2c_read_blocking(i2c->get_i2c(), address, (uint8_t *)&value, sizeof(uint8_t), false) == PICO_ERROR_GENERIC) {
return 0x00;
}
return value;
}
bool IOExpander::reset() {
uint32_t start_time = millis();
set_bits(reg::CTRL, ctrl_mask::RESET);
// Wait for a register to read its initialised value
while(check_reset() != 0x78) {
sleep_ms(1);
if(millis() - start_time >= timeout) {
if(debug)
printf("Timed out waiting for Reset!");
return false;
} }
} }
return succeeded; return true;
} }
i2c_inst_t* IOExpander::get_i2c() const { i2c_inst_t* IOExpander::get_i2c() const {

Wyświetl plik

@ -171,7 +171,12 @@ namespace pimoroni {
// Methods // Methods
//-------------------------------------------------- //--------------------------------------------------
public: public:
bool init(bool skip_chip_id_check = false); bool init(bool skip_chip_id_check = false, bool perform_reset = false);
private:
uint8_t check_reset();
public:
bool reset();
// For print access in micropython // For print access in micropython
i2c_inst_t* get_i2c() const; i2c_inst_t* get_i2c() const;

Wyświetl plik

@ -6,35 +6,29 @@ namespace pimoroni {
bool BreakoutEncoderWheel::init(bool skip_chip_id_check) { bool BreakoutEncoderWheel::init(bool skip_chip_id_check) {
bool success = false; bool success = false;
if(ioe.init(skip_chip_id_check)) { if(ioe.init(skip_chip_id_check, true) && led_ring.init()) {
if(interrupt_pin != PIN_UNUSED) { ioe.setup_rotary_encoder(ENC_CHANNEL, ENC_TERM_A, ENC_TERM_B, 0, true); // count microsteps
ioe.enable_interrupt_out(true);
}
ioe.setup_rotary_encoder(ENC_CHANNEL, ENC_TERM_A, ENC_TERM_B);
if(led_ring.init()) {
led_ring.enable({
0b00000000, 0b10111111,
0b00111110, 0b00111110,
0b00111111, 0b10111110,
0b00000111, 0b10000110,
0b00110000, 0b00110000,
0b00111111, 0b10111110,
0b00111111, 0b10111110,
0b01111111, 0b11111110,
0b01111111, 0b00000000
}, 0);
success = true;
}
ioe.set_mode(SW_UP, IOExpander::PIN_IN_PU); ioe.set_mode(SW_UP, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_DOWN, IOExpander::PIN_IN_PU); ioe.set_mode(SW_DOWN, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_LEFT, IOExpander::PIN_IN_PU); ioe.set_mode(SW_LEFT, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_RIGHT, IOExpander::PIN_IN_PU); ioe.set_mode(SW_RIGHT, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_CENTRE, IOExpander::PIN_IN_PU); ioe.set_mode(SW_CENTRE, IOExpander::PIN_IN_PU);
led_ring.enable({
0b00000000, 0b10111111,
0b00111110, 0b00111110,
0b00111111, 0b10111110,
0b00000111, 0b10000110,
0b00110000, 0b00110000,
0b00111111, 0b10111110,
0b00111111, 0b10111110,
0b01111111, 0b11111110,
0b01111111, 0b00000000
}, 0);
success = true;
} }
return success; return success;
@ -67,7 +61,7 @@ namespace pimoroni {
void BreakoutEncoderWheel::set_ioe_address(uint8_t address) { void BreakoutEncoderWheel::set_ioe_address(uint8_t address) {
ioe.set_address(address); ioe.set_address(address);
} }
bool BreakoutEncoderWheel::get_interrupt_flag() { bool BreakoutEncoderWheel::get_interrupt_flag() {
return ioe.get_interrupt_flag(); return ioe.get_interrupt_flag();
} }
@ -93,36 +87,50 @@ namespace pimoroni {
} }
} }
int BreakoutEncoderWheel::count() { int16_t BreakoutEncoderWheel::count() {
return 0; // TODO take_encoder_reading();
return enc_count;
} }
int BreakoutEncoderWheel::delta() { int16_t BreakoutEncoderWheel::delta() {
return 0; // TODO take_encoder_reading();
}
int BreakoutEncoderWheel::step() { // Determine the change in counts since the last time this function was performed
return 0; // TODO int16_t change = enc_count - last_delta_count;
} last_delta_count = enc_count;
int BreakoutEncoderWheel::turn() { return change;
return 0; // TODO
} }
void BreakoutEncoderWheel::zero() { void BreakoutEncoderWheel::zero() {
ioe.clear_rotary_encoder(ENC_CHANNEL);
enc_count = 0;
enc_step = 0;
enc_turn = 0;
last_raw_count = 0;
last_delta_count = 0;
}
int16_t BreakoutEncoderWheel::step() {
take_encoder_reading();
return enc_step;
}
int16_t BreakoutEncoderWheel::turn() {
take_encoder_reading();
return enc_turn;
} }
float BreakoutEncoderWheel::revolutions() { float BreakoutEncoderWheel::revolutions() {
return 0; // TODO return (float)count() / (float)ENC_COUNTS_PER_REV;
} }
float BreakoutEncoderWheel::degrees() { float BreakoutEncoderWheel::degrees() {
return 0; // TODO return revolutions() * 360.0f;
} }
float BreakoutEncoderWheel::radians() { float BreakoutEncoderWheel::radians() {
return 0; // TODO return revolutions() * M_PI * 2.0f;
} }
Direction BreakoutEncoderWheel::direction() { Direction BreakoutEncoderWheel::direction() {
@ -209,19 +217,31 @@ namespace pimoroni {
return 0; // TODO return 0; // TODO
} }
/* void BreakoutEncoderWheel::take_encoder_reading() {
bool BreakoutEncoderWheel::wheel_available() { // Read the current count
return (ioe.get_interrupt_flag() > 0); int16_t raw_count = ioe.read_rotary_encoder(ENC_CHANNEL) / ENC_COUNT_DIVIDER;
} int16_t raw_change = raw_count - last_raw_count;
last_raw_count = raw_count;
int16_t BreakoutEncoderWheel::read_wheel() { // Invert the change
//int16_t count = ioe.read_rotary_encoder(ENC_CHANNEL); if(enc_direction == REVERSED_DIR) {
//if(direction != DIRECTION_CW) raw_change = 0 - raw_change;
// count = 0 - count; }
ioe.clear_interrupt_flag(); enc_count += raw_change;
//return count;
return 0; enc_step += raw_change;
if(raw_change > 0) {
while(enc_step >= ENC_COUNTS_PER_REV) {
enc_step -= ENC_COUNTS_PER_REV;
enc_turn += 1;
}
}
else if(raw_change < 0) {
while(enc_step < 0) {
enc_step += ENC_COUNTS_PER_REV;
enc_turn -= 1;
}
}
} }
*/
} }

Wyświetl plik

@ -29,6 +29,8 @@ namespace pimoroni {
static const uint8_t ENC_CHANNEL = 1; static const uint8_t ENC_CHANNEL = 1;
static const uint8_t ENC_TERM_A = 12; static const uint8_t ENC_TERM_A = 12;
static const uint8_t ENC_TERM_B = 3; static const uint8_t ENC_TERM_B = 3;
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_UP = 13;
static const uint8_t SW_DOWN = 4; static const uint8_t SW_DOWN = 4;
@ -73,9 +75,14 @@ namespace pimoroni {
private: private:
IOExpander ioe; IOExpander ioe;
IS31FL3731 led_ring; IS31FL3731 led_ring;
//Direction direction = DEFAULT_DIRECTION;
uint interrupt_pin = PIN_UNUSED; // A local copy of the value passed to the IOExpander, used in initialisation
Direction enc_direction = DEFAULT_DIRECTION; Direction enc_direction = DEFAULT_DIRECTION;
int16_t enc_count = 0;
int16_t enc_step = 0;
int16_t enc_turn = 0;
int16_t last_raw_count = 0;
int16_t last_delta_count = 0;
//-------------------------------------------------- //--------------------------------------------------
// Constructors/Destructor // Constructors/Destructor
@ -109,11 +116,11 @@ namespace pimoroni {
// Encoder breakout specific // Encoder breakout specific
bool pressed(uint button); bool pressed(uint button);
int count(); int16_t count();
int delta(); int16_t delta();
int step();
int turn();
void zero(); void zero();
int16_t step();
int16_t turn();
float revolutions(); float revolutions();
float degrees(); float degrees();
float radians(); float radians();
@ -131,6 +138,9 @@ namespace pimoroni {
void gpio_pin_value(int gpio, int value, bool load = true, bool wait_for_load = false); 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); void gpio_pwm_load(bool wait_for_load = false);
int gpio_pwm_frequency(float frequency, bool load = true, bool wait_for_load = false); int gpio_pwm_frequency(float frequency, bool load = true, bool wait_for_load = false);
private:
void take_encoder_reading();
}; };
} }

Wyświetl plik

@ -5,7 +5,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
/***** Methods *****/ /***** Methods *****/
MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutEncoderWheel_set_address_obj, 2, BreakoutEncoderWheel_set_address); MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutEncoderWheel_set_ioe_address_obj, 2, BreakoutEncoderWheel_set_ioe_address);
MP_DEFINE_CONST_FUN_OBJ_1(BreakoutEncoderWheel_get_interrupt_flag_obj, BreakoutEncoderWheel_get_interrupt_flag); MP_DEFINE_CONST_FUN_OBJ_1(BreakoutEncoderWheel_get_interrupt_flag_obj, BreakoutEncoderWheel_get_interrupt_flag);
MP_DEFINE_CONST_FUN_OBJ_1(BreakoutEncoderWheel_clear_interrupt_flag_obj, BreakoutEncoderWheel_clear_interrupt_flag); MP_DEFINE_CONST_FUN_OBJ_1(BreakoutEncoderWheel_clear_interrupt_flag_obj, BreakoutEncoderWheel_clear_interrupt_flag);
@ -32,7 +32,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(BreakoutEncoderWheel_gpio_pwm_frequency_obj, 2, Break
/***** Binding of Methods *****/ /***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t BreakoutEncoderWheel_locals_dict_table[] = { STATIC const mp_rom_map_elem_t BreakoutEncoderWheel_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_address), MP_ROM_PTR(&BreakoutEncoderWheel_set_address_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ioe_address), MP_ROM_PTR(&BreakoutEncoderWheel_set_ioe_address_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_interrupt_flag), MP_ROM_PTR(&BreakoutEncoderWheel_get_interrupt_flag_obj) }, { MP_ROM_QSTR(MP_QSTR_get_interrupt_flag), MP_ROM_PTR(&BreakoutEncoderWheel_get_interrupt_flag_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear_interrupt_flag), MP_ROM_PTR(&BreakoutEncoderWheel_clear_interrupt_flag_obj) }, { MP_ROM_QSTR(MP_QSTR_clear_interrupt_flag), MP_ROM_PTR(&BreakoutEncoderWheel_clear_interrupt_flag_obj) },
@ -92,7 +92,7 @@ STATIC const mp_rom_map_elem_t breakout_encoder_wheel_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_breakout_encoder_wheel) }, { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_breakout_encoder_wheel) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BreakoutEncoderWheel), (mp_obj_t)&breakout_encoder_wheel_BreakoutEncoderWheel_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_BreakoutEncoderWheel), (mp_obj_t)&breakout_encoder_wheel_BreakoutEncoderWheel_type },
{ MP_ROM_QSTR(MP_QSTR_I2C_ADDR), MP_ROM_INT(0x13) }, { MP_ROM_QSTR(MP_QSTR_DEFAULT_IOE_I2C_ADDR), MP_ROM_INT(0x13) },
{ MP_ROM_QSTR(MP_QSTR_DEFAULT_LED_I2C_ADDR), MP_ROM_INT(0x77) }, { MP_ROM_QSTR(MP_QSTR_DEFAULT_LED_I2C_ADDR), MP_ROM_INT(0x77) },
{ MP_ROM_QSTR(MP_QSTR_ALTERNATE_LED_I2C_ADDR), MP_ROM_INT(0x74) }, { MP_ROM_QSTR(MP_QSTR_ALTERNATE_LED_I2C_ADDR), MP_ROM_INT(0x74) },

Wyświetl plik

@ -48,7 +48,7 @@ mp_obj_t BreakoutEncoderWheel_make_new(const mp_obj_type_t *type, size_t n_args,
} }
/***** Methods *****/ /***** Methods *****/
mp_obj_t BreakoutEncoderWheel_set_address(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_obj_t BreakoutEncoderWheel_set_ioe_address(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_self, ARG_address }; enum { ARG_self, ARG_address };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },

Wyświetl plik

@ -6,7 +6,7 @@ extern const mp_obj_type_t breakout_encoder_wheel_BreakoutEncoderWheel_type;
/***** Extern of Class Methods *****/ /***** Extern of Class Methods *****/
extern mp_obj_t BreakoutEncoderWheel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); extern mp_obj_t BreakoutEncoderWheel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
extern mp_obj_t BreakoutEncoderWheel_set_address(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); extern mp_obj_t BreakoutEncoderWheel_set_ioe_address(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t BreakoutEncoderWheel_get_interrupt_flag(mp_obj_t self_in); extern mp_obj_t BreakoutEncoderWheel_get_interrupt_flag(mp_obj_t self_in);
extern mp_obj_t BreakoutEncoderWheel_clear_interrupt_flag(mp_obj_t self_in); extern mp_obj_t BreakoutEncoderWheel_clear_interrupt_flag(mp_obj_t self_in);