#define LED_PIN 13
#define HCS_RECIEVER_PIN 2 // пин подключения приемника для брелков
#define RELAY_PIN 12 // пин подключения твердотельного реле
class HCS301 { // класс принятых данных
public:
unsigned BattaryLow: 1; // На брелке села батарейка
unsigned Repeat: 1; // повторная посылка
unsigned BtnNoSound: 1; // кнопка "Без звука"
unsigned BtnOpen: 1; // кнопка "Открыть"
unsigned BtnClose: 1; // кнопка "Закрыть"
unsigned BtnRing: 1; // кнопка "Звонок"
unsigned long SerialNum; // Серийный номер
unsigned long Encript; // Декодирование
void print(); // функция печати класса принятых данных
};
volatile boolean HCS_Listening = true;
byte HCS_preamble_count = 0;
uint32_t HCS_last_change = 0;
uint32_t HCS_start_preamble = 0;
uint8_t HCS_bit_counter; // счетчик считанных бит данных
uint8_t HCS_bit_array[66]; // массив считанных бит данных
#define HCS_TE 400 // типичная длительность имульса Te
#define HCS_Te2_3 600 // HCS_TE * 3 / 2
HCS301 hcs301;
#define HCS_DEBUG_
#ifdef HCS_DEBUG
uint16_t HCS_PulseDuration[12];
uint16_t HCS_BitDuration[66];
uint32_t HCS_msg_duration;
struct dta_ {
uint16_t delay;
byte f;
byte st;
};
volatile dta_ arr[1000];
volatile int poz_a = 0, poz_b = 0;
#endif //HCS_DEBUG
void HCS301::print(){ // функция печати класса принятых данных
|
|
String btn; // подстрока btn для вывода на печать
// если нажата кнопка "Звонок",
if (BtnRing == 1) btn += "Ring";// поместить "Ring" в подстроку вывода
if (BtnClose == 1) // если нажата кнопка "Закрыть",
{ btn += "Close"; // поместить "Close" в подстроку вывода
digitalWrite(RELAY_PIN, HIGH);}// Включение реле
if (BtnOpen == 1) // если нажата кнопка "Открыть",
{ btn += "Open"; // поместить "Open" в подстроку вывода
digitalWrite(RELAY_PIN, LOW);} // Выключение реле
if (BtnNoSound == 1) btn += "NoSound";//если нажата кн. "Без звука",
//помест. "NoSound" в подстроку выв
String it2; // строка it2 для вывода на печать
it2 += "Encript "; // поместить "Encript " в строку вывода
it2 += Encript; // поместить декодированный код в строку вывода
it2 += " Serial "; // поместить " Serial " в строку вывода
it2 += SerialNum; // поместить серийный номер в строку вывода
it2 += " ";
it2 += btn; // поместить подстроку btn в строку вывода
it2 += " BattaryLow="; // поместить " BattaryLow=" в строку вывода
it2 += BattaryLow; // поместить код разряда батареи в строку вывода
it2 += " Rep="; // поместить " Rep=" в строку вывода
it2 += Repeat; // поместить количество повторов в строку вывода
Serial.println(it2); // напечатать строку it2
}
void setup() { // начальная настройка
Serial.begin(9600); // скорость
attachInterrupt(0, HCS_interrupt, CHANGE);// прерывание
pinMode(LED_PIN, OUTPUT); // назначить выходной пин для светодиода
|
|
pinMode(RELAY_PIN, OUTPUT); // назначить выходной пин для реле
pinMode(HCS_RECIEVER_PIN, INPUT);//назначить вход. пин для приема
}
void loop() { // рабочий цикл
if(HCS_Listening == false){ // прослушка приемника завершена?
HCS301 msg; // сообщение для копии класса принятых данных
memcpy(&msg,&hcs301,sizeof(HCS301));// копируем принятые данные
msg.print(); // заполнить подстроку btn и строку it2 для вывода на печать
#ifdef HCS_DEBUG
if(msg.SerialNum!= 639){ // если серийный номер не равен 639
Serial.println("Raw >>>>>>>>>>>>>>>>>>>>>>>");
while(1){
if(poz_b == poz_a) break;
Serial.println(String(poz_b)+String(" ")+String(arr[poz_b].delay)+\
String(" ")+String(arr[poz_b].f == 0? "LOW":"HIGH")+String(" ")+\
String(arr[poz_b].st));
poz_b++;
}
Serial.println("Data >>>>>>>>>>>>>>>>>>>>>>>");
for(int i = 0;i<66;i++){ Serial.println(HCS_bit_array[i]); }// вывод массива
} else { } // битовых данных
poz_a = 0,poz_b = 0;
#endif //HCS_DEBUG
HCS_Listening = true; // продолжить прослушку приемника
}
}
void HCS_interrupt(){ // функция-обработчик прерывания
if(HCS_Listening == false){
return;
}
uint32_t cur_timestamp = micros(); // текущее время в микросекундах
uint8_t cur_status = digitalRead(HCS_RECIEVER_PIN); // состояние приема
uint32_t pulse_duration = cur_timestamp - HCS_last_change;
HCS_last_change = cur_timestamp; //для опр. продолжительности импульса
#ifdef HCS_DEBUG
if(poz_a < 999){
arr[poz_a].delay = pulse_duration; // продолжительность импульса
arr[poz_a].f = cur_status == HIGH? 0: 1;
poz_a++;
}
#endif //HCS_DEBUG
// ловим преамбулу
if(HCS_preamble_count < 12){ // количество импульсов преамбулы < 12?
if(cur_status == HIGH){
if(((pulse_duration > 200) && (pulse_duration < 400)) || HCS_preamble_count == 0){
// начало импульса преамбулы
if(HCS_preamble_count == 0){
HCS_start_preamble = cur_timestamp; //Отметить время старта
} // преамбулы
} else {
// преамбула не поймана - поймали мусор
//(неправильная пауза между импульсами)
HCS_preamble_count = 0;//сброс сч-ка пойманных импульсов преамбулы
goto exit;
}
} else {
// конец импульса преамбулы
if((pulse_duration > 400) && (pulse_duration < 600)){
#ifdef HCS_DEBUG
HCS_PulseDuration[HCS_preamble_count] = pulse_duration;
#endif //HCS_DEBUG
// поймали импульс преамбулы
HCS_preamble_count ++; //увеличить сч-к пойманных имп. преамбулы
#ifdef HCS_DEBUG
arr[poz_a-1].st = HCS_preamble_count;
#endif //HCS_DEBUG
if(HCS_preamble_count == 12){
// словили преамбулу
HCS_bit_counter = 0;
goto exit;
}
} else {
// преамбула не поймана - поймали мусор
HCS_preamble_count = 0; //сброс сч-ка пойманных импульсов преамбулы
goto exit;
}
}
}
// ловим данные
if(HCS_preamble_count == 12){
if(cur_status == HIGH){
if(((pulse_duration > 300) && (pulse_duration < 900)) || HCS_bit_counter == 0){
// начало импульса данных
} else {
// неправильная пауза между импульсами
HCS_preamble_count = 0;
goto exit;
}
} else {
// конец импульса данных
if((pulse_duration > 300) && (pulse_duration < 900)){
HCS_bit_array[65 - HCS_bit_counter] = (pulse_duration > HCS_Te2_3)? 0: 1;
// импульс больше, чем половина от Те * 3 поймали 0, иначе 1
#ifdef HCS_DEBUG
HCS_BitDuration[HCS_bit_counter] = pulse_duration;
#endif
HCS_bit_counter++;
#ifdef HCS_DEBUG
arr[poz_a-1].st = HCS_bit_counter;
#endif //HCS_DEBUG
if(HCS_bit_counter == 66){
// поймали все биты данных
HCS_Listening = false; //отключаем прослушку приемника и отправляем
// пойманные данные на обработку
HCS_preamble_count = 0;//сброс сч-ка пойманных имп. преамбулы
#ifdef HCS_DEBUG
HCS_msg_duration = cur_timestamp - HCS_start_preamble;
#endif //HCS_DEBUG
hcs301.Repeat = HCS_bit_array[0]; // заполнить класс принятых данных
hcs301.BattaryLow = HCS_bit_array[1]; // из битового массива
hcs301.BtnNoSound = HCS_bit_array[2];
hcs301.BtnOpen = HCS_bit_array[3];
hcs301.BtnClose = HCS_bit_array[4];
hcs301.BtnRing = HCS_bit_array[5];
hcs301.SerialNum = 0; // заполнить серийный номер
for(int i = 6; i < 34;i++){ //из битового массива
hcs301.SerialNum = (hcs301.SerialNum << 1) + HCS_bit_array[i];
};
uint32_t Encript = 0; // заполнить декодированный код
|
|
for(int i = 34; i < 66;i++){ //из битового массива
Encript = (Encript << 1) + HCS_bit_array[i];
};
hcs301.Encript = Encript;
}
} else {
// поймали мусор - отключаемся
HCS_preamble_count = 0;
goto exit;
}
}
}
exit:;
//digitalWrite(LED_PIN,cur_status); // вывод текущего состояния вычитки
} // приемника на светодиод
Примечание: Для вывода в MajorDomo дополнить программу HTTP-запросом:
char http_buf[120];
sprintf(http_buf, "GET
/objects/?script=easyRF&uid=%u&d0=%u&d1=%u&d2=%u HTTP/1.0",
(int)unique_device_id), (int)inv[0], (int)inv[1], (int)inv[2];
Serial.print(http_buf); // Выводим строку со ссылкой HTTP-запроса
Serial.println();
Приложение В