Zrobiłem mały lokalizator pochodni, który wykorzystywał ATtiny85 zasilany z komórki guzikowej (CR2032). To wygląda tak:
Druga strona:
To waży obecnie 5,9 g. Uchwyt baterii waży 1,6 g, więc możesz to zaoszczędzić, wykonując bardziej lekki uchwyt (być może kawałek plastiku do izolacji i lutowanie bezpośrednio do akumulatora). Gniazdo mikroukładu waży co najmniej 0,5 g, więc możesz to również zaoszczędzić, lutując do pinów procesora. Sprowadzamy więc do 3,8 g.
ATtiny85 ma 512 bajtów EEPROM, których można użyć do zarejestrowania odczytów. Nie jestem pewien co do zegara, jeśli próbujesz zaoszczędzić na wadze, ale jeśli uruchomisz go w znanym momencie, możesz mieć rozsądny szacunkowy czas, używając millis()
funkcji do znalezienia milisekund od uruchomienia.
Jakiś czas temu zrobiłem inny, który co kilka sekund miga diodą LED:
To jest podobne. Procesor jest tam (do góry nogami pod gniazdem chipa), a akumulator jest pod spodem. To waży 6 g. Bateria przetrwała kilka lat, a to miga diodą LED co kilka sekund!
Zamiast diody LED możesz mieć termistor do odczytu temperatury.
Możesz zaprogramować go tak, aby dokonywał odczytu co kilka godzin i zapisywał go w EEPROM. Następnie po otrzymaniu instrukcji (np. Łącząc kilka pinów) może przesłać odczyty na inny pin (przez port szeregowy).
Możesz zaoszczędzić więcej wagi, używając urządzeń SMD (montowanych powierzchniowo), a być może za pomocą niewielkiej płytki drukowanej, którą możesz wymyślić.
Kod
Kod mojego lokalizatora pochodni znajduje się poniżej. Interesujący jest fakt, że przez większość czasu śpi. Również śpi podczas próbkowania ADC. Chociaż w moim przypadku mierzę LDR (rezystor zależny od światła), kod pomiaru termistora byłby podobny. Musisz tylko wykonać kilka obliczeń na końcu, aby zmienić odczyt w temperaturę.
// ATtiny85 torch detector
// Author: Nick Gammon
// Date: 25 February 2015
// ATMEL ATTINY 25/45/85 / ARDUINO
// Pin 1 is /RESET
//
// +-\/-+
// Ain0 (D 5) PB5 1| |8 Vcc
// Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1
// Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1
// GND 4| |5 PB0 (D 0) pwm0
// +----+
/*
Pin 2 (PB3) <-- LDR (GL5539) --> Pin 7 (PB2) <----> 56 k <----> Gnd
Pin 5 (PB0) <---- LED ---> 100 R <-----> Gnd
*/
#include <avr/sleep.h> // Sleep Modes
#include <avr/power.h> // Power management
#include <avr/wdt.h> // Watchdog timer
const byte LED = 0; // pin 5
const byte LDR_ENABLE = 3; // pin 2
const byte LDR_READ = 1; // Ain1 (PB2) pin 7
const int LIGHT_THRESHOLD = 200; // Flash LED when darker than this
// when ADC completed, take an interrupt
EMPTY_INTERRUPT (ADC_vect);
// Take an ADC reading in sleep mode (ADC)
float getReading (byte port)
{
power_adc_enable() ;
ADCSRA = bit (ADEN) | bit (ADIF); // enable ADC, turn off any pending interrupt
// set a2d prescale factor to 128
// 8 MHz / 128 = 62.5 KHz, inside the desired 50-200 KHz range.
ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2);
if (port >= A0)
port -= A0;
#if defined(__AVR_ATtiny85__)
ADMUX = (port & 0x07); // AVcc
#else
ADMUX = bit (REFS0) | (port & 0x07); // AVcc
#endif
noInterrupts ();
set_sleep_mode (SLEEP_MODE_ADC); // sleep during sample
sleep_enable();
// start the conversion
ADCSRA |= bit (ADSC) | bit (ADIE);
interrupts ();
sleep_cpu ();
sleep_disable ();
// reading should be done, but better make sure
// maybe the timer interrupt fired
// ADSC is cleared when the conversion finishes
while (bit_is_set (ADCSRA, ADSC))
{ }
byte low = ADCL;
byte high = ADCH;
ADCSRA = 0; // disable ADC
power_adc_disable();
return (high << 8) | low;
} // end of getReading
// watchdog interrupt
ISR (WDT_vect)
{
wdt_disable(); // disable watchdog
} // end of WDT_vect
#if defined(__AVR_ATtiny85__)
#define watchdogRegister WDTCR
#else
#define watchdogRegister WDTCSR
#endif
void setup ()
{
wdt_reset();
pinMode (LED, OUTPUT);
pinMode (LDR_ENABLE, OUTPUT);
ADCSRA = 0; // turn off ADC
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
} // end of setup
void loop ()
{
// power up the LDR, take a reading
digitalWrite (LDR_ENABLE, HIGH);
int value = getReading (LDR_READ);
// power off the LDR
digitalWrite (LDR_ENABLE, LOW);
// if it's dark, flash the LED for 2 mS
if (value < LIGHT_THRESHOLD)
{
power_timer0_enable ();
delay (1); // let timer reach a known point
digitalWrite (LED, HIGH);
delay (2);
digitalWrite (LED, LOW);
power_timer0_disable ();
}
goToSleep ();
} // end of loop
void goToSleep ()
{
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); // timed sequence coming up
// pat the dog
wdt_reset();
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset, clear existing interrupt
watchdogRegister = bit (WDCE) | bit (WDE) | bit (WDIF);
// set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
watchdogRegister = bit (WDIE) | bit (WDP2) | bit (WDP1) | bit (WDP0); // set WDIE, and 2 seconds delay
sleep_enable (); // ready to sleep
interrupts (); // interrupts are required now
sleep_cpu (); // sleep
sleep_disable (); // precaution
} // end of goToSleep