Работа с SIM900
- Войдите на сайт для отправки комментариев
Пнд, 19/01/2015 - 13:22
Всем привет!
Прошу сильно не пинать, если плохо искал (я старался)
ПОмогите, пожалуйста новичку
Есть Ардуино Мега и SIM900 shield. пытаюсь получать на ардуину смс-ки, не могу решить проблему
если в программе есть что-то помимо получения данных от gsm шилда, то асть данных теряется
код:
#include <SoftwareSerial.h>
SoftwareSerial sim900(10, 3);
const int bufsize=256;
byte buffer[bufsize];
int count=0;
void setup(void) {
Serial.begin(9600);
Serial.println("Hello! Arduino starting ");
//starting sim900
sim900.begin(9600); // the GPRS baud rate
delay(500);
sim900.println("AT+IPR=9600"); // Set the baud rate
delay(500);
sim900.begin(9600); // the GPRS baud rate
delay(1000);
sim900.print("AT\r");
delay(300);
Serial.println("Initialized");
}
void GetBufffer()
{
if (sim900.available()) // if date is comming from softwareserial port ==> data is comming from gprs shield
{
while(sim900.available()) // reading data into char array
{
buffer[count++]=sim900.read(); // writing data into array
if(count == bufsize) {
Serial.print("##bufsize##");
break;
}
}
Serial.write(buffer,count); // if no data transmission ends, write buffer to hardware serial port
Serial.print("##");
Serial.print(count);
Serial.print("##");
clearBufferArray(); // call clearBufferArray function to clear the storaged data from the array
count = 0;
}
}
void clearBufferArray() // function to clear buffer array
{
for (int i=0; i<count;i++)
{ buffer[i]=NULL;} // clear all index of array with command NULL
}
String temp ="";
void loop(){
if (Serial.available()>0){
byte in = Serial.read();
if (char(in)=='%') in = byte(char(26));
if (!('^'==char(in))) {
temp+=char(in);
} else {
Serial.print("command: ");
Serial.println(temp);
sim900.print(temp);
sim900.print("\r");
temp = "";
}
}
GetBufffer();
}
при таком варианте работает как надо:
AT+IPR=9600 OK AT OK ##28##command: at at OK##7## ##2## +CMT:##7## "+79607777777","","15/01/19,12:18:19+12" Razdva tri chetyre pyat vyshel zayac pogulyat vdrug oho##98##tnik vybegaet prami v zaixhika strelyaet pif paf oi oi oi umira zyac moi la lya ya Razdvatri ##94## +CMT: "+79607##15##777777","","15/01/19,12:18:25+12" chetyre pyat vyshel zayac pogulyat vdrug ohotnik vybegaet prami v zaixhika strelyaet pif paf oi oi oi umiraet zaya##150##c moi lya lya lya ##19##
но если в loop еще что-то добавить (напр. delay(1000)), то выходит так:
Hello! Arduino starting Initialized AT+IPR=9600 OK AT OK ##28## +CMT: "+79607777777","","15/01/19,12:16:21+12" Razdva tri ch##63## +CMT: "+79607777777","","15/01/19,12:16:28+12" chetyre pyat##63##
В какое именно место программы вы delay() вставляете?
сразу после GetBufffer();
можно не delay, а другими задачами нагрузить, delay-просто эмуляция занятости (обработки других задач) в этом случае)
можете попробовать использовать библиотеку GSM_Shield
можете попробовать использовать библиотеку GSM_Shield
А что от этого глобально изменится?
Для начала уберите
clearBufferArray();из функцииGetBufffer();А еще, я на вашем месте отказался бы от программного порта. На Меге своих аппаратных 4 штуки...
Для начала уберите
clearBufferArray();из функцииGetBufffer();А еще, я на вашем месте отказался бы от программного порта. На Меге своих аппаратных 4 штуки...
порт переклчил на аппаратный, не помогло
а очистка буфера все равно же происходит после его вывода... разве это может влиять? впрочем попробую
попробовал - не помогло
Попробуй мой код, я с ним детям объяснял как работает.
#include <SoftwareSerial.h> SoftwareSerial gprsSerial(7, 8); void setup() { Serial.begin (9600); gprsSerial.begin(19200); // Настраиваем приём сообщений с других устройств // Между командами даём время на их обработку gprsSerial.print("AT+CMGF=1\r"); delay(300); gprsSerial.print("AT+IFC=1, 1\r"); delay(300); gprsSerial.print("AT+CPBS=\"SM\"\r"); delay(300); gprsSerial.print("AT+CNMI=1,2,2,1,0\r"); delay(500); } String currStr = ""; // Переменная принимает значение True, если текущая строка является сообщением boolean isStringMessage = false; void loop() { if (!gprsSerial.available()) return; char currSymb = gprsSerial.read(); if ('\r' == currSymb) { if (isStringMessage) { //если текущая строка - SMS-сообщение, //отреагируем на него соответствующим образом if (!currStr.compareTo("Lera")) { Serial.println ("Hello Lera"); } else if (!currStr.compareTo("Jula")) { Serial.println ("Hello Jula"); } isStringMessage = false; } else { if (currStr.startsWith("+CMT")) { //если текущая строка начинается с "+CMT", //то следующая строка является сообщением isStringMessage = true; } } currStr = ""; } else if ('\n' != currSymb) { currStr += String(currSymb); } }что еще примечательно, когда происходит пропажа данных, count всегда равен 63
Простите, такой немного отвлеченный вопрос: а как оно работает, если нет программного включения сим-шилда?
Простите, такой немного отвлеченный вопрос: а как оно работает, если нет программного включения сим-шилда?
Ручное включение в процессе отладки
накопал, что буфер для serial по умолчанию задан в 64*2 байт, при этом на входящие данные берется 64, поэтому, видимо, происходит пропажа данных после 64 байт (надо пробовать менять это значение в HardwareSerial.cpp)
но тогда возникает другой вопрос:
почему при таком коде
void setup(void) { Serial.begin(9600); Serial.println("Hello! Arduino starting "); //starting Serial1 Serial1.begin(9600); // the GPRS baud rate delay(500); Serial1.println("AT+IPR=9600"); // Set the baud rate delay(500); Serial1.begin(9600); // the GPRS baud rate delay(1000); Serial1.print("AT\r"); delay(300); Serial.println("Initialized"); } String str=""; int buf =NULL; void GetBufffer() { boolean mustlisten = true; if (Serial1.available()) // if date is comming from softwareserial port ==> data is comming from gprs shield { while(mustlisten || Serial1.available()) // reading data into char array { buf=Serial1.read(); if (buf==char('\r')) { buf=byte('^'); mustlisten = false; } else { mustlisten = true; } if (buf==char('\n')) { buf=byte('&'); mustlisten = false; } else { mustlisten = true; } if (!(buf==-1)) { Serial.print(char(buf)); str+=char(buf); } if (!mustlisten) { Serial.print("###"); Serial.print(str); // if no data transmission ends, write buffer to hardware serial port Serial.println("$$$"); str=""; } } } } void serialEvent1(){ GetBufffer(); } String temp =""; void loop(){ while (Serial.available()>0){ byte in = Serial.read(); if (char(in)=='%') in = byte(char(26)); if (!('^'==char(in))) { temp+=char(in); } else { Serial.print("command: "); Serial.println(temp); Serial1.print(temp); Serial1.print("\r"); temp = ""; } } Serial.print("delaying..."); delay(7000); Serial.println("...delayed"); }если в loop не стоит delay , то посылка от модема приходит полностью, даже если в ней больше 64 байт.
но если оставить delay в Loop, то после 64 байт зацикливается из-за отсутствия конца строки (mustlisten=true)
как delay влияет на буфер сериала?:)
Никак не влияет. Просто фаза луны.
Снова посоветую - откажитесь от программеного порта.
И еще - если вы не преследуете какую-то конкретную цель (минимальный размер, понты и т.п.) - воспользуйтесь классом String. Все будет просто и очевидно.
Никак не влияет. Просто фаза луны.
Снова посоветую - откажитесь от программеного порта.
И еще - если вы не преследуете какую-то конкретную цель (минимальный размер, понты и т.п.) - воспользуйтесь классом String. Все будет просто и очевидно.
в моем последнем комменте код уже с аппаратным портом и с классом String :)
спасибо за советы:)
Попробуй мой код, я с ним детям объяснял как работает.
#include <SoftwareSerial.h> SoftwareSerial gprsSerial(7, 8); void setup() { Serial.begin (9600); gprsSerial.begin(19200); // Настраиваем приём сообщений с других устройств // Между командами даём время на их обработку gprsSerial.print("AT+CMGF=1\r"); delay(300); gprsSerial.print("AT+IFC=1, 1\r"); delay(300); gprsSerial.print("AT+CPBS=\"SM\"\r"); delay(300); gprsSerial.print("AT+CNMI=1,2,2,1,0\r"); delay(500); } String currStr = ""; // Переменная принимает значение True, если текущая строка является сообщением boolean isStringMessage = false; void loop() { if (!gprsSerial.available()) return; char currSymb = gprsSerial.read(); if ('\r' == currSymb) { if (isStringMessage) { //если текущая строка - SMS-сообщение, //отреагируем на него соответствующим образом if (!currStr.compareTo("Lera")) { Serial.println ("Hello Lera"); } else if (!currStr.compareTo("Jula")) { Serial.println ("Hello Jula"); } isStringMessage = false; } else { if (currStr.startsWith("+CMT")) { //если текущая строка начинается с "+CMT", //то следующая строка является сообщением isStringMessage = true; } } currStr = ""; } else if ('\n' != currSymb) { currStr += String(currSymb); } }этот код работает, т.к. ответ модема при таких коротких смсках меньше 64 байт + других задач в коде нет, МК только и делает, что слушает порт (при таком раскладе и у меня все работало)
как и ожидалось, проблема решилась при увеличении буфера.
до каких значений его можно увеличить без опасений?:) 256*2 не много?:)
как и ожидалось, проблема решилась при увеличении буфера.
до каких значений его можно увеличить без опасений?:) 256*2 не много?:)
Так буфер, или String?
Так буфер, или String?
SERIAL_BUFFER_SIZE
А как и где именно вы его увеличили? Схожая проблема...кажется....
А как и где именно вы его увеличили? Схожая проблема...кажется....
\arduino\arduino\hardware\arduino\cores\arduino - hardwareserial.cpp
да, надо куда-то в фак такие сведения выложить бы - каждый второй при использовании gsm должен сталкиваться с такой проблемой
Сори...не увидел постом выше что менять надо в HardwareSerial.cpp А для SoftwareSerial есть ли такое значение?
не вдавался в подробности насчет SoftwareSerial, переткнул порты на HardwareSerial до того
Подниму темку. Вопрос назрел.
Какой максимальной длинны может быть одно сообщение, отправляемое с SIM900? Один пакет в 64 байта? Если так, то каким образом отправить SMS в стандартные 160 символов?
проблема со входящими данными с модема. исходящие можно передавать несколькими частями (хотя это не нужно), завершая команду управляющими символами
Дайте наглядный пример кода, для отправки в одно СМС 2 блока по 64 символа.
Sim900Serial.println("AT + CMGS = \"***********\"");//The target phone number delay(100); Sim900Serial.println("hello");//the content of the message delay(100); Sim900Serial.println((char)26);//the ASCII code of the ctrl+z is 26 delay(100); Sim900Serial.println();Sim900Serial.println("AT + CMGS = \"***********\"");//The target phone number delay(100); Sim900Serial.println("hello");//the content of the message delay(100); Sim900Serial.println((char)26);//the ASCII code of the ctrl+z is 26 delay(100); Sim900Serial.println();Этим способом я передам в строке 3 только 64 символа, а как передать 160?
Можно 3ю строку повторить несколько раз
А если я хочу передать 320 или 480 символов сообщение? Так же просто повторять строку до необходимого количества знаков?
void sendSMS () { gprsSerial.println("AT + CMGS = \"" + nomer1 + "\""); delay(300); gprsSerial.println(writeSMS1); delay(300); gprsSerial.println(writeSMS2); delay(300); gprsSerial.println(writeSMS3); delay(300); gprsSerial.println((char)26); // Отправляем Ctrl+Z, конец сообщения delay(300); gprsSerial.print("AT+CMGDA=\"DEL ALL"); //удаляем все принятые сообщения delay(300); gprsSerial.flush(); writeSMS1 = ""; writeSMS2 = ""; writeSMS3 = ""; }Приходит только содержание первого writeSMS1, равное ровно 64 символам. writeSMS2 должно содержать 21 символ, а writeSMS3 вообще пустое.
Что не так?
А какие это 64 и 21 символы?
Разобрался, проблему устранил.