PDA

Просмотр полной версии : плк304 не знает, что отвалился модем



Gvenihvivar
27.08.2014, 15:02
есть простенький проект в cds v3 с помощью библиотеки syscom плк304 передает данные по gprs через модем пм01.

В cds 2.3 был модуль в конфигурации плк, с помощью которого можно было узнать состояние модема и перезагрузить его и другую полезную информацию. Как быть в новом cds. Если модем перестает работать плк304 исправно отправляет инфо в порт и никак на эту ситуацию не реагирует.

Как плк самостоятельно может узнать, что модем отвалился? И можно ли его программно перезагрузить?

capzap
27.08.2014, 15:17
так ктож мешает изучить набор АТ-команд изучить и периодически посылать их модему, чтоб узнать состояние
А вообще странно, передавать данные и не получать таймаута, который дал бы понять что не так с соединением

Gvenihvivar
27.08.2014, 15:24
С изучением АТ команд все в порядке, но такая процедура не подходит. После команды cipstart модем соединяется с жпрс и начинает отсылать сообщения раз в секунду (ответа на сообщения быть не должно, они отсылаются в одностороннем порядке), в этом режиме АТ команды не работают, для того, чтобы опросить модем командами надо переходить в командный режим, а потом обратно. Это займет время и произойдет потеря данных.
После физического отсоединения модема syscomwrite исправно отправляет данные в порт и даже не возвращает никаких ошибок. Это меня тоже удивляет.

capzap
27.08.2014, 16:28
так посылайте данные через командный режим и будете получать ответ модема переданы данные или нет

Gvenihvivar
27.08.2014, 17:03
он тогда не успевает за секунду. Надо сначала команду отправить, потом дождаться ">". Даже если заранее задавать длину, на получение подтверждение уйдет больше секунды

capzap
27.08.2014, 17:16
че фигней то занимаетесь, а как по Вашему это контроллер делает, точно так же написанной программой через АТ команды, только незаметно и на другом языке, но ждать то символ ">" ей всё равно придется

Gvenihvivar
28.08.2014, 11:39
я написала через ат команды. одна отсылка (cipsend, > , send ok) занимает от 3 до 5 секунд. Я не знаю, как это делает модем в режиме tcp channel mode. Но у него явно получается быстрее. Обычно раз в секунду, изредка раз в две.
А для перезагрузки я команду нашла и проверила AT+CFUN=1,1

capzap
28.08.2014, 11:51
Надо видеть проект,чтоб сказать где у Вас лишние паузы появляются, там достаточно сотни миллисекунд чтоб отправить инфу

Gvenihvivar
28.08.2014, 12:39
так выглядит функциональный блок связи с модемов. Может я неправильно организовала его и из-за этого такая задержка. Буду очень благодарна за подсказку


FUNCTION_BLOCK ModemPM
VAR_INPUT
pSett : POINTER TO COM_Settings;(* настройки последовательного порта *)
pSettEX : POINTER TO SYSCOM.COM_SettingsEx;(* настройки последовательного порта *)
tick : BOOL;
close : BOOL;
pReadROC : POINTER TO BYTE;
END_VAR
VAR_OUTPUT
port_opened : BOOL;
unix : DWORD;
pRead : POINTER TO BYTE;
result : UINT ; // result of port opening
byteWR : UDINT;
byteRD : UDINT;
errorWR : UDINT;
errorRD : UDINT;
END_VAR
VAR
handle : SysCom.RTS_IEC_HANDLE :=0;
BufferWrite : ARRAY[0..10] OF BYTE := [2];(* байтовый буфер данных*)
BufferRead : ARRAY[0..38] OF BYTE;(* байтовый буфер данных*)

count : BYTE:=109;
strWR : STRING;
modemAns : STRING:= '';
ans : STRING;
readStr : STRING;

pReadStr : POINTER TO STRING(255);
BufWR : ARRAY[0..255] OF BYTE;(* байтовый буфер данных*)
ptrWR : POINTER TO STRING;
cur, prev: INT;
str2: STRING;
str3: STRING;
ok: BOOL;


