I2C on ATTINY841 to an RpiZ


I'm trying to use the I2C on an 841, to send data to a raspberry Pi. It is currently "kind of" working, where I can see data but it is not fully coherent.
If I try to do a 'BUS.read_i2c_block_data' it fails with an Input/Output error[5]
I can seem to get data if I read byte by byte with 'BUS.read_byte' and a test loop. But weirdly it seems to be missing every other byte from the sent test string.

At the moment I am working through the code on the slave side (ATTINY841) to try and figure out how the function I got (from a forum) is working the TWI to see if I can figure out the problem.

The code that initialises the TWI is a bit curious:
TWSCRA = (1 << TWEN) // Two-Wire Interface Enable
| (1 << TWSHE) // TWI SDA Hold Time Enable
| (1 << TWASIE) // TWI Address/Stop Interrupt Enable
| (1 << TWSIE) // TWI Stop Interrupt Enable
| (1 << TWDIE); // TWI Data Interrupt Enable

I can see how it is setting up the TWSCRA register that controls the I2C using bitwise shifts, but can't see where the bitwise values are coming from.
example "TWSHE" is being shifted in to the register, but what is 'TWSHE' value?

I can only think that "TWSHE" is a const with a value of the correct bit (bit 7 on an ATTINY841)- presumably to allow the library to work with different devices, is this a correct assumption?


Have you got pull up resistors on the two I2C lines?
What value are they?
What voltage are you running the ATTINY841 at?


Both the ATTINY and the Rpi (zeroW) are running at 5.0v, the Rpi is documented as having internal pull-up 1.8K resistors to 3.3v


No, the Rpi (zeroW) runs at 3V3. It might take a 5V power supply, but there is an onboard regulator so the processor board and the signals run at 3V3.

That is only on one of the I2C buses on the the Raspberry Pi. I don't know if that applies to the zero. I am assuming that the ATTINY841 is a board with it on and not simply just the processor of the same name. Can you supply a link to where you bought it. So any pull up resistors would be on the board. As you are connecting it to a 3V3 system any pull up to 5V must be removed or disabled. If, as seems likely, your Arduino library enables the internal pull up resistors, then you must immediately after starting the bus, use a pinMode call to just make them outputs.

Please note that the Raspberry Pi can not act as an I2C slave device, it has to be a master. That means your Arduino has to be the I2C slave and It can only respond to a data request from the Pi. It can not initiate a transaction.

Thanks for your feedback...

It might take a 5V power supply, but there is an onboard regulator so the processor board and the signals run at 3V3.

I didn't know this - so my Rpi is running at 3v3, the ATTINY is on a 5.0 v line (the same feed as the RPI - So I will look in to changing that first...
However - currently I have 3 x systems on the same I2C bus, they are working fine, but the data is read by python modules that came for the hardware modules. My new one is not a module (I can't get one that does what I want) so I'm trying to develop it myself. TheI2C bus works fine for the other units on there, this makes me think that it is the code that might be the issue bot the signal levels?

I did another search on Rpi ZW pull up and didn't get any different results, so for the moment I will have to assume they are 1.8K

I am assuming that the ATTINY841 is a board with it on and not simply just the processor of the same name

No, I'm using a bare IC, not a module, it is on a breadboard via a soldered SOIC to DIL adapter

Raspberry Pi can not act as an I2C slave device..

The Rpi is the Master, for my system, the ATTINY is the slave.


In which case you will know if you have used a pull up resistor or not. I2C signals only pull down, or at least should do. Unfortunately some Arduino libraries activate the internal pull up resistors.

Those constants being used to generate the value being assigned to TWSCSR do exactly what you thought.

I don't know what you're using (with ATTinyCore, the version I maintain at least, you should be able to set wire mode to slave from the tools submenu and use the included Wire library to get I2C slave functionality). With any other core you're probablty going to need your own implementation of I2C. I don't think I actually enable pullups automatically. Certainly it's not my intent to - my policy on that is that users have to go our of their way to enable the on-chip pullups, because they do not meet the I2C specs and do not reliably provide working I2C functionality, and letting people use them for I2C without their being explicitly aware that what they';re doing doesn't meet spec and may or may not work depending on a wide variety of factors) I think you have way too many complicated things going on here. How about first getting it working without involving the RPi and using like, a standard arduino with working hardware I2C master and external pullups on the I2C line? and only when the simple case works, getting things sorted out with the RPi? IMO you are doing too many weird things at the same time that it's impossible to pick out which problem is caused by what./

I should hope the pi is master and the '841 the slave since the hardware I2C on the '841 is slave only, and the software I2C master is pretty halfassed. (It should be improved, but the 841 is legacy hardware anyway and not a priority. Once I finish the new boards.txt)

Hello, I have no pull up resistors installed, I am relying on the RPi installed ones. I can't find any specific documentation about pull ups for the RpiZW, so can only assume they are the same as standards Rpi (1.8K). However, as it is on a breadboard it is a simple task to plug some in and see if it improves, I'll try that. Thanks

Hello, sorry for the delayed response, I only got to do some extra testing last night.
You are right I have too many things going on, I removed all extraneous items from the I2C bus.

I have the ATTINYCore library installed (v1.5.2) (and the 841NoBootloader selected) and tried a new script to configure the ATTINY841 as a slave and simply send a message when contacted from the RpiZ master, unfortunately the script will not compile, I get a whole raft of errors, most of the lines look like this.

error: 'SCL_PORT' was not declared in this scope

#define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2)

I have also tried with 841OptiBoot selected, but get the same issue, some messages on the internet imply the wire library is not compatible with the 841. But since you are the maintainer I guess you know best :grin: So I guess I'm probably doing something wrong but can't figure it out.

So can you post this modified code again in a new post so we can check it out.

Here is the test code I am currently working with...
(I originally only added the 'Wire.h' library, when it would not compile I took out my manual library entry and used the Arduino IDE library selector to add the Wire library, this added all the libraries we see here, but I get the same compile errors...)

ATTINYcore Module 1.5.2 is installed to my IDE

#include <SoftI2CMaster.h>
#include <SoftWire.h>
#include <twi.h>
#include <Wire.h>
#include <WireS.h>

const int I2C_Address=0x3a; //our slave address for the I2C bus
int led_pin = 0; //indicator led
bool led_on = true ; //LED status

void setup() {
//setup function

Wire.begin(I2C_Address); //open the I2C bus
Wire.onRequest(requestEvent); // register event

pinMode (led_pin, OUTPUT); //set the indicator led

void requestEvent() {
Wire.write("WireI2cHello"); // respond with test message

void loop() {
//main loop routine

//flash the led
int delay_time=1000;
digitalWrite(led_pin, led_on);
delay (delay_time);
led_on = !led_on;


I managed to get this working after cleaning up the bus by removing everything else on it, and them removing ALL of my Arduino IDE and libraries and reinstalling them.
I think it would not compile due to some corruption somewhere.

Once I got it to compile with the ATMEGA library it all started working.
Thanks to everyone for their help.