Saya membuat locator obor kecil yang menggunakan ATtiny85 didukung dari sel-tombol (CR2032). Ini terlihat seperti ini:
Sisi lain:
Yang saat ini beratnya 5.9g. Dudukan baterai memiliki berat 1,6g sehingga Anda dapat menghemat dengan membuat dudukan yang lebih ringan (mungkin sedikit plastik untuk insulasi, dan menyolder langsung ke baterai). Soket chip memiliki berat setidaknya 0,5 g, sehingga Anda dapat menyimpannya juga dengan menyolder ke pin prosesor. Jadi kita turun ke 3.8g.
ATtiny85 memiliki 512 byte EEPROM yang dapat Anda gunakan untuk mencatat bacaan. Saya tidak yakin tentang jam jika Anda mencoba untuk menghemat berat, tetapi jika Anda memulainya pada waktu yang diketahui, Anda bisa memiliki perkiraan waktu yang masuk akal dengan menggunakan millis()
fungsi untuk menemukan milidetik sejak startup.
Saya membuat satu lagi beberapa waktu lalu yang mem-flash LED setiap beberapa detik:
Itu mirip. Prosesor ada di sana (terbalik di bawah soket chip) dan baterai di bawahnya. Beratnya 6g. Baterai telah bertahan beberapa tahun, dan itu mem-ledkan LED setiap beberapa detik!
Alih-alih LED Anda bisa memiliki termistor untuk membaca suhu.
Anda dapat memprogramnya untuk membaca setiap beberapa jam dan menyimpannya di EEPROM. Kemudian ketika diinstruksikan (mis. Dengan menggabungkan beberapa pin) itu bisa menampilkan bacaan ke pin lain (melalui serial).
Anda bisa menghemat lebih banyak berat dengan menggunakan perangkat SMD (surface mounted), dan mungkin menggunakan papan sirkuit kecil yang bisa Anda buat.
Kode
Kode untuk pencari obor saya di bawah. Yang menarik adalah kenyataan bahwa itu tidur sebagian besar waktu. Juga tidur selama pengambilan sampel ADC. Meskipun dalam kasus saya, saya mengukur LDR (light dependent resistor) kode untuk mengukur termistor akan serupa. Anda hanya perlu melakukan beberapa perhitungan di akhir untuk mengubah bacaan menjadi suhu.
// 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