Программирование SMSD-1.5Modbus
 

Программирование SMSD-1.5Modbus

Автор andrey-rodin, 21 февраля 2021, 23:23:25

« назад - далее »

andrey-rodin

Программирую SMSD-1.5Modbus при помощи SMC-Program-Modbus.
Почему последний контакт обязательно должен сработать?
См. комментарии, помеченные "А.Р.":


// Инициализация
// Меркеры и регистры
// M0: 0 - требуется инициализация, 1 - инициализация уже осуществлена
// Видеорежим
// M1: 0 - первое нажатие на кнопку Пуск/Стоп, 1 - второе нажатие
// M2: вспомогательный меркер для промежуточного хранения значения M0
// M3: признак изменения направления движения
// D320: энергонезависимый регистр для хранения текущей скорости и направления движения (как знак)
LD      M0                      // для пропуска участка инициализации проверяем
CJ      P1                      // выполнение условия и будем переходить сразу к P1
DLD=    D320    K0              // Если значение скорости в регистре D320 = 0
DMOV    K5000   D320            // записываем в D320 значение 5000
LDP     M108                    // передний фронт у M108 только после инициализации
CALL    P10                     // вызываем подпрограмму установки скорости и направления движения из регистра D320
DMOV    K8      D359            // устанавливаем минимальную скорость 8 pps
MOV     K3      D366            // дробление 1/16
FMOV    K30000  D361    K2      // задаём ускорение и торможение 10000 pps2
SET     M0                      // включаем условие обхода инициализации
P       1                       // метка перехода

// Видеорежим
LD      X3                      // галетный переключатель в положении V
ANI     X4                      // (X3 = 1 AND X4 = 0)
ANDP    X2                      // ловим фронт импульса при нажатии на кнопку Пуск/Стоп
MPS
ANI     M1                      // анализируем M1: если это первое нажатие на кнопку Пуск/Стоп, то
AND&    D371    K3              // только когда двигатель в состоянии HiZ или удерж.
SET     M2                      // устанавливаем меркер M2
MOV     K0      D376            // регистр CMD, команда RUN
SPIN                            // запускаем двигатель
MRD
AND     M1                      // если это второе нажатие на кнопку Пуск/Стоп
RST     M2                      // обнуляем меркер M2
SHIZ                            // останавливаем двигатель
MPP
MOV     M2      M1              // копируем M2 в M1
LD      M1                      // двигатель вращается
AND     X5                      // зелёная кнопка нажата
CALL    P30                     // уменьшаем значение скорости в регистре D320
CALL    P10                     // устанавливаем новую скорость и направление в драйвере двигателя
CALL    P20                     // применяем новые значения скорости и направления
LD      M1                      // двигатель вращается
AND     X6                      // жёлтая кнопка нажата
CALL    P31                     // увеличиваем значение скорости в регистре D320
CALL    P10                     // устанавливаем новую скорость и направление в драйвере двигателя
CALL    P20                     // применяем новые значения скорости и направления
FEND                            // конец основной программы

// Подпрограмма установки скорости и направления движения из регистра D320
P       10
DLD>    D320    K0              // Если значение скорости > 0
MOV     K0      D374            // движение по часовой стрелке
DMOV    D320    D357            // устанавливаем значение скорости из регистра D320
DLD<    D320    K0              // Если значение скорости < 0
MOV     K1      D374            // движение против часовой стрелки
DMOV    D320    D322            // помещаем значение в регистр D322
DABS    D322                    // берём модуль
DMOV    D322    D357            // устанавливаем значение скорости из регистра D322
LD      M1                      // А.Р. - не знаю в чём дело, но последний контакт должен сработать, иначе двигатель не изменяет скорость :-(
SRET

// Подпрограмма применения новых значений скорости и ускорения
P       20
LD      M3
HSTOP                           // необходимо остановить двигатель, поскольку направление движения изменилось
RST     M3
LD      M1
SPIN                            // можем применять новое значение скорости и направления
SRET

