adafruit / seesaw

I2C friend to expand capabilities of other chips.
Other
76 stars 34 forks source link

OSError: [Errno 5] Input/output error #15

Closed wallarug closed 5 years ago

wallarug commented 5 years ago

Hi,

I am still having problems with the SeeSaw firmware and communicating with it as mentioned here. I have triple checked that all the pins match between the board_config, custom adafruit_crickit.py and seesaw map file.

I keep getting the following error when I try to interface with a servo motor control pin on the second call:

>>> from adafruit_crickit import crickit
>>> crickit.servo_2.angle = 0
>>> crickit.servo_2.angle = 90
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_motor/servo.py", line 112, in angle
    self.fraction = new_angle / self.actuation_range
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_motor/servo.py", line 66, in fraction
    self._pwm_out.duty_cycle = duty_cycle
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_seesaw/pwmout.py", line 57, in duty_cycle
    self._seesaw.analog_write(self._pin, value)
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_seesaw/seesaw.py", line 323, in analog_write
    self.write(_TIMER_BASE, _TIMER_PWM, cmd)
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_seesaw/seesaw.py", line 405, in write
    i2c.write(full_buffer)
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_bus_device/i2c_device.py", line 115, in write
    self.i2c.writeto(self.device_address, buf, **kwargs)
  File "/home/pi/.local/lib/python3.5/site-packages/busio.py", line 65, in writeto
    return self._i2c.writeto(address, buffer, stop=stop)
  File "/home/pi/.local/lib/python3.5/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py", line 38, in writeto
    self._i2c_bus.write_bytes(address, buffer[start:end])
  File "/home/pi/.local/lib/python3.5/site-packages/Adafruit_PureIO/smbus.py", line 244, in write_bytes
    self._device.write(buf)
OSError: [Errno 5] Input/output error

I have narrowed down that this problem does not reside in any of the Adafruit CircuitPython libraries for the board and is related to I2C or the way that SeeSaw Firmware interacts with the Raspberry Pi.

Currently I have the following in my board_config.h file:

//* ============== I2C SLAVE =================== *//
#define CONFIG_I2C_SLAVE 1
#define CONFIG_I2C_SLAVE_SERCOM SERCOM3
#define CONFIG_I2C_SLAVE_HANDLER SERCOM3_Handler
#define CONFIG_I2C_SLAVE_IRQn SERCOM3_IRQn
#define CONFIG_I2C_SLAVE_PIN_SDA 22
#define CONFIG_I2C_SLAVE_PIN_SCL 23
#define CONFIG_I2C_SLAVE_MUX 2
#define CONFIG_I2C_SLAVE_FLOW_CONTROL 0
//#define CONFIG_I2C_SLAVE_FLOW_CONTROL_PIN 23
#define CONFIG_I2C_SLAVE_ADDR 0x49

I tried running some individual i2c tests between the SeeSaw Firmware and Raspberry Pi. From my understanding, this should not return 0xff unless there is an issue. I tried hitting many other registers as well.

pi@lightshowpi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- 41 -- -- -- -- -- -- -- 49 -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --
pi@lightshowpi:~ $ i2cget -y 1 0x49 0x00 b
0xff
pi@lightshowpi:~ $ i2cget -y 1 0x49 0x01 b
0xff
pi@lightshowpi:~ $ i2cget -y 1 0x49 0x04 b
0xff
pi@lightshowpi:~ $ i2cget -y 1 0x49 0x03 b
0x00

It looks like a firmware issue with SeeSaw and I2C. I feel that I may have extra configurations that are not required or have missed something basic in the config.

The board uses SERCOM3 (function C, MUX 2) for I2C. SDA PA22, SCL PA23.

I have looked into Clock Stretching as a possible cause of this strange behavior. As a result I have experimented with FLOW_CONTROL being on and off. I also slowed the bus speed of the Raspberry Pi down to 10,000 Hz (10 kHz) as suggested on the Adafruit Learn pages.

I have run out of ideas for this one. Any further assistance would be very very helpful.

ladyada commented 5 years ago

we're not sure either - please let us know and we can update the guide!

