Homemade Hardware - Week 1: Programming the ATtiny85

Creating a handheld battery-powered temperature sensor with the ATtiny85:

Components:

> ATtiny85 Microcontroller

> MLX90614 Infra Red thermometer

> RGB smart NeoPixel

> Assorted discrete components

> 9V battery

Breadboard containing 7805 voltage regulator, RGM smart NeoPixel, ATtiny85, and MXL90614 IR thermometer

Temperature is measured using a Melexis (MLX90614) non-contact IR sensor. It’s a 4-pin sensor that utilizes a form of i2c called “repeat-start”.  The ATTiny85 doesn’t have i2c built in, but instead has a Universal Serial Interface (USI) that facilitates i2c and SPI.  In order to communicate with ATtiny, I made use of the TinyWireM and Adafruit_MiniMLX90614 Arduino libraries.  The temperature of the object being measured is displayed using an RGB smart NeoPixel, with blue representing cold and red representing hot.  The NeoPixel is addressed with the help of the Adafruit_NeoPixel library.

Close-up shot of Melexis MLX90614

The Melexis library allows for readings to be taken of the ambient atmospheric temperature, as well as an object that’s placed in front of the sensor.  By calculating the difference between the two, a positive or negative temperature differential is detected and is then used to set the color value that’s passed to the NeoPixel.  To test the sensor, I used my hand (body heat) as a heat source, and a small tub of hummus that had been chilled in the refrigerator. 

During development, the built-in SoftwareSerial library was used for debugging and to ascertain whether or not the i2c communication between the sensor and the ATtiny was working correctly.  By running the SoftwareSerial library on both the ATTtiny and an Arduino Uno, setting one of the ATtiny’s pins for outgoing data (TX) and one of the Uno’s pins for incoming data (RX), it’s possible to view the values being passed to the ATtiny from the Melexis sensor in the Arduino IDE’s serial monitor.

Dual board setup showing programmer and test circuit.

In order to program the ATtiny, I turned one of my Arduino Uno’s into a programmer using the ArduinoISP sketch, which then allowed me to burn a bootloader on the ATtiny and upload code to it through the Uno. I set up one Arduino as programmer with it’s own breadboard.  I used this to upload code to the ATtiny and then transferred the chip to a separate board with my circuitry.  By running the SoftwareSerial sketch on my second Uno, I was able to read the values coming from the temperature sensor.  After refining the code and once the design of the circuit was complete, I made use of a 7805 voltage regulator to power it using a 9V battery.  Because of the inclusion of the libraries, the sketch (with a size of 6,724 bytes) used up 82% of the ATtiny’s storage space.

The code for the sketch is available here:

//INCLUDE REQUIRED LIBRARIES
#include <Adafruit_NeoPixel.h>
#include <TinyWireM.h>
#include <Adafruit_MiniMLX90614.h>
#include <SoftwareSerial.h>

int TINY_SDA   =     0;               //ATtiny SDA pin 5
int TINY_SCL   =     2;              //ATtiny SCL pin 7
int LED_PIN    =     1;              //NEOPIXEL LED ON ATtuny PIN 6
int NUMPIXELS  =     1;              //THE NEOPIXEL LIBRARY NEEDS YOU TO PASS THE NUMBER OF PIXELS AS A FUNCTION ARGUMENT

Adafruit_MiniMLX90614 mlx = Adafruit_MiniMLX90614();

SoftwareSerial mySerial(4, 3); // RX, TX

Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

int delayval = 50; // DELAY

void setup() {
  mlx.begin();            //INITIALIZE THE MELEXIS SENSOR
  pixel.begin();          //INITIALIZE THE NEOPIXEL
  mySerial.begin(4800);   //INITIALIZE THE SOFTWARE SERIAL
}

void loop() {

  //CREATE VARIABLES TO STORE AMBIENT AND OBJECT TEMPERATURES
  float ambientTemp = mlx.readAmbientTempC();
  float objTemp = mlx.readObjectTempC();

  //CALCULATE THE DIFFERENCE BETWEEN THE TWO
  float diff = ambientTemp - objTemp;

  //UNCOMMENT THE SECTION BELOW FOR DEBUGGING
  /*
  mySerial.print("Object Temp: ");
  mySerial.print(objTemp);
  mySerial.print(" , Ambient Temp: ");
  mySerial.print(ambientTemp);
  mySerial.print("  ,  Difference: ");
  mySerial.println(diff);
 */
 
  if (diff > 2) {
    pixel.setPixelColor(0, pixel.Color(0, 0, 255)); //IF OBJECT IS COLD, SET COLOR TO BLUE
  } else if (diff < -2) {
    pixel.setPixelColor(0, pixel.Color(255, 0, 0)); //IF OBJECT IS HOT, SET COLOR TO RED
  } else {
    pixel.setPixelColor(0, pixel.Color(150, 170, 150)); //REPRESENT AMBIENT TEMP WITH WHITE LIGHT
  }

  pixel.show(); // DISPLAY COLOR ON THE PIXEL

  delay(delayval);

}