SIM800L, реализация алгоритма формирующего sms на кириллице

Sirocco
Offline
Зарегистрирован: 28.09.2013

Есть 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 градусов" и т.д. Казалось бы нет проблем, заранее сформировал сам, а в ардуино вбить как переменную всё сообщение. Но так не получится, потому что служебные символы, которые в заголовке сообщения, должны учитываться, а сообщение содержит переменные. Получается, что заранее никак не просчитать. Поэтому нужно как-то реализовать на ардуино алгоритм, который мог бы в итоге составить смс на кириллице и отправить его. Я просмотрел множество библиотек, но не нашёл такого функционала. Может кто встречал нужный мне кусок кода? Или может для кого-то сделать этот код - дело двух минут, и он поделится им с общественностью?

Araris
Offline
Зарегистрирован: 09.11.2012

Вариант отправлять тексты транслитом не проходит, только кириллица ?

Sirocco
Offline
Зарегистрирован: 28.09.2013

Araris пишет:

Вариант отправлять тексты транслитом не проходит, только кириллица ?

Очень желательно кириллицу. Я уже сделал систему различных оповещений для деда и бабушки на транслите. Им совершенно не понятно что на транслите написано, он их просто пугает. 

Araris
Offline
Зарегистрирован: 09.11.2012

А если так, как описано здесь http://forum.amperka.ru/threads/gprs-shield-v-2-arduino-uno.2955/#post-25495 ?

Правда с переменными сложнее будет.

Araris
Offline
Зарегистрирован: 09.11.2012

А эту http://users.skynet.be/moustic/PduEncoder.zip библиотеку пробовали ?

А это https://sites.google.com/site/marthalprojects/home/arduino/arduino-sends-SMS читали ?

Sirocco
Offline
Зарегистрирован: 28.09.2013

Спасибо! Я это изучу. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Sirocco, а проблема в чём? Вроде всё подробно описано - просто делай как написано и всё. Вы не можете запрограммировать то, что у Вас описано или можете, но оно не работает? В чём беда-то?

Sirocco
Offline
Зарегистрирован: 28.09.2013

ЕвгенийП пишет:

Sirocco, а проблема в чём? Вроде всё подробно описано - просто делай как написано и всё. Вы не можете запрограммировать то, что у Вас описано или можете, но оно не работает? В чём беда-то?

Беда была в последней части этой статьи:  https://sites.google.com/site/marthalprojects/home/arduino/arduino-sends-SMS

Пока нет времени попробовать, но похоже это то, что нужно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ничего не понял, ну, ладно, Вам виднее.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Кое как сделал рабочий скетч отправки СМС на кириллице с 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 ов?

 

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

Подскажите , какие могут быть пути решения для оптимизации скетча?

Неизменные строки положить в PROGMEM, от использования String отказаться полностью. перейти на использование C-style char arrays.

Макс. вы уже который раз об этом спрашиваете... Вас видимо, ответы не устраивают. Надеетесь, что кто-то вдруг взмахнет волшебной палочкой и проблемы исчезнут сами собой? :)

MaksVV
Offline
Зарегистрирован: 06.08.2015

b707 пишет:
Макс. вы уже который раз об этом спрашиваете... Вас видимо, ответы не устраивают. Надеетесь, что кто-то вдруг взмахнет волшебной палочкой и проблемы исчезнут сами собой? :)

конкретно об этом я не справшивал вроде. Про PROGMEM буду читать. 

b707
Offline
Зарегистрирован: 26.05.2017

хотел добавить к предыдущему ответу. но не успел - вы уже ответили.

SD карта вам не поможет, потому что прежде чем использовать сохраненные на ней строки, их все равно сначала надо будет скопировать в оперативку. Напротив, ситуация станет только хуже, потому что сама библиотека работы с SD "жрет" память по черному.

MaksVV
Offline
Зарегистрирован: 06.08.2015

ок, SD не вариант.

ПС. Загрузка оперативы глобальными переменными 67%. И это ещё совсем мало команд смс и нет остального чем управляем GSM. Похоже тяжела задачка для меги 328, но будем пробовать ваши варианты

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

ПС. Загрузка оперативы глобальными переменными 67%.

Есть еще хорошее правило - как можно меньше глобальных переменных. Используйте константы, макросы и локальные переменные.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

MaksVV пишет:

Похоже тяжела задачка для меги 328

Не скромничайте. Это для Вас тяжёлая задачка, а не для меги 328 :)))

MaksVV
Offline
Зарегистрирован: 06.08.2015

вы мне такими сообщениями весь настрой сбиваете. Клапауция хватает, лучше бы по делу

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

вы мне такими сообщениями весь настрой сбиваете. Клапауция хватает, лучше бы по делу

я тебе говорил по делу, что ты - глист.

