From d570ee3d591a05b883e21a9d77ff273c12d3dbd3 Mon Sep 17 00:00:00 2001 From: electrolab Date: Tue, 8 Dec 2020 20:14:41 +0100 Subject: [PATCH] Move common real/simu elements to maurice-common.ini --- lcec.hal | 10 ++ lcec_simu.hal | 8 ++ lcec_simu/lcec_simu.comp | 120 +++++++++++++++++++++ lcec_simu/lcec_simu.so | Bin 0 -> 35384 bytes maurice_gmoccapy.ini => maurice-common.ini | 5 - maurice-simu.ini | 7 ++ maurice.hal | 18 ++-- maurice.ini | 7 ++ 8 files changed, 158 insertions(+), 17 deletions(-) create mode 100755 lcec.hal create mode 100755 lcec_simu.hal create mode 100755 lcec_simu/lcec_simu.comp create mode 100755 lcec_simu/lcec_simu.so rename maurice_gmoccapy.ini => maurice-common.ini (97%) mode change 100644 => 100755 create mode 100755 maurice-simu.ini create mode 100644 maurice.ini diff --git a/lcec.hal b/lcec.hal new file mode 100755 index 0000000..5531cf5 --- /dev/null +++ b/lcec.hal @@ -0,0 +1,10 @@ +loadrt trivkins +loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS + +loadusr -W lcec_conf maurice.xml +loadrt lcec + +addf lcec.read-all servo-thread +addf lcec.write-all servo-thread + +net state-op <= lcec.state-op diff --git a/lcec_simu.hal b/lcec_simu.hal new file mode 100755 index 0000000..8b91ff0 --- /dev/null +++ b/lcec_simu.hal @@ -0,0 +1,8 @@ +loadrt trivkins +loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS + +loadrt lcec_simu names=lcec.0.0,lcec.0.1 +addf lcec.0.0 servo-thread +addf lcec.0.1 servo-thread + +setp iocontrol.0.emc-enable-in 1 diff --git a/lcec_simu/lcec_simu.comp b/lcec_simu/lcec_simu.comp new file mode 100755 index 0000000..f9ac48d --- /dev/null +++ b/lcec_simu/lcec_simu.comp @@ -0,0 +1,120 @@ +// setp lcec.0.0.drivecontrol-1 1 +// setp lcec.0.0.drivecontrol-2 1 +// net state-op <= lcec.state-op +// net X-amp => lcec.0.0.drivecontrol-3 => lcec.0.0.drivecontrol-0 +// net X-poscmd => lcec.0.0.poscommand +// net X-posfb <= lcec.0.0.pos +// net X-fault <= lcec.0.0.drivestatus-3 + +// net X-stat-pos <= lcec.0.0.modestatus-3 +// net X-stat-home <= lcec.0.0.modestatus-2 +// net X-homingok <= lcec.0.0.drivestatus-12 +// net X-athome <= lcec.0.0.drivestatus-10 + +// net X-ctrl-home => lcec.0.0.modecontrol-1 => lcec.0.0.modecontrol-2 +// net X-homestart => lcec.0.0.drivecontrol-4 +// net X-ctrl-pos => lcec.0.0.modecontrol-3 + +// net X-PoT <= lcec.0.0.inputs-1 +// net X-NoT <= lcec.0.0.inputs-0 + +component lcec_simu "ESTUN drive simulator"; +author "Electrolab"; + +pin out bit state_op; + +pin in bit drivecontrol_0; +pin in bit drivecontrol_1; +pin in bit drivecontrol_2; +pin in bit drivecontrol_3; +pin in bit drivecontrol_4; + +pin in float poscommand; +pin out float pos; + +pin out bit drivestatus_3; +pin out bit drivestatus_10; +pin out bit drivestatus_12; + +pin out bit modestatus_2; +pin out bit modestatus_3; + +pin in bit modecontrol_0; +pin in bit modecontrol_1; +pin in bit modecontrol_2; +pin in bit modecontrol_3; +pin in bit modecontrol_4; + +pin out bit inputs_0; +pin out bit inputs_1; + +pin out s32 debug; +pin out s32 state; +pin out float motion_length; + +function _; +license "GPL"; // indicates GPL v2 or later +;; + +#define HOMING_LENGTH 100 +#define LATCH_LENGTH 5 +#define HOMING_SPEED_MM_S 10 +#define SERVO_PERIOD_MILI 1 + +FUNCTION(_) { + state_op = 1; + drivestatus_3 = 0; + inputs_0 = 0; + inputs_1 = 0; + + debug += 1; + + modestatus_2 = modecontrol_2; + modestatus_3 = modecontrol_3; + + if (!drivecontrol_4) { + motion_length = HOMING_LENGTH; + drivestatus_12 = 0; + state = 0; + } + + if (drivecontrol_0 && drivecontrol_1 && drivecontrol_2 && drivecontrol_3) { // Drive enable + + if (!modecontrol_2 && modecontrol_3) { // Position mode + pos = poscommand; + } + + if (modecontrol_2 && !modecontrol_3 && drivecontrol_4) { // Homing mode + switch (state) { + case 0: // idle + state = 1; + break; + case 1: // home + if (motion_length > 0) { + float step = HOMING_SPEED_MM_S * SERVO_PERIOD_MILI / 1000.0; + motion_length -= step; + pos += step; + } + else { + motion_length = LATCH_LENGTH; + state = 2; + } + break; + case 2: // latch + if (motion_length > 0) { + float step = HOMING_SPEED_MM_S * SERVO_PERIOD_MILI / 1000.0; + motion_length -= step; + pos -= step; + } + else { + state = 3; + } + break; + case 3: // homed + drivestatus_12 = 1; + break; + } + } + } + +} \ No newline at end of file diff --git a/lcec_simu/lcec_simu.so b/lcec_simu/lcec_simu.so new file mode 100755 index 0000000000000000000000000000000000000000..86bd8f605ec17394e8744f8cbe58816792f81dd9 GIT binary patch literal 35384 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