да там что то не понятное. блинк заливаетсяна ура и через usbasp и через ардуино. а как заливаю копир,то тинька зависает,даже на кнопку не реагирует. залил этот же скетч на ардуино, все работает, все копирует. кстати на ардуино про мини тоже не заливается. добился при заливке аттини не одной ошибки компиляции, а при заливки мини, ошибка что то там про sck
а вы частоту-то тиньке поднимаете? По умолчанию они прошиты под 1 МГц - на такой частоте ONeWire скорее всего виснет
мне этот копир не нужен, я просто для себя решил китайцов обогнуть. уних копир с размером пульта ду, а тут с пробку. я в прошлом году хотел,или в маркер широкий или в зажигалку уместить. на про мини собрал. все работало только через программатор, а без не работает
достаточно правильно выставить частоту в двух местах - в ИДЕ и во фьюзах. Все остальное подкорректируется само (если конечно у вас код не на ассемблере :)
код написан на ардуиноide , взят тут во время проекторования. успел урвать рабочий. читает, пишет, выводит на мониторпорта. на ардуино работает. может просто тинька команду какую нибудь не понимает, у нее же своя, порты, пины
код написан на ардуиноide , взят тут во время проекторования. успел урвать рабочий. читает, пишет, выводит на мониторпорта. на ардуино работает. может просто тинька команду какую нибудь не понимает, у нее же своя, порты, пины
может и команду. Но перешить на 9.6МГц - это одна минута. я бы попробовал
эх, я уже бредброд разобрал. но завтра соберу обратно. только уже решил вместо батереи устанивоить usbmicro от телефона. батарея сядет со временем, а тут и место не занимает и зарядник всегда рядом. до завтра
9.6мгц толькона аттини13 всавиться,а на у меня только или1 или8. на 8 не прокатило, тинька также зависла,апри загрузке ошибва что то про BS2 . не смог скопировать. может это потому что я использую ide105
Для себя написал следующий код (редактировать лень):
Конструктивные замечания приветствую.
это называется "когда коту делать нечего..."
Функции USART_Init, String, Hex и тд - в классе Serial заменяются одной строчкой. Писать в Ардуино ИДЕ и работать с USART через регистры - тупой и бессмысленный снобизм :)
Не удивлюсь, если собственно запись на болванку еще и не работает :)
Функции USART_Init, String, Hex и тд - в классе Serial заменяются одной строчкой.
Конечно заменяются. Сравним?
сравнили? - выиграли 1000 байт флеша,? - рады?
А теперь сравните вот что - первый код без малейших изменений будет работать на Уно, Меге, Дуе и СТМ32. А ваш?
Выигрывая в размере кода - вы потеряли в переносимости, простоте и наглядности. Если бы в этом был хоть какой-то смысл - например при нехватке места - вы были бы молодец. Но весь ваш код даже в формате Ардуино ИДЕ вряд ли займет хотя бы 20% свободного флеша Атмеги328. Так что остаюсь при своем мнении - это пустое и глупое выеживание на ровном месте.
А то что болванки пишутся - искренне рад. Это неожиданно. Обычно те, кто любит использовать низкоуровневые операторы без нужды - банально не умеют программировать высоуровневым кодом.
Я глубоко уважаю Ваше мнение. Если Вам претит низкоуровневое программирование, то, пожалуйста оставьте это при себе. Скетч был написан под платы на Atmega328. И написан на языке долеко от низкоуровнего - ассемблера. Если Вы просмотрели скетч до конца, то последние строки для UNO:
Скетч использует 2054 байт (6%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 19 байт (0%) динамической памяти, оставляя 2029 байт для локальных переменных. Максимум: 2048 байт.
Причем это лишь часть программного кода моего проекта, где еще используются другие модули, EEPROM. Поэтому ставка на размер кода. А сам скетч легко переписывается для переносимости, простоты и наглядности и наша с Вами полемика уводит в сторону от темы этой ветки форума.
timurtanum - чтобы добавить в этот код "поддержку других домофонов", как вы выразились - надо иметь подробное описание протокола считывания и записи ключей этого формата. А фирмы, делающие домофоны, как-то не очень хотят делится этой информацией.
Поэтому энутзиасты собирают информацию по кусочкам и пытаются написать программы. Например в комментариях в вашем скетче упоминаются ключи форматов RW-1990.1, RW-1990.2, TM-2004, TM-01, T5557, Цифрал а также RFID формата EM-Marine
Только "обещать - не значит женится", не думаю. что этот код умеет работать со всеми этими ключами.
Доброго времени суток . у вас есть возможность протестировать rfid метки которые уже записаны в программу ? мне просто интересно знать эта программа работает с rfid ьетками или нет .
да там что то не понятное. блинк заливаетсяна ура и через usbasp и через ардуино. а как заливаю копир,то тинька зависает,даже на кнопку не реагирует. залил этот же скетч на ардуино, все работает, все копирует. кстати на ардуино про мини тоже не заливается. добился при заливке аттини не одной ошибки компиляции, а при заливки мини, ошибка что то там про sck
а вы частоту-то тиньке поднимаете? По умолчанию они прошиты под 1 МГц - на такой частоте ONeWire скорее всего виснет
мне этот копир не нужен, я просто для себя решил китайцов обогнуть. уних копир с размером пульта ду, а тут с пробку. я в прошлом году хотел,или в маркер широкий или в зажигалку уместить. на про мини собрал. все работало только через программатор, а без не работает
да на 1мгц. на другой делай коректировать надо
да на 1мгц. на другой делай коректировать надо
достаточно правильно выставить частоту в двух местах - в ИДЕ и во фьюзах. Все остальное подкорректируется само (если конечно у вас код не на ассемблере :)
я фьюзы не трогал. я четез ардуиноIDE заливаю
код написан на ардуиноide , взят тут во время проекторования. успел урвать рабочий. читает, пишет, выводит на мониторпорта. на ардуино работает. может просто тинька команду какую нибудь не понимает, у нее же своя, порты, пины
я четез ардуиноIDE заливаю
я тоже . И фьюзы тоже через Ардуино ИДЕ
код написан на ардуиноide , взят тут во время проекторования. успел урвать рабочий. читает, пишет, выводит на мониторпорта. на ардуино работает. может просто тинька команду какую нибудь не понимает, у нее же своя, порты, пины
может и команду. Но перешить на 9.6МГц - это одна минута. я бы попробовал
эх, я уже бредброд разобрал. но завтра соберу обратно. только уже решил вместо батереи устанивоить usbmicro от телефона. батарея сядет со временем, а тут и место не занимает и зарядник всегда рядом. до завтра
9.6мгц толькона аттини13 всавиться,а на у меня только или1 или8. на 8 не прокатило, тинька также зависла,апри загрузке ошибва что то про BS2 . не смог скопировать. может это потому что я использую ide105
Для себя написал следующий код (редактировать лень):
/*****************************************************************************************/ /* \\\|/// */ /* \\ - - // */ /* ( @ @ ) */ /* /--------------------oOOo-(_)-oOOo--------------------\ */ /* | | */ /* | Простой копировщик ключей TouchMemory на Arduino | */ /* | | */ /* | [___]---------> GND (-5V) | */ /* | | ___ | */ /* | }---|___|---> Vcc (+5V) | */ /* | | 4,7 KOm | */ /* | }-----------> PIN 7 (Arduino UNO, | */ /* | Nano, | */ /* | Oooo Pro Mini, etc.) | */ /* \---------------------oooO---( )--------------------/ */ /* ( ) ) / */ /* \ ( (_/ */ /* \_) */ /* */ /* Среда разработки: Arduino IDE v1.8.8 */ /* Плата: Arduino UNO (Китай) */ /* © NEOGAR.2019 */ /*****************************************************************************************/ #include <avr/pgmspace.h> #define number_of_messages 10 #define max_size_of_message 53 #define msg1 ((const char *) &messages[0]) // "Ready!" #define msg2 ((const char *) &messages[1]) // "Help: R - reading ID, W - writing new ID, C - cancel" #define msg3 ((const char *) &messages[2]) // "Reading ID..." #define msg4 ((const char *) &messages[3]) // "Writing new ID..." #define msg5 ((const char *) &messages[4]) // "Cancel" #define msg6 ((const char *) &messages[5]) // "Key ID:" #define msg7 ((const char *) &messages[6]) // "New key ID:" #define msg8 ((const char *) &messages[7]) // " 0x" #define msg9 ((const char *) &messages[8]) // "Error reading! Try again" #define msg10 ((const char *) &messages[9]) // "CRC is not valid!" const char messages [number_of_messages] [max_size_of_message] PROGMEM = { {"Ready!"}, {"Help: R - reading ID, W - writing new ID, C - cancel"}, {"Reading ID..."}, {"Writing new ID..."}, {"Cancel"}, {"Key ID:"}, {"New key ID:"}, {" 0x"}, {"Error reading! Try again"}, {"CRC is not valid!"}, }; uint8_t addr[8]; volatile uint8_t state = 0x00; /*****************************************************************************************/ /* Значения регистра state */ /*****************************************************************************************/ #define cmd_cancel 0x00 // Отмена команд #define read_key 0x01 // Команда на считывание ID ключа. Ожидание ключа (отменяется вводом "C") #define write_key 0x02 // Команда на запись ID ключа. Ожидание ключа (отменяется вводом "C") uint8_t err = 0x00; /*****************************************************************************************/ /* Значения регистра err */ /*****************************************************************************************/ #define err_id 0x01 // Ошибка считывания ID ключа #define err_crc 0x02 // Ошибка CRC ключа /*****************************************************************************************/ /* Функция инициализации последовательного порта */ /*****************************************************************************************/ void USART_Init (void) { UBRR0 = 0x67; // Serial.begin(9600); UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0); } /*****************************************************************************************/ /* Функция передачи данных через последовательный порт */ /*****************************************************************************************/ void USART_Transmit (uint8_t data) { while (!(UCSR0A & (1 << UDRE0))); UDR0 = data; } /*****************************************************************************************/ /* Функция вывода строки через последовательный порт */ /*****************************************************************************************/ void USART_String (const char *str, uint8_t new_str) { char out_char; if (!str) { return; } while ((out_char = pgm_read_byte(str++))) { USART_Transmit(out_char); } if (new_str) { USART_Transmit(0x0A); // Переход на новую строку (\n, LF) } } /*****************************************************************************************/ /* Функция конвертирования шестнадцатеричных чисел в символы ASCII */ /*****************************************************************************************/ void USART_HEX (uint8_t nibble_high) { uint8_t array_simbol[2]; uint8_t counter = 2; uint8_t nibble_low = nibble_high; array_simbol[0] = (((nibble_high &= 0x0F) <= 9) ? (nibble_high + 0x30) : (nibble_high + 0x41 - 10)); array_simbol[1] = (((nibble_low >>= 4 ) <= 9) ? (nibble_low + 0x30) : (nibble_low + 0x41 - 10)); while (counter--) { USART_Transmit(array_simbol[counter]); } } /*****************************************************************************************/ /* Функция приема команд через последовательный порт */ /*****************************************************************************************/ ISR (USART_RX_vect) { switch (UDR0) { case (0x52): { // "R" USART_String(msg3, 1); // "Reading ID..." state = read_key; } break; case (0x57): { // "W" USART_String(msg4, 1); // "Writing new ID..." state = write_key; } break; case (0x43): { // "C" if (state) { USART_String(msg5, 1); // "Cancel" USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" state = cmd_cancel; } } break; } } /*****************************************************************************************/ /* Функция передачи импульса сброса по шине 1-Wire */ /*****************************************************************************************/ bool OneWire_Reset (void) { uint8_t presence; PORTD &= ~(1 << 7); // digitalWrite(7, LOW); DDRD |= (1 << 7); // pinMode(7, OUTPUT); _delay_us(480); // delayMicroseconds(480); DDRD &= ~(1 << 7); // pinMode(7, INPUT); _delay_us(70); // delayMicroseconds(70); presence = (PIND & (1 << 7)); // digitalRead(7); _delay_us(410); // delayMicroseconds(410); return presence; } /*****************************************************************************************/ /* Функция записи данных по шине 1-Wire */ /*****************************************************************************************/ void OneWire_Write (uint8_t wrt_byte) { uint8_t i = 0; DDRD |= (1 << 7); // pinMode(7, OUTPUT); while (i < 8) { if (wrt_byte & 1) { // Запись "1" PORTD &= ~(1 << 7); // digitalWrite(7, LOW); _delay_us(10); // delayMicroseconds(10); } else { // Запись "0" PORTD &= ~(1 << 7); // digitalWrite(7, LOW); _delay_us(60); // delayMicroseconds(60); } PORTD |= (1 << 7); // digitalWrite(7, HIGH); _delay_ms(5); // delay(5); wrt_byte >>= 1; i++; } } /*****************************************************************************************/ /* Функция приема данных по шине 1-Wire и их записи в массив addr */ /*****************************************************************************************/ void OneWire_Read (void) { uint8_t i; OneWire_Reset(); OneWire_Write(0x33); for (i = 0; i < 8; i++) { uint8_t bitMask; uint8_t rd_bit; uint8_t rd_byte = 0; for (bitMask = 0x01; bitMask; bitMask <<= 1) { PORTD &= ~(1 << 7); // digitalWrite(7, LOW); DDRD |= (1 << 7); // pinMode(7, OUTPUT); _delay_us(6); // delayMicroseconds(6); DDRD &= ~(1 << 7); // pinMode(7, INPUT); _delay_us(9); // delayMicroseconds(9); rd_bit = (PIND & (1 << 7)); // digitalRead(7); _delay_us(55); // delayMicroseconds(55); if (rd_bit) { rd_byte |= bitMask; } } addr[i] = rd_byte; } } /*****************************************************************************************/ /* Функция проверки считываемого ID ключа */ /*****************************************************************************************/ bool iButton_Check_ID (void) { uint8_t i; uint8_t addr_temp[8]; for (i = 0; i < 8; i++) { addr_temp[i] = addr[i]; } OneWire_Read(); for (i = 0; i < 8; i++) { if (addr_temp[i] != addr[i]) { USART_String(msg9, 1); // "Error reading! Try again" err = err_id; return 0; // Ошибка считывания ID ключа } else { return 1; // Успешное считывание ID ключа } } } /*****************************************************************************************/ /* Функция проверки контрольной суммы ID ключа */ /*****************************************************************************************/ bool iButton_Checksum (uint8_t *addr) { uint8_t addrsvn = addr[7]; uint8_t len = 7; uint8_t crc = 0; uint8_t inbyte; uint8_t i; uint8_t mix; while (len--) { inbyte = *addr++; for (i = 8; i; i--) { mix = (crc ^ inbyte) & 0x01; crc >>= 1; if (mix) crc ^= 0x8C; inbyte >>= 1; } } if (crc != addrsvn) { USART_String(msg10, 1); // "CRC is not valid!" err = err_crc; return 0; // Ошибка CRC ключа } else { return 1; // Правильный CRC ключа } } /*****************************************************************************************/ /* Функция считывания ID ключа */ /*****************************************************************************************/ void iButton_Read (void) { uint8_t i; if (OneWire_Reset()) { return; } OneWire_Read(); if (!iButton_Check_ID() || !iButton_Checksum(addr)) { USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" state = cmd_cancel; return; } USART_String(msg6, 0); // "Key ID:" for (i = 0; i < 8; i++) { USART_String(msg8, 0); // " 0x" USART_HEX(addr[i]); } USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" err = cmd_cancel; state = cmd_cancel; } /*****************************************************************************************/ /* Функция записи ID ключа */ /*****************************************************************************************/ void iButton_Write (void) { uint8_t i; if (err == err_id) { USART_String(msg9, 1); // "Error reading! Try again" USART_String(msg5, 1); // "Cancel" USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" state = cmd_cancel; return; } if (err == err_crc) { USART_String(msg10, 1); // "CRC is not valid!" USART_String(msg5, 1); // "Cancel" USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" state = cmd_cancel; return; } if (OneWire_Reset()) { return; } OneWire_Reset(); OneWire_Write(0xD1); // Начать запись RW-1990.1 (для RW1990.2 команда "0x1D") OneWire_Write(0x00); OneWire_Reset(); OneWire_Write(0xD5); // Команда на запись RW-1990.1 for (i = 0; i < 8; i++) { // Запись 8-байтного кода OneWire_Write(~addr[i]); // Для RW1990.1 все биты инвертированы (для RW1990.2: OneWire_Write(addr[i]);) } OneWire_Reset(); OneWire_Write(0xD1); // Закончить запись RW-1990.1 (для RW1990.2 команда "0x1D") OneWire_Write(0x01); OneWire_Read(); if (!iButton_Check_ID() || !iButton_Checksum(addr)) { USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" return; } USART_String(msg7, 0); // "New key ID:" for (i = 0; i < 8; i++) { USART_String(msg8, 0); // " 0x" USART_HEX(addr[i]); } USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" state = cmd_cancel; } void setup (void) { uint8_t i; USART_Init(); USART_String(msg1, 1); // "Ready!" USART_Transmit(0x0A); // Переход на новую строку (\n, LF) USART_String(msg2, 1); // "Help: R - reading ID, W - writing new ID, C - cancel" USART_String(msg6, 0); // "Key ID:" for (i = 0; i < 8; i++) { USART_String(msg8, 0); // " 0x" USART_HEX(addr[i]); } USART_Transmit(0x0A); // Переход на новую строку (\n, LF) sei(); } void loop (void) { switch (state) { case (read_key): { iButton_Read(); } break; case (write_key): { iButton_Write(); } break; } _delay_ms(30); } // Скетч использует 2054 байт (6%) памяти устройства. Всего доступно 32256 байт. // Глобальные переменные используют 19 байт (0%) динамической памяти, оставляя 2029 байт для локальных переменных. Максимум: 2048 байт.Скачать можно по ссылке https://yadi.sk/d/lnBduz6H0PYhZQ
Конструктивные замечания приветствую.
Оговорился: state и err - переменные.
Для себя написал следующий код (редактировать лень):
Конструктивные замечания приветствую.
это называется "когда коту делать нечего..."
Функции USART_Init, String, Hex и тд - в классе Serial заменяются одной строчкой. Писать в Ардуино ИДЕ и работать с USART через регистры - тупой и бессмысленный снобизм :)
Не удивлюсь, если собственно запись на болванку еще и не работает :)
Функции USART_Init, String, Hex и тд - в классе Serial заменяются одной строчкой.
Конечно заменяются. Сравним?
void setup() { Serial.begin(9600); Serial.print('a'); } void loop() { } // Скетч использует 1452 байт (4%) памяти устройства. Всего доступно 32256 байт. // Глобальные переменные используют 184 байт (8%) динамической памяти, оставляя 1864 байт для локальных переменных. Максимум: 2048 байт.И такой:
void setup() { UBRR0 = 0x67; // Serial.begin(9600); UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0); while (!(UCSR0A & (1 << UDRE0))); UDR0 = 'b'; // Serial.print('b'); } void loop() { } // Скетч использует 476 байт (1%) памяти устройства. Всего доступно 32256 байт. // Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.Это я к вопросу о регистрах.
Писать в Ардуино ИДЕ и работать с USART через регистры - тупой и бессмысленный снобизм :)
Только никому больше этого не говорите!
это называется "когда коту делать нечего..."
Это называется дать ответ на поставленный вопрос.
Спрашивайте, если в коде что-то непонятно.
И да, китайские болванки пишутся "на ура".
Функции USART_Init, String, Hex и тд - в классе Serial заменяются одной строчкой.
Конечно заменяются. Сравним?
сравнили? - выиграли 1000 байт флеша,? - рады?
А теперь сравните вот что - первый код без малейших изменений будет работать на Уно, Меге, Дуе и СТМ32. А ваш?
Выигрывая в размере кода - вы потеряли в переносимости, простоте и наглядности. Если бы в этом был хоть какой-то смысл - например при нехватке места - вы были бы молодец. Но весь ваш код даже в формате Ардуино ИДЕ вряд ли займет хотя бы 20% свободного флеша Атмеги328. Так что остаюсь при своем мнении - это пустое и глупое выеживание на ровном месте.
А то что болванки пишутся - искренне рад. Это неожиданно. Обычно те, кто любит использовать низкоуровневые операторы без нужды - банально не умеют программировать высоуровневым кодом.
Народ, скиньте рабочий скетч для создания универсального ключа от всех домофонов если есть таковой?
Болванка rw1990
Народ, скиньте рабочий скетч для создания универсального ключа от всех домофонов если есть таковой?
нет такого (универсального ключа)
я обслуживаю домофоны. домофон открывает дверь, только тем ключем, которые записали в него. или копии этих ключей. универсальный ключ это миф.
кстати я заметил, что пустые ячейки памяти заполнены FF
Доброго времени суток . нашел дубликатор домофонных ключей . на болванки RW1990 и т.д читает пишет данный девайс . на 125 mHz нашел только карточку с кодом mifare . если кому не сложно , подкскажите как добавить новые домофоны в эту прошивку ? кто разбирается как добавить новые протоколы для чтение разных карт от домофонов . заранее спасибо #include <OneWire.h> #include "pitches.h" #define CheckL 0 // для настройки катушки временно установите тут единицу #define iButtonPin A3 // Линия data ibutton #define R_Led 2 // RGB Led #define G_Led 3 #define B_Led 4 #define VRpinGnd 5 // Земля подстроечного резистора для аналогового компаратора #define ACpin 6 // Вход Ain0 аналогового компаратора для EM-Marie #define BtnPin 8 // Кнопка переключения режима чтение/запись #define BtnPinGnd 9 // Земля кнопки переключения режима #define speakerPin 10 // Спикер, он же buzzer, он же beeper #define FreqGen 11 // генератор 125 кГц #define speakerPinGnd 12 // земля Спикера #define rfidBitRate 2 // Скорость обмена с rfid в kbps #define rfidUsePWD 0 // ключ использует пароль для изменения #define rfidPWD 123456 // пароль для ключа OneWire ibutton (iButtonPin); byte addr[8]; // временный буфер byte keyID[8]; // ID ключа для записи byte rfidData[5]; // значащие данные frid em-marine bool readflag = false; // флаг сигнализирует, что данные с ключа успечно прочианы в ардуино bool writeflag = false; // режим запись/чтение bool preBtnPinSt = HIGH; enum emRWType {rwUnknown, TM01, RW1990_1, RW1990_2, TM2004, T5557, EM4305}; // тип болванки enum emkeyType {keyUnknown, keyDallas, keyTM2004, keyCyfral, keyMetacom, keyEM_Marie}; // тип оригинального ключа emkeyType keyType; void setup() { pinMode(BtnPin, INPUT_PULLUP); // включаем чтение и подягиваем пин кнопки режима к +5В pinMode(BtnPinGnd, OUTPUT); digitalWrite(BtnPinGnd, LOW); // подключаем второй пин кнопки к земле pinMode(speakerPin, OUTPUT); pinMode(speakerPinGnd, OUTPUT); digitalWrite(speakerPinGnd, LOW); // подключаем второй пин спикера к земле pinMode(ACpin, INPUT); // Вход аналогового компаратора для ключей RFID и аналоговых ключей Cyfral / Metacom pinMode(VRpinGnd, OUTPUT); digitalWrite(VRpinGnd, LOW); // подключаем пин подстроечного резистора к земле pinMode(R_Led, OUTPUT); pinMode(G_Led, OUTPUT); pinMode(B_Led, OUTPUT); //RGB-led clearLed(); pinMode(FreqGen, OUTPUT); digitalWrite(B_Led, HIGH); //awaiting of origin key data Serial.begin(115200); Sd_StartOK(); } void clearLed(){ digitalWrite(R_Led, LOW); digitalWrite(G_Led, LOW); digitalWrite(B_Led, LOW); } //*************** dallas ************** emRWType getRWtype(){ byte answer; // TM01 это неизвестный тип болванки, делается попытка записи TM-01 без финализации для dallas или c финализацией под cyfral или metacom // RW1990_1 - dallas-совместимые RW-1990, RW-1990.1, ТМ-08, ТМ-08v2 // RW1990_2 - dallas-совместимая RW-1990.2 // TM2004 - dallas-совместимая TM2004 в доп. памятью 1кб // пробуем определить RW-1990.1 ibutton.reset(); ibutton.write(0xD1); // проуем снять флаг записи для RW-1990.1 ibutton.write_bit(1); // записываем значение флага записи = 1 - отключаем запись delay(10); pinMode(iButtonPin, INPUT); ibutton.reset(); ibutton.write(0xB5); // send 0xB5 - запрос на чтение флага записи answer = ibutton.read(); //Serial.print("\n Answer RW-1990.1: "); Serial.println(answer, HEX); if (answer == 0xFE){ Serial.println(" Type: dallas RW-1990.1 "); return RW1990_1; // это RW-1990.1 } // пробуем определить RW-1990.2 ibutton.reset(); ibutton.write(0x1D); // пробуем установить флаг записи для RW-1990.2 ibutton.write_bit(1); // записываем значение флага записи = 1 - включаем запись delay(10); pinMode(iButtonPin, INPUT); ibutton.reset(); ibutton.write(0x1E); // send 0x1E - запрос на чтение флага записи answer = ibutton.read(); if (answer == 0xFE){ ibutton.reset(); ibutton.write(0x1D); // возвращаем оратно запрет записи для RW-1990.2 ibutton.write_bit(0); // записываем значение флага записи = 0 - выключаем запись delay(10); pinMode(iButtonPin, INPUT); Serial.println(" Type: dallas RW-1990.2 "); return RW1990_2; // это RW-1990.2 } // пробуем определить TM-2004 ibutton.reset(); ibutton.write(0x33); // посылаем команду чтения ROM для перевода в расширенный 3-х байтовый режим for ( byte i=0; i<8; i++) ibutton.read(); // читаем данные ключа ibutton.write(0xAA); // пробуем прочитать регистр статуса для TM-2004 ibutton.write(0x00); ibutton.write(0x00); // передаем адрес для считывания answer = ibutton.read(); // читаем CRC комманды и адреса byte m1[3] = {0xAA, 0,0}; // вычисляем CRC комманды if (OneWire::crc8(m1, 3) == answer) { answer = ibutton.read(); // читаем регистр статуса //Serial.print(" status: "); Serial.println(answer, HEX); Serial.println(" Type: dallas TM2004"); ibutton.reset(); return TM2004; // это Type: TM2004 } ibutton.reset(); Serial.println(" Type: dallas unknown, trying TM-01! "); return TM01; // это неизвестный тип DS1990, нужно перебирать алгоритмы записи (TM-01) } bool write2iBtnTM2004(){ // функция записи на TM2004 byte answer; bool result = true; ibutton.reset(); ibutton.write(0x3C); // команда записи ROM для TM-2004 ibutton.write(0x00); ibutton.write(0x00); // передаем адрес с которого начинается запись for (byte i = 0; i<8; i++){ digitalWrite(R_Led, !digitalRead(R_Led)); ibutton.write(keyID[i]); answer = ibutton.read(); //if (OneWire::crc8(m1, 3) != answer){result = false; break;} // crc не верный delayMicroseconds(600); ibutton.write_bit(1); delay(50); // испульс записи pinMode(iButtonPin, INPUT); Serial.print('*'); Sd_WriteStep(); if (keyID[i] != ibutton.read()) { result = false; break;} //читаем записанный байт и сравниваем, с тем что должно записаться } if (!result){ ibutton.reset(); Serial.println(" The key copy faild"); Sd_ErrorBeep(); digitalWrite(R_Led, HIGH); return false; } ibutton.reset(); Serial.println(" The key has copied successesfully"); Sd_ReadOK(); delay(500); digitalWrite(R_Led, HIGH); return true; } bool write2iBtnRW1990_1_2_TM01(emRWType rwType){ // функция записи на RW1990.1, RW1990.2, TM-01C(F) byte rwCmd, rwFlag = 1; switch (rwType){ case TM01: rwCmd = 0xC1; break; //TM-01C(F) case RW1990_1: rwCmd = 0xD1; rwFlag = 0; break; // RW1990.1 флаг записи инвертирован case RW1990_2: rwCmd = 0x1D; break; // RW1990.2 } ibutton.reset(); ibutton.write(rwCmd); // send 0xD1 - флаг записи ibutton.write_bit(rwFlag); // записываем значение флага записи = 1 - разрешить запись delay(10); pinMode(iButtonPin, INPUT); ibutton.reset(); ibutton.write(0xD5); // команда на запись for (byte i = 0; i<8; i++){ digitalWrite(R_Led, !digitalRead(R_Led)); if (rwType == RW1990_1) BurnByte(~keyID[i]); // запись происходит инверсно для RW1990.1 else BurnByte(keyID[i]); Serial.print('*'); Sd_WriteStep(); } ibutton.write(rwCmd); // send 0xD1 - флаг записи ibutton.write_bit(!rwFlag); // записываем значение флага записи = 1 - отключаем запись delay(10); pinMode(iButtonPin, INPUT); digitalWrite(R_Led, LOW); if (!dataIsBurningOK()){ // проверяем корректность записи Serial.println(" The key copy faild"); Sd_ErrorBeep(); digitalWrite(R_Led, HIGH); return false; } Serial.println(" The key has copied successesfully"); if ((keyType == keyMetacom)||(keyType == keyCyfral)){ //переводим ключ из формата dallas ibutton.reset(); if (keyType == keyCyfral) ibutton.write(0xCA); // send 0xCA - флаг финализации Cyfral else ibutton.write(0xCB); // send 0xCA - флаг финализации metacom ibutton.write_bit(1); // записываем значение флага финализации = 1 - перевезти формат delay(10); pinMode(iButtonPin, INPUT); } Sd_ReadOK(); delay(500); digitalWrite(R_Led, HIGH); return true; } void BurnByte(byte data){ for(byte n_bit=0; n_bit<8; n_bit++){ ibutton.write_bit(data & 1); delay(5); // даем время на прошивку каждого бита до 10 мс data = data >> 1; // переходим к следующему bit } pinMode(iButtonPin, INPUT); } bool dataIsBurningOK(){ byte buff[8]; if (!ibutton.reset()) return false; ibutton.write(0x33); ibutton.read_bytes(buff, 8); byte Check = 0; for (byte i = 0; i < 8; i++) if (keyID[i] == buff[i]) Check++; // сравниваем код для записи с тем, что уже записано в ключе. if (Check != 8) return false; // если коды совпадают, ключ успешно скопирован return true; } bool write2iBtn(){ int Check = 0; if (!ibutton.search(addr)) { ibutton.reset_search(); return false; } Serial.print("The new key code is: "); for (byte i = 0; i < 8; i++) { Serial.print(addr[i], HEX); Serial.print(":"); if (keyID[i] == addr[i]) Check++; // сравниваем код для записи с тем, что уже записано в ключе. } if (Check == 8) { // если коды совпадают, ничего писать не нужно digitalWrite(R_Led, LOW); Serial.println(" it is the same key. Writing in not needed."); Sd_ErrorBeep(); digitalWrite(R_Led, HIGH); delay(500); return false; } emRWType rwType = getRWtype(); // определяем тип RW-1990.1 или 1990.2 или TM-01 Serial.print("\n Burning iButton ID: "); if (rwType == TM2004) return write2iBtnTM2004(); //шьем TM2004 else return write2iBtnRW1990_1_2_TM01(rwType); //пробуем прошить другие форматы } bool searchIbutton(){ if (!ibutton.search(addr)) { ibutton.reset_search(); return false; } for (byte i = 0; i < 8; i++) { Serial.print(addr[i], HEX); Serial.print(":"); keyID[i] = addr[i]; // копируем прочтенный код в ReadID } if (addr[0] == 0x01) { // это ключ формата dallas keyType = keyDallas; if (getRWtype() == TM2004) keyType = keyTM2004; if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); Sd_ErrorBeep(); digitalWrite(B_Led, HIGH); return false; } return true; } if ((addr[0]>>4) == 0x0E) Serial.println(" Type: unknown family dallas. May be cyfral in dallas key."); else Serial.println(" Type: unknown family dallas"); keyType = keyUnknown; return true; } //************ Cyfral *********************** unsigned long pulseAComp(bool pulse, unsigned long timeOut = 20000){ // pulse HIGH or LOW bool AcompState; unsigned long tStart = micros(); do { AcompState = (ACSR >> ACO)&1; // читаем флаг компаратора if (AcompState == pulse) { tStart = micros(); do { AcompState = (ACSR >> ACO)&1; // читаем флаг компаратора if (AcompState != pulse) return (long)(micros() - tStart); } while ((long)(micros() - tStart) < timeOut); return 0; //таймаут, импульс не вернуся оратно } // end if } while ((long)(micros() - tStart) < timeOut); return 0; } void ACsetOn(){ ACSR |= 1<<ACBG; // Подключаем ко входу Ain0 1.1V для Cyfral/Metacom ADCSRA &= ~(1<<ADEN); // выключаем ADC ADMUX = (ADMUX&0b11110000) | 0b0011; // подключаем к AC Линию A3 ADCSRB |= 1<<ACME; // включаем мультиплексор AC } bool read_cyfral(byte* buf, byte CyfralPin){ unsigned long ti; byte j = 0; digitalWrite(CyfralPin, LOW); pinMode(CyfralPin, OUTPUT); //отклчаем питание от ключа delay(100); pinMode(CyfralPin, INPUT); // включаем пиание Cyfral ACsetOn(); for (byte i = 0; i<36; i++){ // чиаем 36 bit ti = pulseAComp(HIGH); if ((ti == 0) || (ti > 200)) break; // not Cyfral //if ((ti > 20)&&(ti < 50)) bitClear(buf[i >> 3], 7-j); if ((ti > 90) && (ti < 200)) bitSet(buf[i >> 3], 7-j); j++; if (j>7) j=0; } if (ti == 0) return false; if ((buf[0] >> 4) != 0b1110) return false; /// not Cyfral byte test; for (byte i = 1; i<4; i++){ test = buf[i] >> 4; if ((test != 1)&&(test != 2)&&(test != 4)&&(test != 8)) return false; test = buf[i] & 0x0F; if ((test != 1)&&(test != 2)&&(test != 4)&&(test != 8)) return false; } return true; } bool searchCyfral(){ for (byte i = 0; i < 8; i++) addr[i] = 0; if (!read_cyfral(addr, iButtonPin)) return false; keyType = keyCyfral; for (byte i = 0; i < 8; i++) { Serial.print(addr[i], HEX); Serial.print(":"); keyID[i] = addr[i]; // копируем прочтенный код в ReadID } Serial.println(" Type: Cyfral "); return true; } //**********EM-Marine*************************** bool vertEvenCheck(byte* buf){ // проверка четности столбцов с данными byte k; k = 1&buf[1]>>6 + 1&buf[1]>>1 + 1&buf[2]>>4 + 1&buf[3]>>7 + 1&buf[3]>>2 + 1&buf[4]>>5 + 1&buf[4] + 1&buf[5]>>3 + 1&buf[6]>>6 + 1&buf[6]>>1 + 1&buf[7]>>4; if (k&1) return false; k = 1&buf[1]>>5 + 1&buf[1] + 1&buf[2]>>3 + 1&buf[3]>>6 + 1&buf[3]>>1 + 1&buf[4]>>4 + 1&buf[5]>>7 + 1&buf[5]>>2 + 1&buf[6]>>5 + 1&buf[6] + 1&buf[7]>>3; if (k&1) return false; k = 1&buf[1]>>4 + 1&buf[2]>>7 + 1&buf[2]>>2 + 1&buf[3]>>5 + 1&buf[3] + 1&buf[4]>>3 + 1&buf[5]>>6 + 1&buf[5]>>1 + 1&buf[6]>>4 + 1&buf[7]>>7 + 1&buf[7]>>2; if (k&1) return false; k = 1&buf[1]>>3 + 1&buf[2]>>6 + 1&buf[2]>>1 + 1&buf[3]>>4 + 1&buf[4]>>7 + 1&buf[4]>>2 + 1&buf[5]>>5 + 1&buf[5] + 1&buf[6]>>3 + 1&buf[7]>>6 + 1&buf[7]>>1; if (k&1) return false; if (1&buf[7]) return false; //номер ключа, который написан на корпусе rfidData[0] = (0b01111000&buf[1])<<1 | (0b11&buf[1])<<2 | buf[2]>>6; rfidData[1] = (0b00011110&buf[2])<<3 | buf[3]>>4; rfidData[2] = buf[3]<<5 | (0b10000000&buf[4])>>3 | (0b00111100&buf[4])>>2; rfidData[3] = buf[4]<<7 | (0b11100000&buf[5])>>1 | 0b1111&buf[5]; rfidData[4] = (0b01111000&buf[6])<<1 | (0b11&buf[6])<<2 | buf[7]>>6; return true; } byte ttAComp(unsigned long timeOut = 10000){ // pulse 0 or 1 or -1 if timeout byte AcompState, AcompInitState; unsigned long tStart = micros(); AcompInitState = (ACSR >> ACO)&1; // читаем флаг компаратора do { AcompState = (ACSR >> ACO)&1; // читаем флаг компаратора if (AcompState != AcompInitState) { delayMicroseconds(1000/(rfidBitRate*4)); // 1/4 Period on 2 kBps = 125 mks AcompState = (ACSR >> ACO)&1; // читаем флаг компаратора delayMicroseconds(1000/(rfidBitRate*2)); // 1/2 Period on 2 kBps = 250 mks return AcompState; } } while ((long)(micros() - tStart) < timeOut); return 2; //таймаут, компаратор не сменил состояние } bool readEM_Marie(byte* buf){ unsigned long tStart = millis(); byte ti; byte j = 0, k=0; for (int i = 0; i<64; i++){ // читаем 64 bit ti = ttAComp(); if (ti == 2) break; //timeout if ( ( ti == 0 ) && ( i < 9)) { // если не находим 9 стартовых единиц - начинаем сначала if ((long)(millis()-tStart) > 50) { ti=2; break;} //timeout i = -1; j=0; continue; } if ((i > 8) && (i < 59)){ //начиная с 9-го бита проверяем контроль четности каждой строки if (ti) k++; // считаем кол-во единиц if ( (i-9)%5 == 4 ){ // конец строки с данными из 5-и бит, if (k & 1) { //если нечетно - начинаем сначала i = -1; j = 0; k = 0; continue; } k = 0; } } if (ti) bitSet(buf[i >> 3], 7-j); else bitClear(buf[i >> 3], 7-j); j++; if (j>7) j=0; } if (ti == 2) return false; //timeout return vertEvenCheck(buf); } void rfidACsetOn(){ //включаем генератор 125кГц TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); //Вкючаем режим Toggle on Compare Match на COM2A (pin 11) и счет таймера2 до OCR2A TCCR2B = _BV(WGM22) | _BV(CS20); // Задаем делитель для таймера2 = 1 (16 мГц) OCR2A = 63; // 63 тактов на период. Частота на COM2A (pin 11) 16000/64/2 = 125 кГц, Скважнось COM2A в этом режиме всегда 50% OCR2B = 31; // Скважность COM2B 32/64 = 50% Частота на COM2A (pin 3) 16000/64 = 250 кГц // включаем компаратор ADCSRB &= ~(1<<ACME); // отключаем мультиплексор AC ACSR &= ~(1<<ACBG); // отключаем от входа Ain0 1.1V digitalWrite(ACpin, LOW); pinMode(ACpin, OUTPUT); // ускоряем переходные процессы в детекторе с 12мс до 2 мс delay(1); pinMode(ACpin, INPUT); delay(1); } bool searchEM_Marine( bool copyKey = true){ byte gr = digitalRead(G_Led); bool rez = false; rfidACsetOn(); // включаем генератор 125кГц и компаратор delay(4); //4 мс запускается ключ if (!readEM_Marie(addr)) goto l2; rez = true; keyType = keyEM_Marie; for (byte i = 0; i<8; i++){ if (copyKey) keyID[i] = addr [i]; Serial.print(addr[i], HEX); Serial.print(":"); } Serial.print(" ( id "); Serial.print(rfidData[0]); Serial.print(" key "); unsigned long keyNum = (unsigned long)rfidData[1]<<24 | (unsigned long)rfidData[2]<<16 | (unsigned long)rfidData[3]<<8 | (unsigned long)rfidData[4]; Serial.print(keyNum); Serial.println(") Type: EM-Marie "); l2: if (!CheckL) if (!copyKey) TCCR2A &=0b00111111; //Оключить ШИМ COM2A (pin 11). Для настройки катушки в резонанс установите CheckL в 1 digitalWrite(G_Led, gr); return rez; } void TxBitRfid(byte data){ if (data & 1) delayMicroseconds(54*8); else delayMicroseconds(24*8); rfidGap(19*8); //write gap } void TxByteRfid(byte data){ for(byte n_bit=0; n_bit<8; n_bit++){ TxBitRfid(data & 1); data = data >> 1; // переходим к следующему bit } } void rfidGap(unsigned int tm){ TCCR2A &=0b00111111; //Оключить ШИМ COM2A delayMicroseconds(tm); TCCR2A |= _BV(COM2A0); // Включить ШИМ COM2A (pin 11) } bool T5557_blockRead(byte* buf){ byte ti; byte j = 0, k=0; for (int i = 0; i<33; i++){ // читаем стартовый 0 и 32 значащих bit ti = ttAComp(2000); if (ti == 2) break; //timeout if ( ( ti == 1 ) && ( i == 0)) { ti=2; break; } // если не находим стартовый 0 - это ошибка if (i > 0){ //начиная с 1-го бита пишем в буфер if (ti) bitSet(buf[(i-1) >> 3], 7-j); else bitClear(buf[(i-1) >> 3], 7-j); j++; if (j>7) j=0; } } if (ti == 2) return false; //timeout return true; } bool sendOpT5557(byte opCode, unsigned long password = 0, byte lockBit = 0, unsigned long data = 0, byte blokAddr = 1){ TxBitRfid(opCode >> 1); TxBitRfid(opCode & 1); // передаем код операции 10 if (opCode == 0b00) return true; // password TxBitRfid(lockBit & 1); // lockbit 0 if (data != 0){ for (byte i = 0; i<32; i++) { TxBitRfid((data>>(31-i)) & 1); } } TxBitRfid(blokAddr>>2); TxBitRfid(blokAddr>>1); TxBitRfid(blokAddr & 1); // адрес блока для записи delay(4); // ждем пока пишутся данные return true; } bool write2rfidT5557(byte* buf){ bool result; unsigned long data32; digitalWrite(R_Led, LOW); delay(6); for (byte k = 0; k<2; k++){ // send key data data32 = (unsigned long)buf[0 + (k<<2)]<<24 | (unsigned long)buf[1 + (k<<2)]<<16 | (unsigned long)buf[2 + (k<<2)]<<8 | (unsigned long)buf[3 + (k<<2)]; rfidGap(30 * 8); //start gap sendOpT5557(0b10, 0, 0, data32, k+1); //передаем 32 бита ключа в blok k Serial.print('*'); delay(6); } delay(6); rfidGap(30 * 8); //start gap sendOpT5557(0b00); result = readEM_Marie(addr); TCCR2A &=0b00111111; //Оключить ШИМ COM2A (pin 11) for (byte i = 0; i < 8; i++) if (addr[i] != keyID[i]) { result = false; break; } if (!result){ Serial.println(" The key copy faild"); Sd_ErrorBeep(); } else { Serial.println(" The key has copied successesfully"); Sd_ReadOK(); delay(1000); } digitalWrite(R_Led, HIGH); return result; } emRWType getRfidRWtype(){ unsigned long data32, data33; byte buf[4] = {0, 0, 0, 0}; rfidACsetOn(); // включаем генератор 125кГц и компаратор delay(4); //4мс запускается ключ rfidGap(30 * 8); //start gap sendOpT5557(0b11, 0, 0, 0, 1); //переходим в режим чтения Vendor ID if (!T5557_blockRead(buf)) return rwUnknown; data32 = (unsigned long)buf[0]<<24 | (unsigned long)buf[1]<<16 | (unsigned long)buf[2]<<8 | (unsigned long)buf[3]; delay(4); rfidGap(20 * 8); //gap data33 = 0b00000000000101001000000001000000 | (rfidUsePWD << 4); //конфиг регистр 0b00000000000101001000000001000000 sendOpT5557(0b10, 0, 0, data33, 0); //передаем конфиг регистр delay(4); rfidGap(30 * 8); //start gap sendOpT5557(0b11, 0, 0, 0, 1); //переходим в режим чтения Vendor ID if (!T5557_blockRead(buf)) return rwUnknown; data33 = (unsigned long)buf[0]<<24 | (unsigned long)buf[1]<<16 | (unsigned long)buf[2]<<8 | (unsigned long)buf[3]; sendOpT5557(0b00, 0, 0, 0, 0); // send Reset delay(6); if (data32 != data33) return rwUnknown; Serial.print(" The rfid RW-key is T5557. Vendor ID is "); Serial.println(data32, HEX); return T5557; } bool write2rfid(){ bool Check = true; if (searchEM_Marine(false)) { for (byte i = 0; i < 8; i++) if (addr[i] != keyID[i]) { Check = false; break; } // сравниваем код для записи с тем, что уже записано в ключе. if (Check) { // если коды совпадают, ничего писать не нужно digitalWrite(R_Led, LOW); Serial.println(" it is the same key. Writing in not needed."); Sd_ErrorBeep(); digitalWrite(R_Led, HIGH); delay(500); return false; } } emRWType rwType = getRfidRWtype(); // определяем тип T5557 (T5577) или EM4305 if (rwType != rwUnknown) Serial.print("\n Burning rfid ID: "); //keyID[0] = 0xFF; keyID[1] = 0xA9; keyID[2] = 0x8A; keyID[3] = 0xA4; keyID[4] = 0x87; keyID[5] = 0x78; keyID[6] = 0x98; keyID[7] = 0x6A; // если у вас есть код какого-то ключа, можно прописать его тут switch (rwType){ case T5557: return write2rfidT5557(keyID); break; //пишем T5557 //case EM4305: return write2rfidEM4305(keyID); break; //пишем EM4305 case rwUnknown: break; } return false; } void loop() { bool BtnClick, BtnPinSt = digitalRead(BtnPin); if ((BtnPinSt == LOW) &&(preBtnPinSt!= LOW)) BtnClick = true; else BtnClick = false; preBtnPinSt = BtnPinSt; if ((Serial.read() == 't') || BtnClick) { // переключаель режима чтение/запись if (readflag == true) { writeflag = !writeflag; clearLed(); if (writeflag) digitalWrite(R_Led, HIGH); else digitalWrite(G_Led, HIGH); Serial.print("Writeflag = "); Serial.println(writeflag); } else Sd_ErrorBeep(); } if (!writeflag){ if (searchCyfral() || searchEM_Marine() || searchIbutton()){ // запускаем поиск cyfral, затем поиск EM_Marine, затем поиск dallas digitalWrite(G_Led, LOW); Sd_ReadOK(); readflag = true; clearLed(); digitalWrite(G_Led, HIGH); } else { delay(100); //ничего не нашлось - начинаем сначала return; } } if (writeflag && readflag){ if (keyType == keyEM_Marie) write2rfid(); else write2iBtn(); } delay(200); } //***************** звуки**************** void Sd_ReadOK() { // звук ОК for (int i=400; i<6000; i=i*1.5) { tone(speakerPin, i); delay(20); } noTone(speakerPin); } void Sd_WriteStep(){ // звук "очередной шаг" for (int i=2500; i<6000; i=i*1.5) { tone(speakerPin, i); delay(10); } noTone(speakerPin); } void Sd_ErrorBeep() { // звук "ERROR" for (int j=0; j <3; j++){ for (int i=1000; i<2000; i=i*1.1) { tone(speakerPin, i); delay(10); } delay(50); for (int i=1000; i>500; i=i*1.9) { tone(speakerPin, i); delay(10); } delay(50); } noTone(speakerPin); } void Sd_StartOK(){ // звук "Успешное включение" tone(speakerPin, NOTE_A7); delay(100); tone(speakerPin, NOTE_G7); delay(100); tone(speakerPin, NOTE_E7); delay(100); tone(speakerPin, NOTE_C7); delay(100); tone(speakerPin, NOTE_D7); delay(100); tone(speakerPin, NOTE_B7); delay(100); tone(speakerPin, NOTE_F7); delay(100); tone(speakerPin, NOTE_C7); delay(100); noTone(speakerPin); }timurtanum - чтобы добавить в этот код "поддержку других домофонов", как вы выразились - надо иметь подробное описание протокола считывания и записи ключей этого формата. А фирмы, делающие домофоны, как-то не очень хотят делится этой информацией.
Поэтому энутзиасты собирают информацию по кусочкам и пытаются написать программы. Например в комментариях в вашем скетче упоминаются ключи форматов RW-1990.1, RW-1990.2, TM-2004, TM-01, T5557, Цифрал а также RFID формата EM-Marine
Только "обещать - не значит женится", не думаю. что этот код умеет работать со всеми этими ключами.
Доброго времени суток . у вас есть возможность протестировать rfid метки которые уже записаны в программу ? мне просто интересно знать эта программа работает с rfid ьетками или нет .