Sunday, July 17, 2011

LDmicro and Arduino

Ladder Logic for Arduino.

In this article the way how to run program in ladder logic from LDmicro on Arduino is presented. LDmicro is free SW to write and simulate ladder logic programs. When is ladder logic program is successfully simulated it could be compiled for AVR or PIC processor. However ATmega used in Arduino is not supported. Fortunately LDmicro can “compile” code into ANSI C. So, let’s take a look how we can run this code on Arduino.

Little Background

When we select ANSI C Code as Microcontroler type in Settings menu of LDmicro after compile we will get C file. This file contains all logic but it requires header file ladder.h which is missing. So, we have to implement this file. Let say we have input contact called “button” then we have to implement function:

BOOL Read_U_b_Xbutton(void) {
 return digitalRead(10); // button on digital pin 10
}

And similar to others input and output pins. Actually we have to write the layer between leader logic program and real HW of Arduino. And it could be more than simple call of digitalRead or digitalWrite. For example we could control servos, read data from proximity sensor and so on. Ability to write this layer is very powerful. Ladder logic could be used for core logic of application and C only for HW layer.

For more information read actual generated C file. It contains more information.

Generating ladder.h

If we need just direct control of digital IO pins of Arduino ladder.h could be easily generated for us. I wrote PHP script that can do this job. It requires generated code and mapping between variable name we use in ladder logic and pin numbers of Arduino. It will generate ladder.h with all nessesary functions and setup function (correctly calls pinMode for all used digital pin). Script could be used as console application or it’s also available online.

Step by step

Let’s do it step by step. Complete example is available for download.

1. Write code in LDmicro.

2. Select as Microcontroller “ANSI C Code”.

3. Compile it as ladder.cpp (save it as *.cpp file not *.c, otherwise Arduino won’t compile it)

4. Prepare mapping for IO pins of Arduino. Its text file called pinmap.ini. See example for details.

5. Generate ladder.h file by ladder-gen.php.

Tip: Ladder.h generator is available also online. However you can’t use pinmode.ini in online version. So all input and output pins have to have name “d0” for arduino digital pin 0, “d1” for pin 1 and so on.

6. Create Arduino sketch.

#include "ladder.h"

void setup() {
    PlcSetup();
}

void loop() {
    PlcCycle();
    delay(10);
}