wallarug commented 5 years ago

Hi,

I have now worked out what the problem is.

The SAMD21G datasheet says that PB10, PB11, PA20 and PA21 can be accessed by WO (wave output) pads 4 to 7 respectively. This is how they were set in board_config.h

board_config.h

#define CONFIG_TIMER_PWM_OUT0 1
#define CONFIG_TIMER_PWM_OUT0_IS_TCC
#define CONFIG_TIMER_PWM_OUT0_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT0_TCC TCC0
#define CONFIG_TIMER_PWM_OUT0_WO 4
#define CONFIG_TIMER_PWM_OUT0_PIN (32 + 10) //PB10 - SERVO_01

#define CONFIG_TIMER_PWM_OUT1 1
#define CONFIG_TIMER_PWM_OUT1_IS_TCC
#define CONFIG_TIMER_PWM_OUT1_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT1_TCC TCC0
#define CONFIG_TIMER_PWM_OUT1_WO 5
#define CONFIG_TIMER_PWM_OUT1_PIN (32 + 11) //PB11 - SERVO_02

#define CONFIG_TIMER_PWM_OUT2 1
#define CONFIG_TIMER_PWM_OUT2_IS_TCC
#define CONFIG_TIMER_PWM_OUT2_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT2_TCC TCC0
#define CONFIG_TIMER_PWM_OUT2_WO 6
#define CONFIG_TIMER_PWM_OUT2_PIN 20       //PA20 - SERVO_03

#define CONFIG_TIMER_PWM_OUT3 1
#define CONFIG_TIMER_PWM_OUT3_IS_TCC
#define CONFIG_TIMER_PWM_OUT3_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT3_TCC TCC0
#define CONFIG_TIMER_PWM_OUT3_WO 7
#define CONFIG_TIMER_PWM_OUT3_PIN 21       //PA21 - SERVO_04

Note CONFIG_TIMER_PWM_OUTx_WO for each.

These WOx are equivalent (by timer and clock) to WO 0 through 3 as per table below. A forum post on Arduino Forums notified me of this before.

Timer WO WO
TCC0 0 4
TCC0 1 5
TCC0 2 6
TCC0 3 7

SeeSaw might not understand this concept.

The solution is to ignore the datasheet and just set to lower equivalent pin as per table above (it would be impractical to update SeeSaw completely to fix this).

board_config.h

#define CONFIG_TIMER_PWM_OUT0 1
#define CONFIG_TIMER_PWM_OUT0_IS_TCC
#define CONFIG_TIMER_PWM_OUT0_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT0_TCC TCC0
#define CONFIG_TIMER_PWM_OUT0_WO 0
#define CONFIG_TIMER_PWM_OUT0_PIN (32 + 10) //PB10 - SERVO_01

#define CONFIG_TIMER_PWM_OUT1 1
#define CONFIG_TIMER_PWM_OUT1_IS_TCC
#define CONFIG_TIMER_PWM_OUT1_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT1_TCC TCC0
#define CONFIG_TIMER_PWM_OUT1_WO 1
#define CONFIG_TIMER_PWM_OUT1_PIN (32 + 11) //PB11 - SERVO_02

#define CONFIG_TIMER_PWM_OUT2 1
#define CONFIG_TIMER_PWM_OUT2_IS_TCC
#define CONFIG_TIMER_PWM_OUT2_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT2_TCC TCC0
#define CONFIG_TIMER_PWM_OUT2_WO 2
#define CONFIG_TIMER_PWM_OUT2_PIN 20       //PA20 - SERVO_03

#define CONFIG_TIMER_PWM_OUT3 1
#define CONFIG_TIMER_PWM_OUT3_IS_TCC
#define CONFIG_TIMER_PWM_OUT3_TC NOT_ON_TC
#define CONFIG_TIMER_PWM_OUT3_TCC TCC0
#define CONFIG_TIMER_PWM_OUT3_WO 3
#define CONFIG_TIMER_PWM_OUT3_PIN 21       //PA21 - SERVO_04

This helped a bit as well (once I found it) Speeding up I2C.

Thank you for your support in this issue :100: