04/11/2567

ปีการศึกษา 2567 ภาคเรียนที่ 2 ชิ้นงานที่ 4 ครูเต้ง เทคโนฯ Infrared + lcd

  📣ความรู้ไปประยุกต์ใช้อุปกรณ์อิเล็กทรอนิกส์เพื่อสร้างสรรค์เป็นโครงงานตามที่โจทย์กำหนดได้วงจร


📣ความรู้ไปประยุกต์ใช้อุปกรณ์อิเล็กทรอนิกส์เพื่อสร้างสรรค์เป็นโครงงานตามที่โจทย์กำหนดได้คำสั่งเขียน 

#define IRRECEIVER_BUFFERSIZE 16

#define IRRECEIVER_STATE_IDLE 0

#define IRRECEIVER_STATE_START 1

#define IRRECEIVER_STATE_BITS 2

#define IRRECEIVER_STATE_REPEAT 3

typedef struct {

  unsigned int address;

  unsigned int command;

  byte rawBytes[4];

  bool repeat;

  bool error;

} IRdata;

class IRreceiver {

  public:

    IRreceiver(int pin);

    ~IRreceiver();

    int available(void);

    IRdata read(void);

    void flush(void);

 

    void onReceive(void (*)(int));

    static void pinActivity();

  private:

    static IRreceiver* receivers[14];

    static int pinStates[14];

    int pin;

    IRdata buffer[IRRECEIVER_BUFFERSIZE];

    unsigned int buffer_head;

    unsigned int buffer_tail;

    unsigned long prevTime;

    int state;

    char bitStream[32];

    int bitIndex;

    void (*user_onReceive)(int);

    void updateState(int pinValue);

    bool allowDuration(unsigned long duration, unsigned long expected);

    void decodeNECBits(void);

};

IRreceiver* IRreceiver::receivers[14] = {NULL};

int IRreceiver::pinStates[14] = {0};

IRreceiver::IRreceiver(int pinNumber):

  pin(pinNumber), buffer_head(0), buffer_tail(0), state(IRRECEIVER_STATE_IDLE), bitIndex(0)

{

  pinMode(pin, INPUT);

  pinStates[pin] = digitalRead(pin);

  if (receivers[pin] != NULL) delete receivers[pin];

  receivers[pin] = this;

  *digitalPinToPCMSK(pin) |= bit(digitalPinToPCMSKbit(pin)); 

  PCIFR  |= bit(digitalPinToPCICRbit(pin));

  PCICR  |= bit(digitalPinToPCICRbit(pin));

}

IRreceiver::~IRreceiver(){

  *digitalPinToPCMSK(pin) &= ~bit(digitalPinToPCMSKbit(pin));

}

int IRreceiver::available(void){

  return (IRRECEIVER_BUFFERSIZE + buffer_head - buffer_tail) % IRRECEIVER_BUFFERSIZE;

}

IRdata IRreceiver::read(void){

  IRdata result = {};

  if (buffer_head == buffer_tail){

    result.error = true;

  } else {

    result = buffer[buffer_tail];

    buffer_tail = (buffer_tail + 1) % IRRECEIVER_BUFFERSIZE;

  }

  return result;

}


void IRreceiver::flush(void){

  buffer_tail = buffer_head;

}

void IRreceiver::onReceive(void (*function)(int)){

  user_onReceive = function;

}

void IRreceiver::updateState(int value){

  unsigned long now = micros();

  unsigned long dur = now - prevTime;

  switch(state){

  case IRRECEIVER_STATE_IDLE:

      bitIndex = 0;

      if (value == 1 && dur > 5000) state = IRRECEIVER_STATE_START;

      break;

    case IRRECEIVER_STATE_START:

      if (value == 0){

        if (!allowDuration(dur, 9000)) state = IRRECEIVER_STATE_IDLE;

      } else {

        if (allowDuration(dur, 4500)) state = IRRECEIVER_STATE_BITS;

        else if (allowDuration(dur, 2250)) state = IRRECEIVER_STATE_REPEAT; 

        else state = IRRECEIVER_STATE_IDLE;

      }    

      break;

    case IRRECEIVER_STATE_BITS:

      if (value == 1){

        if (allowDuration(dur, 1690)){

          bitStream[bitIndex] = 1;

          bitIndex++;

        } else if (allowDuration(dur, 560)){

          bitStream[bitIndex] = 0;

          bitIndex++;

        } else state = IRRECEIVER_STATE_IDLE;   

      } else {

        if (allowDuration(dur, 560)){

          if(bitIndex == 32) {

          this->decodeNECBits();

          state = IRRECEIVER_STATE_IDLE;

          }

        } else state = IRRECEIVER_STATE_IDLE;

      }

  break;

    case IRRECEIVER_STATE_REPEAT:

      if (allowDuration(dur, 560)) this->decodeNECBits();

      state = IRRECEIVER_STATE_IDLE;

      break;

  }

  prevTime = now;

}                

bool IRreceiver::allowDuration(unsigned long duration, unsigned long expected){    

return (duration > expected*3/4 && duration < expected*5/4);

}                   

void IRreceiver::decodeNECBits(){

  IRdata result = {};

  if (bitIndex == 0) result.repeat = true;

  else {

    for (int i=0; i<bitIndex; i++){

      result.rawBytes[i>>3] |= bitStream[i] << (i&7);

    }

    result.address = result.rawBytes[0] | result.rawBytes[1] << 8;

    result.command = result.rawBytes[2];

    unsigned char commandInverse = ~result.rawBytes[3];

    if (result.rawBytes[2] != commandInverse) result.error = true;

  }

  int newHead = (buffer_head + 1) % IRRECEIVER_BUFFERSIZE;

  if (newHead != buffer_tail){

    buffer[buffer_head] = result;

  buffer_head = newHead;

  }

  if(user_onReceive){

    user_onReceive(this->available());

  }

}                 

void IRreceiver::pinActivity(){

  for (int i=0; i<14; i++){

    int value = digitalRead(i);

    if (value != pinStates[i] && receivers[i] != NULL && (*digitalPinToPCMSK(i) & bit(digitalPinToPCMSKbit(i)))){

    receivers[i]->updateState(!value);

    }

    pinStates[i]=value;

  }

}

ISR(PCINT0_vect){IRreceiver::pinActivity();}

ISR(PCINT1_vect){IRreceiver::pinActivity();}

ISR(PCINT2_vect){IRreceiver::pinActivity();}

#include <LiquidCrystal.h>

IRreceiver receiver(12);

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int led = 13;

void setup() {

  pinMode(led, OUTPUT);

  lcd.begin(16,2);

}

int count = 0;

void loop() {

  if (receiver.available()){

    digitalWrite(led, HIGH);

    IRdata data = receiver.read();

    if (!data.repeat) {

      lcd.clear();

      lcd.print("Button: ");

      lcd.print(data.command);

      lcd.setCursor(0,1);

      lcd.print("Address: ");

      lcd.print(data.address);

      count = 1;

    } else {

      count++;

      lcd.setCursor(11,0);

      lcd.print("x ");

      lcd.print(count);

    }

  } else {

    digitalWrite(led, LOW);

  }

  delay(100);           

}



ไม่มีความคิดเห็น:

แสดงความคิดเห็น

ครูเต้ง เทคโนฯ