Данные через GPRS соединение (Arduino_Uno + GPRS_Shield)

olegtambov
Offline
Зарегистрирован: 13.01.2013

Как указанно в заголовке есть связка Arduino_Uno + GPRS_Shield V1.2 .

Плюс пара кнопок - каждая посылающая свою команду в инет .

Команды передаем самым простым способом - в строке HTTP запроса .

    gprsSerial.print("AT+HTTPINIT\r");
    delay(500);
    gprsSerial.print("AT+HTTPPARA=\"CID\",1\r");
    delay(500);
    gprsSerial.print("AT+HTTPPARA=\"URL\",\"СЕРВЕР.ru/proba.php?name=10\"\r");
    delay(500);
    gprsSerial.print("AT+HTTPACTION=1\r");
    delay(7000);
    gprsSerial.print("AT+HTTPTERM\r");
    delay(500);

Работает все на ура , но уж очень медленно . Каждую команду приходится по 7 секунд ждать .

Понятно что все дело в /delay();/

Там где значение 500 стоит - там мы 'ОК' ответ от GPTRShield'a ждем . Пробовал меньше ставить значение - иногда не работает код . Как грамотно отследить что пришел ответ 'ОК' и можно следующую команду слать ?

Там где параметр 7000 - там помимо 'ОК' еще и соединения ждем (пока придет ответ '+HTTPACTION:1,200,104') - тут подбирать параметр delay вообще безсмысленно - то в 2 секунды соединяется , то по 10 ждать приходится .

step962
Offline
Зарегистрирован: 23.05.2011

olegtambov пишет:

Там где значение 500 стоит - там мы 'ОК' ответ от GPTRShield'a ждем . Пробовал меньше ставить значение - иногда не работает код . Как грамотно отследить что пришел ответ 'ОК' и можно следующую команду слать ?

Что значит "ответ от GPTRShield'a"? Он на экране высвечивается? Динамиком проговаривается? Или все же по Serial-каналу приходит?

Ну уж если по Serial, то после отправки любой команды, на которую ожидается ответ шилда "OK", можно не отсчитывать секунды, а в цикле ждать поступления чего-нибудь в приемный буфер:

while (!Serial.available());