// Подпрограмма уменьшения скорости
P       30
DSUB    D320    K5      D320    // уменьшаем значение скорости в регистре D320 на 5
DLD>    D320    K0              // если значение скорости положительное
DAND<   D320    K100            // и стало меньше 100
DMOV    K-100   D320            // записываем в D320 значение скорости -100
SET     M3                      // устанавливаем признак изменения направления
DLD<    D320    K-12000         // если скорость меньше, чем -12000
DMOV    K-12000 D320            // записываем в D320 значение скорости -12000
LD      M1                      // А.Р. - не знаю в чём дело, но последний контакт должен сработать, иначе двигатель не изменяет скорость :-(
SRET

// Подпрограмма увеличения скорости
P       31
DADD    D320    K5      D320    // увеличиваем значение скорости в регистре D320 на 5
DLD<    D320    K0              // если значение скорости отрицательное
DAND>   D320    K-100           // и стало больше -100
DMOV    K100    D320            // записываем в D320 значение скорости 100
SET     M3                      // устанавливаем признак изменения направления
DLD>    D320    K12000          // если скорость больше, чем 12000
DMOV    K12000  D320            // записываем в D320 значение скорости 12000
LD      M1                      // А.Р. - не знаю в чём дело, но последний контакт должен сработать, иначе двигатель не изменяет скорость :-(
SRET
END

Administrator

Добрый день!

Команда MOV выполняет запись 16 битов, т.е. для копирования значения M2 в M1 она не подходит.
В данном случае необходимо использовать LD M2 + OUT M1, либо LD M2 + SET или RST M1.

Перед командой SRET нельзя использовать входные условия, так как при выполнении программы эта конструкция через некоторое время вызовет переполнение стека.

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

Подправленная программа:


//   ИНИЦИАЛИЗАЦИЯ
//   МЕРКЕРЫ   И   РЕГИСТРЫ
//   M0:   0   -   ТРЕБУЕТСЯ   ИНИЦИАЛИЗАЦИЯ,   1   -   ИНИЦИАЛИЗАЦИЯ   УЖЕ   ОСУЩЕСТВЛЕНА
//   ВИДЕОРЕЖИМ
//   M1:   0   -   ПЕРВОЕ   НАЖАТИЕ   НА   КНОПКУ   ПУСК/СТОП,   1   -   ВТОРОЕ   НАЖАТИЕ
//   M2:   ВСПОМОГАТЕЛЬНЫЙ   МЕРКЕР   ДЛЯ   ПРОМЕЖУТОЧНОГО   ХРАНЕНИЯ   ЗНАЧЕНИЯ   M0
//   M3:   ПРИЗНАК   ИЗМЕНЕНИЯ   НАПРАВЛЕНИЯ   ДВИЖЕНИЯ
//   D320:   ЭНЕРГОНЕЗАВИСИМЫЙ   РЕГИСТР   ДЛЯ   ХРАНЕНИЯ   ТЕКУЩЕЙ   СКОРОСТИ   И   НАПРАВЛЕНИЯ   ДВИЖЕНИЯ   (КАК   ЗНАК)
LD   M0 //   ДЛЯ   ПРОПУСКА   УЧАСТКА   ИНИЦИАЛИЗАЦИИ   ПРОВЕРЯЕМ
CJ   P1//   ВЫПОЛНЕНИЕ   УСЛОВИЯ   И   БУДЕМ   ПЕРЕХОДИТЬ   СРАЗУ   К   P1
DLD=   D320  K0   //   ЕСЛИ   ЗНАЧЕНИЕ   СКОРОСТИ   В   РЕГИСТРЕ   D320   =   0
DMOV   K5000   D320   //   ЗАПИСЫВАЕМ   В   D320   ЗНАЧЕНИЕ   5000
LDP   M108   //   ПЕРЕДНИЙ   ФРОНТ   У   M108   ТОЛЬКО   ПОСЛЕ   ИНИЦИАЛИЗАЦИИ
CALL   P10   //   ВЫЗЫВАЕМ   ПОДПРОГРАММУ   УСТАНОВКИ   СКОРОСТИ   И   НАПРАВЛЕНИЯ   ДВИЖЕНИЯ   ИЗ   РЕГИСТРА   D320
DMOV   K8   D359   //   УСТАНАВЛИВАЕМ   МИНИМАЛЬНУЮ   СКОРОСТЬ   8   PPS
MOV   K3   D366   //   ДРОБЛЕНИЕ   1/16
FMOV   K30000   D361   K2   //   ЗАДАЁМ   УСКОРЕНИЕ   И   ТОРМОЖЕНИЕ   10000   PPS2
SET   M0   //   ВКЛЮЧАЕМ   УСЛОВИЕ   ОБХОДА   ИНИЦИАЛИЗАЦИИ

