News:

SMF - Just Installed!

Main Menu

Code Help

Started by NA, December 19, 2025, 03:23:12 PM

Previous topic - Next topic

NA

Hello long story short I have a simulation that has a pneumatic pusher that I have named "Pusher" I want to script for it to read an analog value from my PLC via Codesys and manipulate the pusher speed and rotation along the y-axis. I have attached the entirety of my code to this post and want to see if anyone can help me. I have been at it for 2 weeks and this is my final portion that I need before my simulation is mostly complete. Any help would be appreciated.

There are 2 versions (any digital inputs are working correctly and dealt with correctly by the PLC):

Version:
// Machines Simulator - Machine Script Code
// FINAL FULL CODE
//
// Behavior:
//  - DO_Launch controls the cylinder: TRUE = extend, FALSE = retract
//  - AO_Pusher_Rotation is a 0–360° command that rotates the pusher about Y only
//  - AO_Pusher_Speed is a 0–360 command that scales into Pusher.Speed
//
// Notes:
//  - Pusher extend/retract is handled internally by the script (AdvanceCyl/BackCyl).



// ---------------- IO MAPPING ----------------

//// DIGITAL INPUTS ////
const int DI_PE1 = 0;
const int DI_PE2 = 1;
const int DI_PE3 = 2;
const int DI_PE4 = 3;
const int DI_PE5 = 4;
const int DI_PE6 = 5;

//// ANALOGIC OUTPUTS ////
const int AO_Pusher_Rotation = 0; // 0–360 degrees
const int AO_Pusher_Speed = 1; // 0–360 (speed command)

// DIGITAL OUTPUTS
const int DO_Catch_all_destroyer = 0;
const int DO_Box_Creator = 1;
const int DO_Launch = 2; // Your launch/extend command // TRUE = extend, FALSE = retract


// ---------------- TUNING ----------------

// Rotation limits (degrees)
const float ROT_MIN_DEG  = 0.0f;
const float ROT_MAX_DEG  = 360.0f;

// Fixed rotation step per Physics() call (deg/tick)
const float ROT_STEP_DEG = 2.0f;     // tune (bigger = faster turning)

// Pusher speed range (tune to your model)
const float PUSH_SPEED_MIN = 0.1f;
const float PUSH_SPEED_MAX = 100.0f;

// ---------------- MAIN LOOP ----------------

public void Main()
{
    // Cylinder command from PLC BOOL input
    bool launch = IOManager.GetOutput(DO_Launch);

    // When DO_Launch is TRUE -> extend
    // When DO_Launch is FALSE -> retract
    if (launch)
    {
        Pusher.AdvanceCyl(true);
        Pusher.BackCyl(false);
    }
    else
    {
        Pusher.AdvanceCyl(false);
        Pusher.BackCyl(true);
    }
   
}

public void Physics()
{
    // ---- 1) Read analog speed commands (value) ----
    float rawSpeedDeg = IOManager.GetAOutput(AO_Pusher_Speed);    // value
    //float norm      = Clamp01(rawSpeedDeg / 360.0f);
    //float pushSpeed = Lerp(PUSH_SPEED_MIN, PUSH_SPEED_MAX, norm);
   
    if (rawSpeedDeg > 0.0f)
    {
       Pusher.Speed = IOManager.SetAOutput(1,rawSpeedDeg);
       Pusher2.Speed = IOManager.SetAOutput(1,20.0f);
    }


}





// ---------------- HELPERS ----------------
float Clamp01(float v)
{
    if (v < 0.0f) return 0.0f;
    if (v > 1.0f) return 1.0f;
    return v;
}

float Clamp(float v, float min, float max)
{
    if (v < min) return min;
    if (v > max) return max;
    return v;
}

float Lerp(float a, float b, float t)
{
    return a + (b - a) * t;
}

float Abs(float v)
{
    return v < 0.0f ? -v : v;
}


_________________________________________________
Version 2:
// Machines Simulator - Machine Script Code
// FINAL FULL CODE
//
// Behavior:
//  - DO_Launch controls the cylinder: TRUE = extend, FALSE = retract
//  - AO_Pusher_Rotation is a 0–360° command that rotates the pusher about Y only
//  - AO_Pusher_Speed is a 0–360 command that scales into Pusher.Speed
//
// Notes:
//  - Pusher extend/retract is handled internally by the script (AdvanceCyl/BackCyl).



// ---------------- IO MAPPING ----------------

//// DIGITAL INPUTS ////
const int DI_PE1 = 0;
const int DI_PE2 = 1;
const int DI_PE3 = 2;
const int DI_PE4 = 3;
const int DI_PE5 = 4;
const int DI_PE6 = 5;

