Convert legacy control panel into LCD alarm and warning system with Arduino.

In the old days, We used to have electronic controller modules or PLCs which give warning or alarms on the panel by turning several light indicators  on or off. To understand these signals we have to refer their operation manual/books to interpret these messages. For example there are three indicators on the panel which has light A(lA), light B(lB) and light C(lC) so there will be 2^3 =8 combinations of warning/alarms. To make it easy to understand , They provide us a troubleshooting table to tell operators or technicians to trace the problem.

lA=0, lB=0, lC=0 -> ” Machine OK” ,

lA=1,lB=0, lC=0 -> ” Motor Overload” ,

lA=1, lB=1 ,lC=0 -> “Motor Overtemperature”,

etc, etc

(0 =OFF, 1 =ON) .

I am sure such  devices or control panels still exists and still be built  today. Sometimes it is not easy to troubleshoot the problem because of missing manual/prints or other reasons. For this purpose we will build Alarm messaging system using Arduino to retrofit old panel  and convert  light bulb/LED  indicators into a LCD display.  Here we go. Let says that we have an  old PLC that control the following system (pic1). The ladder example here  just to show how to manipulate 3 coil or relay outputs. Of course we can build more than 3 outputs when we need.



The ladder diagram looks like this :



Basically, this program tell us to open the  valve 5 seconds  before turning the centrifugal pump on. When we press “Xstart” button,  it will open the valve. The Ylight1 will turn on after  valve open limit switch (XLSopen)  become true. Ylight2 shows the pump is running meanwhile Ylight3 indicate that there is low pressure(XLowPressure) on discharge line.The normal operation should give us Ylight1=1, Ylight2=1 and Ylight3=0. This means valve is fully opened, motor is running and we got normal pressure. Since we can make 8 combinations from these lights, We can convert these states  into meaningful messages with Arduino. There is two option to use Arduino for this purpose. The first one is just for converting the state of indicators into messages. Secondly it can be utilized as both PLC and warning/alarm messages. We will use later for this example.

The Things We Need to build this Project:

  1. Arduino Board.
  2. Arduino IDE.
  3. LCD display (serial or I2C) with Arduino Library.
  4. LDMicro.
  5. PHP script to build  Arduino Library header (optional).

Any Arduino board can be used for this project. All I/O will be configured using Arduino header. Download LDmicro from this site :  

The beauty of this LDmicro is that we can compile the ladder diagram into ANSI- C code and from this cpp format we can build its library in Arduino environment.

For PHP script to generate a header we can get it from here :   

Please remember to run php script, we need to install PHP program  in our computer. For PHP for windows  download the program here :

Now Lets modify the ladder diagram from pic1.


When we look at new ladder, there are some changes and adding some rungs  which have accumulator instruction (Acc ) inserted on them. These four extra rungs actually convert binary status into decimal, Binary Coded Decimal (BCD). From three relay/coil status, we can generate 8 messages.

First, save this ladder diagram as ladder.ld ( we can choose any name for this file). Next step is to choose a microprocessor. On “Setting”->”Microcontrollers” , choose ANSI-C code. Then  go to “Compile” ->”Compile as… ” and save it as ladder.cpp. Click OK and it will shows :


Don’t worry about this warning. Like it said, this is not complete program so we have to build header by itself.  We don’t need to know about C/C++ programming. Just use this cpp together with header we are going to build to create a library to be used in Arduino environment.

Now It is time to build a header(Ladder.h) The header below built using ladder-gen.php ( see  previous link above to download it). Follow instruction there how to run and to build a header for Arduino. We can see that all I/O pins fo Arduino  can be configured here.

  1.     #ifndef LADDER_H
  2.     #define LADDER_H
  3.     #if ARDUINO >= 100
  4.     #include "Arduino.h"
  5.     #else
  6.     #include "WProgram.h"
  7.     #endif
  8.     #define BOOL boolean
  9.     #define SWORD int
  10.     #define EXTERN_EVERYTHING
  11.     #define NO_PROTOTYPES
  12.     EXTERN INT U_i_arduino;
  13.     void PlcCycle(void);
  14.     /* Configure digital I/O according to LD (call this in setup()). */
  15.     inline void PlcSetup()
  16.     {
  17.     pinMode(11, INPUT);
  18.     pinMode(12, INPUT);
  19.     pinMode(5, OUTPUT);
  20.     pinMode(9, INPUT);
  21.     pinMode(6, OUTPUT);
  22.     pinMode(10, INPUT);
  23.     }
  24.     /* Individual pins (this code is used in ladder.cpp) */
  25.     inline extern BOOL Read_U_b_XSTART(void)
  26.     {
  27.     return digitalRead(11);
  28.     }
  29.     inline extern BOOL Read_U_b_XSTOP(void)
  30.     {
  31.     return digitalRead(12);
  32.     }
  33.     inline BOOL Read_U_b_YValve(void)
  34.     {
  35.     return digitalRead(5);
  36.     }
  37.     inline void Write_U_b_YValve(BOOL v)
  38.     {
  39.     digitalWrite(5, v);
  40.     }
  41.     inline extern BOOL Read_U_b_XLSopen(void)
  42.     {
  43.     return digitalRead(9);
  44.     }
  45.     inline extern BOOL Read_U_b_XOverload(void)
  46.     {
  47.     // TODO
  48.     }
  49.     inline BOOL Read_U_b_Ymotor(void)
  50.     {
  51.     return digitalRead(6);
  52.     }
  53.     inline void Write_U_b_Ymotor(BOOL v)
  54.     {
  55.     digitalWrite(6, v);
  56.     }
  57.     inline extern BOOL Read_U_b_XLowPressure(void)
  58.     {
  59.     return digitalRead(10);
  60.     }
  61.     #endif


To write an Arduino sketch, the first step is to create a new folder. Name it as “Ladder” and put both ladder.cpp and ladder.h inside this folder. Copy or move it into Dir://Path/to/Arduino/libraries.

It ‘s time to write an interesting sketch in Arduino IDE.

  1. #define _Digole_Serial_UART_
  2. #include "DigoleSerial.h"
  3. DigoleSerialDisp mydisp(&Serial1, 9600);
  4. #include "ladder.h"
  5. /* Plc cycle interval, set this according to LDmicro settings. (micro sec.) */
  6. #define PLC_INTERVAL 10000
  7. #define LCDCol 16
  8. #define LCDRow 2
  9. int ptr;
  10. const char a[] = "Arduino PLC";
  11. void setup()
  12. {
  14.   mydisp.begin(); 
  15.     mydisp.clearScreen();
  16.     mydisp.disableCursor(); //disable cursor, enable cursore use: enableCursor();
  17.   //  mydisp.drawStr(4, 0, "Testing");
  18.     mydisp.setPrintPos(2, 0);
  19.     mydisp.print(a); // display a char array
  20.   //  resetpos();
  21.    {
  23.   PlcSetup();
  24. }
  25. }
  26. void loop()
  27. {
  28.     if (IsPlcInterval())
  29.     {
  30.         PlcCycle();
  31.     switch (U_i_alarm) {
  32.   case 0:
  33.    mydisp.drawStr(4, 1, "Valve closed");
  34.   break;
  35.   case 1:
  36.   mydisp.drawStr(4, 1, "Valve opened   ");
  37.   break;
  38.   case 2:
  39.   mydisp.drawStr(4, 1, "Check if valve is OK ?   ");
  40.   break;
  41.   case 3:
  42.   mydisp.drawStr(4, 1, "Pump and Valve OK   ");
  43.  break; 
  44.  case 4:
  45.   mydisp.drawStr(4, 1, "Low Pressure , Valve and Pump off   ");
  46.   break;
  47.   case 5:
  48.   mydisp.drawStr(4, 1, "Low pressure , check Pump!   ");
  49.  break; 
  50.   case 6:
  51.   mydisp.drawStr(4, 1, "Low pressure , check Valve!    ");
  52.  break; 
  53.  case 7:
  54.   mydisp.drawStr(4, 1, "Low pressure , check the line/leak   ");
  55.  break;     
  56.  }
  57.     }
  58. }
  59. /* Plc Cycle timing function. */
  60. boolean IsPlcInterval()
  61. {
  62.     static unsigned long last_run;
  64.     if (micros() - last_run >= PLC_INTERVAL)
  65.     {
  66.         last_run = micros();
  67.         return true;
  68.     }
  69.     return false;
  70. }


In the example above we use Digole serial LCD to display the messages. The good thing about  LDmicro is that it much easier to create ladder program  and then modify in the future with no change or few change in Arduino sketch itself. As long we have same numbers of I/O pins we don’t need generate a new header, what we need is  just to compile a new ladder (  newladder.ld)  and save it as  newladder. cpp and copy it to an arduino library folder.

Leave a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>