See example for better sketch implementation (this one is for illustration and it's not accurate for timers).

7. Compile it by Arduino editor and upload it.

8. That’s all.

Tip: Now if you enable “External editor” setting of Arduino editor then you need just hit “F5“ in LDmicro and then push “Upload “ in Arduino editor to run program.

Conclusion

I hope presented method will help you start with ladder logic for Arduino. If you have any suggestion or find a bug in script, let me know.

33 comments:

  1. Acutally I tried but its not happenning
    It is showing this error:

    ladder.cpp:15:20: error: ladder.h: No such file or directory
    ladder.cpp:42: error: 'BOOL' does not name a type
    ladder.cpp:45: error: 'BOOL' does not name a type
    ladder.cpp:48: error: 'SWORD' does not name a type
    ladder.cpp:51: error: 'BOOL' does not name a type
    ladder.cpp:52: error: variable or field 'Write_U_b_Y13' declared void
    ladder.cpp:52: error: 'BOOL' was not declared in this scope
    ladder.cpp: In function 'void PlcCycle()':
    ladder.cpp:61: error: 'I_b_mcr' was not declared in this scope
    ladder.cpp:64: error: 'I_b_rung_top' was not declared in this scope
    ladder.cpp:68: error: 'U_i_Tnew' was not declared in this scope
    ladder.cpp:73: error: 'U_i_Tnew' was not declared in this scope
    ladder.cpp:76: error: 'Write_U_b_Y13' was not declared in this scope

    ReplyDelete
    Replies
    1. It looks like you have omitted to generate ladder.h file.

      Delete
  2. if u upload the procedural video that may help a lot. thanks!!

    ReplyDelete
  3. I am running this on linux.
    Where does the pinmap.ini come into play?
    This looks real exciting but I just quite don't understand.
    Thanks
    Dave

    ReplyDelete
    Replies
    1. pinmap.ini contains mapping between variable names in the LDmicro and actual digital pins of the Arduino (variable name → pin number). Ladder-gen.php use this file to generate ladder.h. If this file is missing default mapping (“d0” → pin 0, “d1” → pin 1 and so on) is used.

      Delete
  4. Why I can't use PWM in LDmicro using this method? Is there any way to use it?

    ReplyDelete
    Replies
    1. Unfortunately LDmicro doesn’t support pwm instruction in C code. However you have access to any variables in LDmicro program from C code.

      So it’s possible to use variable called e.g. “pwn” in LDmicro program and after every PlcCycle set arduino PWM output according to this variable. Variable name in C will be something like “U_i_xxx”.

      Example: http://gist.github.com/2602423#file_pwm.pde (see variable U_i_pwm on line 18)

      Delete
  5. I tried to upload the example code you provided onto my arduino, and i received numerous errors. Could you give any insight into what is wrong? I am Arduino IDE 1.0

    ReplyDelete
    Replies
    1. Thank you for notice. I have made some changes and now I should work fine (tested in 0023 and 1.0 IDE version). Please, download new version and let me know if it works.

      Delete
    2. can you show how get the ladder.h file

      Delete
    3. The easiest way:

      1) Assume you have your program in LDmicro and you have compiled it into ladder.cpp. Input and output pins in LDmicro program are called “d0” for arduino digital pin 0, “d1” for digital pin 1 and so on.

      2) Copy content of ladder.cpp into http://adam.horcica.cz/tools/ladder-gen/ and press generate. The result is content of your ladder.h file.

      pinMode of arduino pins are determined automatically (algorithm is simple, every time when you use pin as output, the pin mode is set to output otherwise it's input).

      If you want to have different names for input and output pins you have to use ladder-gen.php as described in article. However you need PHP interpreter installed on your computer.

      Delete
    4. i am a student working on arduino project
      i want to use ladder-gen.php (No previous knowledge of php)
      can you tell me how to use this tool
      php ladder-gen.php [path-to-sketch-folder]

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. hi adam
    i have done correctly but i am getting error


    sketch_jun04a.cpp.o: In function `loop':
    C:\Users\RINKU\AppData\Local\Temp\build8371174935676393128.tmp/sketch_jun04a.cpp:11: undefined reference to `PlcCycle()'

    ReplyDelete
    Replies
    1. hi,
      program is running correctly, initially i was doing some mistake now it working fine.

      Delete
    2. Hi :
      I also got same error:

      ladder.cpp.o: In function `loop':
      C:\Users\steve\Documents\arduino-1.0.5/ladder.ino:15: undefined reference to `PlcCycle()'

      Will you please tell me how to to fix ?!

      THANKS!

      Delete
  8. Hi,
    This error is coming because you didn't include the .cpp file in your program,your program should contain main program, .cpp file and ladder.h file and main program should be like

    #include "ladder.h"
    void setup() {
    PlcSetup();
    }

    void loop()
    {
    PlcCycle();
    delay(10);
    }
    only hope your problem will solve ...

    ReplyDelete
  9. i prove it, and it works :D Arduino 1.0.5 with generic Arduino

    ReplyDelete
  10. I have error

    sketch_jan23a.cpp.o: In function `loop':
    C:\Program Files\Arduino/sketch_jan23a.ino:9: undefined reference to `PlcCycle()'

    if I include ladder.cpp, ima got error
    sketch_jan23b.ino:2:22: error: ladder.cpp: No such file or directory

    Can you help me?

    ReplyDelete
    Replies
    1. I find these errors with Arduino 1.0.5-r2

      Will you please tell me how to to fix ?!

      THANKS!

      Delete
  11. You are getting this error becoz you miss some file
    your arduino program should contain there window..

    1. .cpp file
    2. ladder.h file
    3. main program

    .cpp window is code which contain c program of ladder logic
    ladder.h window is code after generating form ladder-gen.php
    main window simple call the all function
    your main program look like this
    #include "ladder.h"
    void setup() {
    PlcSetup();
    }

    void loop()
    {
    PlcCycle();
    delay(10);
    }

    now it should work ..!! :)

    ReplyDelete
  12. Can not get it to work on a mega 2560. I was able to get it to work with Uno but not mega. Can anyone help?

    ReplyDelete
    Replies
    1. Figured out that it will not do higher pins. I tried on 44 and it won't work. However, it does work on pin 11 and 12.

      Delete
  13. Hello Adam,
    can be used in LDmicro analog inputs?
    It makes me a brief example of syntax?
    Luigi

    ReplyDelete
  14. Hello Adam,
    can be used in LDmicro analog inputs of arduino?
    It makes me a brief example of syntax?
    Luigi

    ReplyDelete
  15. Hello,
    I have a hard time understanding the code files LDmicro, they are part of what compiler? Would Visual Studio? Which version?
    I would be grateful if you would point me a way forward.
    Thank you.

    ReplyDelete
  16. i have error when i use ANSI c Code its not support file

    ReplyDelete
  17. #include

    /* Define EXTERN_EVERYTHING in ladder.h if you want all symbols extern.
    This could be useful to implement `magic variables,' so that for
    example when you write to the ladder variable duty_cycle, your PLC
    runtime can look at the C variable U_duty_cycle and use that to set
    the PWM duty cycle on the micro. That way you can add support for
    peripherals that LDmicro doesn't know about. */
    #ifdef EXTERN_EVERYTHING
    #define STATIC
    #else
    #define STATIC static
    #endif

    /* Define NO_PROTOTYPES if you don't want LDmicro to provide prototypes for
    all the I/O functions (Read_U_xxx, Write_U_xxx) that you must provide.
    If you define this then you must provide your own prototypes for these
    functions in ladder.h, or provide definitions (e.g. as inlines or macros)
    for them in ladder.h. */
    #ifdef NO_PROTOTYPES
    #define PROTO(x)
    #else
    #define PROTO(x) x
    #endif

    /* U_xxx symbols correspond to user-defined names. There is such a symbol
    for every internal relay, variable, timer, and so on in the ladder
    program. I_xxx symbols are internally generated. */
    STATIC BOOL I_b_mcr = 0;
    #define Read_I_b_mcr() I_b_mcr
    #define Write_I_b_mcr(x) I_b_mcr = x
    STATIC BOOL I_b_rung_top = 0;
    #define Read_I_b_rung_top() I_b_rung_top
    #define Write_I_b_rung_top(x) I_b_rung_top = x

    /* You provide this function. */
    PROTO(extern BOOL Read_U_b_X1(void);)


    /* You provide these functions. */
    PROTO(BOOL Read_U_b_Y1(void);)
    PROTO(void Write_U_b_Y1(BOOL v);)



    /* Call this function once per PLC cycle. You are responsible for calling
    it at the interval that you specified in the MCU configuration when you
    generated this code. */
    void PlcCycle(void)
    {
    Write_I_b_mcr(1);

    /* start rung 1 */
    Write_I_b_rung_top(Read_I_b_mcr());

    /* start series [ */
    if(!Read_U_b_X1()) {
    Write_I_b_rung_top(0);
    }

    Write_U_b_Y1(Read_I_b_rung_top());

    /* ] finish series */

    ReplyDelete
  18. this is the error come out, but i am trying to solve i can't
    thanks

    ReplyDelete
    Replies
    1. Have you tried to save it as *.cpp file (as I write in article)?

      Delete
  19. This comment has been removed by a blog administrator.

    ReplyDelete
  20. Sir please help me....
    I have an error like below....
    Thanks....

    In file included from sketch_may19a.ino:1:
    C:\Program Files\Arduino\libraries\ladder/ladder.h: In function 'boolean Read_U_b_Yunroller()':
    C:\Program Files\Arduino\libraries\ladder/ladder.h:62: error: 'v' was not declared in this scope
    C:\Program Files\Arduino\libraries\ladder/ladder.h:63: warning: no return statement in function returning non-void
    C:\Program Files\Arduino\libraries\ladder/ladder.h: In function 'void Write_U_b_Yunroller(boolean)':
    C:\Program Files\Arduino\libraries\ladder/ladder.h:67: error: return-statement with a value, in function returning 'void'
    C:\Program Files\Arduino\libraries\ladder/ladder.h: In function 'boolean Read_U_b_Yledroller()':
    C:\Program Files\Arduino\libraries\ladder/ladder.h:72: error: 'v' was not declared in this scope
    C:\Program Files\Arduino\libraries\ladder/ladder.h:73: warning: no return statement in function returning non-void
    C:\Program Files\Arduino\libraries\ladder/ladder.h: In function 'void Write_U_b_Yledroller(boolean)':
    C:\Program Files\Arduino\libraries\ladder/ladder.h:77: error: return-statement with a value, in function returning 'void'
    C:\Program Files\Arduino\libraries\ladder/ladder.h: In function 'boolean Read_U_b_Xlimitswitchunro()':
    C:\Program Files\Arduino\libraries\ladder/ladder.h:82: error: 'v' was not declared in this scope
    C:\Program Files\Arduino\libraries\ladder/ladder.h:83: warning: no return statement in function returning non-void

    ReplyDelete
  21. Hi all, I have taken on the task of making a video about this method, thanks adam by this method.

    https://www.youtube.com/watch?v=W7YL1HNweh8

    ReplyDelete