Всем привет, делаю дипломный проект в котором нужно реализовать пропуск по номеру телефона и RFID меткам, с записью лог файла на флешку. Исходя из того, что памяти маловато, решено было GSM номера и RFID хранить в файлах на флешке. Логика работы GSM такая: если приходит звонок, берем номер, сравниваем с номерами из файла, если есть, то открываем и пишем в лог, если нет, то тупо сброс вызова. Логика работы RFID: при запуске из файла в переменную записывается ID мастер-карты, далее если подносится метка, происходит чтение ID и сравнение с имеющимися в файле. Но при окончательном тесте столкнулся с проблемой, если подносить метки (не мастер), то как у меня происходит после 13-ого раза ID карты считывается, но проверка в файле не происходит. Мастер метку если подносить, то все работает замечательно( я так понимаю это из-за того, что она в переменной висит). Кто с таким сталкивался или имеет какие-то мысли в какую сторону капать. Код прилагается.
Код прилагается. Код (C++): #include <SoftwareSerial.h> #include <SPI.h> #include <MFRC522.h> #include <SD.h> #include<iarduino_RTC.h> #define PIN_RELEY 6 //порт реле1 D6 #define PIN_RELEY2 7 //порт реле2 D7 #define RST_PIN 9 //RST RFID #define SS1_PIN 10 //SS1 RFID #define SS2_PIN 8 //SS2 SD #define ERR_PIN 5 //LED ERROR D5 int LED_OK = A1; //LED OK SoftwareSerial mySerial(2, 3); //RX D3, TX D2 для GSM uint8_t tonePin = 4; //порт пищалки D4 String num = ""; //переменная для номера при вызове String MASTER = ""; //мастер RFID String st = ""; //RFID метка из файла, GSM номер из файла String ID = ""; //считаная RFID iarduino_RTC time(RTC_DS1302, A0, A2, A3); //RST,CLK,DAT порты для модуля времени File LIST; MFRC522 mfrc522(SS1_PIN, RST_PIN); //Create MFRC522 instance void setup() { //настройка портов Serial.begin(9600); pinMode(tonePin, OUTPUT); pinMode(PIN_RELEY, OUTPUT); pinMode(PIN_RELEY2, OUTPUT); pinMode(ERR_PIN, OUTPUT); pinMode(13, OUTPUT); pinMode(LED_OK, OUTPUT); pinMode(A4, INPUT_PULLUP); pinMode(SS1_PIN, OUTPUT); pinMode(SS2_PIN, OUTPUT); digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); digitalWrite(PIN_RELEY, HIGH); digitalWrite(PIN_RELEY2, HIGH); time.begin(); //инициализация модуля времени mySerial.begin(19200); //подключаем порт модема (при других скоростях не отвечает) mySerial.println(F("AT+CLIP=1")); //включаем АОН delay(600); Serial.println(F("SD_RFID_R_FIL_DIPLOM_V4.r1")); Serial.println(time.gettime(F("d-m-Y H:i:s;"))); delay(30); Start(); delay(800); InitSD(); //инициализация SD R_MASTER(); //чтение файла SET } void ERROR_BEEP() { //сигнал ошибки tone(tonePin, 600); delay(500); noTone(tonePin); } void Start() { //сигнал старта модуля tone(tonePin, 630); delay(100); noTone(tonePin); } void rele() { //реле для открытия 1 digitalWrite(PIN_RELEY, LOW); delay(800); digitalWrite(PIN_RELEY, HIGH); delay(100); } void rele2() { //реле для открытия 2 digitalWrite(PIN_RELEY2, LOW); delay(800); digitalWrite(PIN_RELEY2, HIGH); delay(100); } void open_beep() { //сигнал открытия замка tone(tonePin, 630); delay(100); noTone(tonePin); delay(100); tone(tonePin, 630); delay(100); noTone(tonePin); } void R_MASTER() { //чтение SET digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, LOW); String st = F(""); //переменная для строки char ch = ""; //переменная для символа LIST = SD.open(F("SET.txt")); //читаем файл if (LIST) { while (LIST.available()) { ch = (char)LIST.read(); if (ch == ';') { MASTER = st; //вносим собранную строку в массив } else { st = st + ch; //собираем строку ch = ""; //очищаем для дальнейшей работы } } } LIST.close(); digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); } void InitSD() { //инициализация SD initsd:; digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, LOW); if (!SD.begin(SS2_PIN)) { digitalWrite(ERR_PIN, HIGH); analogWrite(LED_OK, 0); ERROR_BEEP(); goto initsd; } else { digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); digitalWrite(ERR_PIN, LOW); analogWrite(LED_OK, 255); } } void IDRFID() { //чтение RFID метки digitalWrite(SS1_PIN, LOW); digitalWrite(SS2_PIN, HIGH); digitalWrite(RST_PIN, LOW); //костыль SPI.begin(); mfrc522.PCD_Init(); if ( ! mfrc522.PICC_IsNewCardPresent()) //ожидание метки return; if (! mfrc522.PICC_ReadCardSerial()) //считывание ID return; for (byte i = 0; i < mfrc522.uid.size; i++) { ID = ID + String(mfrc522.uid.uidByte[i], HEX); } digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); digitalWrite(RST_PIN, HIGH); //костыль DETECTED(); delay(2000); } void DETECTED () { //проверка меток Serial.println(ID); st = ""; if (MASTER.equals(ID) == true) { //если мастер KEY if (analogRead(4) < 500) { Start(); analogWrite(LED_OK, 0); delay(300); // Serial.println(F("Запись новой RFID")); //для теста ADD_KEY(); goto br; } W_LOG(); open_beep(); rele(); delay(10); ID = ""; goto br; } else { //если не мастер KEY digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, LOW); char ch = ""; LIST = SD.open(F("RFID.txt"), FILE_READ); if (LIST) { while (LIST.available()) { ch = (char)LIST.read(); if (ch == ';') { if (ID.equals(st) == true) { Serial.println(st); W_LOG(); open_beep(); rele(); delay(10); ID = ""; st = ""; goto br; } st = ""; } else { st = st + ch; ch = ""; } } LIST.close(); } else { Serial.println("ERROR OPEN FILES"); LIST.close(); } } br:; ID = ""; st = ""; digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); } void ADD_KEY() { //добавление метки ID = "" ; delay(5000); //задержка для поднесения новой метки if ( ! mfrc522.PICC_IsNewCardPresent()) { //ожидание метки goto au; } else { if (! mfrc522.PICC_ReadCardSerial()) //считывание ID return; for (byte i = 0; i < mfrc522.uid.size; i++) { ID = ID + String(mfrc522.uid.uidByte[i], HEX); } Start(); digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, LOW); LIST = SD.open(F("RFID.txt"), FILE_WRITE); if (LIST) { LIST.print(ID); LIST.print(F(";")); } LIST.close(); ID = "" ; } au:; digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); delay(50); open_beep(); analogWrite(LED_OK, 255); } void W_LOG() { //запись лога digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, LOW); LIST = SD.open(F("LOG.txt"), FILE_WRITE); if (LIST) { LIST.print(time.gettime(F("d/m/Y; H:i:s"))); LIST.print(F(" ")); LIST.println(ID); } LIST.close(); } void GSM_PING() { //ожидание и проверка данных от GSM uint8_t ch = 0; //переменная для GSM String val = F(""); //переменная для данных GSM st = ""; if (mySerial.available()) { //есть данные от GSM модуля delay(500); //выждем, чтобы строка успела попасть в порт целиком раньше чем будет считана while (mySerial.available()) { //сохраняем входную строку в переменную val ch = mySerial.read(); val += char(ch); delay(10); } if (val.indexOf(F("RING")) > -1) { //если обнаружен звонк "RING" num = val.substring(18, 30); digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, LOW); LIST = SD.open(F("REG_NUM.txt")); //проверка записей в REG_NUM.txt if (LIST) { while (LIST.available()) { ch = (char)LIST.read(); if (ch == ';') { if (ID.equals(num) == true) { W_LOG(); rele2(); open_beep(); delay(10); num = ""; st = ""; goto brg; } st = ""; } else { st = st + ch; ch = ""; } } } LIST.close(); brg:; mySerial.println(F("ATH0")); delay(50); val = ""; num = ""; digitalWrite(SS1_PIN, HIGH); digitalWrite(SS2_PIN, HIGH); } } } void loop() { if (Serial.available() > 0) { byte pas; //переменная для работы серийным портом char cp = ""; int sek, minut, chas, den, mes, god, den_ned; pas = Serial.read(); String port = F(""); if (pas == '9') { if (Serial.available() > 0) { port = Serial.readStringUntil(';'); //переменная для установки даты и времени sek = port.substring(0, 2).toInt(); minut = port.substring(2, 4).toInt(); chas = port.substring(4, 6).toInt(); den = port.substring(6, 8).toInt(); mes = port.substring(8, 10).toInt(); god = port.substring(10, 12).toInt(); den_ned = port.substring(12, 13).toInt(); time.settime(sek, minut, chas, den, mes, god, den_ned); //настройка времени и даты //(сек,мин,час, день, мес, год, номер дня недели) Serial.println(F("Время и дата установлены!")); Serial.print(F("Текущее время и дата: ")); Serial.println(time.gettime(F("d-m-Y, H:i:s, D;"))); } goto ext; } } ext:; IDRFID(); delay(10); GSM_PING(); delay(50); InitSD(); }
В смысле мало места ? Вам сколько записей то надо ? Во флеш 328ой можно тысяч пять напихать номеров телефона, и останется ещё под программу 12кб. Если этого мало , возьмите 2560, туда влезет тысяч 60, номеров. А вот скорость проверки базы, хранящейся на sd будет унылая. В качестве хранилища логов ещё подойдёт, но не в качестве хранения базы номеров.
У меня программа занимает 26500 и 830 динамической, скорость не сильно важна, эта прошивка будет работать как система пропуска на территорию. Дело в том, что номера записываешь на флешку, вот и всё обновление, а так каждый раз прошиваться нужно.
код просто кровь из глаз. Куча повторов, невероятное число делеев, переходы по метке. Есди бы этот г-код работал, я бы очень удивился. Вы сами-то в нем хоть что-то понимаете? Вот такую инициализацию строки вам кто показал? Код (C++): String port = F(""); Можете своими словами прокомментировать, к чему тут F() ?
На форуме наткнулся, когда искал как сэкономить динамическую память. F() это для того что бы переменная записывалась в постоянную память при компиляции , а не в динамическую. Код писал сам, поэтому такой и «корявый», я не великий спец в ардуино. Да, код я этот замечательно, читаю, у меня проблема при обращении к флешке при проверке меток из файла (функция DETECTED), при многократном циклическом обращении к файлу, перестаёт видеть файл, но флешку при этом замечательно видит, после перезагрузки всё повторяется.
вы в этой фразе противоречия не замечаете? Если _переменную_ записать в _постоянную_ память - она перестанет быть переменной, а станет константой - то есть ее нельзя будет изменить. А запись F(""); - это бред вдвойне, потому что двойными кавычками обозначается пустая строка. Что вы собрались сохранять в "постоянной памяти" - пустое место? И еще и заботитесь, чтобы это пустое место поменьше места занимало )) Поэтому я и спрашиваю, много ли вы в этом коде понимаете, когда вижу в нем такие строки . рад за вас. Не могу сказать того же про себя., я в этом коде ничего не понимаю. Так что помочь вам не смогу.
Прошу прощения я не правильно выразился, и вот нашёл, где я это подсмотрел https://alexgyver.ru/lessons/code-optimisation/#Использовать_F_макро
Ну там то говорится не о пустой строке. А у вас пустая строка. Смысл? Да и дальше ошибка: Код (C++): char ch = ""; char сh - переменная байтовая. Зачем вы в нее адрес пустой строки записываете? Вы включите Compiler warnings: ALL, и вас завалит варнингами от вашего кода. Включается здесь: А каждый варнинг - звоночек, что-то тут не так. После метки <;> ставить не нужно, но оптимизатор это выкидывает.
был случай, когда из-за варнинга компилятором выкидывался целый кусок кода и программа в целом работала криво.
Нужно разбираться с каждым варнингом, не зря он появляется. Я обычно их внимательно смотрю, и убираю прямым преобразованием, если так и задумано.
Этот код у меня работает, при компиляции проблем нет, проблема только при работе, несколько раз файл для работы открывается, но через несколько циклов перестаёт открываться…
Так и будет, если есть ошибки с размерами буферов, некорректными типами и т.д. Вы возьмите пример с ардуино.сс там записывается текст в файл на SD карту, потом один раз читается и кидается в монитор порта. В loop() там ничего нет, а я скопировал чтение из файла в loop() и добавил delay(2000); в конце. SS пин указал как у вас. Вот код: Код (C++): /* SD card read/write This example shows how to read and write data to and from an SD card file The circuit: SD card attached to SPI bus as follows: ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 8 created Nov 2010 by David A. Mellis modified 9 Apr 2012 by Tom Igoe This example code is in the public domain. */ #include <SPI.h> #include <SD.h> File myFile; void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.print("Initializing SD card..."); if (!SD.begin(8)) { Serial.println("initialization failed!"); while (1); } Serial.println("initialization done."); // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. myFile = SD.open("test.txt", FILE_WRITE); // if the file opened okay, write to it: if (myFile) { Serial.print("Writing to test.txt..."); myFile.println("testing 1, 2, 3."); // close the file: myFile.close(); Serial.println("done."); } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } // re-open the file for reading: myFile = SD.open("test.txt"); if (myFile) { Serial.println("Setup test.txt:"); // read from the file until there's nothing else in it: while (myFile.available()) { Serial.write(myFile.read()); } // close the file: myFile.close(); } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } } void loop() { // re-open the file for reading: myFile = SD.open("test.txt"); if (myFile) { Serial.println("Loop test.txt:"); // read from the file until there's nothing else in it: while (myFile.available()) { Serial.write(myFile.read()); } // close the file: myFile.close(); } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } delay(2000); } Попробуйте его скомпилировать и загрузить. И понаблюдайте, в мониторе порта будут ли проблемы с чтением из файла. Если не будет проблем и будет читаться без ошибок - проблема в вашем коде.
Вопрос решён, был не закрыт файл и открывался другой, эти модули не поддерживают открытие нескольких файлов одновременно.