Mifare Ultralight 7 byte
- Войдите на сайт для отправки комментариев
Ср, 30/01/2019 - 19:30
Здравствуйте, прошу не судить меня строго, сам еще новичёк в Ардуино!
Пишу проект на ардуино, выбрал Arduino Mega2560, хотел сделать чтобы с помощью пассивного тега открывать дверь(в данном случае серво), при этом в программу заранее ввел его UID метку. Но ранее я использовал Mifare 1K(4 byte), проблем с кодом не было. Позже хотел попробовать с новыми метками Mifare Ultralight (7 byte), с кодом проблема. Не знаю как написать чтобы он принял тэг.
#define RST_PIN 8 //Pin 9 is for the RC522 reset
#define SS_PIN 9 //Pin 10 is the SS (SDA) of RC522 module
MFRC522 mfrc522(SS_PIN, RST_PIN); //Create anew RC522 object
Servo motor_1;
//Variables
boolean door_opened=false;
boolean first_read=false;
boolean normal_mode=true;
boolean countdown = false;
int timer=0;
int user_added=0;
int add_ID_counter = 0;
//I/O
int buzzer_pin=2;
int inside_open = 4; //pin for the button of the inside open
void setup() {
SPI.begin(); //Start a new SPI bus
mfrc522.PCD_Init(); // Startt the MFRC522
motor_1.attach(3); //Set digital pin D3 to be the PWM signal for the servo motor
pinMode(buzzer_pin,OUTPUT); //Set digital pin D7 to be the buzzer OUTPUT
//Config of the i2c LCD screen
lcd.begin();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Place card here!");
lcd.setCursor(0,1);
lcd.print(" ");
motor_1.writeMicroseconds(1000); //Put the servo in to the close position
}
byte ActualUID[5]; //This will store the ID each time we read a new ID code
byte USER1[5]= {0xFE, 0x6D, 0x04, 0xA3} ; //Master ID code Change it for yor tag. First use the READ exampel and check your ID
byte USER2[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER2
byte USER3[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER3
byte USER4[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER4
у вас в коде что-то незаметно вообще чтения меток - ни 4хбайтных, ни семи. Так не пойдет, тут на форуме за новичков код не пишут, только правят то. что уже написано.
Зачем-то только создано куча массивов размером пять(?) байт. Почему пять? - если раньше было 4, а теперь нужно семь? - тайна
Я не полный код вам выслал.
byte ActualUID[5]; //This will store the ID each time we read a new ID code byte USER1[5]= {0xFE, 0x6D, 0x04, 0xA3} ; //Master ID code Change it for yor tag. First use the READ exampel and check your ID byte USER2[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER2 byte USER3[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER3 byte USER4[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER4 byte USER5[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER5 byte USER6[5]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER6 продолжение кода: if(!normal_mode) { // Мы проверяем, есть ли новые карты if ( mfrc522.PICC_IsNewCardPresent()) { //Мы выбираем карту if ( mfrc522.PICC_ReadCardSerial()) { // Мы отправим ваш UID for (byte i = 0; i < mfrc522.uid.size; i++) { ActualUID[i]=mfrc522.uid.uidByte[i]; }Пять сделано для 5 карт, которые могут валидировать. Проблема в том, что я не знаю как писать 7 байтную метку, чтобы она сопоставляла с программой. При сходимости, серво открывается. Еще раз повторяю не полностью написал код. Остальное неважно
Пять сделано для 5 карт, которые могут валидировать.
вы не поняли, я не про число массивов спрашивал, а про число элементов в них.
Давайте начнем с азов - вы понимаете, что происходит вот в этой строке:
byte USER1[5]= {0xFE, 0x6D, 0x04, 0xA3} ;сможете обьяснить?
Рахмет, я уже понял получается [] - количество допустимых байтов. ТАк?
Рахмет, я уже понял получается [] - количество допустимых байтов. ТАк?
Я не знаю, что значит "допустимых байтов" - и что такое недопустимые байты...
Цифра в квадратных скобках - это размер массива. Значит для хранения 4хбайтных ключей вам нужен массив байт из четырех элементов, а для Ультралайта - из семи.
Должен сказать. что если даже смысл числа в квадратных скобках вы знаете нетвердо - вам явно рано писать код для работы с РФИД. Ничего из этого не выйдет. Отложите на время ардуину и потратьте пару недель на чтение какой-нибудь методички по языку Си. Вы потом быстро эти недели отобьете...
модераторам - просьба перенести в песочницу.
Nuradil - прежде чем что-то отвечать - зайдите в Песочнице в заглавную тему и прочитайте хотя бы начальные сообщения МАКСИМАЛЬНО ВНИМАТЕЛЬНО.
b707, не хотел вас тревожить по пустякам, но вы реально помогаете. Есть еще один вопросик и все:
Функция в серво writemicroseconds отвечает за поворот сервопривода, она отличается от простого write тем, что позволяет поворачивать в стороне часовой или против
Вопрос: в коде написал writeMicroseconds(1000), но серво поворачивает не полностью(на 15-20 градусов), какие проблемы возможны?
нда, b707 как вы быстро про карты донесли, чел все понял моментально, теперь про серву... ржу :))
Ты бы помог лучше)
Поржем потом
нда, b707 как вы быстро про карты донесли, чел все понял моментально, теперь про серву... ржу :))
а то :)
Я б и про серву ему разом все обьяснил - если б сам знал
write(градусы) пересчитывает значение градусов в микросекунды. А writeMicroseconds(микросекунды) напрямую активирует управляющий пин на заданное время. Серва считает на сколько мкс был активен управляющий пин и, соотвественно, поворачивает качалку. Для SG90 0 градусов ~540мкс.
Огромное спасибо, b707. Красавчик
sadman41, ты уверен??
есть проблемы с writeMicroseconds(1000) - это команда же значение 1000 максимальный поворот против часовой стрелки. http://arduino.ru/Reference/Library/Servo/writeMicroseconds
sadman41, ты уверен??
есть проблемы с writeMicroseconds(1000) - это команда же значение 1000 максимальный поворот против часовой стрелки. http://arduino.ru/Reference/Library/Servo/writeMicroseconds
ну почему ты первый абзац прочитал, а второй нет?
"Замечание: некоторые производители не придерживаются стандартных значение и такие приводы могут управляться значениями от 700 до 2300. Поэкспериментируйте со значениями, до момента пока привод не повернется и остановится в крайнем положение."
sadman41, ты уверен??
Есть аргументированные возражения? Спорьте с этим (Servo.h):
Огромное спасибо, b707. Красавчик
вот и помогай после этого :(
К сожалению топикстартер не привёл код целиком! Пришлось гуглить, чтобы найти его источник!
Там одна карта используется как управляющая, а остальные - простые!
Интересно, что для сравнения используется только 4-ре байта карты, а не 7! То есть сравнивается не весь идентификатор, а только его часть, если я правильно понял
Вот функция сравнения
//Compare the 4 bytes of the users and the received ID boolean compareArray(byte array1[],byte array2[]) { if(array1[0] != array2[0])return(false); if(array1[1] != array2[1])return(false); if(array1[2] != array2[2])return(false); if(array1[3] != array2[3])return(false); return(true); }Насколько я понял, здесь идет сравнение массивов побайтно, и только если всё четыре байта совпадут, то она возвратит TRUE!
Вопрос только в том, какие по счету байты сравниваются? 1,2,3,4 ? Верно? Справа налево? Или наоборот?
Я имею в виду, как их считывает эта функция?
if ( mfrc522.PICC_ReadCardSerial()) { // Enviamos serialemente su UID for (byte i = 0; i < mfrc522.uid.size; i++) { ActualUID[i]=mfrc522.uid.uidByte[i]; }Интересно, что для сравнения используется только 4-ре байта карты, а не 7! То есть сравнивается не весь идентификатор, а только его часть, если я правильно понял
просто этот код - для карт Мифаре Классик, а в них UID 4 байта
Я думаю, что если правильно вписать сюда байты
byte USER2[4]= {0x00, 0x00, 0x00, 0x00} ; //Empty ID of USER2или в аналогичный массив, то оно будет работать!
Если например у меня UID 35 D3 AF 51 E5 29 70 мне достаточно просто подставить первых 4-ре байта? Я только не понимаю, какие вписывать! младшие? (то есть 51 E5 29 70) или старшие? (35 D3 AF 51).
Если ли какой-то способ узнать, от какого байта начинается отсчет?
по хорошему, если у вас UID из 7 байт. то и массив надо сделать на 7 байт и вписать в него все
Так дело в том, что если оставить 4 байта, то подойдут те и другие карты, а вот, если увеличить до 7, то те, что с менньшим количеством байт уже использовать не получится!
Кстати в заголовочном файле библиотеки, там вроде бы под UID выделяется 10 байт. Вот структура
// A struct used for passing the UID of a PICC. typedef struct { byte size; // Number of bytes in the UID. 4, 7 or 10. byte uidByte[10]; byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection. } Uid;size переменная для размера массива? а uidByte[10]; показывает сколько элементов в нем иожет быть максимум. Верно?
Так дело в том, что если оставить 4 байта, то подойдут те и другие карты, а вот, если увеличить до 7, то те, что с менньшим количеством байт уже использовать не получится!
А вы распознавайте тип карты - и те, у которых 4 байта - сравнивайте с 4 байтами, а те у которых 7 - с семью. Иначе вы сознательно снижаете взломостойкость своей программы.
Функция для проверки типа карты в библиотеке есть, ищите.
Я ещё даже толком не разобрался с функцией чтения. Не могу понять, почему вместо байт вылезают какие-то крякозябрики? Знаки вопроса, скобки и т.д. Скетч простейший:
#include <SPI.h> #include <MFRC522.h> #define RST_PIN 9 //Pin 9 is for the RC522 reset #define SS_PIN 10 //Pin 10 is the SS (SDA) of RC522 module MFRC522 mfrc522(SS_PIN, RST_PIN); //Create anew RC522 object byte ActualUID[7]; //byte USER1[4]= {0x09, 0x92, 0x53, 0x28} ; void setup() { Serial.begin(9600); SPI.begin(); //Start a new SPI bus mfrc522.PCD_Init(); // Startt the MFRC522 } void loop() { // Look for new cards if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return;} else{ for (byte i = 0; i < mfrc522.uid.size; i++) { ActualUID[i] = mfrc522.uid.uidByte[i]; } } Serial.print(F("Readed data: ")); //Dump a byte array to Serial for (byte i = 0; i < 7; i++) { Serial.write(ActualUID[i]); } Serial.println(); mfrc522.PICC_HaltA(); }Наверно вывод просто идет не в том формате! Подскажите пожалуйста, мне нужно всего лишь как-то изменить эту строку
или нет?
все верно - ошибка (если можно так сказать) была в ней! Нужно было использовать print, а не write! То есть написать так
теперь выводяться цифры номера, а не какие-то кракозябрики!
У меня остался только вопрос, зачем там в этой строчке
Serial.print(F("Readed data: "));буква F перед скобками? Подскажите пожалуйста, кто знает!
b707, не хотел вас тревожить по пустякам, но вы реально помогаете. Есть еще один вопросик и все:
Функция в серво writemicroseconds отвечает за поворот сервопривода, она отличается от простого write тем, что позволяет поворачивать в стороне часовой или против
Вопрос: в коде написал writeMicroseconds(1000), но серво поворачивает не полностью(на 15-20 градусов), какие проблемы возможны?
1000 это обычно нулевое положение ПРАВИЛЬНОЙ СЕРВЫ, 2000 - конечное
Тут и к бабке не ходи у вас "неправильные пчёлы и неправильный мёд"
все верно - ошибка (если можно так сказать) была в ней! Нужно было использовать print, а не write! То есть написать так
теперь выводяться цифры номера, а не какие-то кракозябрики!
У меня остался только вопрос, зачем там в этой строчке
Serial.print(F("Readed data: "));буква F перед скобками? Подскажите пожалуйста, кто знает!
экономит память
подозреваю, что это сокращение от FLASH, то есть записать эту строку не в оперативку, а во флеш! Верно?
Со словом "флеш" угадали, а со словом "записать" - нет.
Я имею в виду, что это команда для компилятора записать эту строку во флеш память! Это строка ведь константа? Точнее массив констант типа CHAR? Верно? Тогда зачем тратить на неё оперативку?
Всё и так будет записано в progmem. Вопрос только в том - будет ли данная строка перегружаться в RAM на старте или не будет. F() - это такая ардуино-магия, которая придает правильные атрибуты строке и помогает print() найти ее (строку) в progmem space.
кстати я просмотрел скетч и не обнаружил там вообще никакой записи в память (для хранения)! То есть получается, что карточки записанные мастер картой будут работать только до тех пор, пока устройство включено! А дальше оно о них просто забудет. Верно?
Посмотрите
if(user_added==0) { USER2[0] = ActualUID[0]; USER2[1] = ActualUID[1]; USER2[2] = ActualUID[2]; USER2[3] = ActualUID[3]; user_added = user_added+1; lcd.setCursor(0,0); lcd.print("New user stored "); ...... }а по идее должно быть что-то вроде EEPROM.put(eeAddress, USER2[]); и чтения EEPROM.get(eeAddress, USER2[]);
Но тут возникает ещё вопрос, как записывать, чтобы значение eeAddress тоже сохранялось после откл. питания!
Наверно под него нужно выделить 1 или 2 байта и обновлять после каждой записи? То есть добавили массив в память и
Или как-то по другому?