www.youtube.com
// #include<avr/io.h>
// #include<avr/wdt.h>
// #include <avr/interrupt.h>
#include <avr/sleep.h>
#ifdef ARDUINO_AVR_UNO
#define PWM_PIN A0
#define LED_PIN1 3 // 1, 2 for Serial
#define LED_PIN2 4
#define LED_PIN3 5
#define LED_PIN4 6
#else
#define PWM_PIN 4
#define LED_PIN1 0
#define LED_PIN2 1
#define LED_PIN3 2
#define LED_PIN4 3
#endif
void setup()
{
#ifdef ARDUINO_AVR_UNO
Serial.begin(9600);
#endif
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
pinMode(LED_PIN3, OUTPUT);
pinMode(LED_PIN4, OUTPUT);
pinMode(PWM_PIN, INPUT);
#ifdef ARDUINO_AVR_UNO
TCCR2A = (1<<WGM21); // CTC mode
TCCR2B = (1<<CS22); // 64 Division
OCR2A = 250 - 1; // 1ms
TIMSK2 |= (1 << OCIE2A);
#else
// WGM02 WGM01 WGM00
// モード CTCとかPWMとか。
// CTCではカウンタレジスタTCNT0とOCR0Aが一致するとカウンタリセット
// CS02 CS01 CS00
// 分周
// OCIE0B OCIE0A
// タイマ/カウンタ比較B, A割り込み許可。
// CTCではOCR0Aが使われるのにOCIE0Bがあるのはと思ったがCTCはカウンタリセットのみで、
// 割り込みタイミングとは別ということか?
// CTCでOCIE0BセットならカウンタリセットにはOCR0Aが、割り込みにはOCIE0Bが使われると予想(要確認)
// TOIE0
// タイマ/カウンタオーバーフロー割り込み許可
// FOCOA FOCOA
// 強制コンペアマッチ、たぶんセットした瞬間に割り込み発生
// 動作クロック1.2MHz (9.6MHzをFUSE設定で8分周=1.2)
// クロック当たり1.0/(1.2*1.0e6)秒、8分周すると1.0/(1.2*1.0e6)*8秒でカウントアップ
// 75カウントで割り込みをかけると1.0/(1.2*1.0e6)*8*150=0.001秒で割り込み
TCCR0A = 0b00000010; // COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00
TCCR0B = 0b00000010; // FOC0A FOC0B - - WGM02 CS02 CS01 CS00.
OCR0A = 150 - 1; // 0.001 sec
TIMSK0 = 0b00000100; // - - - - OCIE0B OCIE0A TOIE0 0 : タイマ/カウンタ比較A割り込み許可
#endif
set_sleep_mode(SLEEP_MODE_IDLE);
sei();
}
long ppm;
int isLedOn = false;
int ledInterval = 200;
int timer = 0;
bool buzzer = false;
void loop()
{
sleep_mode();
}
long lowCount = 0;
long highCount = 0;
int prevValue = LOW;
#ifdef ARDUINO_AVR_UNO
ISR(TIMER2_COMPA_vect)
{
#else
ISR(TIM0_COMPA_vect)
{
#endif
if (buzzer)
{
digitalWrite(LED_PIN4, !digitalRead(LED_PIN4));
}
else
{
digitalWrite(LED_PIN4, LOW);
}
int pwmValue = digitalRead(PWM_PIN);
if (pwmValue == HIGH)
{
if (prevValue == pwmValue)
{
++highCount;
}
else
{
ppm = 5000 * (highCount - 2) / (lowCount + highCount - 4);
#ifdef ARDUINO_AVR_UNO
Serial.println(ppm);
#endif
lowCount = 0;
highCount = 0;
}
}
else
{
++lowCount;
}
prevValue = pwmValue;
++timer;
if (timer > ledInterval)
{
timer = 0;
userDisplay();
}
}
void userDisplay()
{
isLedOn = !isLedOn;
digitalWrite(LED_PIN1, LOW);
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN3, LOW);
ledInterval = 1000;
buzzer = false;
if (ppm > 1000)
{
buzzer = true;
}
else if (ppm > 800)
{
digitalWrite(LED_PIN3, isLedOn);
}
else if (ppm > 600)
{
digitalWrite(LED_PIN2, isLedOn);
}
else if (ppm > 500)
{
digitalWrite(LED_PIN1, isLedOn);
}
else
{
digitalWrite(LED_PIN1, isLedOn);
ledInterval = (isLedOn)? 1000 : 3000;
}
}