Tôi tạo ra một bộ định vị đèn pin nhỏ sử dụng ATtiny85 được cấp nguồn từ một tế bào nút (CR2032). Nó trông như thế này:
Mặt khác:
Mà hiện tại nặng 5,9g. Giá đỡ pin nặng 1,6g để bạn có thể tiết kiệm bằng cách tạo ra giá đỡ nhẹ hơn (có thể là một chút nhựa để cách điện và hàn trực tiếp vào pin). Ổ cắm chip nặng ít nhất 0,5g, vì vậy bạn cũng có thể lưu nó bằng cách hàn vào các chân của bộ xử lý. Vì vậy, chúng tôi xuống đến 3,8g.
ATtiny85 có 512 byte EEPROM mà bạn có thể sử dụng để ghi nhật ký đọc. Tôi không chắc chắn về đồng hồ nếu bạn đang cố gắng tiết kiệm trọng lượng, nhưng nếu bạn khởi động nó vào một thời điểm đã biết, bạn có thể ước tính thời gian hợp lý bằng cách sử dụng millis()
chức năng để tìm miliis giây kể từ khi khởi động.
Tôi đã làm một cái khác một lúc trước, đèn flash cứ sau vài giây:
Điều đó cũng tương tự. Bộ xử lý ở đó (lộn ngược dưới ổ cắm chip) và pin bên dưới. Mà nặng 6g. Pin đã kéo dài một vài năm và đèn flash cứ sau vài giây!
Thay vì đèn LED, bạn có thể có một nhiệt điện trở để đọc nhiệt độ.
Bạn có thể lập trình để đọc một vài giờ và lưu nó vào EEPROM. Sau đó, khi được hướng dẫn (ví dụ: bằng cách nối một vài chân), nó có thể xuất các số đọc sang một chân khác (thông qua nối tiếp).
Bạn có thể tiết kiệm trọng lượng hơn bằng cách sử dụng các thiết bị SMD (gắn trên bề mặt) và có thể sử dụng bảng mạch nhỏ mà bạn có thể tạo nên.
Mã
Mã cho định vị ngọn đuốc của tôi là dưới đây. Điều đáng quan tâm là thực tế là nó ngủ hầu hết thời gian. Nó cũng ngủ trong quá trình lấy mẫu ADC. Mặc dù trong trường hợp của tôi, tôi đang đo LDR (điện trở phụ thuộc ánh sáng), mã để đo điện trở nhiệt sẽ tương tự. Bạn chỉ cần thực hiện một số tính toán ở cuối để biến việc đọc thành nhiệt độ.
// 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