P   1   //   МЕТКА   ПЕРЕХОДА
//   ВИДЕОРЕЖИМ
//LD   X3   //   ГАЛЕТНЫЙ   ПЕРЕКЛЮЧАТЕЛЬ   В   ПОЛОЖЕНИИ   V
//ANI   X4   //   (X3   =   1   AND   X4   =   0)
LDP   X2           //   ЛОВИМ   ФРОНТ   ИМПУЛЬСА   ПРИ   НАЖАТИИ   НА   КНОПКУ   ПУСК/СТОП
MPS
ANI   M1         //   АНАЛИЗИРУЕМ   M1:   ЕСЛИ   ЭТО   ПЕРВОЕ   НАЖАТИЕ   НА   КНОПКУ   ПУСК/СТОП,   ТО
AND&   D371   K3      //   ТОЛЬКО   КОГДА   ДВИГАТЕЛЬ   В   СОСТОЯНИИ   HIZ   ИЛИ   УДЕРЖ.
SET   M2   //   УСТАНАВЛИВАЕМ   МЕРКЕР   M2
MOV   K0   D376   //   РЕГИСТР   CMD,   КОМАНДА   RUN
SPIN   //   ЗАПУСКАЕМ   ДВИГАТЕЛЬ
MRD     
AND   M1   //   ЕСЛИ   ЭТО   ВТОРОЕ   НАЖАТИЕ   НА   КНОПКУ   ПУСК/СТОП
RST      M2      //   ОБНУЛЯЕМ   МЕРКЕР   M2
SHIZ   //   ОСТАНАВЛИВАЕМ   ДВИГАТЕЛЬ
MRD
AND M2
SET M1
MPP
ANI M2
RST M1


LD   M1   //   ДВИГАТЕЛЬ   ВРАЩАЕТСЯ
AND   X5   //   ЗЕЛЁНАЯ   КНОПКА   НАЖАТА
CALL   P30         //   УМЕНЬШАЕМ   ЗНАЧЕНИЕ   СКОРОСТИ   В   РЕГИСТРЕ   D320
LD   M1   //   ДВИГАТЕЛЬ   ВРАЩАЕТСЯ
AND   X5   //   ЗЕЛЁНАЯ   КНОПКА   НАЖАТА
CALL   P10        //   УСТАНАВЛИВАЕМ   НОВУЮ   СКОРОСТЬ   И   НАПРАВЛЕНИЕ   В   ДРАЙВЕРЕ   ДВИГАТЕЛЯ
LD   M1   //   ДВИГАТЕЛЬ   ВРАЩАЕТСЯ
AND   X5   //   ЗЕЛЁНАЯ   КНОПКА   НАЖАТА
CALL   P20        //   ПРИМЕНЯЕМ   НОВЫЕ   ЗНАЧЕНИЯ   СКОРОСТИ   И   НАПРАВЛЕНИЯ

