ARDUINO и iButton DS1990A

Данная статья является логическим продолжением сразу трех статей, статьи о самодельном силовом шилде (arduino-kit.com.ua/samodelnyy-silovoy-shild-dlya-arduino.html ), статьи о термодатчиках DS18B20 (arduino-kit.com.ua/tsifrovoy-termometr-ds18b20-i-arduino-uno.html ) и статьи об RFID метках (arduino-kit.com.ua/arduino-i-karty-dostupa.html ), однако читателю совсем не обязательно для понимания всего нижеизложенного штудировать все вышеперечисленное, данная статья является полностью самодостаточной и в ней есть все необходимое для изучения предлагаемого материала. В отличие от других моих статей, данную статью я написал скорее для себя самого. На просторах интернета достаточно много толковой информации по считыванию данных с ключей iButton (в простонародье называемых «таблетками») при помощи Ардуино. Все мои первоначальные, не совсем удачные, эксперименты объясняются не недостатком информации, либо её некорректностью, а исключительно недостатками у меня знаний, да и обычной человеческой невнимательностью. Но начнем по порядку. Для реализации всего задуманного мне понадобилось: ARDUINO UNO, купить её проще всего можно здесь: arduino-kit.com.ua/uno-r3-new.html или здесь:arduino-kit.com.ua/arduino-leonardo-original-italiya-new-rev3.html , и несколько ключей iButton, которые, вполне возможно, и покупать не придется, так как очень часто ими пользуются для открытия домофона, наряду с RFID метками, хотя лично я парочку прикупил на ближайшем радиорынке (около 1,2$ за штуку). Говорят, что в некоторых городах они используются для поездок в метро, а после того, как полностью используются – выбрасываются, ну может быть... При экспериментах с Ардуино вполне можно взять «таблетки» у своих домашних, они свободно «держат» 9В, так что если пользоваться аккуратно они не пострадают, но позволят сэкономить массу времени и немного денег. Также понадобится пару проводочков и резистор на 4,7 КОм. Еще мне понадобился маленький кусочек фольгированного стеклотекстолита, немного припоя и канифоли, а также колодка на 3 входа. Но это мне понадобилось только для того, чтобы украсить статью, для простых экспериментов можно обойтись проводками, для коммерческого проекта необходимое гнездо считывателя все равно лучше купить, хоть и стоимость его начинается c 20$. Если кто-то захочет более полно повторить мои эксперименты – файлик с чертежом считывателя прилагается к статье. Как и прочие мои статьи, данная статья рассчитана на новичков и состоит из частей, изложение информации идет по нарастающей, от простого к сложному.

Часть первая. Первое знакомство.

То, что метка iButton представляет из себя микросхему (а в некоторых случаях даже «микрофлешку») детально описано в техдокументации. В данной статье не рассматриваются технологии изменения информации, находящейся на этих метках, в данной статье мы рассмотрим возможности по чтению серийного номера с этой «таблетки» и последующим оперированием этим номером. Что собой представляет метка (ключ) iButton видно на Рисунке 1. 

 
Рисунок 1. iButton DS1990A



В каждом из подобных ключей хранится уникальный 48 битный (6 байтный) серийный номер. Вроде как ничего впечатляющего, но это на первый взгляд, если немного посчитать, то это будет 2.81 * 1014 комбинаций, а это действительно очень много. В общем, если выпускать по 6 миллиардов ключей в год (на каждого жителя Земли (по состоянию на теперешний момент) в год по новому ключику) то без повторения комбинации можно работать чуть больше 46833 лет, а если учесть, что в систему заложена возможность выпускать 128 типов различных устройств... Но я немного отвлекся. Итак: считываем серийный номер с ключа. Способ «взять и посмотреть» мы здесь не рассматриваем, причем, не только по причине его простоты и банальности, но еще и потому, что через некоторое время он визуально становится нечитаемым. И здесь речь не о каких-то сверхсекретных шпионских технологиях, просто при долгом ношении в карманах одежды он банально стирается, особенно, когда находится на связке с ключами. Что собой представляет серийный номер хорошо видно на Рисунке 2. 

 
Рисунок 2. Надписи на DS1990A



Полный серийный номер, кроме знаков, расположенных в ряд также включает в себя 4 знака (два справа и два слева) чуть выше номера. Данный номер нанесен в шестнадцатеричном виде. Таким образом, данный конкретный ключ iButton несет полный серийный номер BA000014630D3D01. Первые 2 знака (если слева вверху, любое устройство читает наоборот – справа) – контрольная сумма CRC (вычисляется особым образом из оставшихся 7 байт). Следующие 12 знаков – уникальный серийный номер, последние 2 знака (справа вверху) – код типа устройства. И еще одно – на данной фотографии видно, что полностью «таблетка» называется DS1990A+F5. Последняя пара знаков (F5) в названии указывает на исполнение данной таблетки, а именно толщину 5,9 мм. Есть еще один типоразмер – 3,1 мм, в этом случае маркировка была бы F3. Подключается данная таблетка к Ардуинке по шине 1-Wire, т.е. полностью аналогично термодатчику DS18B20. В нижеследующем примере мы подключим массу (GND) arduino к внешней части «таблетки», 10-й пин к IO (Input-Output) это торцевая плоскость (та плоскость, на которой выгравирован серийный номер), а кроме этого этот же 10-й пин с помощью резистора на 4,7 КОм подключим к контакту «5V». В интернете также распространены схемы, где применяются резисторы от 2,2 до 5 КОм, лично я привык к номиналу 4,7 и во избежание путаницы применяю для данной шины его. В данном, конкретном эксперименте резистор я напаял напрямую на плату считывателя, что получилось – видно на Рисунке 3. 

 
Рисунок 3. Подключение к считывателю.



