Ricky the Reasonable Ashtray

Full name: Ricky the Reasonable Ashtray who is concerned with your health but is being pretty cool about it all things considered.

So I find myself, a freshman at University of Illinois at Chicago, intent on a degree in Industrial Design, in this interesting course titled Introduction to New Media Studies (AD100, if you’re keeping score). Now, the course is basically an introduction to small electronics and microcontrollers, specifically the Arduino platform (Send them free equipment, they’re woefully under equipped in my opinion), as well as Processing, and the ways these projects can be incorporated into artwork. It was indeed a full on introduction for me, as I have had no exposure to any of the covered subjects. No coding, no soldering, no nothing, but I rather dived right in.

Well, my final critique for the course is in… 5 hours, and Ricky the Reasonable Ashtray is finally complete. As I received all manner of guidance from the Arduino forums, all of it passive, archive reading and all that, I thought I might share the results.

See, I smoke a lot. A lot a lot. It’s rather unhealthy. People are concerned. Objects are concerned. Apparently, a bakelite ashtray and collection of electronics components and a few ones and zeroes were concerned. They got together and decided to speak up. I named them Ricky.

The project utilizes:

The code is mostly of my own devising, though admittedly largely adapted and hacked together from works I found on the Arduino boards and elsewhere. The function to drive the MLX90614 is taken from Sensorjunkies excellent post. This project exists only because of that guy right there. Thanks, that guy.

The functionality is as such:

  • Ricky starts up, scans the ambient temperature of the ashtray and saves it to an array, averages 50 reads at a time to get a comparative value.
  • You light a smoke, stick it in the ash tray. Ricky detects that the temperature at a point has increased by whatever threshold is set, in this case 1.2 times the average ambient. This is not written to the array, as to not make him ineffective over time.
  • Should this heat source remain for the randomly slash loop time derived period, three red LEDs are lit on the rim of the tray. These LEDs will stay lit for the set duration, currently set to one minute for ease of demonstration at critique. If at any time a heat source reenters Ricky’s domain the count is reset.
  • You feel bad for smoking so often and cut back. You live a long and full life and have many fat and happy grandchildren. Not like, American fat (I’m in Chicago, relax, I can say that), just pleasant and well cared for.

Seriously, guys, 3 months ago I didn’t know what a resistor was. I’m pretty proud of myself, no lie.

Feedback on more efficient ways to handle this would be appreciated. I’m here to learn.

Thanks for checking it out.

Code block BAM!

#include <i2cmaster.h>

const int mainArraySize = 50;
int mainArray[mainArraySize];

int total;
int average;

int currentTemp;

int heatCount = 0;
int smoked = 0;

int minutes = 30;
unsigned long lastMillis = 0;
unsigned long countMillis = 0;

void setup()
  while (millis() < 500)
    average = MainArraySmoother();

void loop()

  if (heatCount > 200)
    smoked = 1;
    heatCount = 0;
    countMillis = 0;
    lastMillis = millis();

  if (smoked == 1)
    countMillis = millis() - lastMillis;
    if (countMillis > minutes * 60000)
      smoked = 0;

  if (smoked == 0)

int MainArraySmoother()
  total = total + mainArray[0];
  total = total - mainArray[mainArraySize - 1];
  return total / (mainArraySize - 1);

int MainArrayWriter(int sensorValue)
  int total;
  mainArray[0] = sensorValue;
  for ( int i = mainArraySize - 1; i > 0; i--){
    mainArray[i] = mainArray[i-1];

void TempCompare()
  currentTemp = TempMonitor();
  if (currentTemp >= average * 1.2)
    heatCount ++;
  else if (currentTemp < average * 1.2)
    average = MainArraySmoother();
    heatCount = 0;

void TempMonitorSetup()
  i2c_init(); //Initialise the i2c bus 
  Serial.println("Return from i2c_init"); 
  PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups

int TempMonitor() 
  int dev = 0x5A<<1; 
  int data_low = 0; 
  int data_high = 0; 
  int pec = 0; 

  data_low = i2c_readAck(); //Read 1 byte and then send ack 
  data_high = i2c_readAck(); //Read 1 byte and then send ack 
  pec = i2c_readNak(); 

  //This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps 
  double tempFactor = 0.02; // 0.02 degrees per LSB 
  double tempData = 0x0000; 
  int frac; 

  // This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte. 
  tempData = (double)(((data_high & 0x007F) << 8) + data_low); 
  tempData = (tempData * tempFactor)-0.01; 
  tempData = tempData - 273.15; 
  return tempData;

The man himself, in all his filthiness: http://imgur.com/bKrVA.jpg

Well done !

Take great care though, electronics can be extremely addictive.;)

Before you know it Ricky will be saying things like "Man, cut down, You're a walking Chimney... " and "Are those legal to smoke ?..." :D

More efficient ways ? I haven't tested your code, but it looks good.

Commenting every detail in your program might help you with larger projects. In a world with zillions of components and protocols it's nice to read what you've done in a particular piece of programming should you want to adapt it later. If you do, you may be able to change the code without having to read those data sheets again. It does.... work, but... Please don't quote me on this one, cause you'll laugh yourself headless after you've seen some of my code :)

Success with your study !