Показано с 1 по 10 из 10

Тема: Работа ПЛК и модем (SIEMENS M35i)

  1. #1

    Question Работа ПЛК и модем (SIEMENS MC35i)

    Вот решил освоить работу ПЛК с модемами, вроде разобрался как работать с портом, с настройками, чтением и записью. Но вот с модемом ничего не выходит, при отправке ему любой АТ команды, модем отвечает "$R" не могу понять почему, подскажите как программно работать с модемом, если вас не затруднит поясните как работает ваша программа, которую я здесь скачал. Основная часть в принципе понятна, но лучше если полностью мне кто нибудь пояснить саму суть. По Гипер Терминалу модем все прекрасно понимает, отвечает на АТ команды. Подключал так же ПЛК - ПК - Модем, контроллер по изменению переменной отправлял АТ команду, в гипер терминале я ее увидел, так же контроллер принимает данные отправленные с гипер терминала, а модем ничего не видит, думал что то с кабелем, но нет, скорее всего я где то в программе допускаю ошибку, мне кажется что неправильно принимаю данные, подскажите как именно это делается?

    FUNCTION_BLOCK GSM_Modem_SMS
    VAR_INPUT
    com_num:PORTS:=COM1; (*Номер порта для работы с модемом*)
    phone_num:STRING; (*Телефонный номер для посылки смс*)
    send_SMS_text:STRING(255); (*Строка для отправки по указанному номеру шлем если не пустая*)
    rcvSMS:BOOL:=FALSE; (*Флаг необходимости проверки SMS*)
    use_unicode: BOOL := FALSE; (* Использование кодовой таблицы - юникод - ограничение на сообщ - 21 символ*)
    END_VAR
    VAR_OUTPUT
    rcvedSMS:STRING(255); (*Полученное СМС*)
    rcvedPhonNum:STRING(20); (*Телефон с которого отправлено SMS*)
    rcvedTm:STRING(25); (* Время отправки*)
    sended_OK:BOOL; (*Признак отправки СМС*)
    END_VAR
    VAR
    port_opened: BOOL := FALSE; (*Признак открытия порта*)
    com_handle: DWORD;
    init_stage:BYTE:=0; (*Стадия инициализации*)
    dbecodeBuf;
    (*Буфферы для обмена*)
    rcvBUF: ARRAY [0..1023] OF BYTE;
    rcvStr:STRING(255);
    snd_str:STRING(255);


    iter: DWORD;
    com_set: COMSETTINGS;


    (*Комманда чтения СМС*)
    strTakeNewSMS:STRING:='AT+CNMI=1,1$R';
    strGetNewSMS:STRING:='+CMTI: ';
    strSetCharSetUC:STRING:='AT+CSCS="UCS2"$R'; (* Формат UNICODE*)
    strSetCharSet8B:STRING:='AT+CSCS="GSM"$R'; (* Формат UNICODE*)
    strSetMsgMode:STRING:='AT+CMGF=0$R'; (* Использовать !НЕ! Text Mode!! А __PDU__*)
    strGetNewMsg:STRING:='AT+CMGR=';
    strGetDelMsg:STRING:='AT+CMGD=';
    strGetAllMsg:STRING:='AT+CMGL=1$R';
    strSMS_num:STRING(20);

    do_send_sms2: BOOL := FALSE;
    sz: DWORD := 0;
    a_char: POINTER TO STRING;
    do_rcv_sms2: BOOL := FALSE;
    port_init:BOOL:=FALSE;
    res:BOOL;

    (*Таймеры ожидания для работы*)
    tmr_rcv_wait:TON;
    tmr_snd_wait:TON;
    tmr_rq_wait:TON;
    (* Number out*)

    NUMBER_OUT: STRING(20);
    I: BYTE;
    PACKET:STRING(255);
    uc_sms_text:STRING(255);

    sms_c:STRING(255);
    END_VAR



    (*Открываем порт*)
    IF NOT port_opened THEN
    com_handle:=SysComOpen(com_num);
    IF com_handle<>16#FFFFFFFF THEN
    port_init:=TRUE;
    ELSE
    SysComClose( com_num);
    com_handle:=SysComOpen( com_num);
    port_init:=TRUE;
    END_IF

    (*Настраиваем скорость*)
    com_set.Port:=com_num;
    com_set.dwBaudRate:=9600;
    com_set.byParity:=0;
    com_set.dwTimeout:=0;
    com_set.byStopBits:=0; (* *)
    com_set.dwBufferSize:=0;
    com_set.dwScan:=0;
    res:=SysComSetSettings(com_num,ADR(com_set));
    (*Успешно открыли*)
    IF NOT res THEN
    port_opened:=TRUE;
    END_IF
    (* Установка PDU*)
    SysComWrite(com_num,ADR(strSetMsgMode),LEN(strSetM sgMode),0);
    rcvstr:='';
    END_IF

    IF init_stage<2 THEN (* Ожидание настройки PDU*)
    tmr_rq_wait(in:=(init_stage=1),PT:=t#3s);
    init_stage:=1;
    sz:=SysComRead(com_num,ADR(rcvBUF),1024,0);
    IF sz>0 THEN (*Что то приняли*)
    FOR iter:=0 TO sz-1 DO
    a_char:=ADR(rcvBuf[iter]);
    rcvStr:=CONCAT(rcvStr,LEFT(a_char^,1) );
    IF LEN(rcvStr)>250 THEN
    rcvStr:=DELETE(rcvStr,1,1);
    END_IF
    END_FOR
    END_IF
    IF FIND(rcvStr,'OK')<>0 THEN
    init_stage:=2;
    (*Инициализация успешна шлем CharSet*)
    IF use_unicode THEN
    SysComWrite(com_num,ADR(strSetCharSetUC),LEN(strSe tCharSetUC),0);
    ELSE
    SysComWrite(com_num,ADR(strSetCharSet8B),LEN(strSe tCharSet8B),0);
    END_IF
    rcvstr:='';
    END_IF
    IF tmr_rq_wait.Q THEN (*Недождались - переиниц-ая*)
    init_stage:=0;
    port_init:=FALSE;
    END_IF
    RETURN;
    END_IF

    IF init_stage>1 AND init_stage<4 THEN (* Ожидание настройки CSCS*)
    tmr_rq_wait(in:=(init_stage=3),PT:=t#3s);
    init_stage:=3;
    sz:=SysComRead(com_num,ADR(rcvBUF),1024,0);
    IF sz>0 THEN (*Что то приняли*)
    FOR iter:=0 TO sz-1 DO
    a_char:=ADR(rcvBuf[iter]);
    rcvStr:=CONCAT(rcvStr,LEFT(a_char^,1) );
    IF LEN(rcvStr)>250 THEN
    rcvStr:=DELETE(rcvStr,1,1);
    END_IF
    END_FOR
    END_IF
    IF FIND(rcvStr,'OK')<>0 THEN
    init_stage:=4;
    (*Инициализация успешна*)
    rcvstr:='';
    SysComWrite(com_num,ADR(strTakeNewSMS),LEN(strTake NewSMS),0);
    END_IF
    IF tmr_rq_wait.Q THEN (*Недождались - переиниц-ая*)
    init_stage:=0;
    port_init:=FALSE;
    END_IF
    RETURN;
    END_IF

    IF init_stage>3 AND init_stage<6 THEN

    tmr_rq_wait(in:=(init_stage=4),PT:=t#3s);
    init_stage:=5;
    sz:=SysComRead(com_num,ADR(rcvBUF),1024,0);

    IF sz>0 THEN (*Что то приняли*)
    FOR iter:=0 TO sz-1 DO
    a_char:=ADR(rcvBuf[iter]);
    rcvStr:=CONCAT(rcvStr,LEFT(a_char^,1) );
    IF LEN(rcvStr)>250 THEN
    rcvStr:=DELETE(rcvStr,1,1);
    END_IF
    END_FOR
    END_IF

    IF FIND(rcvStr,'OK')<>0 THEN
    init_stage:=6;
    (*Инициализация успешна*)
    rcvstr:='';
    END_IF

    IF tmr_rq_wait.Q THEN (*Недождались - переиниц-ая*)
    init_stage:=0;
    port_init:=FALSE;
    END_IF
    RETURN;
    END_IF


    (*Взводим таймер если надо*)
    tmr_snd_wait(IN:=LEN(send_SMS_text)>0 AND do_send_sms2,PT:=t#5s);

    (*Если таймер сработал больше не ждем ответа от модема*)
    IF tmr_snd_wait.Q THEN
    do_send_sms2:=FALSE;
    tmr_snd_wait(IN:=LEN(send_SMS_text)>0 AND do_send_sms2,PT:=t#5s);
    rcvStr:='';
    END_IF

    (*Начинаем посылку*)
    sended_OK:=FALSE;
    (*Если нужно послать СМС*)
    IF LEN(send_SMS_text)>0 AND NOT do_send_sms2 THEN
    NUMBER_OUT:='';
    FOR I:=1 TO 10 DO
    IF (I MOD 2)<>0 THEN
    NUMBER_OUT:=CONCAT(NUMBER_OUT,MID(phone_num,1,I+1) );
    ELSIF (I MOD 2)=0 THEN
    NUMBER_OUT:=CONCAT(NUMBER_OUT,MID(phone_num,1,I-1));
    END_IF
    END_FOR

    NUMBER_OUT:=CONCAT(NUMBER_OUT, 'F');
    NUMBER_OUT:=CONCAT(NUMBER_OUT, MID(phone_num,1,11));

    PACKET:='0001000B91'; (*SCA =00 PDU=01 MR=00*)
    PACKET:=CONCAT(PACKET,NUMBER_OUT);

    IF use_unicode THEN

    PACKET:=CONCAT(PACKET,'0008'); (*PID 00(обычн смс) = DCS=06(кодовая схема - полный UCS2)*)

    IF LEN(send_sms_text)>69 THEN (*Обрезаем строку до 70*)
    send_sms_text:=LEFT(send_sms_text,69);
    END_IF
    uc_sms_text:=CP1251_TO_UTF8oct(send_sms_text);
    ELSE
    (* 0001000B919762527348F500040E *)

    PACKET:=CONCAT(PACKET,'0004'); (*PID 00(обычн смс) = DCS=04(кодовая схема - 8 битовое)*)
    IF LEN(send_sms_text)>159 THEN (*Обрезаем строку до 255 символов*)
    send_sms_text:=LEFT(send_sms_text,159);
    END_IF
    uc_sms_text:=CP1251_TO_Octets(send_sms_text);

    END_IF

    uc_sms_text:=CONCAT(uc_sms_text,'$1A');
    IF use_unicode THEN
    I:=INT_TO_BYTE(LEN(send_sms_text)*2);
    ELSE
    I:=INT_TO_BYTE(LEN(send_sms_text));
    END_IF
    PACKET:=CONCAT(PACKET,tetr2hex[SHR(I,4)]);
    PACKET:=CONCAT(PACKET,tetr2hex[I AND 16#F]);

    snd_str:=CONCAT('AT+CMGS=',INT_TO_STRING((LEN(PACK ET)/2)-1+I));
    snd_str:=CONCAT(snd_str,'$R');

    SysComWrite(com_num,ADR(snd_str),LEN(snd_str),0);

    rcvStr:='';

    (*Ждать ответа от модема*)
    do_send_sms2:=TRUE;

    END_IF

    (*
    (*Таймер ожидания получения*)
    tmr_rcv_wait(IN:=do_rcv_sms2,PT:=t#5s);
    IF tmr_rcv_wait.Q THEN
    do_rcv_sms2:=FALSE;
    SysComWrite(com_num,ADR(strSetDelivRep),LEN(strSet DelivRep),0);
    tmr_rcv_wait(IN:=do_rcv_sms2,PT:=t#5s);
    rcvStr:='';
    END_IF
    *)

    (*Если нужно получить ответ от модема*)
    IF rcvSMS AND NOT do_send_sms2 AND NOT do_rcv_sms2 THEN
    rcvStr:='';
    do_rcv_sms2:=TRUE;
    END_IF

    (*Получаем данные из порта*)
    sz:=SysComRead(com_num,ADR(rcvBUF[0]),20,0);
    (*Таймер получения ответа от модема -2 секунды*)
    IF LEN(rcvStr)=0 THEN
    tmr_rq_wait(IN:=FALSE,PT:=t#2s);
    ELSE
    tmr_rq_wait(IN:=TRUE,PT:=t#2s);
    END_IF
    IF sz<>0 THEN

    FOR iter:=0 TO sz-1 DO
    a_char:=ADR(rcvBuf[iter]);
    rcvStr:=CONCAT(rcvStr,LEFT(a_char^,1) );
    IF LEN(rcvStr)>250 THEN
    rcvStr:=DELETE(rcvStr,1,1);
    END_IF
    END_FOR

    IF do_send_sms2 THEN
    (*При посылке СМС ожидаем готовности модема знак >*)
    IF FIND(rcvStr,'>') <> 0 THEN
    (*Шлем SMS*)
    SysComWrite(com_num,ADR(PACKET),LEN(PACKET),0);
    SysComWrite(com_num,ADR(uc_sms_text),LEN(uc_sms_te xt),0);
    i:=16#1A;
    SysComWrite(com_num,ADR(i),1,0);
    do_send_sms2:=FALSE;
    (*СМС Послано*)
    sended_OK:=TRUE;
    END_IF
    END_IF
    END_IF
    (*Если прием СМС*)
    IF do_rcv_sms2 AND tmr_rq_wait.q THEN
    (*Если ждем эхо*)

    IF FIND(rcvStr,strGetNewSMS) <> 0 THEN
    rcvStr:=DELETE(rcvStr,FIND(rcvStr,strGetNewSMS) +LEN(strGetNewSMS)+1,1);
    WHILE (LEFT(rcvStr,1)<>',') DO
    rcvStr:=DELETE(rcvStr,1,1);
    END_WHILE
    rcvStr:=DELETE(rcvStr,1,1);
    strSMS_num:=rcvStr;
    rcvStr:=CONCAT(strGetNewMsg,rcvSTR);

    SysComWrite(com_num,ADR(rcvSTR),LEN(rcvSTR),0);

    rcvStr:='';
    END_IF

    (*Начато тел. номера из россии это +7 *)
    IF FIND(rcvStr,'+CMGR: ')<>0 THEN

    rcvStr:=DELETE(rcvStr,FIND(rcvStr,'$0A') ,1);
    rcvStr:=DELETE(rcvStr,FIND(rcvStr,'$0A') ,1);
    (*СМС ограничено переводами строк*)
    DB(pBuf:=ADR(rcvStr),str_sender=>rcvedPhonNum,str_ time=>rcvedTm,str_message=>rcvedSMS);

    rcvStr:=CONCAT(strGetDelMsg,strSMS_num);
    SysComWrite(com_num,ADR(rcvSTR),LEN(rcvSTR),0);
    rcvStr:='';
    END_IF

    rcvStr:='';

    END_IF
    Последний раз редактировалось deniska13; 27.01.2010 в 20:42.

  2. #2

    По умолчанию

    deniska13, ставьте точки останова и смотрите как работает

  3. #3
    Пользователь
    Регистрация
    11.01.2009
    Адрес
    Кострома
    Сообщений
    3,144

    По умолчанию

    Этот пример выложенн на диске входящем в ПЛК
    Проверено все работает.
    Смотрите,читайте и пользуйтесь.
    Последний раз редактировалось lara197a; 29.01.2010 в 10:05.

  4. #4

    По умолчанию

    Пример, кстати, фигово работает ))) Основная проблема в работе с модемом - это понимание принципа "сканирующего выполнения", т.е. то что весь текст программы пробегается каждую миллисекунду. Это вызывает большие трудности в синхронизации и обеспечении последовательностей выполнения функций.
    Когда нужно обеспечить строгую последовательность обмена лучше использовать конструкции CASE ... тогда видно в каком месте нахродиться диалог с модемом. А плохая работа примера объясняется не полной инициализацией модема перед обменом и отсутствием способа выходить из ошибок.... Очень часто модему что-то не понравиться и он ответит "ERROR"... и будет так отвечать до выключения питания )))
    Последний раз редактировалось Дмитрий Артюховский; 28.01.2010 в 21:11.

  5. #5

    Question

    у меня этот пример не работает в том то и дело, как только я загружаю программу в контроллер, при нажатии Run он перезагружается, причем загорается лампа "работа" и при этом он вообще не "дышит" если замкнуть один из входов то соответствующая лампа не светится, приходится его снова перегружать и заливать программу снова, ну и так по кругу)...

  6. #6
    Пользователь
    Регистрация
    21.12.2006
    Адрес
    Красноярск
    Сообщений
    68

    Unhappy

    Извините, если не в тему, но у меня тоже проблема при работе плк100 и указанного терминала - не принимает SMS. Через гиппертерминал AT командой +CMGD= удаляю SMS из памяти SIM карты - и пример работает и принимает и отправляет SMS. Однако работает только пока не заполнится память SIM - 25 сообщений. Если кто сталкивался - подскажите какой параметр терминала нужно изменить, чтобы он работал независимо от заполненности памяти?

  7. #7

    По умолчанию

    Здравствуйте!
    Пожалуйста выложите здесь последнюю версию примера sms_send_seample.pro. Буду очень признателен.
    Я верю в светлое будущее...
    http://epservice.ru

  8. #8

    По умолчанию

    Здравствуйте. Разложил всю программу на косточки и натолкнулся на такую проблему не как не могу понято что означает rcvStr:="; просмотрел справку так и не нашел может кто подскажет.

  9. #9

    По умолчанию

    Рассматривал пример работы с модемом и наткнулся на

    IF FIND(rcvStr,strGetNewSMS) <> 0 THEN
    rcvStr:=DELETE(rcvStr,FIND(rcvStr,strGetNewSMS) +LEN(strGetNewSMS)+1,1);
    WHILE (LEFT(rcvStr,1)<>',') DO
    rcvStr:=DELETE(rcvStr,1,1);
    END_WHILE

    И тут возник вопрос по поводу цикла WHILE
    Может ли этот цикл работать в ПЛК?
    Я по рекомендациям форума исспользую его для перезагрузки плк при отключении питания, чтоб контроллер не работал от аккумулятора.

  10. #10

    По умолчанию

    Если Вы его использовали - значит может.
    Для перезагрузки он специально вводится в "не правильные условия".
    Надо просто четко понимать как он работает. И особо важно понимать, что If While и прочие команды в ПЛК работают ПО ДРУГОМУ, нежели на ПК.

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •