chottoshitahanashi’s diary

基本的に間違ったことばかり書いてるブログ。検索ひっかかるな

CO2コード改良

ATTiny13Aにはタイマーが一つしかなくてのでLED blinkのために調整するとdelay()が影響を受けて計算が面倒/コードが煩雑になるのでdelay()をなくした。Arduino UNOとATTiny13Aでコードを共通化させた。スリープ機能を使った・・と思う。スリープとATTiny13Aの分周についてもちゃんと調べねば。ハードウェアやるつもりが組み込みソフトやってるけどまあいいか、楽しいから。


昨日まで大丈夫だったのに今朝動かすとCO2濃度1300ppmとかあり得ない数値出たんでてっきりバグかと思って数時間頑張ってたら結局風呂場の換気扇を動かしてなかったからだった。

// #include<avr/io.h>
// #include<avr/wdt.h>
// #include <avr/interrupt.h>
#include <avr/sleep.h>

#ifdef ARDUINO_AVR_UNO
#define PWM_PIN A5
#define LED_PIN1 3
#define LED_PIN2 4
#define LED_PIN3 5
#define LED_PIN4 6
#define LED_PIN5 7
#else
#define PWM_PIN A0
#define LED_PIN1 0
#define LED_PIN2 1
#define LED_PIN3 2
#define LED_PIN4 3
#define LED_PIN5 4
#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(LED_PIN5, 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
  DDRB     = 0b00000001;//PORTB出力設定
  PORTB    = 0b00000000;//PORTB_LOW
  TCCR0A   = 0b00000010;//CTC
  TCCR0B   = 0b00000101;//1024分周
  OCR0A    = 117;//0.0998sec
  TIMSK0  |= 0b00000100;//比較A割り込み
#endif

  set_sleep_mode(SLEEP_MODE_IDLE);
  sei();
}

long ppm;
int isLedOn = false;
int ledInterval = 200;
int timer = 0;

void loop()
{
  sleep_mode();
}

int lowCount = 0;
int highCount = 0;
int prevValue = LOW;

#ifdef ARDUINO_AVR_UNO
ISR(TIMER2_COMPA_vect)
{
#else
ISR(TIM0_COMPA_vect)
{
#endif

  int pwmValue = digitalRead(PWM_PIN);

  if (pwmValue == HIGH)
  {
    if (prevValue == pwmValue)
    {
      ++highCount;
    }
    else
    {
      ppm = 5000 * float((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);
  digitalWrite(LED_PIN4, LOW);
  digitalWrite(LED_PIN5, LOW);

  ledInterval = 1000;
  if (ppm > 1000)
  {
    digitalWrite(LED_PIN5, HIGH);
    ledInterval = 200;
  }
  else if (ppm > 900)
  {
    digitalWrite(LED_PIN5, isLedOn);
  }
  else if (ppm > 800)
  {
    digitalWrite(LED_PIN4, isLedOn);
  }
  else if (ppm > 700)
  {
    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;
  }
}

実演
www.youtube.com