LD   M1   //   ДВИГАТЕЛЬ   ВРАЩАЕТСЯ
AND   X6   //   ЖЁЛТАЯ   КНОПКА   НАЖАТА
CALL   P31   //   УВЕЛИЧИВАЕМ   ЗНАЧЕНИЕ   СКОРОСТИ   В   РЕГИСТРЕ   D320
LD   M1   //   ДВИГАТЕЛЬ   ВРАЩАЕТСЯ
AND   X6   //   ЖЁЛТАЯ   КНОПКА   НАЖАТА
CALL   P10   //   УСТАНАВЛИВАЕМ   НОВУЮ   СКОРОСТЬ   И   НАПРАВЛЕНИЕ   В   ДРАЙВЕРЕ   ДВИГАТЕЛЯ
LD   M1   //   ДВИГАТЕЛЬ   ВРАЩАЕТСЯ
AND   X6   //   ЖЁЛТАЯ   КНОПКА   НАЖАТА
CALL   P20   //   ПРИМЕНЯЕМ   НОВЫЕ   ЗНАЧЕНИЯ   СКОРОСТИ   И   НАПРАВЛЕНИЯ



FEND   //   КОНЕЦ   ОСНОВНОЙ   ПРОГРАММЫ

//   ПОДПРОГРАММА   УСТАНОВКИ   СКОРОСТИ   И   НАПРАВЛЕНИЯ   ДВИЖЕНИЯ   ИЗ   РЕГИСТРА   D320

P   10
DLD>   D320   K0   //   ЕСЛИ   ЗНАЧЕНИЕ   СКОРОСТИ   >   0
MOV   K0   D374   //   ДВИЖЕНИЕ   ПО   ЧАСОВОЙ   СТРЕЛКЕ
DMOV   D320   D357      //   УСТАНАВЛИВАЕМ   ЗНАЧЕНИЕ   СКОРОСТИ   ИЗ   РЕГИСТРА   D320
DLD<   D320   K0          //   ЕСЛИ   ЗНАЧЕНИЕ   СКОРОСТИ   <   0
MOV         K1   D374   //   ДВИЖЕНИЕ   ПРОТИВ   ЧАСОВОЙ   СТРЕЛКИ
DMOV   D320   D322   //   ПОМЕЩАЕМ   ЗНАЧЕНИЕ   В   РЕГИСТР   D322
DABS   D322   //   БЕРЁМ   МОДУЛЬ
DMOV   D322   D357   //   УСТАНАВЛИВАЕМ   ЗНАЧЕНИЕ   СКОРОСТИ   ИЗ   РЕГИСТРА   D322
SRET     


//   ПОДПРОГРАММА   ПРИМЕНЕНИЯ   НОВЫХ   ЗНАЧЕНИЙ   СКОРОСТИ   И   УСКОРЕНИЯ
P             20
LD   M3
HSTOP   //   НЕОБХОДИМО   ОСТАНОВИТЬ   ДВИГАТЕЛЬ,   ПОСКОЛЬКУ   НАПРАВЛЕНИЕ   ДВИЖЕНИЯ   ИЗМЕНИЛОСЬ
RST   M3
LD   M1
SPIN   //   МОЖЕМ   ПРИМЕНЯТЬ   НОВОЕ   ЗНАЧЕНИЕ   СКОРОСТИ   И   НАПРАВЛЕНИЯ


SRET


//   ПОДПРОГРАММА   УМЕНЬШЕНИЯ   СКОРОСТИ
P   30
LD   M1
DSUB   D320   K5   D320   //   УМЕНЬШАЕМ   ЗНАЧЕНИЕ   СКОРОСТИ   В   РЕГИСТРЕ   D320   НА   5
DLD>   D320   K0   //   ЕСЛИ   ЗНАЧЕНИЕ   СКОРОСТИ   ПОЛОЖИТЕЛЬНОЕ
DAND<   D320   K100   //   И   СТАЛО   МЕНЬШЕ   100
DMOV   K-100   D320   //   ЗАПИСЫВАЕМ   В   D320   ЗНАЧЕНИЕ   СКОРОСТИ   -100
SET   M3   //   УСТАНАВЛИВАЕМ   ПРИЗНАК   И ЗМЕНЕНИЯ   НАПРАВЛЕНИЯ
DLD<    D320   K-12000   //   ЕСЛИ   СКОРОСТЬ   МЕНЬШЕ,   ЧЕМ   -12000
DMOV   K-12000   D320   //   ЗАПИСЫВАЕМ   В   D320   ЗНАЧЕНИЕ   СКОРОСТИ   -12000
   
