Troubles with multiple functions in a component

More
11 Nov 2013 23:46 #40741 by ArcEye
No problem

I plainly missed the bit in the switch, I saw it over and over, it just didnt click and didnt throw the error.


Sometimes the more you look at something and the more familiar you are with it, the less you see.
It is peculiar that it just warns that the test value is outside the range of the variable, expected it would error, the same as it would if you tried to assign those values.

regards

Please Log in or Create an account to join the conversation.

More
12 Nov 2013 05:22 #40758 by andypugh

It is peculiar that it just warns that the test value is outside the range of the variable, expected it would error, the same as it would if you tried to assign those values.


It's normal to use an int (or a char) as a boolean in C. (wasteful, but normal).
I think some parts of LinuxCNC (including comp) might now be using the boolean_t that (I think) is defined in the kernel headers.

It used to be possible to have values in HAL "bit" pins that were not 0 or 1. And that could cause some very odd behaviour. (It might still be possible)

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 03:56 #42398 by JR1050
Hello,
Im.at the point where im.actually testing the comps ive written with the multiple functions, and, im getting realtime errors or the main function simply refuses to call a sub function. Is this par for the course with the realtime system, or are there some things im missing? Thanks

JR

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 04:00 #42399 by andypugh

Im.at the point where im.actually testing the comps ive written with the multiple functions, and, im getting realtime errors or the main function simply refuses to call a sub function.


You might get realtime errors if your comp does any waiting. Does every function run to completion as fast as possible every time?

Kernel space is tricksy, some things you might be used to are not available.

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 04:03 #42400 by JR1050
Some sections of.the.code have delays in them while waiting for a switch to be made or a flag to change.

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 04:13 #42401 by andypugh

Some sections of.the.code have delays in them while waiting for a switch to be made or a flag to change.


If it's a realtime module then you can't do that.

You need to code that sort of thing as a state machine.
static int the_state = 0

switch (the_state) {
case 0: // Init code
    ...
    the_state = 1;
    break:
case 1: // waiting
    if (flag == true) state = 2;
    break;
case 2: 
     // Do something
    the_state=1; // go back to waiting
}

So, the code always exits immediately, but knows what it was doing last time when it re-enters

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 04:21 #42402 by JR1050
It is a state machine, im using the timedelay component as a timer, as ive had luck with it before. To immediately solve the problem, i.rewrote the main function with out the sub functions as seperate sets of case statements, so instead of jumping to orient_spindle(); , it jumps to case 200 ect. It seems to work, but i would have preferred to have pulled it off with single functions, it was less cumbersome. I can post the original comp, it will be an hour or so though, maybe you might see something, it would be hugely appreciated.....

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 06:20 #42409 by JR1050
original component with multiiple functions.



File Attachment:

File Name: orient.comp
File Size:10 KB
Attachments:

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 07:18 #42414 by andypugh
It's a bit late to look at that in detail now, but some comments about things that are probably not the issue.

Your indenting is strange. If your editor allows it, try auto-indenting and see if it still looks right.

In fact: pastebin.com/LsZvC1rZ

Is your code auto-indented, and it looks like all your "else" clauses are incorrectly bracketed.

The syntax is

if (condition) {
// firs set of code
}
else
{
// second set of code
}

