# (very) basic program flow control question

Status
Not open for further replies.

#### Mark_R

##### Member
Hi,

I'm an accomplished ladder logic programmer trying to transition to embedded micro controllers. I'm struggling with the basic concept of program flow control. I have avoided C/Basic/Etc. like the plague, but the project at hand is forcing me in that direction.

In ladder logic, the ladder scans continuously, updating rungs as it goes. If there is a timer running, or some other task / condition pending on a rung, program execution moves on. The rung gets re-visited on the next scan and so on. The point is, multiple things can be happening simultaneously.

In C, BASIC whatever, I'm missing the big picture here.

An example of somthing we have built with a PLC;
Let's say I have a machine that controls a widget filler and has a serial modem for reporting status.
The widget filling is ongoing, one widget after another, I can visualize this code well enough.
Now, lets say I need to send information out of the modem, I branch to a loop to open the serial port and initialize the modem, now I need to wait for the modem to open a port and reply ready, so I loop until success or error comes in on the receive buffer. Let's say this takes 20 seconds, What about the widgets? has production stopped? Are they overflowing?

It seems to me that only one thing can happen at once and if one has to wait for an event then everything else has to stop. This can't be the case.

I don't get it, and I can't seem to find the answer.

Anyone?

Thanks.

Last edited:

#### Nigel Goodwin

##### Super Moderator
Hi,

I'm an accomplished ladder logic programmer trying to transition to embedded micro controllers. I'm struggling with the basic concept of program flow control. I have avoided C/Basic/Etc. like the plague, but the project at hand is forcing me in that direction.

In ladder logic, the ladder scans continuously, updating rungs as it goes. If there is a timer running, or some other task / condition pending on a rung, program execution moves on. The rung gets re-visited on the next scan and so on. The point is, multiple things can be happening simultaneously.

In C, BASIC whatever, I'm missing the big picture here.

An example of somthing we have built with a PLC;
Let's say I have a machine that controls a widget filler and has a serial modem for reporting status.
The widget filling is ongoing, one widget after another, I can visualize this code well enough.
Now, lets say I need to send information out of the modem, I branch to a loop to open the serial port and initialize the modem, now I need to wait for the modem to open a port and replay ready, so I loop until success or error comes in on the receive buffer. Let's say this takes 20 seconds, What about the widgets? has production stopped? Are they overflowing?

It seems to me that only one thing can happen at once and if one has to wait for an event then everything else has to stop. This can't be the case.

I don't get it, and I can't seem to find the answer.

Anyone?

Basically two options, one is to use interrupts, the other to use looping and polling.

Either would be fine for your application, mechanical processes like widget filling are extremely slow, and micro-controllers run extremely fast.