SRET


//   ПОДПРОГРАММА   УВЕЛИЧЕНИЯ   СКОРОСТИ
P   31
LD   M1
DADD   D320   K5   D320      //   УВЕЛИЧИВАЕМ   ЗНАЧЕНИЕ   СКОРОСТИ   В   РЕГИСТРЕ   D320   НА   5
DLD<   D320   K0   //   ЕСЛИ   ЗНАЧЕНИЕ   СКОРОСТИ   ОТРИЦАТЕЛЬНОЕ
DAND>   D320   K-100      //   И   СТАЛО   БОЛЬШЕ   -100
DMOV   K100   D320   //   ЗАПИСЫВАЕМ   В   D320   ЗНАЧЕНИЕ   СКОРОСТИ   100
SET   M3   //   УСТАНАВЛИВАЕМ   ПРИЗНАК   ИЗМЕНЕНИЯ   НАПРАВЛЕНИЯ
DLD>   D320   K12000   //   ЕСЛИ   СКОРОСТЬ   БОЛЬШЕ,   ЧЕМ   12000
DMOV   K12000   D320      //   ЗАПИСЫВАЕМ   В   D320   ЗНАЧЕНИЕ   СКОРОСТИ   12000

SRET

END

andrey-rodin

Спасибо большое за столь полный ответ!

Еще пара вопросов:

  • В поправленной программе условия (LD   M1 + AND   X6) стоят теперь перед каждым вызовом подпрограмм. Это обязательно?
  • ЦитироватьПеред командой SRET нельзя использовать входные условия, так как при выполнении программы эта конструкция через некоторое время вызовет переполнение стека.

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

Administrator

1.
Строго говоря, должно быть достаточно одного входного условия для нескольких  исполнительных интрукций, в том числе для трех команд CALL. Однако, в данном конкретном случае второй и третий вызовы CALL не срабатывают. Очевидно, что это ошибка прошивки блока, наши программисты уже занялись этим вопросом. Выпустим обновление прошивки для блоков SMSD-1.5Modbus как только разберемся, в чем дело.

Пока для точного выполнения Вашего алгоритма оставьте входные условия перед каждым вызовом CALL.

2. Есть команды, которые требуют обязательного наличия входного условия, их нельзя поставить на выполнение как одиночные инструкции. Это большинство исполнительных иснтрукций.
И наоборот, существуют команды, которые по логике не должны иметь входного условия.
В документации на блок в описании команд есть указание, какие команды используются с входным условием, а какие без.

Без входных условий должны быть указатели I, P, команды конца программы END, FEND, а также IRET, SRET, EI, DI, NEXT, FOR

Для инструкций, которые используются без входного условия в документации стоит отметка: "Примечание: для выполнения инструкции контакт не требуется."