Из файла iButton1 в Ардуинку грузим следующий скетч:

#include
OneWire ds(10);// Определяем пин подключения к ключу
byte addr[8]; // Обозначаем массив из 8 байт
void setup() {
Serial.begin(9600);}// Запускаем порт
void loop() {
if (ds.search(addr)){// Если устройство подключено - считываем
for(int i=7; i>-1; i--){// Запускаем цикл печати данных из массива
Serial.print(addr[i], HEX);// Печатаем нужный байт в шестнадцатиричном виде
Serial.print(" ");}// Печатаем пробел
Serial.println();// В конце цикла переводим строку
ds.reset_search();}} // Сбрасываем устройство


Библиотека OneWire.h та же самая, которую я применял в статье о термодатчиках DS18B20. Результат работы скетча видно на Рисунке 4. 

 
Рисунок 4. Скетч и результат работы.



На рисунке видно, что часть символов «не хватает», а именно отображается «всего» 12 символов вместо 16. Дело в том, что программа при считывании байта игнорирует «не значащий» ноль. То есть вместо «00» отображается «0», вместо «01» отображается «1» и т.д.

Часть вторая, совсем чуть-чуть усложненная.

Так как основное предназначение ключей iButton это идентификация, т.е. разделение по принципу «свой – чужой» дополним скетч несколькими строчками кода, чтобы это самое разделение (пока простейшее) сделать.
Из файла iButton2 в Ардуинку грузим следующий скетч:

#include
OneWire ds(10);// Определяем пин подключения к ключу
byte aaa[8] = {0x01,0x3D,0x0D,0x63,0x14,0x00,0x00,0xBA};// Массив известного ключа
byte addr[8]; // Обозначаем массив для чтения ключа из 8 байт
void setup() {
Serial.begin(9600);}// Запускаем порт
void loop() {
if (ds.search(addr)){// Если устройство подключено - считываем
if(aaa[0] == addr[0] && aaa[1] == addr[1] && aaa[2] == addr[2] // Сравниваем побайтно массивы
&& aaa[3] == addr[3] && aaa[4] == addr[4] && aaa[5] == addr[5] // Да, это чересчур громоздко,
&& aaa[6] == addr[6] && aaa[7] == addr[7]){ // зато просто "как кувалда".
Serial.println("OK");}// Если код совпал пишем ОК!
else {Serial.println("NO!");}// Если несовпадение пишем NO!
for(int i=7; i>-1; i--){// Запускаем цикл печати данных из массива.
Serial.print(addr[i], HEX);// Печатаем нужный байт в шестнадцатеричном виде
Serial.print(" ");}// Печатаем пробел
Serial.println();// В конце цикла переводим строку
ds.reset_search();}} // Сбрасываем устройство


Результат работы данного скетча видно на Рисунке 5. 

 
Рисунок 5. Простейшее определение ключей.


Часть третья, еще более полезная, хоть тоже простая.

Наступило время придать данному проекту хоть какую-то видимость пользы. Пусть видимость пользы будет в эмулировании электрозамка. Простейшего электрозамка с электромагнитной задвижкой, который с одной стороны открывается вручную, а с другой при помощи «таблетки» или обычного ключа, если, например, отключили электроэнергию. Код также растет совсем немного, единственное, что – массив хранящий данные ключей делаем двухмерным, чтобы можно было разместить в нем при желании несколько серийных номеров этих самых ключей.
Грузим в Ардуинку код из файла iButton3:

#include
OneWire ds(10);// Определяем пин подключения к ключу
byte aaa[2][8] = {{0x01,0x3D,0x0D,0x63,0x14,0x00,0x00,0xBA},// Двухмерный массив известных ключей
{0x01,0xF9,0x24,0x63,0x14,0x00,0x00,0xF2}};// Первое число - количество ключей, второе - количество байт в ключе
byte addr[8], k, m; // Обозначаем массив для чтения ключа из 8 байт
void setup() {
pinMode(13, OUTPUT);// Прописываем диод на пин 13.
Serial.begin(9600);}// Запускаем порт
void loop() {
m = 0;// Обнуляем указатель наличия ключа
if (ds.search(addr)){// Если устройство подключено - считываем
for (k=0; k<2; k++){// Запускаем цикл перебора ключей
if(aaa[k][0] == addr[0] && aaa[k][1] == addr[1] && aaa[k][2] == addr[2] // Сравниваем побайтно массивы
&& aaa[k][3] == addr[3] && aaa[k][4] == addr[4] && aaa[k][5] == addr[5] // Да, это чересчур громоздко, зато просто "как кувалда".
&& aaa[k][6] == addr[6] && aaa[k][7] == addr[7]){ m=1;}} // Если ключ есть увеличиваем значение указателя
if (m > 0) {// Проверяем значение указателя
Serial.println("OK");// Если код совпал пишем ОК!
digitalWrite(13, HIGH);// Зажигаем диод
delay(1000);// Выдерживаем паузу
digitalWrite(13, LOW);}// Гасим диод
else {Serial.println("NO!");// Если несовпадение пишем NO!
delay(500);}
for(int i=7; i>-1; i--){// Запускаем цикл печати данных из массива
Serial.print(addr[i], HEX);// Печатаем нужный байт в шестнадцатеричном виде
Serial.print(" ");}// Печатаем пробел
Serial.println();// В конце цикла переводим строку
ds.reset_search();}} // Сбрасываем устройство 


Результат работы данного скетча видно на Рисунке 6. 

 
Рисунок 6. Простейший эмулятор электрозамка.



Конечно, данная тема совсем не исчерпывается тремя простенькими примерами, если будет потребность и желание – в планах написать более полную и более сложную статью по контролю доступа. 

Обзор подготовил Павел Сергеев