тебе подсказали все возможные варианты решения твоей личной проблемы, но ты - глист, способный потреблять переваренное и добытое кем-то.

MaksVV
Offline
Зарегистрирован: 06.08.2015

А ты не будь занозой в заднице. Проблема не только моя личная. Думаю пользователи форума не прочь овладеть посылкой смс на кириллице, сто процентов кому то ещё пригодится. про глиста ты загнул конечно, дружище. расслабься, я благодарен за предоставленную инфу, нужно время разобраться. 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

Думаю пользователи форума не прочь овладеть посылкой смс на кириллице, сто процентов кому то ещё пригодится. 

под "овладеть" ты, конечно, подразумеваешь, что тебе кто-то притащит готовое или ты найдёшь в тырнетах готовое, но оно у тебя работать не будет и ты будешь возмущаться, что скетч по-дыбильному написан.

так себе представляешь процесс овладения? :D

MaksVV
Offline
Зарегистрирован: 06.08.2015

кончай язвить а, да с моим уровнем пргограммирования нихера путнего не сделать. Но на чужих примерах и пытаюсь учится. У меня только так получается, читая теорию, всё бросить сразу хочется. А так Скил потихоньку качается. Если всё заработет, ничё не вижу плохого в том, что какой-нить чел взял скетч и пользуется. я вроде и не возмущаюсь, т.к. у самого скетчи такие же пока. 

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

MaksVV пишет:

всё бросить сразу хочется.

дык ... ото ж :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

MaksVV пишет:

лучше бы по делу

А чего по делу? По делу Вы сами себе дано ответили, причём ответили Вы правильно, только ответ Вам не нравится, вот Вы и прячете голову в песок и пудрите мозг себе и нам.

Вот Вы пишете:

MaksVV пишет:
т.к. всё сообщение должно записаться в одну строку String и потом перейти в массив байтов . На это видимо не хватает оперативки

Ну??? И дальше чего???

У меня к Вам простой вопрос: нахера? Даю с разбивкой на-хе-ра Вы используете String, а потом преобразуете в char[]? Нахера? Вам память девать некуда? Другого объяснения не вижу.

Да и само использование String - у Вас же не ужас, а ужас-ужас-ужас! Вы выбрали САМЫЕ дорогие операции (типа concat) и юзаете их в хвост и в гриву! Нахера?

Вы читали мою стаьтю про String и память? Читали вообще мои заметки про память? Вот эту, например? Они вель приклеены сверху раздела! Исследовали свою программу MemroyExplorer'ом? Так сделайте это - сами ужаснётесь!

А ведь главное, Вы всё отлично понимаете! Так садитесь и изучайте работу с массивами символов. Объявите слово String матерным и недопустимым в приличном скетче и ... Вы удивитесь как много памяти у Вашего контроллера.

MaksVV
Offline
Зарегистрирован: 06.08.2015

вот так бы сразу, а. 

ЕвгенийП пишет:
У меня к Вам простой вопрос: нахера? Даю с разбивкой на-хе-ра Вы используете String, а потом преобразуете в char[]? Нахера? Вам память девать некуда? Другого объяснения не вижу.

я хотел как проще, подозревал что памяти не хватит, но чтоб так быстро. Понято, перехожу на array char

MaksVV
Offline
Зарегистрирован: 06.08.2015

почитал заметку про String, мой случай))

MaksVV
Offline
Зарегистрирован: 06.08.2015

вопрос про текстовые константы или как там их назвать, используемые с  -  mySerial.print ("Вот эти строки"). Достаточно ли просто для высвобождения оперативки

 mySerial.print("AT+CMGF=1\r");  

заменить на 

 mySerial.print(F("AT+CMGF=1\r"));  

поможет ли это?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Там по второй ссылке в моём прошлом посте, есть такая программа MemoryExplorer.

Делаете маленький пример со своим строками, запускаете так и эдак и смотрите на состояние памяти в том и в другом случае.

Во-первых получаете ответ на вопрос, а во-вторых привыкаете самостоятельно решать возникающие проблемы.

MaksVV
Offline
Зарегистрирован: 06.08.2015

понял, работаем над собой

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

поможет ли это?

Макс, Вы меньше спрашивайте, а больше делайте. Пока вы писали это сообщение, я загрузил ваш скетч и заключил "Все эти строки" в макрос F(). И откомпилировал. И сразу увидел, что выигрыш есть, но небольшой. Заняло у меня это действо 8 минут, включая вход в Ардуино и создание нового скетча.

К сожалению, большая часть ваших строк - String - а с ними этот метод не работает. малой кровью не отделаетесь.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

MaksVV пишет:

 Перед заливкой в ардуино скетч нужно скопировать в новое окно (в новый скетч) и не сохраняя на компе залить в ардуино. Это нужно так как имеется косяк с кодировками кириллицы. 

