Хранение 13-значного числа
- Войдите на сайт для отправки комментариев
Ср, 05/02/2020 - 21:46
Здравствуйте. Модулем RDM6300 считываю пропуска.
Код такой:
#include <SoftwareSerial.h>
SoftwareSerial RFIDSerial(7, 6); // RX, TX
uint8_t input;
String temp="";
void setup()
{
Serial.flush();
Serial.begin(19200);
RFIDSerial.begin(9600);
}
void loop(){
if (RFIDSerial.available() > 0) {
input = RFIDSerial.read();
temp+=input;
if (temp.length()==13) {
Serial.println(temp);
temp="";
}
}
}//loop
Нужно организовать хранение 13 символов, количество пропусков будет около 100 штук.
Заранее вписать все пропуска возможности нет.
Подскажите как хранить информацию.
Подскажите как хранить информацию.
В EEPROM, например.
Подскажите как хранить информацию.
Перевести в тип uint64_t, а потом, как сказали выше - в ЕЕПРОМ
Сто пропусков займут 100 * 8 = 800 байт, а емкость ЕЕПРОМ обычной Уно-Нано - 1024, так что влезет
Теперь, собственно, два вопроса, как перевести строку String в uint64_t?
uint64_t занимает 8 байт.
Не особо понимаю как осуществить запись более 1 байта в ячейку в EEPROM
Теперь, собственно, два вопроса, как перевести строку String в uint64_t?
скорее всего, придется писать свою функцию, библиотечные не умеют работать с uint64_t
Не особо понимаю как осуществить запись более 1 байта в ячейку в EEPROM
Никак. В одну ячейку ЕЕПРОМ пишется 1 байт, соответвенно каждый uint64_t займет 8 ячеек.
Никак. В одну ячейку ЕЕПРОМ пишется 1 байт, соответвенно каждый uint64_t займет 8 ячеек.
А как разбить uint64_t на 8 ячеек (байт) ?
А как разбить uint64_t на 8 ячеек (байт) ?
изучайте и делайте по аналогии
http://arduino.ru/forum/programmirovanie/zapis-i-chtenie-eeprom-peremennykh-tipa-float-unsigned-long-long-unsigned-int
А как разбить uint64_t на 8 ячеек (байт) ?
Пишете: делите по степеням двойки и заносите в восемь ячеек, читаете: по восемь ячеек на число и возводите в степени.
bwn, делить и возводить - это дорого. Старый добрый union jack решает проблему дёшево и сердито.
А как разбить uint64_t на 8 ячеек (байт) ?
Пишете: делите по степеням двойки и заносите в восемь ячеек, читаете: по восемь ячеек на число и возводите в степени.
Так мне более понятно.
1024 байт, по 8 байт на каждый пропуск, итого 1024/8=128 пропусков.
Хотел брать из стринга по два символа переводить в число и записывать....чувствется что это чушь.
Как делить по степеням, не понял.
#include <EEPROM.h> void setup() { uint64_t passCode = 1234ULL; uint8_t passNo = 22; passCode *= random(4321); EEPROM.put(passNo * sizeof(passCode), passCode); } void loop() {}Старый добрый union jack решает проблему дёшево и сердито.
Не ругайси, что есть бритишь флаг, растолмачь, я нихрена не математик.(((
Старый добрый union jack решает проблему дёшево и сердито.
Не ругайси, что есть бритишь флаг, растолмачь, я нихрена не математик.(((
typedef union { uint64_t full; uint8_t chunks[sizeof(full)]; } passCode_t; void setup() { Serial.begin(115200); passCode_t passCode; passCode.full = 0x1234ULL; // print() does not support uint64_t // Serial.print("full pass: 0x"); Serial.println(passCode.full, HEX); Serial.print("chunks: "); for (uint8_t chunkNo = 0x00; sizeof(passCode.chunks) > chunkNo; chunkNo++) { Serial.print(" 0x"); Serial.print(passCode.chunks[chunkNo], HEX); } } void loop() {}#include <EEPROM.h> void setup() { uint64_t passCode = 1234ULL; uint8_t passNo = 22; passCode *= random(4321); EEPROM.put(passNo * sizeof(passCode), passCode); } void loop() {}Прошу разъяснить что значит EEPROM.put(passNo * sizeof(passCode), passCode);
для чего умножаем 22 на 8
Положим, что passNo - порядковый номер пароля/идентификатора/etc.
Надеюсь, что у вас не было плана сгружать все 100 пропусков в одни и те же 8 ячеек?
#include <EEPROM.h> uint16_t Adress = 0; uint64_t CodKartu = 1234567890123;//13 символов void setup() { Serial.begin(19200); EEPROM.put(Adress,CodKartu); Adress+= sizeof(CodKartu); Serial.println(Adress); } void loop() { }Я записал своё число в ячейки начиная с адреса 0, соответственно следующий свободный адрес будет 8, всё верно.
Как мне назад получить своё число?
Надеюсь, что у вас не было плана сгружать все 100 пропусков в одни и те же 8 ячеек?
Нет нет, общий смысл я понял, что моё число это 8 байт, соответственно 8 ячеек памяти из 1024
https://www.arduino.cc/en/Reference/EEPROMGet
#include <EEPROM.h> uint16_t Adress = 0; uint64_t CodKartu = 1234567890123;//13 символов void setup() { Serial.begin(19200); EEPROM.put(Adress,CodKartu); Adress+= sizeof(CodKartu); Serial.println(Adress); uint64_t chislo=EEPROM.get(Adress,CodKartu); Serial.println(chislo); } void loop() { }Ругается на Serial.println(chislo);
Как я понимаю, Serial.println не поддерживает вывод uint64_t ?
Пока не поддерживает, увы.
#include <EEPROM.h> uint16_t Adress = 0; uint64_t CodKartu = 1234567890123;//13 символов void setup() { Serial.begin(19200); //EEPROM.put(Adress,CodKartu); //Adress+= sizeof(CodKartu); //Serial.println(Adress); uint64_t chislo=EEPROM.get(Adress,CodKartu); if (CodKartu==chislo){ Serial.println("Ok"); }else{ Serial.println("Error"); } }//setup void loop() { }Что-то не понимаю.
Записал число uint64_t CodKartu = 1234567890123;//13 символов
Потом в скетче меняю uint64_t CodKartu = 2224567890123;//13 символов
и не записываю
А условие всё равно выдает Ок, хоть числа и не равны
#include <EEPROM.h> uint16_t Adress = 0; uint64_t CodKartu = 55555;//13 символов //Печать числа uint64_t void print_uint64_t(uint64_t num) { char rev[128]; char *p = rev+1; while (num > 0) { *p++ = '0' + ( num % 10); num/= 10; } p--; while (p > rev) { Serial.print(*p--); } } //end void setup() { Serial.begin(19200); // EEPROM.put(Adress,CodKartu); // Adress+= sizeof(CodKartu); //Serial.println(Adress); uint64_t chislo=EEPROM.get(Adress,CodKartu); print_uint64_t(chislo); Serial.println(""); if (CodKartu==chislo){ Serial.println("Ok"); }else{ Serial.println("Error"); } }//setup void loop() { }Монитор порта:
Неправильно используется EEPROM.get()
См. пример в справочнике внимательней. Можете потренироваться на uint32_t, а потом заменить его на uint64_t
----
get()
Parameters
address: the location to read from, starting from 0 (int)
data: the data to read, can be a primitive type (eg. float) or a custom struct
Returns
A reference to the data passed in
-----------
#include <EEPROM.h> uint16_t Adress = 0; uint64_t CodKartu = 2234567890123;//13 символов //Печать числа uint64_t void print_uint64_t(uint64_t num) { char rev[128]; char *p = rev+1; while (num > 0) { *p++ = '0' + ( num % 10); num/= 10; } p--; while (p > rev) { Serial.print(*p--); } } //end void setup() { Serial.begin(19200); // EEPROM.put(Adress,CodKartu); //Adress+= sizeof(CodKartu); //Serial.println(Adress); uint64_t chislo_read; EEPROM.get(0,chislo_read); print_uint64_t(chislo_read); Serial.println(""); if (CodKartu==chislo_read){ Serial.println("Ok"); }else{ Serial.println("Error"); } }//setup void loop() { }Спасибо. Ошибку понял.
Теперь надо разобраться с String to uint64_t
//функция чтения из EEPROM переменной типа long long EEPROM_long_read(int addr) { //передаем в функцию адрес ячейки из которой читать byte raw[4]; for(byte i = 0; i < 4; i++) raw[i] = EEPROM.read(addr+i); long &num = (long&)raw; return num; } //возвращает считанное значение //==================== //функция записи в EEPROM переменной типа long void EEPROM_long_write(int addr, long num){//передаем в функцию адрес куда писать и данные что писать byte raw[4]; (long&)raw = num; for(byte i = 0; i < 4; i++) EEPROM.write(addr+i, raw[i]); }//ничего не возвращаетПерепиши под 64-битную переменную и пользуйся на здоровье.
bwn, делить и возводить - это дорого. Старый добрый union jack решает проблему дёшево и сердито.
Та нифига не дорого. Если с юнионом тяжко, можно сдвигать и складывать.)
bwn, делить и возводить - это дорого.
Спасибо
#include <SoftwareSerial.h> SoftwareSerial RFIDSerial(7, 6); // RX, TX #include <avr/wdt.h> #include <EEPROM.h> #define DEBUG #ifdef DEBUG #define SERIAL_BEGIN Serial.begin(19200) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINTLN(x) Serial.println (x) #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) #define SERIAL_BEGIN #endif uint8_t PropuskovEEPROM;//Число пропусков в EEPROM памяти String input,temp; bool FlagReads=true; unsigned long TimeReads; //Функция чтения из EEPROM String EEPROM_String_read(uint16_t addr) { String num; byte raw[8]; for(uint8_t i = 0; i < 8; i++){ raw[i] = EEPROM.read(addr+i); num = (String&)raw; } return num; } //Функция записи в EEPROM void EEPROM_String_write(uint16_t addr, String num){ byte raw[8]; (String&)raw = num; for(uint8_t i = 0; i < 8; i++){ EEPROM.write(addr+i, raw[i]); delay(10); } } void setup() { wdt_disable(); SERIAL_BEGIN; RFIDSerial.begin(9600); //for (int i = 0; i < EEPROM.length(); i++) EEPROM.update(i, 0); DEBUG_PRINTLN("Zagruzka"); PropuskovEEPROM=EEPROM.read(1000); DEBUG_PRINT("Propuskov v EEPROM - "); DEBUG_PRINT(PropuskovEEPROM); DEBUG_PRINTLN(""); for (uint8_t i = 0; i <= 100; i++){ DEBUG_PRINT("Nomer - "); DEBUG_PRINT(i); DEBUG_PRINT(" Adres - "); DEBUG_PRINT(i*8); DEBUG_PRINT(" Kod - "); DEBUG_PRINT(EEPROM_String_read(i*8)); DEBUG_PRINTLN(""); delay(5); } wdt_enable (WDTO_8S); } void loop() { wdt_reset(); if (RFIDSerial.available()>0 && FlagReads) { input = RFIDSerial.read(); temp+=input; if (temp.length()==26) { String kods=temp.substring(13, 26); DEBUG_PRINT("Schitannyi propusk: "); DEBUG_PRINT(kods); DEBUG_PRINTLN(""); EEPROM_String_write(PropuskovEEPROM*8,kods); FlagReads=false; TimeReads=millis(); temp=""; input=""; }//if (temp.length()==26) { }//if (RFIDSerial.available()>0 && FlagReads) { if (!FlagReads && millis()-TimeReads>=500){ FlagReads=true; while (RFIDSerial.available()) RFIDSerial.read(); } }//loopПомогите разобраться.
После считывания пропуска происходит запись в EEPROM.
Но после считывания кода пропуска ардуина нано перезагружается.
Иногда успевает записаться код пропуска, но не корректно.
Сижу, рыдаю над этим
042voidEEPROM_String_write(uint16_t addr, String num){043byteraw[8];044(String&)raw = num;045for(uint8_t i = 0; i < 8; i++){046EEPROM.write(addr+i, raw[i]);047delay(10);048}049}Watchdog ресетит или что-то другое?
raw[i] = EEPROM.read(addr+i); num = (String&)raw;Что вторая строчка должна значить?
Для начала отключить вачдог.
Отключив вачдог ардуина зависает.
Код я взял из образца выше, #25 пост (в нём не разобрался)
Код я взял из образца выше, #25 пост (в нём не разобрался)
так разберись сначала. Ты код перекорежил, не разбираясь - вот все и зависло. И так будет на каждой строчке, пока не начнешь учебники читать.
Было бы всё просто, не понимаю я что за & и для чего, не понимаю как стринг побайтно хранить.
Не храни стринг побайтно, храни byte[].
не понимаю как стринг побайтно хранить.
так ты сам себе проблемы создаешь. Вот ты в своем коде сначала читаешь код пропуска посимвольно (строка 82), потом запихиваешь его в стринг - а потом сам не знаешь, как его оттуда достать. Может тогда не надо String испольовать7
#include <SoftwareSerial.h> SoftwareSerial RFIDSerial(7, 6); // RX, TX #include <avr/wdt.h> #include <EEPROM.h> #define DEBUG #ifdef DEBUG #define SERIAL_BEGIN Serial.begin(19200) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINTLN(x) Serial.println (x) #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) #define SERIAL_BEGIN #endif String Propusk[]={ "1234514948663",// "5678517048553",// "6848715667788",// }; String chislo_read; uint16_t Adress=0; void setup() { wdt_disable(); SERIAL_BEGIN; RFIDSerial.begin(9600); for (int i = 0; i < EEPROM.length(); i++) EEPROM.update(i, 0); DEBUG_PRINTLN("Zagruzka"); //byte kodpropuska[Propusk.length()]; //Propusk.getBytes(kodpropuska, Propusk.length()); //DEBUG_PRINTLN( Propusk.length()); DEBUG_PRINT("Zapis` v adres - "); DEBUG_PRINT(Adress); DEBUG_PRINT(" Kod - "); DEBUG_PRINT(Propusk[0]); DEBUG_PRINTLN(""); EEPROM.put(Adress,Propusk[0]); Adress+= sizeof(Propusk[0]); DEBUG_PRINT("Zapis` v adres - "); DEBUG_PRINT(Adress); DEBUG_PRINT(" Kod - "); DEBUG_PRINT(Propusk[1]); DEBUG_PRINTLN(""); EEPROM.put(Adress,Propusk[1]); Adress+= sizeof(Propusk[1]); DEBUG_PRINT("Zapis` v adres - "); DEBUG_PRINT(Adress); DEBUG_PRINT(" Kod - "); DEBUG_PRINT(Propusk[2]); DEBUG_PRINTLN(""); EEPROM.put(Adress,Propusk[2]); Adress+= sizeof(Propusk[2]); EEPROM.get(0,chislo_read); DEBUG_PRINTLN(chislo_read); EEPROM.get(6,chislo_read); DEBUG_PRINTLN(chislo_read); EEPROM.get(12,chislo_read); DEBUG_PRINTLN(chislo_read); } void loop() { wdt_reset(); }Записывается, читается.
Код пропуска занимает 6 байт.
Всё ли верно?
Отключив вачдог ардуина зависает.
Код я взял из образца выше, #25 пост (в нём не разобрался)
Так потому и перезагружается, что зависла.
Ищи теперь в каком месте виснет.
Персональных Serial.print'ов навтыкай после каждой строки.
Поймёшь в каком месте виснет
Ничего не понимаю
String Propusk[]={ "12345149485666666689688998554545454589",// "567851704855375757557575757",// "68487156677887575757574545454",// };Добавил символов.
"читается корректно"? -уверен?
Ты в своем коде записываешь в ЕЕПРОМ не саму строку, а только ее адрес.
Чтоб проверить - запиши длинную строку в ЕЕПРОМ, выключи ардуину, подожди минут пять, чтоб все кондеры в БП разрядились - потом включи обратно и попробуй прочитать строку обратно в другую переменную.
короче, замаялся править предыдущее сообщение, никак не могу придумать метод проверки правильности чтения и записи в ЕЕПРОМ.
Как я уже писал, ты пишешь в ЕЕПРОМ не саму строку, а ее адрес в памяти. Когда у тебя статичные строки, заданные прямо в коде - их адрес не меняется и при такой "записи в ЕЕПРОМ" у тебя будет иллюзия, что все пишется и читается правильно.
Попробуй написать код, где строка вводится из Сериал - например с твоего считывателя. Потом запиши ее в ЕЕПРОМ. выключи ардуину, подожди... и потом попробуй прочитать строку обратно. Вот тут ты сразу убедишься. что в ЕЕПРОМ-то ничего и нет!
Тогда я не понимаю, как работает put()
Тебеговорили уже, что код ключей прекрасно укладывается в uint64_t. Пошто ты так не пишешь? Нахрена строки то приплетать?
Тогда я не понимаю, как работает put()
нет, ты не понимаешь, как устроен String. Это ссылочный тип, к нему EEPROM.put() get() напрямую неприменимы.
Впрочем, это повод задуматься над тем, о чем тебе написали несколько человек - о том что String в твоей программе только мешает.
#include <SoftwareSerial.h> SoftwareSerial RFIDSerial(7, 6); // RX, TX #include <avr/wdt.h> #include <EEPROM.h> #define DEBUG #ifdef DEBUG #define SERIAL_BEGIN Serial.begin(19200) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINTLN(x) Serial.println (x) #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) #define SERIAL_BEGIN #endif //Печать числа uint64_t void print_uint64_t(uint64_t num) { char rev[128]; char *p = rev+1; while (num > 0) { *p++ = '0' + ( num % 10); num/= 10; } p--; while (p > rev) { Serial.print(*p--); } } //end uint64_t propusk=1234567891234; uint16_t Adress=0; // Чтение uint64_t EEPROM_read(uint16_t addr) { byte raw[8]; for(byte i = 0; i < 8; i++) raw[i] = EEPROM.read(addr+i); uint64_t &num = (uint64_t&)raw; return num; } // Запись void EEPROM_write(uint16_t addr, uint64_t num) { byte raw[8]; (uint64_t&)raw = num; for(byte i = 0; i < 8; i++) EEPROM.write(addr+i, raw[i]); } void setup() { wdt_disable(); SERIAL_BEGIN; RFIDSerial.begin(9600); //for (int i = 0; i < EEPROM.length(); i++) EEPROM.update(i, 0); DEBUG_PRINTLN("Zagruzka"); EEPROM_write(Adress,propusk); Adress+= sizeof(propusk); DEBUG_PRINT("Svobodnaia iacheika: "); DEBUG_PRINT(Adress); DEBUG_PRINTLN(""); DEBUG_PRINT("Reads: "); print_uint64_t(EEPROM_read(0)); DEBUG_PRINTLN(""); } void loop() { wdt_reset(); }Верно?
не понимаю как стринг побайтно хранить.
так ты сам себе проблемы создаешь. Вот ты в своем коде сначала читаешь код пропуска посимвольно (строка 82), потом запихиваешь его в стринг - а потом сам не знаешь, как его оттуда достать. Может тогда не надо String испольовать7
081if(RFIDSerial.available()>0 && FlagReads) {082input = RFIDSerial.read();083temp+=input;084if(temp.length()==26) {085String kods=temp.substring(13, 26);Скажите, как мне сделать, чтобы можно было сравнивать с uint_64? хранимой в еепром
При считывании я получаю 26 символов, из которых полезные только 13 последних.
Скажите, как мне сделать, чтобы можно было сравнивать с uint_64?
написать свою собственную функцию конверсии строки в число, вот образец (не ардуино)
// Program to implement atoi() in C #include <stdio.h> // A simple atoi() function int myAtoi(char* str) { int res = 0; // Initialize result // Iterate through all characters of input string and // update result for (int i = 0; str[i] != '\0'; ++i) res = res * 10 + str[i] - '0'; // return result. return res; } // Driver program to test above function int main() { char str[] = "89789"; int val = myAtoi(str); printf("%d ", val); return 0; }только обрати внимание, что здесь строка - вовсе не String, а символьный массив
И тут я совсем ничего не понял...