Though

} else {

is not unusual. In any case the "else" or "elseif" needs a new { and a } at the end.

Please Log in or Create an account to join the conversation.

More
07 Jan 2014 17:55 - 07 Jan 2014 17:58 #42429 by ArcEye
Hi

Several observations

The syntax question Andy raised makes things hard to follow if nothing else
switch (spl_cond){
	case 40:	
		if(((spindle_rpm_cmd)<=800&&(in_low_gear)==1)&&((mot_spl_on)==1&&(low_gear_m141)==1))
			{
				spl_cond = 43;
					}
					else
		if(((spindle_rpm_cmd)>100&&(in_low_gear)==1)&&((mot_spl_on)==1&&(hi_gear_m142)==1))
			{
				spl_cond = 41;
					}
					else
		if(((spindle_rpm_cmd)>100&&(in_hi_gear)==1)&&((mot_spl_on)==1&&(hi_gear_m142)==1))
			{	
				spl_cond = 43;
					}
					else
		if(((spindle_rpm_cmd)<=800&&(in_low_gear)==0)&&((mot_spl_on)==1&&(low_gear_m141)==1))
			{
				spl_cond = 41;
					}						
				break;
could be written
switch (spl_cond){
	    case 40:	
		    if(((spindle_rpm_cmd)<=800&&(in_low_gear)==1)&&((mot_spl_on)==1&&(low_gear_m141)==1))
			    spl_cond = 43;
		    else if(((spindle_rpm_cmd)>100&&(in_low_gear)==1)&&((mot_spl_on)==1&&(hi_gear_m142)==1))
    			 spl_cond = 41;
		    else if(((spindle_rpm_cmd)>100&&(in_hi_gear)==1)&&((mot_spl_on)==1&&(hi_gear_m142)==1))
			    spl_cond = 43;
		    else if(((spindle_rpm_cmd)<=800&&(in_low_gear)==0)&&((mot_spl_on)==1&&(low_gear_m141)==1))
				spl_cond = 41;
		    break;

and it becomes a lot easier to track stray brackets, not least because when there only one line after a conditional test you don't need them.

I think the problem is that this is not a state machine

It is superficially similar, but when you look closer, each state does not do something and return, setting its state for the next poll.

There are nested calls: FUNCTION() calls run_the_spindle(), which in turn calls free_the_spindle()
I don't know what happens to the stack between polls on a realtime component, but I think you can be fairly certain it is destroyed

Another thing I commented on earlier is still present
FUNCTION(_)
{

	switch (orient_cond){
	case 0:
		if((orient_m119)==1&&(ls1_plunger_in)==1)
		{
			orient_m119=0;
				orient_cond = 59;			//spindle is oriented
				}
			  
	case 1:
		if(((orient_m119)==1||(tc_orient)==1)&&(ls1_plunger_in)==0)
		{
			orient_feed_hold = 1;			// spindle needs orient
				tc_orient_comp=0;
					spl_run=0;
					orient_the_spindle();
				}
	case 2:
		if((orient_m118)==1&&(ls1_plunger_in)==1)		// shift to spindle free
		{
			orient_feed_hold = 1;
				free_the_spindle();
				}
	case 3:
		if((orient_m118)==1&&(ls1_plunger_in)==0)
		{
			 orient_m118=0;
				orient_cond = 61;			// spindle is free
				}
	case 4:
		if((low_gear_m141)==1&&((ls3_low_gear)==1&&(ls2_hi_gear)==0))
		{
			low_gear_m141=0;
				orient_cond = 61;			// spindle in low gear ,no shifting
				}
			
	case 5:
		if((low_gear_m141)==1&&((ls3_low_gear)==0&&(ls2_hi_gear)==1))
		{		
			orient_feed_hold = 1;
				spl_run=0;			       // spindle in not low gear needs shift 
					shift_the_transmission();
				}
			
	case 6:
		if((hi_gear_m142)==1&&((ls2_hi_gear)==1&&(ls3_low_gear)==0))
		{
			hi_gear_m142=0;
			orient_cond = 61;			// spindle in hi gear no shift 
				}
				
	case 7:
		if(((hi_gear_m142)==1&&(ls2_hi_gear)==0)&&(ls3_low_gear)==1)
		{
			orient_feed_hold = 1;				// spindle not in hi gear need shift 
				spl_run=0;
					shift_the_transmission();
				}
				
	case 8:
		if(((ls3_low_gear)==1&&(ls2_hi_gear)==1)||((ls3_low_gear)==0&&(ls2_hi_gear)==0))
		{
			orient_cond = 62;			// transmission shift malfunction
				orient_feed_hold = 1;
				}
				break;

Because there are no break; statements after each case: ALL the cases down to and including case 8: will be executed every time a number from 0 - 7 is passed
This potentially includes 4 function calls.

The only reason for having functions is to save repeating code.

Each function could be a state number, in post 40637 I demonstrated how you can set a return state number, then use the same state (function) multiple times from different levels and control what return state was set when its condition
was satisfied.

The linear nature of the 'state machine' type coding is peculiar and not aesthetically pleasing if you are used to classes and neatly packed functions doing the work behind the scenes.

But it is the only thing that works reliably, IN -> do something -> set the next level -> OUT

regards
Last edit: 07 Jan 2014 17:58 by ArcEye.

Please Log in or Create an account to join the conversation.

Time to create page: 0.177 seconds
Powered by Kunena Forum