Костыль у вас имеется, а не рабочий код, вот и всё. Я вам приводил пример, повторюсь: https://github.com/Porokhnya/GreenhouseProject/blob/master/Main/PDUClasses.h - вот тут объявление всего ДВУХ классов, которые корректно и кодируют (в UCS2), и раскодируют SMS-сообщения в ЛЮБОЙ кодировке. Есть проверка на то, что SMS пришло с правильного номера, чтобы память раскодировкой не насиловать. Рядом валяется файл *.cpp, как это дело подключить к проекту и как юзать - доступно самому-самому джуниору (только вырезать ненужные include в cpp-файле, да чуть подточить, при необходимости). Собственно, эти классы являются некой компиляцией разнородного кода, найденного в сети, плюс - дописанный ручками нужный функционал. И будет вам автоматом SMS на любом языке, не только на кириллице - главное, чтобы строка, которую надо отправить по SMS - была в формате UTF-8, который, как известно, имеет переменную длину кодирования символа, т.е. туда впихуется практически всё, с точки зрения языков (думаю, вам хватит).

А вы непонятный секс с сохранением скетча развели.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DIYMan пишет:

А вы непонятный секс с сохранением скетча развели.

Ну, почему непонятный? Как раз понятный :)))

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

я делал перекодировку просто таблицей соответсвия

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

 

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

andycat пишет:

я делал перекодировку просто таблицей соответсвия

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

 

 

Ну тады исходник дайте, на предмет посмотреть ;)

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
b707
Offline
Зарегистрирован: 26.05.2017

andycat пишет:

я делал перекодировку просто таблицей соответсвия

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. Выходит, все сложные алгоритмы и таблицы можно заменить одним арифметическим действием?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

Если верить данным из статьи по ссылке, код 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 тоже нужны некоторые алгоритмы.

b707
Offline
Зарегистрирован: 26.05.2017

Я сейчас конкретно говорю о коде andycat, у него в табличке 66 значений, из чего следует что никаких белорусских или македонских символов там нет. Если все 64 символа русского алфавита за исключением Ё идут единым блоком, то нафига вообще эта таблицва соответсвий?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

В русском алфавите 33 буквы, соответственно, 66 символов (различая строчные и прописные). И, повтоторюсь, таблицы далеко не исчерпываются буквами русского алфавита отличными от Ё. 

Что касается конкретно кода andycat, то откуда там что берется и что чему соответствует, не разбирался т.к. не интересно. На 1251->utf не похоже. Может КОИ-8, 866, ГОСТ или еще чего. Например, я в своей библиотеке для OLED подобную таблицу делал для преобразования utf-8 в смещение в таблице знакогенератора, которое не аповторяло ни одну из известных таблиц, т.к. знакогенератор не содержал "лишних" с моей точки зрения символов.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Нет, у меня именно идёт преобразование из кода нажатой клавиатуры win1251 в UTF 8 одним действием, и оно работает. У компьютера буду только в понедельник и опишу все "на пальцах"

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

andycat пишет:
Нет, у меня именно идёт преобразование из кода нажатой клавиатуры win1251 в UTF 8 одним действием, и оно работает. У компьютера буду только в понедельник и опишу все "на пальцах"

Вероятно, я бы понял, что Вы хотели сказать, если бы знал, что такое "клавиатура win1251".

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

С клавиатуры идёт ascii код, соответствующий нажатой кнопке латинской, я в массив забил именно латинские коды а не кириллицу win1251, возможно по этому и происходит недопонимание. Для преобразования из реальных кодов из win1251 достаточно массив поменять по таблице ссылку на которую я выше давал. Буду у компа после обеда - если необходимо - могу построено код прокомментировать.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

andycat пишет:
С клавиатуры идёт ascii код, соответствующий нажатой кнопке латинской, я в массив забил именно латинские коды а не кириллицу win1251, возможно по этому и происходит недопонимание. Для преобразования из реальных кодов из win1251 достаточно массив поменять по таблице ссылку на которую я выше давал. Буду у компа после обеда - если необходимо - могу построено код прокомментировать.

Вообще-то с клавиатуры идут скан-коды, а в ASCII их преобразует уже драйвер клавиатуры. Который с тем же успехом может преобразовывать их в CP1251, КОИ8, UTF-16 и все, что душенька пожелает. А Вы из ASCII преобразуете в коды кириллицы букв, расположенных на тех же клавишах, что и латинница? Смысл?

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

andriano пишет:

А Вы из ASCII преобразуете в коды кириллицы букв, расположенных на тех же клавишах, что и латинница? Смысл?

он раскладку переключает и драйвер клавы даёт ему нужные символы ASCII

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Да, мне было лень разбираться и русифицировать библиотеку PS2Keyboard.h и я сам сделал русификацию.