I'm trying to interface a Pi with smbus2 to an ATTiny85 with TinyWireS.
I have two questions:
- Why does the smbus write not work?
- Why does the read i2c_block_data return only 0xff where the single byte read succeed?
Here is the output from the python script:
Test started
Results from smbus2 single byte reads:
Register 0 = 0x20
Register 1 = 0x21
Register 2 = 0x22
Register 3 = 0x23
Register 4 = 0x24
Register 5 = 0x25
Register 6 = 0x26
Register 7 = 0x27
Results from smbus2 block read:
Register 0 255
Register 1 255
Register 2 255
Register 3 255
Register 4 255
Register 5 255
Register 6 255
Register 7 255
The AtTiny85 code comes from the example here and looks like this:
#include <TinyWireS.h>
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 8 )
#endif
const byte I2C_SLAVE_ADDRESS = 4;
volatile byte i2c_regs[] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27};
// Tracks the current register pointer position
volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);
void requestEvent()
{
TinyWireS.send(i2c_regs[reg_position]);
// Increment the reg position on each read, and loop back to zero
reg_position++;
if (reg_position >= reg_size)
{
reg_position = 0;
}
}
void receiveEvent(uint8_t howMany)
{
if (howMany < 1)
{
// Sanity-check
return;
}
if (howMany > TWI_RX_BUFFER_SIZE)
{
// Also insane number
return;
}
reg_position = TinyWireS.receive();
howMany--;
if (!howMany)
{
// This write was only to set the buffer for next read
return;
}
while(howMany--)
{
i2c_regs[reg_position] = TinyWireS.receive(); // write data into reg
reg_position++;
if (reg_position >= reg_size)
{
reg_position = 0;
}
}
}
void setup()
{
TinyWireS.begin(I2C_SLAVE_ADDRESS);
TinyWireS.onReceive(receiveEvent); // receive data from Pi to write into regs
TinyWireS.onRequest(requestEvent); // request to send data (regs) back to Pi
}
void loop()
{
TinyWireS_stop_check();
}
The python code on the Pi looks like this:
#!/usr/bin/python3
import smbus2
import time
bus = smbus2.SMBus(1) # Pi uses i2c bus 1
address = 4 # I2C slave Address
upsRegister = list((0,0,0,0,0,0,0,0))
upsRegLen = len(upsRegister)
# -------------------------------------------
def writeReg(offset, data):
try:
bus.write_i2c_block_data(address, offset, data)
return True
except OSError as oserr:
message = "writeRegisters " + str(oserr)
print(message)
return False
def readReg1(): # using loop with single byte reads
try:
bus.write_byte(address, 0) # start from reg 0
for reg in range (8):
upsRegister[reg] = bus.read_byte(address)
return True
except OSError as oserr:
print("readRegisters " + str(oserr))
return False
def readReg2(): # using block read
try:
rxblock = bus.read_i2c_block_data(address, 0, 8)
return True, rxblock
except OSError as oserr:
print("readRegisters " + str(oserr))
return False, 0
def main():
print("Test started")
writeReg(0, [0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68])
# ----- Using single byte reads
print("Results from smbus2 single byte reads:")
if (readReg1()):
for i in range (8):
print("Register", i, "=", hex(upsRegister[i]))
print()
# ----- Using block read
print("Results from smbus2 block read:")
success, rxblock = readReg2()
for i in range (8):
print("Register", i, rxblock[i])
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
sys.exit(0)