//// ANALOGIC OUTPUTS ////
const int AO_Pusher_Rotation = 0; // 0–360 degrees
const int AO_Pusher_Speed = 1; // 0–360 (speed command)

// DIGITAL OUTPUTS
const int DO_Catch_all_destroyer = 0;
const int DO_Box_Creator = 1;
const int DO_Launch = 2; // Your launch/extend command // TRUE = extend, FALSE = retract


// ---------------- TUNING ----------------

// Rotation limits (degrees)
const float ROT_MIN_DEG  = 0.0f;
const float ROT_MAX_DEG  = 360.0f;

// Fixed rotation step per Physics() call (deg/tick)
const float ROT_STEP_DEG = 2.0f;     // tune (bigger = faster turning)

// Pusher speed range (tune to your model)
const float PUSH_SPEED_MIN = 0.1f;
const float PUSH_SPEED_MAX = 100.0f;

// ---------------- MAIN LOOP ----------------

public void Main()
{
    // Cylinder command from PLC BOOL input
    bool launch = IOManager.GetOutput(DO_Launch);

    // When DO_Launch is TRUE -> extend
    // When DO_Launch is FALSE -> retract
    if (launch)
    {
        Pusher.AdvanceCyl(true);
        Pusher.BackCyl(false);
    }
    else
    {
        Pusher.AdvanceCyl(false);
        Pusher.BackCyl(true);
    }
   
}

public void Physics()
{
    // ---- 1) Read analog rotation and speed commands (0..360) ----
    float rawRotDeg   = IOManager.GetAOutput(AO_Pusher_Rotation); // 0..360
    float rawSpeedDeg = IOManager.GetAOutput(AO_Pusher_Speed);    // 0..360

    // ---- 2) Rotate pusher about Y axis only ----
    float targetY = Clamp(rawRotDeg, ROT_MIN_DEG, ROT_MAX_DEG);

    Vector3 Rotation r   = Pusher.Rotation;
    float currY = r.y;
    float error = targetY - currY;

    float step;
    float absErr = Abs(error);

    if (absErr <= ROT_STEP_DEG)
        step = error; // close enough: snap to target
    else
        step = (error > 0.0f ? 1.0f : -1.0f) * ROT_STEP_DEG;

    float newY = currY + step;

    // Lock rotation strictly to Y axis
    Pusher.Rotation = new Vector3(0.0f, newY, 0.0f);

    // ---- 3) Dynamic cylinder speed from analog ----
    float norm      = Clamp01(rawSpeedDeg / 360.0f);
    float pushSpeed = Lerp(PUSH_SPEED_MIN, PUSH_SPEED_MAX, norm);

    Pusher.Speed = pushSpeed;
}



// ---------------- HELPERS ----------------
float Clamp01(float v)
{
    if (v < 0.0f) return 0.0f;
    if (v > 1.0f) return 1.0f;
    return v;
}

float Clamp(float v, float min, float max)
{
    if (v < min) return min;
    if (v > max) return max;
    return v;
}

float Lerp(float a, float b, float t)
{
    return a + (b - a) * t;
}

float Abs(float v)
{
    return v < 0.0f ? -v : v;
}

EasyPLC_Master

Are you using a UDC or directly the code in the machine?
Can you share your .maq file in order to help you?

NA

Hello! Yes I have the .maq attached here as a zip folder and I am directly coding in the Machine Simulator via scripting.

jpardos

En el código hay varias cosas que no están bien hechas:
Script Code da error por dos cosas:

1- Deben existir la siguiente función:
public void Finish()
{
}

2- No se puede hacer:
       Pusher.Speed = IOManager.SetAOutput(1,rawSpeedDeg);
       Pusher2.Speed = IOManager.SetAOutput(1,20.0f);
SetAoutput no devuelve ningún valor.
En su lugar, puede hacer:
       IOManager.SetAOutput(1,rawSpeedDeg);
       IOManager.SetAOutput(1,20.0f);
       Pusher.Speed = rawSpeedDeg;
       Pusher2.Speed = 20.0f;
De igual forma, puede hacer:
       Pusher.Speed = rawSpeedDeg;
       Pusher2.Speed = 20.0f;
       IOManager.SetAOutput(1,Pusher.Speed);
       IOManager.SetAOutput(1,Pusher2.Speed);
Pero está asignando a la misma salida analógica (la 1) dos valores diferentes, lo que no es lógico.


Espero le haya servido
Saludos