Go Down

Topic: Hot Yet? (a tiny85 project) (Read 782 times) previous topic - next topic

mrburnette

The concept is simple, if a thermistor detects a temperature change when the tiny85 wakes which was significantly different from the previous awake period, turn PWM on a RGB led based upon the current temperature and track the change until it stabilizes.
http://youtu.be/PTEd7IiuHaE
http://www.youtube.com/watch?v=PTEd7IiuHaE&feature=youtu.be

The example here is just for fun, but was intended to provide a visual feedback for a hot water faucet; that is, as the temperature moves from cold to hot, the RGB LED goes from Blue to Green to Red with overlap in the crossover ranges.
http://youtu.be/AhAL-5vd79U
http://www.youtube.com/watch?v=AhAL-5vd79U&feature=youtu.be

The code is simple.  The sleep routines are a combination of Nick Gammon low-power settings, Watchdog settings from the InsideGadgets site, and the tiny core from Coding Badly.

This is a project that simply screams for hacking.  If the temperature has not changed during the wakeup, the circuit goes back to sleep.  Here in the lab, I have been running the project off of a CR2032 (already half-dead) for several weeks.  So, what about a wearable "mood" pendant, or "mood" wrist-band?  Using surface mount tiny, you may be able to get this into a large ring?  

Whatever you decide to do, have fun and keep us posted!


Ray

Code: [Select]

/*
  M. Ray Burnette 20140210 Open Source: for "Hot Yet?" publication
  Coding Badly Tiny core: https://code.google.com/p/arduino-tiny/
  Binary sketch size: 2,852 bytes (of a 8,192 byte maximum)
  Arduino 1.0.5 No bootloader used.  Upload via ISP.
  Project 3.3V Attiny85 @8MHz internal,  under 10mA idle at 68F

  Schematic:
  x-----------------/\/\/\/\/\/\/\/---------------x---/\/\/\/\/\/\/\----xGND
  |                NTC 10K Thermistor             |  10K 1% Resistor
  |                                               |
  |              ATTINY85 / ARDUINO               |
  |                     +-\/-+                    |
  |    Ain0 (D 5) PB5  1|    |8  Vcc              |
  x--- Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1 ---
(Blue)- Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1  (Green) ----------|<---x
  |               GND  4|    |5  PB0 (D 0) pwm0  (Red) ------------|<---x
  |                     +----+                                          |    100 Ohm
  x----------------------------------------------------------------|<---x---/\/\/\/\/---Vcc 3.3V

*/
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

boolean flag_wdt = 1;

int pinT = PB3;           // Thermistor source voltage
int pinR = PB0;           // Digital pin #0  Red
int pinG = PB1;           // Digital pin #1  Green
int pinB = PB4;           // Digital pin #4  Blue
int r; int g; int b;
const int nToSleep = 50 ; // # of stable temp readings before sleep
const int Delay =    100; // main loop delay in mS
double ADCcount;
double ADCprevious;
int nCount;
int ThermistorPin  = 1 ;  // A1 is physical pin #7 (PB2)

void setup()
{
 // WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS,
 // WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S
 setup_watchdog(WDTO_4S);  // Periodic Heartbeat to awaken deep sleep()
 sleep_disable();
 pinMode(pinT, OUTPUT); digitalWrite(pinT, HIGH);  // Thermistor Source
 pinMode(pinR, OUTPUT);
 pinMode(pinG, OUTPUT);
 pinMode(pinB, OUTPUT);
}
 
void loop()
{
 wdt_reset();    // pat K9
 ADCcount = analogRead(ThermistorPin) ;
 if (ADCcount == ADCprevious) ++nCount;
 if ( nCount > nToSleep )
 { // prepare for low current power-down state
   pinMode(pinR, INPUT); digitalWrite(pinR, HIGH);  // pullup enabled
   pinMode(pinG, INPUT); digitalWrite(pinG, HIGH);
   pinMode(pinB, INPUT); digitalWrite(pinB, HIGH);
   SleepLonger:    // Come here to re-sleep
   pinMode(pinT, INPUT); digitalWrite(pinT, HIGH);
     system_sleep();
     sleep_disable();  // deep sleep until WDT kicks
     pinMode(pinT, OUTPUT); digitalWrite(pinT, HIGH);
     delay(50);
     // Yawn, exercise a few reads for stabilization
     for (uint8_t z=0; z<5; z++) {
       ADCcount = analogRead(ThermistorPin) ;
     }
     if (abs(ADCcount - ADCprevious) < 4) goto SleepLonger;  // hysteresis
   // restore LED output drivers ... temp has gone up
   pinMode(pinR, OUTPUT); digitalWrite(pinR, HIGH);
   pinMode(pinG, OUTPUT); digitalWrite(pinG, HIGH);
   pinMode(pinB, OUTPUT); digitalWrite(pinB, HIGH);
   nCount = 0;
 } else {
 // 261 = 32F, 447 = 64F, 537 = 75F, 575 = 82F
 b = map(ADCcount, 261,  447, 100, 255 );
 g = map(ADCcount, 435,  574, 250, 100);  // overlap green & blue
 r = map(ADCcount, 575, 1023, 250,  50);

 if (ADCcount > 574)              // HOT: ADCcount goes up with increase temperature
   {
     // Show only Red when Hot with Red intensity increasing with temperature
     analogWrite(pinR,   r);
     analogWrite(pinG, 255);      // 255 = 100% High == NO LED Current Common Anode --> Vcc
     analogWrite(pinB, 255);      // Blue Off
   } else {                       // Cold to Cool transition with Blue fading into Green
     analogWrite(pinR, 255);      // Red Off
     analogWrite(pinG, g);
     analogWrite(pinB, b);        // Brighter Blue with colder temp
   }
 }
 ADCprevious = ADCcount;
 delay(Delay);
}

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
// http://www.insidegadgets.com/wp-content/uploads/2011/02/ATtiny85_watchdog_example.zip
void system_sleep()
{
   cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF
   power_all_disable ();                // power off ADC, Timer 0 and 1, serial interface
   set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
   noInterrupts ();                     // timed sequence coming up
   sleep_enable();
   interrupts ();                       // interrupts are required now
   sleep_mode();                        // System sleeps here
   sleep_disable();                     // System continues execution here when watchdog timed out
   power_all_enable ();                 // power everything back on
   sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms, 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii)
{
 byte bb;
 int ww;
 if (ii > 9 ) ii=9;
 bb=ii & 7;
 if (ii > 7) bb|= (1<<5);
 bb|= (1<<WDCE);
 ww=bb;

 MCUSR &= ~(1<<WDRF);
 // start timed sequence
 WDTCR |= (1<<WDCE) | (1<<WDE);
 // set new watchdog timeout value
 WDTCR = bb;
 WDTCR |= _BV(WDIE);
}
 
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
    // wdt_disable();  // disable watchdog
}

elac

Very cool 8) ... or hot  ]:)
My 85s should be here this week, great project to play around with.
The wrist band idea is neat, could be done with a few segments of an RGB strip.
It's all about the skills

Go Up