Bir düğme hücresinden (CR2032) güç alan bir ATtiny85 kullanan küçük bir meşale bulucu oluşturdum. Şöyle görünüyor:
Diğer taraf:
Şu anda 5,9 g ağırlığında. Pil tutucu 1,6 g ağırlığındadır, böylece daha hafif bir tutucu (belki de yalıtım için biraz plastik ve doğrudan pile lehimleme) yaparak tasarruf edebilirsiniz. Çip soketi en az 0,5 g ağırlığındadır, böylece işlemci pimlerine lehimleyerek de tasarruf edebilirsiniz. Yani 3.8g'a düştük.
ATtiny85, okumaları günlüğe kaydetmek için kullanabileceğiniz 512 bayt EEPROM'a sahiptir. Kilo almaya çalışıyorsanız bir saat hakkında emin değilim, ancak bilinen bir zamanda başlatırsanız, başlangıçtan bu millis()
yana miliiseconds bulmak için işlevi kullanarak süreyi makul bir şekilde tahmin edebilirsiniz .
Bir süre önce başka bir tane yaptım, bu da birkaç saniyede bir LED yanıp sönüyor:
Bu benzer. İşlemci orada (baş aşağı çip soket altında) ve pil altta. Bu 6g ağırlığında. Pil birkaç yıl sürdü ve bu her birkaç saniyede bir LED yanıp sönüyor!
LED yerine sıcaklığı okumak için bir termistörünüz olabilir.
Her birkaç saatte bir okuma almak ve EEPROM'a kaydetmek için programlayabilirsiniz. Daha sonra talimat verildiğinde (örn. Birkaç pime katılarak) okumaları başka bir pime (seri üzerinden) çıkarabilir.
SMD (yüzeye monte) cihazları kullanarak ve belki de oluşturabileceğiniz küçük bir devre kartı kullanarak daha fazla ağırlık tasarrufu yapabilirsiniz.
kod
Meşale konum belirleyicimin kodu aşağıda. İlginç olan, çoğu zaman uyuduğu gerçeğidir. Ayrıca ADC örneklemesi sırasında uyur. Her ne kadar benim durumumda bir LDR (ışığa bağlı direnç) ölçsem de, bir termistörün ölçüm kodu benzer olacaktır. Okumayı bir sıcaklığa dönüştürmek için sonunda bazı hesaplamalar yapmanız yeterlidir.
// 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