SIM800L, реализация алгоритма формирующего sms на кириллице
- Войдите на сайт для отправки комментариев
Есть GSM модуль SIM800L. Если специальным образом сформировать сообщение, то можно отправить sms на кириллице. Как формируется узнал тут: http://www.edgemodem.ru/forum/viewtopic.php?f=8&t=901
Цитирую:
Само сообщение состоит из HEX-последовательности, прописанной ASCII-символами (0..9,A..F). Пример - надо отправить сообщение абоненту +79212345678 и в нем написать 'Привет'. ВНИМАНИЕ! РЕЧЬ ИДЕТ О ТОМ, КАК ЭТО СДЕЛАТЬ ПРОГРАММНО (или через HyperTerminal), А НЕ С ПОМОЩЬЮ, например, SiMoCo. Т.е. ручками. Итак: 1. Берем бумажку и составляем последовательность: 00 - всегда - это означает, что телефон/модем берет адрес сервис-центра SMS из Симки 11 - всегда 00 - указывает, что в качество отправителя будет указан собственный номер тел/модема 0B - длина цифр телефонного номера = 11(дес) 91 - указывает на интернациональный формат тел. номера (+7...) 9712325476F8 - номер адресата, которому отправляем SMS Тут интересно - 1. в начале записываем номер (на другую бумажку) 2. проверяем, четное ли количество цифр и если нет (как у нас - 11), добавляем в конце "F" 3. переставляем каждые две цифры местами - получаем результат В нашем случае: 79212345678 79212345678F 9712325476F8 00 - идентификатор протокола 08 - формат кодирования сообщения - в нашем случае - USC2 17 - время действия SMS возможные коды (дес) 0-143: (код + 1)*5минут - наш случай ((17H = 23дес) + 1)*5=120минут=2часа 144-167: 12 часов + (код - 143)*30минут 168-196: (код - 166) * 1день 197-255: (код - 192) * 1неделя 0C - количество байт в сообщении = количество символов*2, т.к. USC2 041F П 0440 р 0438 и 0432 в 0435 е 0442 т Коды символов соответствуют нормальному Unicode. Можно посмотреть, например, встроенную программу "Таблица символов", выбрать шрифт, например Arial, прокрутить вниз до начала кириллицы и посмотреть их коды (отображаются в HEX-виде внизу окна). 2. Даем команду тел/модему AT+CMGF=0 - включаем режим PDU AT+CMGS=26 - длина байтов сообщения (по 2 цифры), без учета первого нулевого байта >0011000B919712325476F80008170C041F04400438043204350442Ctrl+Z +CMGS: 13 - это уже ответ модема OK И еще. Тот же симоко, иногда почему-то, вставляет вместо первого нуля явный адрес сервис центра - 07919712999090F0 - понятно (см. выше), что это телефон 79219909090. Первый байт - длина последовательности (без него самого). Вроде все правильно, но MC35 возвращает ERROR. Причину не знаю.
А теперь нужно чтобы ардуино могла сама слать таике смс. Причём чтоб могда переводить в нужную кодировку.
Мне нужно отправлять смс по хозяйству вида: "Проникновение в гараж", "Напряжение в сети 200 Вольт", "Температура котла снизилась до 40 градусов" и т.д. Казалось бы нет проблем, заранее сформировал сам, а в ардуино вбить как переменную всё сообщение. Но так не получится, потому что служебные символы, которые в заголовке сообщения, должны учитываться, а сообщение содержит переменные. Получается, что заранее никак не просчитать. Поэтому нужно как-то реализовать на ардуино алгоритм, который мог бы в итоге составить смс на кириллице и отправить его. Я просмотрел множество библиотек, но не нашёл такого функционала. Может кто встречал нужный мне кусок кода? Или может для кого-то сделать этот код - дело двух минут, и он поделится им с общественностью?
Вариант отправлять тексты транслитом не проходит, только кириллица ?
Вариант отправлять тексты транслитом не проходит, только кириллица ?
Очень желательно кириллицу. Я уже сделал систему различных оповещений для деда и бабушки на транслите. Им совершенно не понятно что на транслите написано, он их просто пугает.
А если так, как описано здесь http://forum.amperka.ru/threads/gprs-shield-v-2-arduino-uno.2955/#post-25495 ?
Правда с переменными сложнее будет.
А эту http://users.skynet.be/moustic/PduEncoder.zip библиотеку пробовали ?
А это https://sites.google.com/site/marthalprojects/home/arduino/arduino-sends-SMS читали ?
Спасибо! Я это изучу.
Sirocco, а проблема в чём? Вроде всё подробно описано - просто делай как написано и всё. Вы не можете запрограммировать то, что у Вас описано или можете, но оно не работает? В чём беда-то?
Sirocco, а проблема в чём? Вроде всё подробно описано - просто делай как написано и всё. Вы не можете запрограммировать то, что у Вас описано или можете, но оно не работает? В чём беда-то?
Беда была в последней части этой статьи: https://sites.google.com/site/marthalprojects/home/arduino/arduino-sends-SMS
Пока нет времени попробовать, но похоже это то, что нужно.
Ничего не понял, ну, ладно, Вам виднее.
Кое как сделал рабочий скетч отправки СМС на кириллице с GSM sim800L ну или sim900 тоже будет работать. Для исходящих СМС с модуля используется формат PDU. Принимаются СМС в обычном текстовом режиме. Перед заливкой в ардуино скетч нужно скопировать в новое окно (в новый скетч) и не сохраняя на компе залить в ардуино. Это нужно так как имеется косяк с кодировками кириллицы.
#include <EEPROM.h> // для GSM модуля ********************* #include <SoftwareSerial.h> SoftwareSerial mySerial(7, 8); //Rx, Tx На этот порт GSM модуль String currStr = ""; String TelNumber1 = "000000000000"; String TelNumber2 = "000000000000"; String BufferNumber = "000000000000"; String DelSMS = "AT+CMGDA=\"DEL ALL\"\r"; String phone_nr=""; String message= ""; bool SaveNumber2 = 0; // флаг, когда необходима запись номера#2, он true int isStringMessage = 0; int KTOzapros = 0; int KTOreport = 1; // пример переменных, используемых в проекте int Temp1 =45; int Temp2 =11; int Temp3 =20; bool device = 0; bool trevoga = 0; bool alarmSMS = false; int TimeWorkDevice_1 = 10; void setup() { delay (10000); // Serial.begin (9600); // Serial.print ("Restart"); mySerial.begin(19200); delay(2000); NastroykaGSM (); for (int i=0; i<12; i++) TelNumber1[i] = EEPROM.read (i+10); for (int i=0; i<12; i++) TelNumber2[i] = EEPROM.read (i+30); } void loop() { if (trevoga && !alarmSMS) AlarmSMS(); readSMS(); } void NastroykaGSM () { mySerial.print("AT+CMGF=1\r"); //устанавливает текстовый режим смс-сообщения delay(400); mySerial.print("AT+IFC=1, 1\r"); //устанавливает программный контроль потоком передачи данных delay(400); mySerial.print("AT+CPBS=\"SM\"\r"); //открывает доступ к данным телефонной книги SIM-карты delay(400); mySerial.print("AT+GSMBUSY=1\r"); //запрет всех входящих звонков delay(400); mySerial.print("AT+CNMI=1,2,2,1,0\r"); //включает оповещение о новых сообщениях delay(400); mySerial.print(DelSMS); // удаляем все смс, ки delay(2000); } void readSMS() //_____Цикл чтения входящих СМС-сообщений______________ { if (!mySerial.available()) return; char currSymb = mySerial.read(); // Serial.print (currSymb); if ('\r' == currSymb) { if (isStringMessage!=0&&isStringMessage!=10) //если текущая строка - SMS-сообщение, отреагируем на него соответствующим образом { if (currStr.equalsIgnoreCase("ZAPROS")) { SMSzapros();} // Запрос состояния параметров (переменных проекта) по СМС else if (currStr.equalsIgnoreCase("ZAPROSTEL")) { SMSzaprosTEL();} // Передача сохраненных номеров телефонов пользователей по СМС else if (currStr.equalsIgnoreCase("device_1-ON")) {if (!device) {device = 1; // тут что то включаем по этой команде, если например булевая переменная device - 0 выключена ; if (isStringMessage == 1) {phone_nr = TelNumber1; } else if (isStringMessage == 2) {phone_nr = TelNumber2; } message = "Устройство_1 ВКЛ"; EndSMS();} else {if (isStringMessage == 1) phone_nr = TelNumber1; // ничё не делаем, т.к. булевая переменная device - 1 и так включена ; else if (isStringMessage == 2) phone_nr = TelNumber2; message = "Устройство_1 уже было включено"; EndSMS();}} else if (currStr.equalsIgnoreCase("device_1-OFF")) {if (device) {device = 0; // тут выключаем устройство, если например булевая переменная Work - 1 включена ; if (isStringMessage == 1) {phone_nr = TelNumber1; } else if (isStringMessage == 2) {phone_nr = TelNumber2; } message = "Устройство_1 ВЫКЛ"; EndSMS();} else {if (isStringMessage == 1) phone_nr = TelNumber1; // ничё не делаем, т.к. булевая переменная device - 0 и так выключена ; else if (isStringMessage == 2) phone_nr = TelNumber2; message = "Устройство_1 уже было выключено"; EndSMS();}} else if (currStr.endsWith("min")) {TimeWorkDevice_1 = currStr.toInt()*60000UL; // для задания время цикла работы отправить сообщение вида "25 min", где 25 время работы в мин if (TimeWorkDevice_1>3540000UL) TimeWorkDevice_1 = 3540000UL; if (TimeWorkDevice_1<=600000UL) TimeWorkDevice_1 = 600000UL; EEPROM.write(1,TimeWorkDevice_1/60000UL); if (isStringMessage == 1) phone_nr = TelNumber1; else if (isStringMessage == 2) phone_nr = TelNumber2; message = ("Время работы Устройства_1: "); message+= String (currStr.toInt()); message += ("мин"); EndSMS();} else if (currStr.equalsIgnoreCase("ResetNumbers")) {if (isStringMessage == 1) phone_nr = TelNumber1; else if (isStringMessage == 2) phone_nr = TelNumber2; message = "Тел.номера пользователей стерты из памяти"; EndSMS(); TelNumber1 = "000000000000"; TelNumber2 = "000000000000"; for (int i=0; i<12; i++) {EEPROM.write (i+10, TelNumber1[i]); EEPROM.write (i+30, TelNumber2[i]); }} else if (currStr.equalsIgnoreCase("WriteNumber2")&& isStringMessage == 1) { SaveNumber2 = 1; phone_nr = TelNumber1; message = "Отправьте любое СМС с номера#2 для его сохранения"; EndSMS();} else if (currStr.equalsIgnoreCase("Balance")) SMSbalance(); isStringMessage = 0; } else if (isStringMessage==10){ if (currStr.equalsIgnoreCase("WriteNumber1")) { TelNumber1 = BufferNumber; for (int i=0; i<12; i++) {EEPROM.write (i+10, BufferNumber[i]);} phone_nr = TelNumber1; message = "Тел. номер #1 сохранен"; EndSMS(); } else if (currStr.equalsIgnoreCase("ZAPROS")) SMSzapros(); else if (currStr.equalsIgnoreCase("ZAPROSTEL")) SMSzaprosTEL(); // Передача номеров телефонов пользователей по СМС isStringMessage = 0; } else if (isStringMessage==0) { if (TelNumber1!="000000000000" && !SaveNumber2 && TelNumber1!="яяяяяяяяяяяя"){ if (currStr.startsWith("+CMT: \""+TelNumber1)) { isStringMessage = 1; KTOzapros = 1; } else if (currStr.startsWith("+CMT: \""+TelNumber2)) { isStringMessage = 2; KTOzapros = 2; } else if (currStr.startsWith("+CUSD: 0,")) //если текущая строка начинается с "+CUSD",то следующая строка является запросом баланса { if (KTOzapros == 1) phone_nr = TelNumber1; else if (KTOzapros == 2) phone_nr = TelNumber2; message = currStr; EndSMS(); } } else if (currStr.startsWith("+CMT:") && !SaveNumber2) { isStringMessage = 10; for (int i =0; i<12; i++) {BufferNumber[i]=currStr[i+7];}} else if (currStr.startsWith("+CMT:") && SaveNumber2) { for (int i =0; i<12; i++) {BufferNumber[i]=currStr[i+7];} TelNumber2 = BufferNumber; for (int i=0; i<12; i++) {EEPROM.write (i+30, BufferNumber[i]);} phone_nr = TelNumber2; message = "Ваш номер сохранен в памяти как номер#2"; EndSMS(); SaveNumber2 = 0; } } currStr = ""; } else if ('\n' != currSymb) { currStr += String(currSymb);} } void EndSMS () { String newphone_nr; int numlength; mySerial.print("AT+CMGF=0\r"); delay(200); numlength=phone_nr.length()-1; if (numlength% 2 != 0 ) { phone_nr += "F"; } for(int x = 0; x < numlength; x = x+2){ newphone_nr.concat(phone_nr.charAt(x+2)); newphone_nr.concat(phone_nr.charAt(x+1));} byte textbyte[200] = {0}; for (int i=0; i<message.length(); i++){ textbyte[i]= byte(message[i]); } int k = 0; int n=0; while ( k<(message.length()*2)) { byte b0 = byte (message[k]); if (b0<128) {textbyte[k+n] = 0; textbyte[k+n+1] = message[k]; } else { int val = b0+0x350; byte b1 = ( byte )( val >> 8 ); textbyte[k+n] = b1; byte b2 = ( byte )val; textbyte[k+n+1] = b2; } k++; n++; } int pdu_length = 0; int textlength = message.length()*2; // text message length: number of characters*7/8 // Serial.println ((message.length()*2), HEX); if ((message.length()*2) != 0) {textlength++;} if (numlength%2 != 0) { //if the length of phone number was uneven, it now increases by 1 because of the added "F" pdu_length = (7 + (numlength+1)/2 + textlength); } else { //8 bytes of parameters + (length of phonenumber)/2 + number of bytes in the text pdu_length = (7 + numlength/2 + textlength); } mySerial.print("AT+CMGS="); //message will be stored in the mobile phone - AT+CMGS will send it off. // Serial.print("AT+CMGS="); //message will be stored in the mobile phone - AT+CMGS will send it off. mySerial.println(pdu_length); // Serial.println(pdu_length); delay(3000); mySerial.print("001100"); //these are some parameters which we don't need to bother about // Serial.print("001100"); //these are some parameters which we don't need to bother about if (numlength<16){ //now we have to send the byte containing the length of the phone number in HEX format mySerial.print(0); // Serial.print(0); } //the byte in HEX format needs to be 2 characters long; if needed we add a 0 in front, e.g. "C" will become "0C" mySerial.print(numlength,HEX); // Serial.print(numlength,HEX);//length telnr - this time any additional F is not to be considered mySerial.print("91"); // Serial.print("91");//international format of phone number //81 for national format mySerial.print(newphone_nr); // Serial.print(newphone_nr);//now we send the rearranged phone number mySerial.print("0008AA"); // Serial.print("0008AA");//some more parameters if ((message.length()*2)<16){ mySerial.print(0); // Serial.print(0); } //now a byte in HEX format indicating the length of the text. Again the byte needs to be made of 2 characters mySerial.print((message.length()*2),HEX); // Serial.print((message.length()*2),HEX); for (int i=0; i<(message.length()*2); i++){ if (textbyte[i]<16) {mySerial.print (0); //Serial.print (0); } mySerial.print (textbyte[i], HEX);} delay (3000); mySerial.println((char)26); // Команда отправки СМС delay(3500); message = ""; phone_nr = ""; pdu_length=0; newphone_nr=""; numlength=0; mySerial.print(DelSMS); // удаляем все смс, ки delay(2500); mySerial.print("AT+CMGF=1\r"); delay (500); } void SMSzapros() { if (isStringMessage == 10){ phone_nr = BufferNumber; message = "Тел.номер #1 не записан. Управление невозможно!"; // message+= ("Тел.#1: "); message+=String (TelNumber1); message+="\r\n"; // message+= ("Тел.#2: "); message+=String(TelNumber2); } else { if (isStringMessage == 1) phone_nr = TelNumber1; else if (isStringMessage == 2) phone_nr = TelNumber2; if (device) message = "Устройство_1 ВКЛ\r\n"; else message ="Устройство_1 ВЫКЛ\r\n"; if (trevoga) message += ("Внимание! Тревога!\r\n"); message +=("Температура_1: "); message += String (Temp1); message +=("*C"); // message +=("Температура_2: "); message += String (Temp2); message +=("*C"); // message +=("Температура_3: "); message += String (Temp3); message +=("*C"); } EndSMS(); } void SMSzaprosTEL(){ if (isStringMessage == 1) phone_nr = TelNumber1; else if (isStringMessage == 2) phone_nr = TelNumber2; else if (isStringMessage == 10) phone_nr = BufferNumber; message = ("Тел.#1: "); message+=String (TelNumber1); message+="\r\n"; message+= ("Тел.#2: "); message+=String(TelNumber2); EndSMS(); } void SMSbalance() { mySerial.print("AT+CMGF=1\r"); delay(200); mySerial.println ("AT+CUSD=1,\"#100#\""); delay(2000); } void AlarmSMS() { phone_nr = TelNumber1; message = ("Внимание!!! Тревога! Сирена Вкл!"); EndSMS(); phone_nr = TelNumber2; message = ("Внимание!!! Тревога! Сирена Вкл!"); EndSMS(); alarmSMS = true; }Есть проблема, что большое СМС не получается отправить, т.к. всё сообщение должно записаться в одну строку String и потом перейти в массив байтов . На это видимо не хватает оперативки, и ардуино начивает нехило глючить или перезагружается. Подскажите , какие могут быть пути решения для оптимизации скетча?
Может использовать SD карту для хранения строковых констант и других String ов?
Подскажите , какие могут быть пути решения для оптимизации скетча?
Неизменные строки положить в PROGMEM, от использования String отказаться полностью. перейти на использование C-style char arrays.
Макс. вы уже который раз об этом спрашиваете... Вас видимо, ответы не устраивают. Надеетесь, что кто-то вдруг взмахнет волшебной палочкой и проблемы исчезнут сами собой? :)
конкретно об этом я не справшивал вроде. Про PROGMEM буду читать.
хотел добавить к предыдущему ответу. но не успел - вы уже ответили.
SD карта вам не поможет, потому что прежде чем использовать сохраненные на ней строки, их все равно сначала надо будет скопировать в оперативку. Напротив, ситуация станет только хуже, потому что сама библиотека работы с SD "жрет" память по черному.
ок, SD не вариант.
ПС. Загрузка оперативы глобальными переменными 67%. И это ещё совсем мало команд смс и нет остального чем управляем GSM. Похоже тяжела задачка для меги 328, но будем пробовать ваши варианты
ПС. Загрузка оперативы глобальными переменными 67%.
Есть еще хорошее правило - как можно меньше глобальных переменных. Используйте константы, макросы и локальные переменные.
Похоже тяжела задачка для меги 328
Не скромничайте. Это для Вас тяжёлая задачка, а не для меги 328 :)))
вы мне такими сообщениями весь настрой сбиваете. Клапауция хватает, лучше бы по делу
вы мне такими сообщениями весь настрой сбиваете. Клапауция хватает, лучше бы по делу
я тебе говорил по делу, что ты - глист.
тебе подсказали все возможные варианты решения твоей личной проблемы, но ты - глист, способный потреблять переваренное и добытое кем-то.
А ты не будь занозой в заднице. Проблема не только моя личная. Думаю пользователи форума не прочь овладеть посылкой смс на кириллице, сто процентов кому то ещё пригодится. про глиста ты загнул конечно, дружище. расслабься, я благодарен за предоставленную инфу, нужно время разобраться.
Думаю пользователи форума не прочь овладеть посылкой смс на кириллице, сто процентов кому то ещё пригодится.
под "овладеть" ты, конечно, подразумеваешь, что тебе кто-то притащит готовое или ты найдёшь в тырнетах готовое, но оно у тебя работать не будет и ты будешь возмущаться, что скетч по-дыбильному написан.
так себе представляешь процесс овладения? :D
кончай язвить а, да с моим уровнем пргограммирования нихера путнего не сделать. Но на чужих примерах и пытаюсь учится. У меня только так получается, читая теорию, всё бросить сразу хочется. А так Скил потихоньку качается. Если всё заработет, ничё не вижу плохого в том, что какой-нить чел взял скетч и пользуется. я вроде и не возмущаюсь, т.к. у самого скетчи такие же пока.
всё бросить сразу хочется.
дык ... ото ж :)
лучше бы по делу
А чего по делу? По делу Вы сами себе дано ответили, причём ответили Вы правильно, только ответ Вам не нравится, вот Вы и прячете голову в песок и пудрите мозг себе и нам.
Вот Вы пишете:
Ну??? И дальше чего???
У меня к Вам простой вопрос: нахера? Даю с разбивкой на-хе-ра Вы используете String, а потом преобразуете в char[]? Нахера? Вам память девать некуда? Другого объяснения не вижу.
Да и само использование String - у Вас же не ужас, а ужас-ужас-ужас! Вы выбрали САМЫЕ дорогие операции (типа concat) и юзаете их в хвост и в гриву! Нахера?
Вы читали мою стаьтю про String и память? Читали вообще мои заметки про память? Вот эту, например? Они вель приклеены сверху раздела! Исследовали свою программу MemroyExplorer'ом? Так сделайте это - сами ужаснётесь!
А ведь главное, Вы всё отлично понимаете! Так садитесь и изучайте работу с массивами символов. Объявите слово String матерным и недопустимым в приличном скетче и ... Вы удивитесь как много памяти у Вашего контроллера.
вот так бы сразу, а.
я хотел как проще, подозревал что памяти не хватит, но чтоб так быстро. Понято, перехожу на array char
почитал заметку про String, мой случай))
вопрос про текстовые константы или как там их назвать, используемые с - mySerial.print ("Вот эти строки"). Достаточно ли просто для высвобождения оперативки
mySerial.print("AT+CMGF=1\r");заменить на
mySerial.print(F("AT+CMGF=1\r"));поможет ли это?
Там по второй ссылке в моём прошлом посте, есть такая программа MemoryExplorer.
Делаете маленький пример со своим строками, запускаете так и эдак и смотрите на состояние памяти в том и в другом случае.
Во-первых получаете ответ на вопрос, а во-вторых привыкаете самостоятельно решать возникающие проблемы.
понял, работаем над собой
поможет ли это?
Макс, Вы меньше спрашивайте, а больше делайте. Пока вы писали это сообщение, я загрузил ваш скетч и заключил "Все эти строки" в макрос F(). И откомпилировал. И сразу увидел, что выигрыш есть, но небольшой. Заняло у меня это действо 8 минут, включая вход в Ардуино и создание нового скетча.
К сожалению, большая часть ваших строк - String - а с ними этот метод не работает. малой кровью не отделаетесь.
Перед заливкой в ардуино скетч нужно скопировать в новое окно (в новый скетч) и не сохраняя на компе залить в ардуино. Это нужно так как имеется косяк с кодировками кириллицы.
Костыль у вас имеется, а не рабочий код, вот и всё. Я вам приводил пример, повторюсь: https://github.com/Porokhnya/GreenhouseProject/blob/master/Main/PDUClasses.h - вот тут объявление всего ДВУХ классов, которые корректно и кодируют (в UCS2), и раскодируют SMS-сообщения в ЛЮБОЙ кодировке. Есть проверка на то, что SMS пришло с правильного номера, чтобы память раскодировкой не насиловать. Рядом валяется файл *.cpp, как это дело подключить к проекту и как юзать - доступно самому-самому джуниору (только вырезать ненужные include в cpp-файле, да чуть подточить, при необходимости). Собственно, эти классы являются некой компиляцией разнородного кода, найденного в сети, плюс - дописанный ручками нужный функционал. И будет вам автоматом SMS на любом языке, не только на кириллице - главное, чтобы строка, которую надо отправить по SMS - была в формате UTF-8, который, как известно, имеет переменную длину кодирования символа, т.е. туда впихуется практически всё, с точки зрения языков (думаю, вам хватит).
А вы непонятный секс с сохранением скетча развели.
А вы непонятный секс с сохранением скетча развели.
Ну, почему непонятный? Как раз понятный :)))
я делал перекодировку просто таблицей соответсвия
byte Rus1251keys[66] = {70, 60, 68, 85, 76, 84, 58, 80, 66, 81, 82, 75, 86, 89, 74, 71, 72, 67, 78, 69, 65, 123, 87, 88, 73, 79, 125, 83, 77, 34, 62, 90, 102, 44, 100, 117, 108, 116, 59, 112, 98, 113, 114, 107, 118, 121, 106, 103, 104, 99, 110, 101, 97, 91, 119, 120, 105, 111, 93, 115, 109, 39, 46, 122};а вдохновение и теорию я брал из этой статьи
http://i.voenmeh.ru/kafi5/Kam.loc/inform/UTF-8.htm
я делал перекодировку просто таблицей соответсвия
byte Rus1251keys[66] = {70, 60, 68, 85, 76, 84, 58, 80, 66, 81, 82, 75, 86, 89, 74, 71, 72, 67, 78, 69, 65, 123, 87, 88, 73, 79, 125, 83, 77, 34, 62, 90, 102, 44, 100, 117, 108, 116, 59, 112, 98, 113, 114, 107, 118, 121, 106, 103, 104, 99, 110, 101, 97, 91, 119, 120, 105, 111, 93, 115, 109, 39, 46, 122};а вдохновение и теорию я брал из этой статьи
http://i.voenmeh.ru/kafi5/Kam.loc/inform/UTF-8.htm
Ну тады исходник дайте, на предмет посмотреть ;)
Там банально один цикл
http://arduino.ru/forum/proekty/arduino-bluetooth-klaviatura-s-shifrovan...
я делал перекодировку просто таблицей соответсвия
byte Rus1251keys[66] = {70, 60, 68, 85, 76, 84, 58, 80, 66, 81, 82, 75, 86, 89, 74, 71, 72, 67, 78, 69, 65, 123, 87, 88, 73, 79, 125, 83, 77, 34, 62, 90, 102, 44, 100, 117, 108, 116, 59, 112, 98, 113, 114, 107, 118, 121, 106, 103, 104, 99, 110, 101, 97, 91, 119, 120, 105, 111, 93, 115, 109, 39, 46, 122};а вдохновение и теорию я брал из этой статьи
http://i.voenmeh.ru/kafi5/Kam.loc/inform/UTF-8.htm
Честно говоря, не вполне ясно, почему в этой таблице почти случайные числа. Если верить данным из статьи по ссылке, код Unicode для любого символа кириллицы получается прибавлением 848 к кодам символов win-1251. Выходит, все сложные алгоритмы и таблицы можно заменить одним арифметическим действием?
Если верить данным из статьи по ссылке, код Unicode для любого символа кириллицы получается прибавлением 848 к кодам символов win-1251. Выходит, все сложные алгоритмы и таблицы можно заменить одним арифметическим действием?
Если внимательно посмотреть соответствие кодировок 1251 и UTF-16:
https://ru.wikipedia.org/wiki/Windows-1251#.D0.9A.D0.BE.D0.B4.D0.B8.D1.8...
то можно заметить, что 64 символе кириллицы (по 32 заглавных и строчных) идут одним непрерывным блоком. Соответственно, все они действительно преобразуются добавлением константы.
Остается буква Ё/ё русского алфавита, а также несколько букв украинского (он же русинский), белорусского, сербского (он же черногорский) и македонского (болгарский целиком помещается в непрерывный 64-символьный блок). Ну и все остальные символы, присутствующие в 1251. Отсюда и "сложные алгоритмы".
Опять же, мы сеейчас говорим про UTF-16, а в Ардуино используется UTF-8 для преобразования которой в UTF-16 тоже нужны некоторые алгоритмы.
Я сейчас конкретно говорю о коде andycat, у него в табличке 66 значений, из чего следует что никаких белорусских или македонских символов там нет. Если все 64 символа русского алфавита за исключением Ё идут единым блоком, то нафига вообще эта таблицва соответсвий?
В русском алфавите 33 буквы, соответственно, 66 символов (различая строчные и прописные). И, повтоторюсь, таблицы далеко не исчерпываются буквами русского алфавита отличными от Ё.
Что касается конкретно кода andycat, то откуда там что берется и что чему соответствует, не разбирался т.к. не интересно. На 1251->utf не похоже. Может КОИ-8, 866, ГОСТ или еще чего. Например, я в своей библиотеке для OLED подобную таблицу делал для преобразования utf-8 в смещение в таблице знакогенератора, которое не аповторяло ни одну из известных таблиц, т.к. знакогенератор не содержал "лишних" с моей точки зрения символов.
Нет, у меня именно идёт преобразование из кода нажатой клавиатуры win1251 в UTF 8 одним действием, и оно работает. У компьютера буду только в понедельник и опишу все "на пальцах"
Вероятно, я бы понял, что Вы хотели сказать, если бы знал, что такое "клавиатура win1251".
С клавиатуры идёт ascii код, соответствующий нажатой кнопке латинской, я в массив забил именно латинские коды а не кириллицу win1251, возможно по этому и происходит недопонимание. Для преобразования из реальных кодов из win1251 достаточно массив поменять по таблице ссылку на которую я выше давал. Буду у компа после обеда - если необходимо - могу построено код прокомментировать.
Вообще-то с клавиатуры идут скан-коды, а в ASCII их преобразует уже драйвер клавиатуры. Который с тем же успехом может преобразовывать их в CP1251, КОИ8, UTF-16 и все, что душенька пожелает. А Вы из ASCII преобразуете в коды кириллицы букв, расположенных на тех же клавишах, что и латинница? Смысл?
А Вы из ASCII преобразуете в коды кириллицы букв, расположенных на тех же клавишах, что и латинница? Смысл?
он раскладку переключает и драйвер клавы даёт ему нужные символы ASCII
Да, мне было лень разбираться и русифицировать библиотеку PS2Keyboard.h и я сам сделал русификацию.