Страница 12 из 69 ПерваяПервая ... 210111213142262 ... ПоследняяПоследняя
Показано с 111 по 120 из 688

Тема: Программирование ПЛК110 [М02] для задач реального времени

  1. #111

    По умолчанию

    Я посмотрю конечно все это, самому интересно, но вот что сразу бросается в глаза : модуль PRU0 физически подключен в выводам 3 и 4, поэтому на выводе 1 (подключенному к PRU1) ничего не будет по определению... т.е. автор не очень внимательно проверял предлагаемый модуль....

  2. #112

    По умолчанию

    Посмотрите, пожалуйста, пристально на такой код.
    Первая же команда PRU_FB_GetParameter(pru_num:=0, index:=28, value:=ADR(TMP)) уводит ПЛК в перезагрузку.
    ADR(TMP) используется нормально?

    Вроде, тут POINTER TO DWORD, и ADR я применяю только к DWORD переменным. С выравниванием всё ок? Или нужны какие-то песни-пляски?

    Второе подозрение у меня на то, что, возможно, прошивка ПЛК поддерживает только 1 dword на обмен с PRU, а я пытаюсь 5 dword'ов синхронизировать.

    Код:
    FUNCTION_BLOCK PRU_PULSE
    VAR_INPUT
      ENABLE: BOOL;
      CYCLE_LENGTH: WORD; (* PRU cycles *)
      QUANTITY: DWORD;
    END_VAR
    VAR_OUTPUT
      READY : BOOL;
      QUANTITY_LEFT: DWORD; (* for debugging *)
    END_VAR
    VAR
      TMP: DWORD;
    END_VAR
    ..
    
    PRU_FB_GetParameter(pru_num:=0, index:=28, value:=ADR(TMP));
    READY := TMP <> 0;
    PRU_FB_GetParameter(pru_num:=0, index:=29, value:=ADR(QUANTITY_LEFT));
    PRU_FB_SetParameter(pru_num:=0, index:=25, value:=ADR(QUANTITY));
    TMP := WORD_TO_DWORD(CYCLE_LENGTH);
    PRU_FB_SetParameter(pru_num:=0, index:=26, value:=ADR(TMP));
    TMP := SEL(ENABLE, 0, 1);
    PRU_FB_SetParameter(pru_num:=0, index:=27, value:=ADR(TMP));
    Собственно, определения функций get/set из pruAccessLib.lib:
    Код:
    FUNCTION PRU_FB_GetParameter : DINT
    VAR_INPUT
    	pru_num:DWORD; (*from 0 to 1*)
    	index:DWORD; (*from 2 to 31*)
    	value: POINTER TO DWORD;
    END_VAR
    VAR
    END_VAR
    Код:
    FUNCTION PRU_FB_SetParameter : DINT
    VAR_INPUT
    	pru_num:DWORD; (*from 0 to 1*)
    	index:DWORD; (*from 2 to 31*)
    	value: POINTER TO DWORD;
    END_VAR
    VAR
    END_VAR

  3. #113
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,243

    По умолчанию

    Цитата Сообщение от vladimirisitnikov Посмотреть сообщение
    Посмотрите, пожалуйста, пристально на такой код.
    Первая же команда PRU_FB_GetParameter(pru_num:=0, index:=28, value:=ADR(TMP)) уводит ПЛК в перезагрузку.
    ADR(TMP) используется нормально?

    Вроде, тут POINTER TO DWORD, и ADR я применяю только к DWORD переменным. С выравниванием всё ок? Или нужны какие-то песни-пляски?

    Второе подозрение у меня на то, что, возможно, прошивка ПЛК поддерживает только 1 dword на обмен с PRU, а я пытаюсь 5 dword'ов синхронизировать.

    Код:
    FUNCTION_BLOCK PRU_PULSE
    VAR_INPUT
      ENABLE: BOOL;
      CYCLE_LENGTH: WORD; (* PRU cycles *)
      QUANTITY: DWORD;
    END_VAR
    VAR_OUTPUT
      READY : BOOL;
      QUANTITY_LEFT: DWORD; (* for debugging *)
    END_VAR
    VAR
      TMP: DWORD;
    END_VAR
    ..
    
    PRU_FB_GetParameter(pru_num:=0, index:=28, value:=ADR(TMP));
    READY := TMP <> 0;
    PRU_FB_GetParameter(pru_num:=0, index:=29, value:=ADR(QUANTITY_LEFT));
    PRU_FB_SetParameter(pru_num:=0, index:=25, value:=ADR(QUANTITY));
    TMP := WORD_TO_DWORD(CYCLE_LENGTH);
    PRU_FB_SetParameter(pru_num:=0, index:=26, value:=ADR(TMP));
    TMP := SEL(ENABLE, 0, 1);
    PRU_FB_SetParameter(pru_num:=0, index:=27, value:=ADR(TMP));
    Собственно, определения функций get/set из pruAccessLib.lib:
    Код:
    FUNCTION PRU_FB_GetParameter : DINT
    VAR_INPUT
    	pru_num:DWORD; (*from 0 to 1*)
    	index:DWORD; (*from 2 to 31*)
    	value: POINTER TO DWORD;
    END_VAR
    VAR
    END_VAR
    Код:
    FUNCTION PRU_FB_SetParameter : DINT
    VAR_INPUT
    	pru_num:DWORD; (*from 0 to 1*)
    	index:DWORD; (*from 2 to 31*)
    	value: POINTER TO DWORD;
    END_VAR
    VAR
    END_VAR
    иногда бывает что может помочь добавление к константам тип данных через решетку или объявить эти значения константными переменными

    ЗЫ из представленного не ясно, какой срок получения ответа, возможно стоит возвращать результат в переменную и анализировать на равенство нулю например
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  4. #114

    По умолчанию

    Первая же команда PRU_FB_GetParameter(pru_num:=0, index:=28, value:=ADR(TMP)) уводит ПЛК в перезагрузку.
    PRU_FB_GetParameter(pru_num:=0, index:=29, value:=ADR(QUANTITY_LEFT));
    а вот определение в программе...

    #define in_reg R29
    #define out_reg R28

    Вы пытаетесь писать в регистр для чтения... а регистр можно использовать для обмена либо в одну, либо в другую сторону...

    кстати, за один проход цикла PRU считывается и записывается по одному регистру, надеюсь в вашем модуле данные поступят в блок синхронизированным пакетом?
    Последний раз редактировалось Дмитрий Артюховский; 19.09.2016 в 22:20.

  5. #115

    По умолчанию

    Цитата Сообщение от Дмитрий Артюховский Посмотреть сообщение
    а вот определение в программе...

    #define in_reg R29
    #define out_reg R28

    Вы пытаетесь писать в регистр для чтения... а регистр можно использовать для обмена либо в одну, либо в другую сторону...
    Это всё ерунда.
    Я же говорил какая у меня программа:
    Цитата Сообщение от vladimirisitnikov Посмотреть сообщение
    Для примера, вот так выглядит pulse.p -- т.е. просто вызов одного моего ФБ.
    Код:
    ;include "target.trg"
    FBDECL
    #defFB PRU_PULSE PRU_PULSE
    /FBDECL
    
    SYNCLIST
    IN=R25
    IN=R26
    IN=R27
    OUT=R28
    OUT=R29
    /SYNCLIST
    PROGRAMM
    PRU_PULSE
    /PROGRAMM
    Я вообще 3 регистра на вход и 2 на выход использую.


    Скорее всего, проблема в том, что PRU не даёт отмашку "данные переданы/прочитаны", поэтому на ПЛК стороне операции PRU_FB_SetParameter/PRU_FB_GetParameter зависают (похоже, они ждут) и в конце концов ПЛК перегружается по watchdog'у.

    Поправлю программу, чтобы были отмашки, и, наверняка заработает.

  6. #116

    По умолчанию

    Поправил обмен данными между PRU и ПЛК.

    pru_pulse_v2.zip

    Теперь-то уж наверняка заработает.

    Итого:

    Код:
    FUNCTION_BLOCK PRU_PULSE
    (* Output will be generated to FAST OUTPUT 3 *)
    VAR_INPUT
      ENABLE: BOOL;
      CYCLE_LENGTH: WORD; (* PRU cycles: 40...65486 == 65486-50;   40 == 0.27us,  65486 == 436 us *)
      QUANTITY: DWORD; (* 0..2147483647 == (2<<30)-1 *)
    END_VAR
    VAR_OUTPUT
      READY : BOOL;
      QUANTITY_LEFT: DWORD; (* for debugging *)
    END_VAR
    Последний раз редактировалось Владимир Ситников; 20.09.2016 в 12:58.

  7. #117

    По умолчанию

    Цитата Сообщение от vladimirisitnikov Посмотреть сообщение
    Прошу провести натурные испытания.
    Обмен с PRU так не работает. смотрим ФБ END_1_1 и понимаем 2 номера регистра, по которым идёт обмен.
    Если надо больше - модифицируем ФБ соответственно.

    Сама библиотека работает с любым номером регистра, если он задаётся и поддерживается ФБ END и опредёлен в программе в разделе
    SYNCLIST

    Копирование данных в PRU и из PRU происходит силами самой PRU. Через разделяемую память, куда пишет библиотека
    Последний раз редактировалось Филоненко Владислав; 20.09.2016 в 09:34.
    Тролль-наседка, добрый, нежный и ласковый

  8. #118

    По умолчанию

    Цитата Сообщение от Дмитрий Артюховский Посмотреть сообщение
    "и сказано в писании.." что в программе обязательно присутствуют модули PRU_START и PRU_END, которые подставляются автоматически... возможно там...
    На заборе тоже написано, а там дрова лежат.

    Я составляю *.p программу сам, и никаких PRU_START/PRU_END никуда не добавляется.


    Цитата Сообщение от Дмитрий Артюховский Посмотреть сообщение
    "и сказано в писании.." что в программе обязательно присутствуют модули PRU_START и PRU_END, которые подставляются автоматически... возможно там...
    т.е. вы категорически не хотите сами проверять свой код?
    Дмитрий:
    1) Я проверяю код на эмуляторе. На PRU процессор есть документация -- я его эмулирую. На pruAccessLib.lib документации нет -- приходится гадать и проводить натурные эксперименты.
    2) У меня нет проводов для соединения ПЛК
    3) Можете проверить? Ну, реально. Если у вас "расчехлён ПЛК", то проверить должно быть недолго.
    Последний раз редактировалось Владимир Ситников; 20.09.2016 в 09:47.

  9. #119

    По умолчанию

    Цитата Сообщение от Филоненко Владислав Посмотреть сообщение
    Копирование данных в PRU и из PRU происходит силами самой PRU. Через разделяемую память, куда пишет библиотека
    У меня вопрос про HOST составляющую.
    Библиотека pruAccessLib.lib, похоже, не просто "пишет в память", а ещё и ждёт того, как PRU обработает данные. Вот этот момент ни в "писании" не сказан, ни из исходных кодов тоже не считывается.
    Последний раз редактировалось Владимир Ситников; 20.09.2016 в 09:47.

  10. #120

    По умолчанию

    Спасибо прибористу за тестирование.

    Собственно, лучше не скажешь:
    Цитата Сообщение от приборист
    Поробовал, все заработало.
    Скорость на ходу изменяет.
    Вечером будет побольше времени потестировать.
    Шах и мат?


    Собственно, программа:

    Код:
    PROGRAM PRU_PULSE_GENERATOR 
      variables: 
        burst : PRU_GENER_BURST; 
        enable : BOOL; 
        cycleLength : WORD; 
        quantity : DWORD; 
        ready : BOOL; 
        qtyLeft : DWORD; 
        dataReady : BOOL; 
        controlRegisterAddress : DWORD; 
        currentCycles : WORD; 
       
      body: 
        (* безопасные значения *) 
        enable := FALSE; 
        cycleLength := 100; 
        quantity := 0; 
        WHILE TRUE DO 
          (* собственно полезная работа *) 
          burst(enable := enable, quantity := quantity); 
           
          controlRegisterAddress := 16#700C;
          (* Пока есть время, передаём-принимаем данные *)
          REPEAT 
            ASM 
              LBCO dataReady, 3, 0, 1 
            END_ASM 
             
            IF dataReady THEN 
              (* Приём *) 
              ASM 
                LBCO quantity, 3, 100, 4 
                LBCO cycleLength, 3, 104, 2 
                LBCO enable, 3, 108, 1 
              END_ASM 
               
              (* Передача *) 
              ready := burst.ready; 
              ASM 
                SBCO ready, 3, 112, 1 
              END_ASM 
              qtyLeft := burst.qtyLeft; 
              ASM 
                SBCO qtyLeft, 3, 116, 4 
              END_ASM 
               
              dataReady := FALSE; 
              ASM 
                SBCO dataReady, 3, 0, 1 
              END_ASM 
            END_IF; 
             
            ASM 
              LBBO currentCycles, controlRegisterAddress, 0, 2
            END_ASM 
            currentCycles := currentCycles + 40; 
          UNTIL currentCycles < cycleLength 
          END_REPEAT; 
          (* Остаток задержки ждём более точно, без приёма-передачи *)
          WAIT_TICK(pruCycleLength := cycleLength); 
           
          PRU_OUT1(Q := burst.out); 
        END_WHILE; 
    END_PROGRAM
    Код:
    FUNCTION_BLOCK PRU_GENER_BURST 
      variables: 
        input enable : BOOL; 
        input quantity : DWORD; 
        output out : BOOL; 
        output ready : BOOL; 
        retain output qtyLeft : DWORD; 
       
      body: 
        IF enable THEN 
          IF qtyLeft > 0 THEN 
            (* Идёт генерация *) 
            qtyLeft := qtyLeft - 1; 
          ELSIF ready THEN 
            (* Всё сгенерировали, ждём пока передёрнут enable для следующего включения *) 
          ELSE 
            (* Поступила команда на включение *) 
            qtyLeft := SHL(quantity, 1); 
            qtyLeft := qtyLeft - 1; 
          END_IF; 
          ready := qtyLeft = 0; 
        ELSE 
          (* Выключаемся *) 
          qtyLeft := 0; 
          ready := FALSE; 
        END_IF; 
        (* Если всё сделали, то out выключится. Если пачка ещё генерируется, то младший бит и есть меандр *) 
        out := qtyLeft.0;
    Код:
    FUNCTION_BLOCK WAIT_TICK 
      variables: 
        input pruCycleLength : WORD; 
        cyclesLeft : WORD; 
        currentCycles : WORD; 
        controlRegisterAddress : DWORD; 
       
      body: 
        (* 0x00007000..0x00007FFF -- PRU0 Control Registers, 0xC -- cycle count register *) 
        controlRegisterAddress := 16#700C; 
        ASM 
          LBBO currentCycles, controlRegisterAddress, 0, 2 ; Load cycle count, 1+wdcnt*1==2 cycles 
        END_ASM 
        currentCycles := currentCycles + 8; 
        IF pruCycleLength > currentCycles THEN 
          cyclesLeft := pruCycleLength - currentCycles; 
          cyclesLeft := cyclesLeft XOR 0; 
          IF cyclesLeft.0 THEN 
            cyclesLeft := cyclesLeft XOR 1; 
          END_IF; 
          WHILE cyclesLeft <> 0 DO 
            cyclesLeft := cyclesLeft - 2; 
          END_WHILE; 
        ELSE 
          cyclesLeft := 0; 
        END_IF; 
        ASM 
          SBBO cyclesLeft, controlRegisterAddress, 0, 2 ; Load cycle count, 1+wdcnt*1==2 cycles 
        END_ASM

Страница 12 из 69 ПерваяПервая ... 210111213142262 ... ПоследняяПоследняя

Похожие темы

  1. Ответов: 38
    Последнее сообщение: 24.01.2022, 11:56
  2. Ответов: 10
    Последнее сообщение: 11.06.2021, 14:55
  3. часы реального времени
    от vetaly в разделе ПЛК1хх
    Ответов: 4
    Последнее сообщение: 28.08.2015, 16:21
  4. Таймер реального времени УТ1-РiС
    от ser10 в разделе Трёп (Курилка)
    Ответов: 0
    Последнее сообщение: 16.09.2010, 12:24

Ваши права

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