Thanks parky and DR.
I have made a program to simulate the latch example. It seems
to work, and it has helped me understand better how the program
should be structured, at least better than before (trying to
juggle a bunch of different arrays).
The simulation has a single array that stores all the inputs,
outputs, and internal variables. The array size is the same
as the maximum number of io's (external + internal). Each array
entry is a structure, which holds all the channel's info:
Interface card number (1-12)
Interface card channel (0-15)
Global channel number (0-255)
Channel name
The array entries are in order: array[0] is channel 0,
array[255] is channel 255.
What I like about it is that writing the ladder logic is very easy,
compared to before, when I was trying to pick channel states from
different arrays. Now everything is easy to find by channel name,
making the ladder logic a lot cleaner. And the big bonus is that it
seems to work, so even if I'm still a bit confused, I can go ahead
with the real project.
Thanks for all your input.
Code:
#ifdef __cplusplus
extern "C" {
#endif
// Compiler gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
#include <stdio.h>
#include <unistd.h> // for sleep()
//#include <stdlib.h> // for system("clear") Linux clear screen
#define CHANNEL_NAME_LEN 15
#define INTERNAL -1
void ladder(void);
void set_outputs(void);
enum State{ OFF=0, ON };
const char* state_names[] = {"OFF", "ON"}; // Used to print "OFF" and "ON", from 0 and 1
// IPC90 Handles a maximum of 12 interface cards, and 256 io channels (0-255)
// Each interface card can control 16 channels
// Maximum real io channels: 12*16 = 192, in global address range 0 - 191
// Channel numbers higher than 191 are internal relays
struct Channel{
int global_address; // 0-255
char name[CHANNEL_NAME_LEN];
int interface_card_num; // 1-12
int interface_card_channel; // 0-15
enum State state; // ON/OFF
};
struct Channel channel_array[256];
#define BUTTON channel_array[0].state
#define LAMP channel_array[16].state
#define ONESHOT channel_array[200].state
#define ONESHOT_LATCH channel_array[201].state
int main() {
printf("Starting...\n\n");
// Create input channel "Button"
struct Channel button = {
.global_address = 0,
.name = "Button\0",
.interface_card_num = 1,
.interface_card_channel = 0,
.state = ON
};
// Create input channel "Lamp"
struct Channel lamp = {
.global_address = 16,
.name = "Lamp\0",
.interface_card_num = 2,
.interface_card_channel = 0,
.state = OFF
};
// Create internal relay "OneShot"
struct Channel oneshot = {
.global_address = 200,
.name = "OneShot\0",
.interface_card_num = INTERNAL,
.interface_card_channel = INTERNAL,
.state = OFF
};
// Create internal relay "OneShotLatch"
struct Channel oneshotlatch = {
.global_address = 201,
.name = "OneShotLatch\0",
.interface_card_num = INTERNAL,
.interface_card_channel = INTERNAL,
.state = OFF
};
// Save input channels to array
channel_array[button.global_address] = button;
channel_array[oneshot.global_address] = oneshot;
channel_array[oneshotlatch.global_address] = oneshot;
channel_array[lamp.global_address] = lamp;
// Clear screen for both Windows and Linux
printf("\033[2J\033[1;1H");
int run = 1;
int loop_count = 0;
while(run){
ladder();
set_outputs();
sleep(2);
loop_count++;
if(loop_count == 3) run = 0;
}
return 0;
}
int scan_count = 0;
void ladder(){
// Ladder start
// Line 1
ONESHOT = BUTTON & !ONESHOT_LATCH;
// Line 2
ONESHOT_LATCH = BUTTON;
// Line 3
LAMP = ONESHOT;
// End ladder
scan_count++;
printf("Scan number %d\n", scan_count);
printf("System state: \n Button: %d\n Oneshot latch: %d\n Oneshot: %d\n Lamp: %d\n ",
BUTTON, ONESHOT_LATCH, ONESHOT, LAMP );
printf("\n");
}
void set_outputs(){
printf("Turning lamp %s\n\n", state_names[LAMP]);
}
/*
References:
ipC90 Installation and Maintenance Manual ISSC I-201
https://stackoverflow.com/questions/3789340/combining-c-and-c-how-does-ifdef-cplusplus-work
https://codeforwin.org/2018/07/how-to-declare-initialize-and-access-structures-in-c.html
https://stackoverflow.com/questions/17335816/clear-screen-using-c
https://stackoverflow.com/questions/3168306/print-text-instead-of-value-from-c-enum
*/
Output:
Code:
Result of scan 1
----------------
System state:
Button: 1
Oneshot latch: 1
Oneshot: 1
Lamp: 1
Turning lamp ON
Result of scan 2
----------------
System state:
Button: 1
Oneshot latch: 1
Oneshot: 0
Lamp: 0
Turning lamp OFF
Result of scan 3
----------------
System state:
Button: 1
Oneshot latch: 1
Oneshot: 0
Lamp: 0
Turning lamp OFF