Возможно, Вам будет удобнее составлять программу в виде лестничной диаграммы (LD), а затем преобразовывать ее в лист инструкций IL. Автоматически это делает программа SMC-Program-Modbus (https://electroprivod.ru/program/download/smc_program-modbus.zip).

Administrator

https://electroprivod.ru/pdf/smsd-1.5Modbus-manual.pdf

andrey-rodin

Да, проблемы в прошивке есть, и немалые.
Вот пример неработающей подпрограммы. Она определяет некое внутреннее значение из текущего положения потенциометра 2 (10 градаций). Понятно, что задачу можно решить проще, поделив текущее значение потенциометра на нужное число и получив индекс от 0 до 9. Но факт остаётся фактом - формально правильный код не работает.


P 21
LD< D354 K410
MOV K18 D0
LD< D354 K820
AND>= D354 K410
MOV K20 D0
LD< D354 K1230
AND>= D354 K820
MOV K24 D0
LD< D354 K1640
AND>= D354 K1230
MOV K30 D0
LD< D354 K1640
AND>= D354 K1230
MOV K36 D0
LD< D354 K2050
AND>= D354 K1230
MOV K45 D0
LD< D354 K2460
AND>= D354 K2050
MOV K60 D0
LD< D354 K2870
AND>= D354 K2460
MOV K72 D0
LD< D354 K3280
AND>= D354 K2870
MOV K90 D0
LD> D354 K3690
MOV K120 D0
SRET


К софту тоже имеются претензии. С программой SMC-Program-Modbus работать практически невозможно, она постоянно зависает при попытке записать программу в контроллер. UI откровенно плох. Если уж работать с диаграммами, то не хватает возможности преобразования IL -> LD.

SMSD Demonstrator получше, но UI тоже не блестящий. И уж простите меня, было бы неплохо подправить грамматику в сообщениях пользователю.

Кстати говоря, я не нашёл в руководстве указания, что команду MOV нельзя использовать для меркеров...

Administrator

По ошибкам работы SMC-Program-Modbus, пожалуйста, пишите на mail@electroprivod.ru
Последняя версия v.2.0.3.beta.exe - многие ошибки и зависания в ней исправлены, эта версия сейчас на нашем сайте.

Преобразование IL в LD пока не планируется. Возможно, в будущем.

MOV можно использовать для меркеров, только учитывать нужно, что перезаписываются 16 бит, т.е. 16 реле сразу.
Об этом прямо написано в описании инструкции (см. вложение).

ЦитироватьБитовые операнды будут занимать соответствующее типу инструкции количество
адресов, 16 либо 32 адреса. При этом можно комбинировать типы операндов для
источника и цели. Например, в результате выполнения команды MOV D3 M0 реле
M0...M15 будет представлено значение регистра D3 в бинарном виде.


Administrator


P 21
LD< D354 K410
MOV K18 D0
LD< D354 K820
AND>= D354 K410
MOV K20 D0
LD< D354 K1230
AND>= D354 K820
MOV K24 D0
LD< D354 K1640
AND>= D354 K1230
MOV K30 D0
LD< D354 K1640
AND>= D354 K1230
MOV K36 D0
LD< D354 K2050
AND>= D354 K1230
MOV K45 D0
LD< D354 K2460
AND>= D354 K2050
MOV K60 D0
LD< D354 K2870
AND>= D354 K2460
MOV K72 D0
LD< D354 K3280
AND>= D354 K2870
MOV K90 D0
LD> D354 K3690
MOV K120 D0
SRET


Данный код выполняется правильно. Какие именно ошибки у Вас появляются?
Приведите всю программу целиком, пожалуйста. Посмотрим, что именно не так.

andrey-rodin

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

Хотелось бы узнать как происходит трансляция IL в ассемблер. Это делают программы SMSD Controller demonstrator и SMC-Program Modbus или IL-программа записывается в контроллер и затем интерпретируется контроллером? И почему запись программы в контроллер занимает довольно много времени?

Administrator

IL в ассемблер не переводится.
IL записывается в контроллер построчно.
Каждая строка программы  - это 42 байта, содержащие код инструкции,  типы и значения операндов, а также информацию об индексировании.

Во вложении поясняющая иллюстрация.
Подробно с примерами и пояснениями запись программы в контроллер приводится в руководстве в главе 11.

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

SMC-Program-Modbus и SMSD Controller demonstrator после записи каждой строки дополнительно проверяют, не возникло ли ошибок.

andrey-rodin

ЦитироватьIL в ассемблер не переводится.

Т.е. процессор контроллера является узкоспециализированным и основан на системе IL-команд?

Administrator

Сам процессор, конечно, не узкоспециализированный.
Но прошивка блока предполагает запись и чтение пользовательской программы в виде IL. Каждая инструкция IL - это 42 байта, содержащие код и параметры.

Вопрос был в том, переводится ли IL в ассемблер при записи в блок - нет, не переводится. По Modbus отправляются команды записи данных в специальные регистры контроллера, откуда откуда затем они записываются в память блока.
Каждая инструкция отправляется и хранится в виде 42 байт данных.

clive

Цитата: andrey-rodin от 21 февраля 2021, 23:23:25
Программирую SMSD-1.5Modbus при помощи SMC-Program-Modbus.
Почему последний контакт обязательно должен сработать?
См. комментарии, помеченные "А.Р.":


// Инициализация
// Меркеры и регистры
// M0: 0 - требуется инициализация, 1 - инициализация уже осуществлена
// Видеорежим
// M1: 0 - первое нажатие на кнопку Пуск/Стоп, 1 - второе нажатие
// M2: вспомогательный меркер для промежуточного хранения значения M0
// M3: признак изменения направления движения
// D320: энергонезависимый регистр для хранения текущей скорости и направления движения (как знак)
LD      M0                      // для пропуска участка инициализации проверяем
CJ      P1                      // выполнение условия и будем переходить сразу к P1
DLD=    D320    K0              // Если значение скорости в регистре D320 = 0
DMOV    K5000   D320            // записываем в D320 значение 5000
LDP     M108                    // передний фронт у M108 только после инициализации
CALL    P10                     // вызываем подпрограмму установки скорости и направления движения из регистра D320
DMOV    K8      D359            // устанавливаем минимальную скорость 8 pps
MOV     K3      D366            // дробление 1/16
FMOV    K30000  D361    K2      // задаём ускорение и торможение 10000 pps2
SET     M0                      // включаем условие обхода инициализации
P       1                       // метка перехода

// Видеорежим
LD      X3                      // галетный переключатель в положении V
ANI     X4                      // (X3 = 1 AND X4 = 0)
ANDP    X2                      // ловим фронт импульса при нажатии на кнопку Пуск/Стоп
MPS
ANI     M1                      // анализируем M1: если это первое нажатие на кнопку Пуск/Стоп, то
AND&    D371    K3              // только когда двигатель в состоянии HiZ или удерж.
SET     M2                      // устанавливаем меркер M2
MOV     K0      D376            // регистр CMD, команда RUN
SPIN                            // запускаем двигатель
MRD
AND     M1                      // если это второе нажатие на кнопку Пуск/Стоп
RST     M2                      // обнуляем меркер M2
SHIZ                            // останавливаем двигатель
MPP
MOV     M2      M1              // копируем M2 в M1
LD      M1                      // двигатель вращается
AND     X5                      // зелёная кнопка нажата
CALL    P30                     // уменьшаем значение скорости в регистре D320
CALL    P10                     // устанавливаем новую скорость и направление в драйвере двигателя
CALL    P20                     // применяем новые значения скорости и направления
LD      M1                      // двигатель вращается
AND     X6                      // жёлтая кнопка нажата
CALL    P31                     // увеличиваем значение скорости в регистре D320
CALL    P10                     // устанавливаем новую скорость и направление в драйвере двигателя
CALL    P20                     // применяем новые значения скорости и направления
FEND                            // конец основной программы

// Подпрограмма установки скорости и направления движения из регистра D320
P       10
DLD>    D320    K0              // Если значение скорости > 0
MOV     K0      D374            // движение по часовой стрелке
DMOV    D320    D357            // устанавливаем значение скорости из регистра D320
DLD<    D320    K0              // Если значение скорости < 0
MOV     K1      D374            // движение против часовой стрелки
DMOV    D320    D322            // помещаем значение в регистр D322
DABS    D322                    // берём модуль
DMOV    D322    D357            // устанавливаем значение скорости из регистра D322
LD      M1                      // А.Р. - не знаю в чём дело, но последний контакт должен сработать, иначе двигатель не изменяет скорость :-(
SRET

// Подпрограмма применения новых значений скорости и ускорения
P       20
LD      M3
HSTOP                           // необходимо остановить двигатель, поскольку направление движения изменилось
RST     M3
LD      M1
SPIN                            // можем применять новое значение скорости и направления
SRET

// Подпрограмма уменьшения скорости
P       30
DSUB    D320    K5      D320    // уменьшаем значение скорости в регистре D320 на 5
DLD>    D320    K0              // если значение скорости положительное
DAND<   D320    K100            // и стало меньше 100
DMOV    K-100   D320            // записываем в D320 значение скорости -100
SET     M3                      // устанавливаем признак изменения направления
DLD<    D320    K-12000         // если скорость меньше, чем -12000
DMOV    K-12000 D320            // записываем в D320 значение скорости -12000
LD      M1                      // А.Р. - не знаю в чём дело, но последний контакт должен сработать, иначе двигатель не изменяет скорость :-(
SRET

// Подпрограмма увеличения скорости
P       31
DADD    D320    K5      D320    // увеличиваем значение скорости в регистре D320 на 5
DLD<    D320    K0              // если значение скорости отрицательное
DAND>   D320    K-100           // и стало больше -100
DMOV    K100    D320            // записываем в D320 значение скорости 100
SET     M3                      // устанавливаем признак изменения направления
DLD>    D320    K12000          // если скорость больше, чем 12000
DMOV    K12000  D320            // записываем в D320 значение скорости 12000
LD      M1                      // А.Р. - не знаю в чём дело, но последний контакт должен сработать, иначе двигатель не изменяет скорость :-(
SRET
END


Удалите строки с "// А.Р." и обновите прошивку контроллера онлайн до версии 1.6. Должно помочь.

andrey-rodin

Хотелось бы поделиться своими впечатлениями от программирования.

  • Опытным путём выяснил, что нельзя осуществлять переход по метке через входные условия. Таким образом, запрограммировать элементарный цикл DO WHILE невозможно. Это означает, что о полноте по Тьюрингу говорить не приходится.
  • Выяснил также, что подпрограммы выполняются постоянно в цикле программы, независимо от того, участвует ли в данный момент подпрограмма в текущей ветке исполнения или нет. Это было несколько неожиданно для меня.
  • К сожалению, нет никакого контроля правильности IL-программы. Можно написать бессмысленный код, содержащий, например, две инструкции LD, следующие непосредственно друг за другом, и такая программа будет загружена и будет выполняться.
  • Можно написать бесконечный цикл. Тогда контроллер просто перестаёт реагировать на входные сигналы без сообщений об ошибках.

Administrator

ЦитироватьОпытным путём выяснил, что нельзя осуществлять переход по метке через входные условия.

Можно - для этого существует команда CJ.

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

В цикле программы выполняется весь код от начала программы до команды FEND или END.
Если подпрограмма написана до этой команды, она будет выполняться.

Если как и положено, код подпрограммы расположен после  FEND, то ее вызов будет выполняться из основного цикла при выполнении входного условия.

ЦитироватьК сожалению, нет никакого контроля правильности IL-программы. Можно написать бессмысленный код, содержащий, например, две инструкции LD, следующие непосредственно друг за другом, и такая программа будет загружена и будет выполняться.

Большинство критических ошибок отлавливается контроллером, о наличии ошибки и коде контроллер сообщает.

Отлавливаемые контроллером ошибки и их коды приведены в разделе 5. "5. Коды ошибок."

Две последовательно расположенные инструкции LD через некоторое время работы вызовут переполнение стека, контроллер отобразит ошибку с кодом 2002h (Команда LD, стек переполнен).

Так как мы не можем заранее знать, что именно Вы хотите получить на выходе программы, на этапе загрузки в контроллер ошибки программы не проверяются. При работе программы контроллер отображает возникающие в процессе ошибки. Некоторые можно выявить сразу на этапе предварительного сканирования. Некоторые нет.

В любом случае мы предполагаем, что пользователь понимает, какую логику работы он хочет создать. Если допущены случайные ошибки, контроллер даст об этом знать в процессе работы.

ЦитироватьМожно написать бесконечный цикл. Тогда контроллер просто перестаёт реагировать на входные сигналы без сообщений об ошибках.

Конечно можно. Например, написать бесконечное повторение рабочих операций для шагового двигателя, когда обрабатывать внешние сигналы и вмешиваться в работу привода не нужно.
Остановка в этом случае выполняется переводом контроллера в режим STOP.


В любом случае, спасибо за обратную связь!
По третьему замечанию передадим информацию программисту. Возможно, добавим предупреждение о двух инструкциях LD подряд.