send : BOOL;
wait : BOOL;

buf : ARRAY [0..500] OF BYTE;
bb : ARRAY [0..2] OF BYTE := [10,10,10];
cc: BYTE:=0;
bytew : UDINT;

r_trig : r_trig;
errCount : BYTE;

END_VAR




IF port_opened=0 THEN
handle := SysComOpen2(pSettings:= pSett, pSettingsEx:= pSettEX, pResult:= result);
SysComPurge(hCom:= handle);
IF NOT (handle = 16#FFFFFFFF) THEN
port_opened := 1;
END_IF
pReadStr := ADR(readStr);
ptrWR := ADR(BufWR[0]); // to string
ELSE
IF close THEN
count := 13 ;
END_IF
CASE count OF
//================================================== ================================================== ====
109: strWR := 'ATE0$R$N';
IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
count :=110; // AT+CGDCONT
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 109; // AT+CIPSHUT
END_IF
110: strWR := 'AT$R$N';
IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
count :=120; // AT+CGDCONT
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 190; // AT+CIPSHUT
END_IF
120: strWR := 'AT+CGATT=1$R$N';
IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
count :=133; // AT+CGDCONT
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 110; // AT+CIPSHUT
END_IF
130: strWR:='AT+CIPMODE=1$R$N';
IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
count :=140; // AT+CIPCCFG
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 133;
END_IF

133: strWR :='AT+CIPMODE?$R$N';
IF (find(modemAns,'$R$N+CIPMODE: 0') > 0) THEN
count :=140;
ELSIF (find(modemAns,'$R$N+CIPMODE: 1') > 0) THEN
count :=130; // AT+CIPCCFG
END_IF
140: strWR :='AT+CSTT="www.ab.kyivstar.ua","",""$R$N';
IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
count :=150;
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 190;
END_IF
150: strWR :='AT+CIICR$R$N';
IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
count :=160;
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 150;
END_IF
160: strWR :='AT+CIFSR$R$N';
IF (find(modemAns,'$R$N10.') > 0) THEN
count :=170;
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
count := 160;
END_IF
170: strWR:='AT+CIPSTART="TCP","46.202.226.243","2323"$R$N';
IF (find(modemAns,'$R$NCONNECT FAIL$R$N') > 0) THEN
count :=190; // cipclose
ELSIF find(modemAns,'$R$NCONNECT OK$R$N') > 0 THEN // if result of find > 0 this string is in, if "0", no need string in
count :=180; // transparant
modemAns:='';
ELSIF (find(modemAns,'$R$NOK$R$N') > 0) THEN
modemAns:='';
wait := TRUE; cc:=0;
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
// count :=12; // AT+CIPSTATUS
END_IF
180: strWR := 'AT+CIPSEND$R$N';
IF (find(modemAns,'>') > 0) THEN
count := 188;
END_IF
188: strWR := '100101010a1f0000090000000042c8666642c8666642c8666 642c8666653696633000000008d54$1A';
IF (find(modemAns,'$R$NSEND OK$R$N') > 0) THEN
count := 180;
END_IF
190: strWR:='AT+CIPSHUT$R$N';
IF (find(modemAns,'$R$NSHUT OK$R$N') > 0) THEN
count:=110;
END_IF
END_CASE

modemAns := '';
// transparant mode
IF count=180 OR count=188 THEN
IF tick AND pReadROC<>16#000000000 AND count=180 THEN
byteWR:= SysComWrite( hCom := handle, pbyBuffer := ADR(strWR), ulSize := SIZEOF(strWR),
ulTimeout := 50, pResult := errorWR);
ELSIF count=188 THEN
byteWR:= SysComWrite( hCom := handle, pbyBuffer := ADR(strWR), ulSize := SIZEOF(strWR),
ulTimeout := 50, pResult := errorWR);
END_IF
// initialization of gprs connection
ELSE
IF tick THEN
cc:= cc + 1;
END_IF

R_TRIG(CLK:= (cc=5 AND NOT wait), Q=> send);
IF cc = 45 AND wait THEN // wait answer from modem 1 min after ask again
wait:= FALSE;
cc := 0;
errCount := errCount + 1;
END_IF
cur := len(strWR);
IF send AND handle <> 16#FFFFFFFF THEN
bytew := SysComWrite( hCom := handle, pbyBuffer := ADR(strWR), ulSize := cur,
ulTimeout := 50, pResult := errorWR);
IF bytew <> 0 THEN
send := FALSE;
wait := TRUE;
cc := 0;
END_IF //send := FALSE;
END_IF
END_IF
//pReadStr^:='';
byteRD := SysComRead(
hCom := handle,
pbyBuffer := pReadStr,
ulSize := 596,
ulTimeout := 50,
pResult := errorRD);

// cut waste bytes
IF (byteRD <> 0) THEN
wait := FALSE;
cc := 0;
modemAns := '';
IF pReadStr^<>'' THEN
modemAns := '';
modemAns := left(pReadStr^, UDINT_TO_INT(byteRD));
pReadStr^ := '';
ans :='';
ans := modemAns;
// sinc time with PC
IF find(modemAns,'0108')>0 AND (count=105 or count=9) THEN
SysTimeRtcSet(ulTimestamp := HEX_TO_DWORD(Hex:= mid(modemAns,8,5)) );
END_IF
END_IF
END_IF


IF (find(modemAns,'$R$NOK$R$N') > 0) THEN
errCount := 0;
ELSIF (find(modemAns,'OK$R$N') > 0) THEN
errCount := 0;
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
errCount := errCount + 1;
END_IF

IF errCount = 3 THEN
count := 8;
END_IF

IF (find(modemAns,'$R$NCLOSED$R$N') > 0) THEN
count:=0;
ELSIF (find(modemAns,'$R$NALREADY CONNECT$R$N') > 0) THEN
count:=12;
// ELSIF (find(modemAns,'ALREADY CONNECTION') > 0) THEN
// count:=9;
ELSIF (find(modemAns,'$R$N+PDP: DEACT$R$N') > 0) THEN
count:=8;
ELSIF (find(modemAns,'$R$NSTATE: TCP CLOSED$R$N$R$NCONNECT FAIL$R$N') > 0) THEN
count := 0;
END_IF

END_IF

capzap
28.08.2014, 13:47
очень много несоответствий присвоениями и коментариями, трудно понять куда на самом деле предполагается перейти в кейсе
еще я могу предположить, что когда переменная strWR равна 'AT+CIPSEND$R$N'; то судя по коду, постоянно,каждый цикл, отправляется в порт, мешая ему тем самым отвтетить

Gvenihvivar
28.08.2014, 13:56
cipsend срабатывает раз в секунду получает > и отсылает сообщение, переключается в следующий шаг case и начинает ждать send ok. Как только send ok приходит, снова case идет в шаг с cipsend. Чтения из порта происходит постоянно. Максимальный цикл программы 8 млсек

capzap
28.08.2014, 14:15
ну я и говорю, ниже кейса идет запись в порт, не увидел там, какого нибудь семафора, который бы не забивал каждые 8мс порт строчкой 'AT+CIPSEND$R$N'

если переместите присвоение строки как показано ниже, побыстрее сработает модем с ответом

170: strWR:='AT+CIPSTART="TCP","46.202.226.243","2323"$R$N';
IF (find(modemAns,'$R$NCONNECT FAIL$R$N') > 0) THEN
count :=190; // cipclose
ELSIF find(modemAns,'$R$NCONNECT OK$R$N') > 0 THEN // if result of find > 0 this string is in, if "0", no need string in
count :=180; // transparant

strWR := 'AT+CIPSEND$R$N';

modemAns:='';
ELSIF (find(modemAns,'$R$NOK$R$N') > 0) THEN
modemAns:='';
wait := TRUE; cc:=0;
ELSIF (find(modemAns,'$R$NERROR$R$N') > 0) THEN
// count :=12; // AT+CIPSTATUS
END_IF
180:
IF (find(modemAns,'>') > 0) THEN
count := 188;
END_IF
188: