低い電力消費プロジェクトを作るために、
ATTiny85というマイクロコントローラーを勉強しています。
消費電力を抑えるためには、
マイクロコントローラーをスリープさせ、
インタラプトでマイクロコントローラーを起こすのが鍵です。
でも、ATTiny85は一つのピンインタラプトしかありません。
複数のピンで反応させるには、pin change interruptという方法が必要です。
Pin change interruptを可能にすれば、
ピンの電圧が変わると、インタラプトが発生します。
今回の例は二つのスイッチ(PB0とPB2につないである)によって、
どっちかがオープンになればLEDを点灯します。
まずは
GIMSK |= _BV(PCIE);
でpin change interruptを可能にします。
そして、インタラプトに使いたいピンを設定します。
PCMSK |= _BV(PCINT0); // PB0
PCMSK |= _BV(PCINT2); // PB2
次は使わないADCをオフに、スリープのモード()完全にパワーダウン)を設定します。
ADCSRA &= ~_BV(ADEN);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei();
そして、実際にスリープをさせます。
sleep_cpu();
で、起きたら、もとへ戻します。
サンプルコードはこれです。
#include <avr/sleep.h>
#include <avr/interrupt.h>
const int switchPin1 = 0;
const int switchPin2 = 2;
const int statusLED = 1;
void setup()
{
pinMode(switchPin1, INPUT);
pinMode(switchPin2, INPUT);
digitalWrite(switchPin1, HIGH);
digitalWrite(switchPin2, HIGH);
pinMode(statusLED, OUTPUT);
}
void sleep()
{
GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
PCMSK |= _BV(PCINT0); // Use PB0 as interrupt pin
PCMSK |= _BV(PCINT2); // Use PB2 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable(); // Sets the Sleep Enable bit
sei(); // Enable interrupts
sleep_cpu(); // sleep
cli(); // Disable interrupts
PCMSK &= ~_BV(PCINT0); // Turn off PB0 as interrupt pin
PCMSK &= ~_BV(PCINT2); / Turn off PB2 as interrupt pin
sleep_disable(); // Clear SE bit
ADCSRA |= _BV(ADEN); // ADC on
sei(); // Enable interrupts
}
ISR(PCINT0_vect) {
}
void loop()
{
sleep();
if(digitalRead(switchPin1) == HIGH) {
digitalWrite(statusLED, HIGH);
delay(1000);
digitalWrite(statusLED, LOW);
}
else
digitalWrite(statusLED, LOW);
if(digitalRead(switchPin2) == HIGH) {
digitalWrite(statusLED, HIGH);
delay(2000);
digitalWrite(statusLED, LOW);
}
else
digitalWrite(statusLED, LOW);
}
ATTiny85というマイクロコントローラーを勉強しています。
消費電力を抑えるためには、
マイクロコントローラーをスリープさせ、
インタラプトでマイクロコントローラーを起こすのが鍵です。
でも、ATTiny85は一つのピンインタラプトしかありません。
複数のピンで反応させるには、pin change interruptという方法が必要です。
Pin change interruptを可能にすれば、
ピンの電圧が変わると、インタラプトが発生します。
今回の例は二つのスイッチ(PB0とPB2につないである)によって、
どっちかがオープンになればLEDを点灯します。
まずは
GIMSK |= _BV(PCIE);
でpin change interruptを可能にします。
そして、インタラプトに使いたいピンを設定します。
PCMSK |= _BV(PCINT0); // PB0
PCMSK |= _BV(PCINT2); // PB2
次は使わないADCをオフに、スリープのモード()完全にパワーダウン)を設定します。
ADCSRA &= ~_BV(ADEN);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei();
そして、実際にスリープをさせます。
sleep_cpu();
cli();
PCMSK &= ~_BV(PCINT0);
PCMSK &= ~_BV(PCINT2);
sleep_disable();
ADCSRA |= _BV(ADEN);
sei();
PCMSK &= ~_BV(PCINT0);
PCMSK &= ~_BV(PCINT2);
sleep_disable();
ADCSRA |= _BV(ADEN);
sei();
サンプルコードはこれです。
#include <avr/sleep.h>
#include <avr/interrupt.h>
const int switchPin1 = 0;
const int switchPin2 = 2;
const int statusLED = 1;
void setup()
{
pinMode(switchPin1, INPUT);
pinMode(switchPin2, INPUT);
digitalWrite(switchPin1, HIGH);
digitalWrite(switchPin2, HIGH);
pinMode(statusLED, OUTPUT);
}
void sleep()
{
GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
PCMSK |= _BV(PCINT0); // Use PB0 as interrupt pin
PCMSK |= _BV(PCINT2); // Use PB2 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable(); // Sets the Sleep Enable bit
sei(); // Enable interrupts
sleep_cpu(); // sleep
cli(); // Disable interrupts
PCMSK &= ~_BV(PCINT0); // Turn off PB0 as interrupt pin
PCMSK &= ~_BV(PCINT2); / Turn off PB2 as interrupt pin
sleep_disable(); // Clear SE bit
ADCSRA |= _BV(ADEN); // ADC on
sei(); // Enable interrupts
}
ISR(PCINT0_vect) {
}
void loop()
{
sleep();
if(digitalRead(switchPin1) == HIGH) {
digitalWrite(statusLED, HIGH);
delay(1000);
digitalWrite(statusLED, LOW);
}
else
digitalWrite(statusLED, LOW);
if(digitalRead(switchPin2) == HIGH) {
digitalWrite(statusLED, HIGH);
delay(2000);
digitalWrite(statusLED, LOW);
}
else
digitalWrite(statusLED, LOW);
}
0 件のコメント:
コメントを投稿