Появился какой-то символ в приемном буфере - подождали еще 5-6 миллисекунд (чтобы не только "O", но и "K" успело прийти, ну и завершающие CR+LF (или только CR)), потерли буфер (чтобы на следующей команде  все снова начиналось  с ожидания, а не с проскока if'а) и приступили к отработке следующей команды.

Можно даже набраться наглости и не просто тереть буфер, а читать из него и анализировать прочитанное: вдруг там вместо ожидаемого "OK" какая-нибудь ересь пришла? Например, ваш шилд об ошибке что-нибудь лепечет...

Цитата:

Там где параметр 7000 - там помимо 'ОК' еще и соединения ждем (пока придет ответ '+HTTPACTION:1,200,104') - тут подбирать параметр delay вообще безсмысленно - то в 2 секунды соединяется , то по 10 ждать приходится .

И в этом случае ровно так же ждем поступления данных в приемный буфер. С той лишь разницей, что прийти их должно не 2 буквы + конец строки, а чуть-чуть больше (сами посчитаете?).

olegtambov
Offline
Зарегистрирован: 13.01.2013

спасибо огромное ! 

while(gprsSerial.available()==0);
delay(100);  

вот так получилось . Всё работает

step962
Offline
Зарегистрирован: 23.05.2011

И все же, все же, все же...

Буфер чистить надо. Иначе при следующей проверке условие Serial.available() будет выполняться автоматически:

while(gprsSerial.available()==0);
delay(100); // этого достаточно, чтобы на скорости 9600 принять около 100 (!!!) символов
while(gprsSerial.available())  dummy = gprsSerial.read();

 

olegtambov
Offline
Зарегистрирован: 13.01.2013

вот мой кусок программы

    gprsSerial.print("AT+HTTPINIT\r");
    while(gprsSerial.available()==0);
    delay(100);
    gprsSerial.print("AT+HTTPPARA=\"CID\",1\r");
    while(gprsSerial.available()==0);
    delay(100);    
    gprsSerial.print("AT+HTTPPARA=\"URL\",\"olegtambov.myjino.ru/proba.php?name=10\"\r");
    while(gprsSerial.available()==0);
    delay(100);    
    gprsSerial.print("AT+HTTPACTION=1\r");
    while(gprsSerial.available()==0);
    delay(150);
    while(gprsSerial.available()==0);
    delay(50);
    gprsSerial.print("AT+HTTPTERM\r");
    while(gprsSerial.available()==0);
    delay(150);  

работает же ? С ардуино работаю не давно , въезжаю медленно .

Но - спасибо - перепишу .

step962
Offline
Зарегистрирован: 23.05.2011

olegtambov пишет:

работает же ? С ардуино работаю недавно, въезжаю медленно.

Ну, видно, delay(100) в данном конкретном случае помогают. Или переполнение буфера очень удачно к самой медлительной команде подоспело.

В общем, работает до поры до времени.

Поставив чтение из приемного буфера в пустоту (dummy=...), вполне можете сократить время ожидания раз в 10 (delay(10);). ну или в 8 (delay(12);)

olegtambov
Offline
Зарегистрирован: 13.01.2013

думаю так пойдет ?

Serial.flush();

сейчас попробую - отпишусь 

olegtambov
Offline
Зарегистрирован: 13.01.2013

Да - получилось вот так 

    gprsSerial.print("AT+HTTPPARA=\"URL\",\"СЕРВЕР.ru/proba.php?name=10\"\r");
    while(gprsSerial.available()==0);  // ждем ОК
    delay(20);
    gprsSerial.flush();    
    gprsSerial.print("AT+HTTPACTION=1\r");
    while(gprsSerial.available()==0);  // ждем ОК
    delay(20);
    gprsSerial.flush();
    while(gprsSerial.available()==0);  //  ждем +HTTPACTION:1,200,104
    delay(50);
    gprsSerial.flush();

теперь правильно ?

olegtambov
Offline
Зарегистрирован: 13.01.2013

сам спросил - сам ответил - не прокатило . передает данные через раз.

вот так вроде все стабильно 

    gprsSerial.print("AT+HTTPPARA=\"URL\",\"СЕРВЕР.ru/proba.php?name=10\"\r");
    while(gprsSerial.available()==0);
    delay(20);
while(gprsSerial.available())        
dum=gprsSerial.read();
    gprsSerial.print("AT+HTTPACTION=1\r");
    while(gprsSerial.available()==0);
    delay(20);
while(gprsSerial.available())        
dum=gprsSerial.read();
    while(gprsSerial.available()==0);
    delay(50);
while(gprsSerial.available())        
dum=gprsSerial.read();

но объясните мне пожалуйста алгоритм.

gprsSerial.print("AT+HTTPACTION=1\r");     -тут отослали команду в шилд

while(gprsSerial.available()==0);     - ждем пока хоть что то шилд пришлет в ответ (если ОК то ждем первую букву О)

delay(20);                           - даем время на прием всей информации от шилда (т.е. букву К)

while(gprsSerial.available())        - тут что ждем ???

dum=gprsSerial.read();      - зачем считывать что то в какую то переменную ? что это дает ?

step962
Offline
Зарегистрирован: 23.05.2011

Первые два предположения верны - в первом if'е ждем, пока не начнется передача ответа от шилда.

Затем даем некоторое время для того, чтобы весь ответ от шилда пришел в буфер приема (на скорости 9600 каждый символ передается примерно за миллисекунду. Так что если ожидается "OK", достаточно подождать 3-4 мсек, чтобы принять сами буквы плюс завершающие передаваемый пакет символы).

Ну а в последних двух строках (кстати, строки то две, а операция одна) читаем из входного буфера все те символы, что туда упали. Читаем до тех пор, пока в буфер не станет пуст, то есть очередной вызов Serial.available не вернет 0. Символы читаем и тут же забываем (поскольку сохраняем их в одной скалярной переменной). Этим добиваемся, что при подаче следующей команды наш if (тот, который ожидает поступления первого символа ответа от шилда) будет работать правильно

Если встанет задача не просто очистить буфер, а прочитать полученный ответ и проанализировать его, например, чтобы принять решение, что же делать дальше (т.е. когда логика программы станет чуть сложнее лома), придется освоить чтение этой информации из приемного буфера в строку.

Но это уже совсем другая история...

olegtambov
Offline
Зарегистрирован: 13.01.2013

да хоть ты тресни - теперь совсем все висит .

 

int dum = 0;
..............
digitalWrite(l1Pin, HIGH);                   -включаем светодиод
gprsSerial.print("AT\r");                     -отсылаем команду шилду
 while(gprsSerial.available()==0);      -пока не поступил ответ от шилда крутимся в этой строке
 delay(20);                                          -ждем полного ответа
while(gprsSerial.available()!=0){dum=gprsSerial.read();}   -пока буфер не станет пустой все из него читаем в переменную
digitalWrite(l1Pin, LOW);                    -выклчаем светодиод
 
при запуске светодиод включается и горит постоянно - значит даже на команду АТ не приходит ответа ? Что не так ?
step962
Offline
Зарегистрирован: 23.05.2011

Проблема может быть и в куску программы, отличном от вышеприведенного - лучше выложить (тестовый) скетч полностью (не забываем о кнопке [---]code). 

olegtambov
Offline
Зарегистрирован: 13.01.2013

вот вся программа

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(0, 1);
int dum=0;
int k0Pin = 10;boolean prevk0 = LOW;int l0Pin = 5;
int k1Pin = 11;boolean prevk1 = LOW;int l1Pin = 6;
int k2Pin = 12;boolean prevk2 = LOW;int l2Pin = 7;

void setup()
{gprsSerial.begin(19200);delay(500);pinMode(l0Pin, OUTPUT);pinMode(l1Pin, OUTPUT);pinMode(l2Pin, OUTPUT);}

void loop(){
boolean currk0 = digitalRead(k0Pin);if (prevk0 != currk0 && currk0 == HIGH) {kn0();}prevk0 = currk0;

}
    
void kn0()
{
digitalWrite(l0Pin, HIGH);
    gprsSerial.print("AT\r");
    while(gprsSerial.available()==0);
    delay(100);
   while(gprsSerial.available()!=0){dum=gprsSerial.read();} 
gprsSerial.print("AT+SAPBR=3,1,\"APN\",\"INTERNET\"\r");
    while(gprsSerial.available()==0);
    delay(100);
   while(gprsSerial.available()!=0){dum=gprsSerial.read();} 
gprsSerial.print("AT+SAPBR=1,1\r");
    while(gprsSerial.available()==0);
    delay(100);
   while(gprsSerial.available()!=0){dum=gprsSerial.read();} 
   gprsSerial.print("AT+HTTPINIT\r");
    while(gprsSerial.available()==0);
    delay(100);
while(gprsSerial.available()!=0){dum=gprsSerial.read();}
    gprsSerial.print("AT+HTTPPARA=\"CID\",1\r");
    while(gprsSerial.available()==0);
    delay(100);
while(gprsSerial.available()!=0){dum=gprsSerial.read();}
    gprsSerial.print("AT+HTTPPARA=\"URL\",\"olegtambov.myjino.ru/proba.php?name=10\"\r");
    while(gprsSerial.available()==0);
    delay(100);
while(gprsSerial.available()!=0){dum=gprsSerial.read();}
    gprsSerial.print("AT+HTTPACTION=1\r");
    while(gprsSerial.available()==0);
    delay(100);
while(gprsSerial.available()!=0){dum=gprsSerial.read();}
    while(gprsSerial.available()==0);
    delay(100);
while(gprsSerial.available()!=0){dum=gprsSerial.read();}
    gprsSerial.print("AT+HTTPTERM\r");
    while(gprsSerial.available()==0);
    delay(100);
digitalWrite(l0Pin, LOW);

}  

сим карту проверил - баланс ок , в гипертерминале все работает 

step962
Offline
Зарегистрирован: 23.05.2011

Настройку скорости UART в последнее время не меняли?

Шилд точно на 19200 работает?

И зачем это вы программный Serial используете?

И зачем вешаете его на те же выводы, что и аппаратный Serial?

olegtambov
Offline
Зарегистрирован: 13.01.2013

скорость никогда не менял 

скорость сейчас поменяю на 9600

програмный - аппаратный сериал не понял вопроса . 

leshak
Offline
Зарегистрирован: 29.09.2011

 

olegtambov пишет:

програмный - аппаратный сериал не понял вопроса . 

Это не вопрос, а указание на ошибку. Либо используйте обычный Serial, либо переносите свой gprsSerial на другие пины.

Как правило эти шилды имеют джампер. Куда подключится его RX,TX - либо на D0,D1 - тогда используем просто Serial, либо на какие-то другие пины (например D8,D9 - это уже в доках на шилд смотреть), тогда используем SoftwareSerial как у вас в коде.

Если решите использовать обычный Serial (это и есть "аппаратный", он меньше грузит проц), то что-бы не лопатить весь код, можете просто вместо строки

 

SoftwareSerial gprsSerial(0, 1);

 

 

Написать

 

#define gpsSerial Serial

 

 

Тогда больше в коде ничего менять не прийдется

olegtambov
Offline
Зарегистрирован: 13.01.2013

Немного не по теме , но всё же - Что за фигня такая ? Вот простейшая программа - каждая кнопка включает свой светодиод на 2 секунды. Почему после того как скетч записался в ардуино безо всяких нажатий кнопок загорается сначала один светодиод , потом второй ??? Напрягает ...

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(7, 8);

int dum=0;
int k0Pin = 10;boolean prevk0 = LOW;int l0Pin = 5;
int k1Pin = 11;boolean prevk1 = LOW;int l1Pin = 6;

void setup()
{gprsSerial.begin(9600);delay(500);pinMode(l0Pin, OUTPUT);pinMode(l1Pin, OUTPUT);}

void loop(){
boolean currk0 = digitalRead(k0Pin);if (prevk0 != currk0 && currk0 == HIGH) {kn0();}prevk0 = currk0;
boolean currk1 = digitalRead(k1Pin);if (prevk1 != currk1 && currk1 == HIGH) {kn1();}prevk1 = currk1;}

void kn0(){
digitalWrite(l0Pin, HIGH);    
delay(2000);
digitalWrite(l0Pin, LOW);}  

void kn1(){      
digitalWrite(l1Pin, HIGH);
delay(2000);
digitalWrite(l1Pin, LOW);}  

А по теме - поставил програмный сериал , скорость 9600 , толку ноль . Учу матчасть ...

leshak
Offline
Зарегистрирован: 29.09.2011

 

olegtambov пишет:

Немного не по теме , но всё же - Что за фигня такая ? Вот простейшая программа - каждая кнопка включает свой светодиод на 2 секунды. Почему после того как скетч записался в ардуино безо всяких нажатий кнопок загорается сначала один светодиод , потом второй ??? Напрягает ...

Больше напрягает что вы ожидаете тут телепатов. Нужно догадыватся "что вы там наподключали". Скорее всего забыли про подтягивающие резисторы.  Смотрите базовый пример, один из первых с которым нужно с дуиной знакомится http://arduino.ru/tutorials/button - как правильно подлючать кнопку.

И зачем все лепить в одну строчку? Что-бы труднее было заметить проблемы? В 12,13 строке, что у вас за чехарда со скобками на prevXXX=currkXXX?

 

leshak
Offline
Зарегистрирован: 29.09.2011

 

olegtambov пишет:

А по теме - поставил програмный сериал , скорость 9600 , толку ноль . Учу матчасть ...

"Поставил програмный", всмысле джампером?

И откуда вы 9600 скорость взяли? Судя по wiki-шилда у него "родная скорость", таки 19200.

Поискал вверх по теме. Никто вам ставить 9600 - не советовал. Первый раз эта цифра упомнял step962. Причем со смыслом что "100 миллисекунд точно хватит и на скорости 9600 что бы успеть передать" (так что 500 - не нужно). Но это же не значит что "нужно ставить 9600 скорость" . Это значит что "для 19200" delay(100) - хватит с головой. А можно и меньше сделать.

И "ишо".

Раз вы все равно не пытаетесь парсить получаемые данные, то вместо delay() можно просто ждать пока из сериал прийдет перевод строки \n (или если там ожидается несколько строк ответа - считаем нужное количество переводов). Тогда не нужно будет "ждать лишнего".

olegtambov
Offline
Зарегистрирован: 13.01.2013

Да не - в телепатов сам не верю :)

