Я створив невеликий локатор-факел, який використовував ATtiny85, що живиться від кнопкової комірки (CR2032). Це виглядає приблизно так:
Інша сторона:
Зараз важить 5,9 г. Власник батареї важить 1,6 г, так що ви можете врятувати це, зробивши більш легкий тримач (можливо, трохи пластику для ізоляції та пайки безпосередньо до акумулятора). Розетка мікросхеми важить щонайменше 0,5 г, тому ви також можете врятувати це, припаявши до штифтів процесора. Так ми знизилися до 3,8г.
ATtiny85 має 512 байтів EEPROM, до яких можна використовувати для реєстрації показань. Я не впевнений у годиннику, якщо ви намагаєтесь зберегти вагу, але якщо ви запускаєте його у відомий час, ви можете мати розумну оцінку часу, використовуючи millis()
функцію пошуку мілісекунд після запуску.
Я зробив ще один час тому, який миготить світлодіод кожні пару секунд:
Це схоже. Процесор знаходиться там (догори дном під розеткою мікросхеми), а батарея - під ним. Важить 6г. Акумулятор прослужив пару років, і це миготить світлодіод кожні пару секунд!
Замість світлодіода у вас міг бути термістор для зчитування температури.
Ви можете запрограмувати його на читання кожні кілька годин і зберегти його в EEPROM. Тоді за вказівкою (наприклад, приєднавши пару штифтів), вона може вивести показання на інший контакт (через серійний).
Ви можете зекономити більше ваги, використовуючи пристрої SMD (поверхневі), а можливо, використовуючи крихітну плату, яку ви могли б скласти.
Код
Код мого локатора-факела знаходиться нижче. Цікавим є той факт, що вона спить більшу частину часу. Також він спить під час відбору проб АЦП. Хоча в моєму випадку я вимірюю LDR (резистор, залежний від світла), код для вимірювання термістора був би подібним. Вам просто потрібно зробити кілька обчислень в кінці, щоб перетворити показання в температуру.
// 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