📣ความรู้ไปประยุกต์ใช้อุปกรณ์อิเล็กทรอนิกส์เพื่อสร้างสรรค์เป็นโครงงานตามที่โจทย์กำหนดได้วงจร
#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);
}
ไม่มีความคิดเห็น:
แสดงความคิดเห็น
ครูเต้ง เทคโนฯ