I love AVR ATtinyx5 series microcontrollers. They are cheap, easy to use, they can be programmed just like Arduinos and comparing to their size they offer great features. For example, they can be used as a remote analog to digital converters connected to a master device using an I2C bus.

Background: A few years ago I've built a weather station based on Raspberry Pi. It collects various data and displays them on a dedicated web page and Android app. Every few months I try to add a new sensor to it. Last time it was a daylight sensor. Raspberry Pi does not offer ADC inputs and I had a few ATtiny85 on hand tat hand. One to another, a few hours later: a photoresistor based daylight meter sensor connected via the I2C bus.

ATtiny85 as light sensor with I2C bus

Electric assembly is pretty simple: ATtiny85 directly connected to Raspberry Pi via I2C, photoresistor with 10kOhm pull down connected to ATtiny85 and signal LED.

attiny85 i2c slave light sensor with photoresistor

Code driving this rig is also pretty simple: watchdog timer wakes up ATtiny85 every few minutes, measures voltage, filters it and stores in memory. Every time read operation is requested, last filtered ADC value (10 bits as 2 bytes).

I2C support is provided by TinyWireS library that configures USI as an I2C slave.

/**
 * This function is executed when there is a request to read sensor
 * To get data, 2 reads of 8 bits are required
 * First requests send 8 older bits of 16bit unsigned int
 * The second request sends 8 lower bytes
 * Measurement is executed when a request for the first batch of data is requested
 */
void requestEvent()
{  
  TinyWireS.send(i2c_regs[reg_position]);

  reg_position++;
  if (reg_position >= reg_size)
  {
      reg_position = 0;
  }
}

/*
 * Setup I2C
 */
TinyWireS.begin(I2C_SLAVE_ADDRESS);
TinyWireS.onRequest(requestEvent); //Set I2C read event handler
`</pre>

Example code to read from device might look like this:

<pre>`Wire.requestFrom(0x13, 2);    // request 2 bytes from slave device #0x13

int i =0;
unsigned int readout = 0;

while (Wire.available()) { // slave may send less than requested
byte c = Wire.read(); // receive a byte as character

if (i == 0) {
    readout = c;
} else {
    readout = readout &lt;&lt; 8;
    readout = readout + c;
}

i++;
}

Serial.print(readout);

Full source code is available on GitHub and my Weather Station with almost a year of light level history is available here.