Opening your serial port might take a few micro-seconds, and sending each byte can take less than that (if using the hardware UART - as you just feed it the byte, and it's send automatically).

It's a question of understanding how long you've got to do things, and not sitting in a permanent loop waiting for something to happen.

For example - you've got a loop waiting for a switch to be pressed - if the switch is never pressed the loop will never complete. In this situation the other processes could be interrupt driven, or just polled every so many times through the loop - crude 'code' like this:

Code:
While Switch not Pressed
X=X+1;
If X = 10 then Begin
Gosub Check for something else;
X=0;
End;
Wend

#### Mark_R

##### Member
So typically the main program loop is quite short?
I guess I'm still thinking like a ladder programmer where you typically cycle through most of your program but only act on the active parts.

#### Mike - K8LH

##### Well-Known Member
Mark,

Please show me a "typical" ladder logic diagram like the kind you would want to run on a PIC? Inputs, Time(on), Time(off), LED output, Serial output, Control Relays, etc.

Please humor me. I'm very interested. I used to work with AB and Modicon PLCs many many years ago.

Regards, Mike

#### Mark_R

##### Member
Mike,

Here is a typical project for us, granted, this is far more complicated than something I would be trying to implement in a uC, but It's something to look at.

To understand whats going on;
This is molding / heat seal machine, The plates have mold cavities which the sheet plastic is pulled into via vacuum, the nozzle meters out a 2-part mix (+/- 1%), the size and ratio varies based on the "recipe" selected.
The two hand buttons clamp the press to seal and bake the part and a count down timer begins. After the timer counts down, the mold opens.
All the while the four mold plates are maintaining heat +/- 1.5 degree via PID loops. (no external temperature controllers, PIDs are part of the PLC) There are other secondary functions such as temperature deviation alarms, temp probe averaging, probe fail indication, auto heat start via real time clock/timer, finished parts counters, prototype mode, storage of 20 recipes, etc.

I have to leave the office today but I'll try to whip up a ladder equivalent of what I'm trying to implement in the embedded controller.

#### Attachments

144.2 KB · Views: 189
• DSC_0246.JPG
544.2 KB · Views: 147
Last edited:

#### Noggin

##### Member
I use a cooperative multitasking type system when I write code for most of my projects. Here is a post I made in another thread which details how to implement the co-op multitasking system.

Basically, what you'd need to do here to utilize a modem is add something like the following:

modem.c
Code:
void Service_Modem( Uint8 cmd, Uint8 *data, Uint8 length )
{
static Uint8 modem_state = MODEM_IDLE;
static Uint8 out_data[100];
static Uint8 in_data[100];
static Uint8 out_len = 0;
static Uint8 in_len = 0;
static Uint8 i;
Uint8* response;

switch (modem_state)
{
case MODEM_IDLE:
switch (cmd)
{
case CMD_OPEN_MODEM:
modem_state = OPEN_MODEM;
i = 0;
sprintf(out_data, "whatever command you send to the modem to open it\r\n");
out_len = strlen(out_data);
break;

case CMD_CLOSE_MODEM:
modem_state = CLOSE_MODEM;
break;

case CMD_SEND_DATA:
memcpy( out_data, data, length );
out_len = length;
modem_state = SEND_DATA;
break;
}
break;

case OPEN_MODEM:
Open_Modem( OPEN_MODEM );
modem_state = WAIT_FOR_OPEN_MODEM_RESPONSE;
break;

case WAIT_FOR_OPEN_MODEM_RESPONSE:
result = Open_Modem( TICK );
if (result == TRUE )
modem_state = MODEM_IDLE;
break;

case SEND_DATA:
if ((i != out_len) && (uart_tx_buffer_is_empty))
{
tx_modem_uart( out_data[i] );
i++;
}
else if (i == out_len)
{
modem_state = MODEM_IDLE;
in_len = 0;   // we just sent data, clear the rx buffer
}
break;
}
}

Uint8 Open_Modem( Uint8 cmd )
{
static Uint8 out_data[100];
static Uint8 in_data[100];
static Uint8 in_len;
static Uint8 out_len;
static Uint8 i;
static Uint8 state;
static Uint8 modem_is_open = FALSE;

switch (state)
{
case IDLE:
switch (cmd)
{
case CMD_OPEN_MODEM:
if (modem_is_open == FALSE)
state = OPEN_MODEM;
break;

case CMD_TICK:
break;
}
break;

case OPEN_MODEM:
if ((i != out_len) && (uart_tx_buffer_is_empty))
{
tx_modem_uart( out_data[i] );
i++;
}
else if (i == out_len)
{
in_len = 0;
modem_state = WAIT_FOR_OPEN_RESPONSE;
}
break;

case WAIT_FOR_OPEN_RESPONSE:
if (uart_rx_buffer_has_data)
{
in_data[in_len] = uart_rx_data;
in_len++;
state = IDLE;
}

if (strcmp(in_data, "OK\r\n", 4) == 0)
modem_is_open = TRUE;
break;
}

return modem_is_open;
}

I have to go to work now otherwise I'd try to flesh it out some more. But as you can see, it uses state machines to remember what is going on in the modem code. It doesn't spin in a loop waiting for the modem to response with OK, it comes and checks on it later.

#### Mark_R

##### Member
I use a cooperative multitasking type system <snip>

Noggin:
While not completely following the code yet, I get the general concept.

Thanks.

#### 3v0

##### Coop Build Coordinator
Forum Supporter
Mark,

C or any procedural language can work in much the same way as ladder programming.

A main loop checks each task in turn and activates it only if the task is ready to run. It could be waiting on a timer or blocked waiting for IO. In either of these cases it is skipped.

A while back I wrote a detailed tutorial illustrating ) but it can easily be used with any working PIC.

3v0

#### Attachments

• coop.jpg
95.6 KB · Views: 226
Last edited:

#### Mark_R

##### Member
3vO,

thanks, good info there. I printed the .PDF and I'll study it tonight.

#### Mike - K8LH

##### Well-Known Member
Mark,

Thank you for the program example. Seems the features and capabilities of these PLCs has evolved quite a bit from my experience with them some 35 years ago as an Electrical Field Service Engineer for a material handling company. I look forward to studying it and will try to offer some program flow suggestions as I become more familiar with it.

Regards, Mike

#### 3v0

##### Coop Build Coordinator
Forum Supporter
Mark you will want to download the source code DJ_COOP.zip from here. The interupt vector in the tutorial may be incorrect but has been fixed in the source in the zip.

3v0

Last edited:

#### Mark_R

##### Member
Mark,

Thank you for the program example. Seems the features and capabilities of these PLCs has evolved quite a bit from my experience with them some 35 years ago as an Electrical Field Service Engineer for a material handling company. I look forward to studying it and will try to offer some program flow suggestions as I become more familiar with it.

Regards, Mike

If you really want to wade through 200 rungs of logic, you should know;
X are (real world) inputs
Y are outputs
GX are inputs from the HMI (touchscreen buttons)
C are "coils" (internal software bits)
T are timers (resolution in tenths of a second)
TA are timer accumulators (the memory location of the associated timers current value)
V are word length memory locations
B is one bit-of-word
if you see "K" that is a constant value.

Don't forget, this is not the logic I'm trying to implement in a uC, just a (far more complicated) example.

#### Mark_R

##### Member
Mark you will want to download the source code DJ_COOP.zip from here. The interupt vector in the tutorial may be incorrect but has been fixed in the source in the zip.

3v0

Good resource for a noob to C like me, thanks I'll study it.

Status
Not open for further replies.

Replies
15
Views
6K
Replies
7
Views
5K
Replies
2
Views
1K
Replies
3
Views
927
Replies
3
Views
845