Говорю же - только начинаю изучать ардуино . Всегда везде все на Basic`е делал (Bascom - для прошивки в AVR , PureBasic для под винду программы и т.д.) а тут совершенно незнакомый язык...

Говорю же - пока что ушел учить мат часть :)
 
По поводу непонятных скобок - все взято отсюда - такие исходники попались .
 
подтягивающие резисторы на месте - вот доказуха :)
 
PS Програмный сериал поставил джампером. 9600 поставил не по совету а в надежде что на маленькой скорости всяко работать будет ...
step962
Offline
Зарегистрирован: 23.05.2011

olegtambov пишет:

PS Програмный сериал поставил джампером. 9600 поставил не по совету а в надежде что на маленькой скорости всяко работать будет ...

Обязательным условием работы связки Arduino + GPRS-шилд является настройка и того и другого устройства на одинаковую скорость. А будет это 9600 или 19200 (либо какая еще) - не столь важно.

Хотя вру - для программного Serial важно. Чем выше скорость программного Serial, тем больше проблем с передачей данных. Поэтому, пока есть такая возможность, лучше работать с аппаратным.

leshak
Offline
Зарегистрирован: 29.09.2011

olegtambov пишет:

По поводу непонятных скобок - все взято отсюда - такие исходники попались .

Ну так отформатируйте в приличный вид. Возможно в этом дело, раз резисторы на месте. 

Можете проверить это сделав тестовый скетч с loop(){serial.println(analogRead(PIN_BUTTON);}

И посмотрите - стоит ли у вас ноль, как ожидается при отпущенной кнопке или нет. И появляется ли четкий 1, при этом.

 
 
olegtambov пишет:
Програмный сериал поставил джампером. 9600 поставил не по совету а в надежде что на маленькой скорости
Смотрите. Что бы арудино и шилд могли общатся через Serial - то и дуина и шилд должны говорить на одной скорости. Со стороны дуины - вы легко это можете меня. А со стороны шилда - нет. С какой скоростью он с завода пришел  - на ту вы и дуину должны настраивать.
Потом, когда вы "установите с ним связь", вы можете командами перевести его на другую скорость (а потом и в дуине переключится на новую скорость). Но вначале, вам в любом случае нужно установить связь. То есть сделать gprsBegin.begin на скорость указанную в даташите на шилд.
leshak
Offline
Зарегистрирован: 29.09.2011

leshak пишет:

olegtambov пишет:

По поводу непонятных скобок - все взято отсюда - такие исходники попались .

Ну так отформатируйте в приличный вид. Возможно в этом дело, раз резисторы на месте. 

Нажмите в ArduinoIDE CTRL-T оно вам само отформатит.

Судя по всему - с кодом все нормально. Так что перепроверяйте подключение.

olegtambov
Offline
Зарегистрирован: 13.01.2013

Огромное всем спасибо . Всё заработало . 

  while(!gprsSerial.available());
  delay(10);
  while(gprsSerial.available())  val = gprsSerial.read();

Перепроверил соединения , заменил блок питания , общение с шилдом сделал через 7 и 8 пины , скорость для шилда включил 9600 (AT+IPR=9600) как и прописывал в скетче . Все заработало . Отправляет данные на сервер , принимает данные с сервера . Если интересно то видео будет завтра .

 

НО! :) а как же без но ? 

На сервер данные передаются в строке адреса 

gprsSerial.println("AT+HTTPPARA=\"URL\",\"СЕРВЕР.ru/p.php?n=1\"");

сначала показалось так и проще и быстрее . На деле же на отсылку одной команды уходит 5-10 секунд . И , к тому же , если с платы нет команды на отсылку делается запрос на сервер - нет ли там команд на прием ? - это тоже 5-10 секунд. (задержка - это долгое соединение шилда с сервером)

Вобщем все очень долго работает .

Алгоритм отсылки команды :

1-задать адрес 

2-соединиться

3-разъединиться

 

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