Communication using I2C between Attiny85 (Slave) and NodeMCU (Master)

I was looking to expand the analogue input on my NodeMCU as I needed to interface with both an LDR to get light levels; as well as a capacitive soil moisture sensor. (for monitoring my greenhouse)

This is being added as an afterthought to my original project as I am now giving it the ability to water based on recent conditions - I’ve already completed that part but I’m having issues with the IO expansion.

I had an Attiny85 lying around, as it has 3 ADCs on board I was hoping I could get it to read the voltage and then transfer it to the NodeMCU (via I2C) so that the Node could then post it to the Blynk server.

I built a small board (as seen in image below) that has the data pull-up resistors and the other passives required to run the moisture sensor.

I have the Attiny using the TinyWireS library for I2C communication with Attiny as slave. The attiny is running the code:

#include <TinyWireS.h>       // Requires fork by Rambo with onRequest support
#include <avr/wdt.h>         // watchdog

const int I2CSlaveAddress = 8;      // I2C Address.

void setup() {
  TinyWireS.begin(I2CSlaveAddress);      // Begin I2C Communication
  TinyWireS.onRequest(transmit);         // When requested, call function transmit()

  wdt_enable(WDTO_500MS);               // Watchdog

void loop() {
  wdt_reset();                          // feed the watchdog


void transmit() {
  int16_t rawRead = analogRead(A3);

  rawRead = rawRead - 340;
  if (rawRead < 0) rawRead = 0;
  if (rawRead > 255) rawRead = 255;
  byte processed = rawRead;

This gets the useful information from the sensor and fits it into one byte so that it can be sent in one cycle. It’s supposed to read, then send the data each time it gets a request.

I tested it with an Arduino Uno running the code:

#include <Wire.h>

byte analogData = 0;
const int I2CSlaveAddress = 8;      // I2C Address.

void setup()
  Wire.begin(); //SDA , SCL 

void loop()
  Serial.print(" | ");
  analogData = readTiny(I2CSlaveAddress);
  Serial.print(" | ");

byte readTiny(int address) {
  byte rawRead;

  Wire.requestFrom(address, 1);                  // The TinyWire library only allows for one byte to be requested at a time
  while (Wire.available() == 0)  Serial.print("W");
  rawRead =;
  return rawRead;

This seems to run flawlessly, I get the appropriate value from the sensor and never see a “W” in the Serial monitor.

I thought I would be able to run the same code on the NodeMCU with
Wire.begin(D1, D2); //SDA , SCL
instead. With the other connections the same. When I run this on the NodeMCU, I only see a line of "W"s.

I validated the functionality of the NodeMCU and the wiring by using an Arduino Uno wired in place of the attiny to be the slave.

I’m really sorry for the long post, and the fact that this is more hardware related than Blynk itself, however I’ve found this forum to be filled with such genuine and helpful members.
Thank you in advance for any incite you can offer.

It might be simpler to use a digital LDR sensor, or an analogue multiplexer.


I completely agree, but I have it working well with an arduino and thus was hoping I was missing something obvious :confused:

Thank you none the less

Try existing libraries for this type of data transfer - Arduino EasyTransfer is one I have worked with before.

Thank you so much for the pointer, I will for sure look into this as an option!

Are you aware if this library supports Attinys, or wether it’s exclusively for arduino variants and ESP boards?

Not a clue… I don’t have any ATtinys, so have never worked with them. But I understand they can run the same Arduino code.

Yeah, they can run most arduino code, although they don’t work with the library you linked, that’s the many reason I was trying to use the TinyWireS library, I ended up replacing the the Attiny with an arduino nano and then using the Wire library on both sides.
This worked well.