Am I doing this right? (component programming)
02 May 2022 12:10 #241843
by thewho
Am I doing this right? (component programming) was created by thewho
Hello
I'm writing my first own component to rotate the table/pallet in my machine.
So I'm looking for some guidance on formatting and syntax. And not really if my code will work as it's still under development and is untested.
I'm writing my first own component to rotate the table/pallet in my machine.
So I'm looking for some guidance on formatting and syntax. And not really if my code will work as it's still under development and is untested.
- "function _ nofp;" I'm guessing this calls the "FUNCTION(_)" but what does the underscore do?
- " ;; " no idea what this is for??
- Line 41: Will this code show a popup in Axis?
- Line 42: How do I halt the code after an error occurred?
- General errors I've made?
component palletchange "Rotates pallets all day";
pin in bit tableIsUp; //HW pin
pin in bit tableIsDown; //HW pin
pin in bit tableIsCW; //HW pin
pin in bit tableIsCCW; //HW pin
pin in bit tableReady; //SW pin
pin in bit tableRotate; //SW pin
pin in bit enable; //SW pin - Net to "machine-is-enabled"
pin out bit tableUp;
pin out bit tableDown;
pin out bit tableRotateCW;
pin out bit tableRotateCCW;
pin out bit tableAirblast;
pin out bit startHydPump;
pin out bit rotateDone; //1 if rotation completed successfully
pin out bit tableInMachine; //Return which table is under the spindle
license "GPL";
author "D.E";
function _ nofp;
;;
bool tableIsReady; //Set 1 if tableReady button is pressed
FUNCTION(_) {
if(enable){
//-------------Check state of tableReady button-------------------------------
if(tableReady && !tableIsReady){
tableIsReady = 1; //Enable tableIsReady (physical buttonpress)
while(tableReady){} //Halt program from continuing while button is pressed
}
else if(tableReady && tableIsReady){
tableIsReady = 0; //Disable tableIsReady (physical button was pressed again)
while(tableReady){} //Halt program from continuing while button is pressed
}
//-------------Send error message and halt program----------------------------
if(tableRotate && !tableReady){ //If a rotation is requested but table is not set to ready
rtapi_print_msg(RTAPI_MSG_ERR, "Pallet not ready!");
//exit program somehow?
}
//-------------Everything is ok, rotate pallet--------------------------------
if(tableRotate){ //Table rotate pin is high
startHydPump =1; //Start hyd pump
tableUp =1; //Lift table
tableAirblast =1; //Turn on table airblast
while(!tableIsUp){} //Do nothing while table is lifting (should have timeout..)
if(tableIsCW){
tableRotateCCW =1; //Rotate table CCW
while(!tableIsCCW){} //Wait
for(int i=0; i<1000; i++){} //Wait 1 sec to let table reach rotation stop
tableRotateCCW =0; //Turn off output
}
else if{tableIsCCW){
tableRotateCW =1; //Rotate table CCW
while(!tableIsCW){} //Wait
for(int i=0; i<1000; i++){} //Wait 1 sec to let table reach rotation stop
tableRotateCW =0; //Turn off output
}
tableUp =0; //Turn off output
tableDown =1; //Lower table
while(!tableIsDown){} //Do nothing while table is lowering (should have timeout..)
for(int i=0; i<1000; i++){} //Wait 1 sec to let table settle
tableDown =0; //Turn off output
startHydPump =0; //Turn off output
tableAirblast =0; //Turn off output
tableIsReady = 0; //Set table to not ready
}
}
}
Please Log in or Create an account to join the conversation.
02 May 2022 12:37 #241846
by andypugh
The _ is used to indicate that the function does not have a name in HAL.
Often a component will have a read and a write (or some other multiple functions) and then you will see:
addf function.read servo-thread
addf function.make-pulses base-thread
etc.
In your case the function will just be called palletchange.
"nofp" means that the component does no floating-point calculations. Which is probably true in this case, but you can probably imit it for a component that runs in the servo thread.
Note that "addf" means that the component will be called every servo or base-thread period. More on that later.
It is used to split the bit of the file which is halcompile directives from the bit that is pure C-code.
Yes
These are the same thing
A realtime HAL component must never stop. It has to run through to completion in a very few microseconds or the entire system will lock up.
This also means "no while loops that depend on input" too. You have to be sure that loops will complete every time.
So, the normal way to code a HAL component is as a state machine. A variable (often set up as a HAL pin, so you can see what is happening) is used to tell the component what it was doing last time it was called.
See, as an example, the carousel.comp, specifically the main "switch" statement github.com/LinuxCNC/linuxcnc/blob/master...s/carousel.comp#L228
For example note that in state 0 (waiting) the system can move to states 1, 5 or 10. But that every state always runs straight through to completion.
Replied by andypugh on topic Am I doing this right? (component programming)
"function _ nofp;" I'm guessing this calls the "FUNCTION(_)" but what does the underscore do?
The _ is used to indicate that the function does not have a name in HAL.
Often a component will have a read and a write (or some other multiple functions) and then you will see:
addf function.read servo-thread
addf function.make-pulses base-thread
etc.
In your case the function will just be called palletchange.
"nofp" means that the component does no floating-point calculations. Which is probably true in this case, but you can probably imit it for a component that runs in the servo thread.
Note that "addf" means that the component will be called every servo or base-thread period. More on that later.
" ;; " no idea what this is for??
It is used to split the bit of the file which is halcompile directives from the bit that is pure C-code.
Line 41: Will this code show a popup in Axis?
Yes
Line 42: How do I halt the code after an error occurred?
General errors I've made?
These are the same thing
A realtime HAL component must never stop. It has to run through to completion in a very few microseconds or the entire system will lock up.
This also means "no while loops that depend on input" too. You have to be sure that loops will complete every time.
So, the normal way to code a HAL component is as a state machine. A variable (often set up as a HAL pin, so you can see what is happening) is used to tell the component what it was doing last time it was called.
See, as an example, the carousel.comp, specifically the main "switch" statement github.com/LinuxCNC/linuxcnc/blob/master...s/carousel.comp#L228
For example note that in state 0 (waiting) the system can move to states 1, 5 or 10. But that every state always runs straight through to completion.
The following user(s) said Thank You: thewho
Please Log in or Create an account to join the conversation.
02 May 2022 14:32 #241853
by thewho
Replied by thewho on topic Am I doing this right? (component programming)
Thank you Andy
Ah, makes total sense that it needs to complete every time. I'll rewrite with switch instead.
So how do I do a "delay"? I did check the code for "timedelay.comp" but I can't really figure out how "fperiod" works?
Am I on the right track with this?
Ah, makes total sense that it needs to complete every time. I'll rewrite with switch instead.
So how do I do a "delay"? I did check the code for "timedelay.comp" but I can't really figure out how "fperiod" works?
Am I on the right track with this?
variable double timer;
variable float on-delay = 1.0;
//--------------------------------
//--------------------------------
timer += fperiod;
if(timer >= on_delay) {
//Do something now
timer = 0.0;
}
Please Log in or Create an account to join the conversation.
02 May 2022 18:16 #241862
by rodw
Replied by rodw on topic Am I doing this right? (component programming)
fperiod is a convenience macro that contains the time in seconds for this servo cycle.
Ref: linuxcnc.org/docs/devel/html/hal/comp.html#_convenience_macros
Do not use hyphens which are reserved for pin names. eg use time_delay.
time_delay could be a pin or parameter so it can be set in your hal file to be more universal.
Yes you are on the right track but I would ensure on_delay is initialised to 0.0 on declaration.
Why don't you make your timer example a complete component that turns a pin on and off every time_delay fperiods as a learning exercise? Something like this;
flash_pin |=1;
time_delay = 0.0;
Install it in your hal file and observe in halshow.
Ref: linuxcnc.org/docs/devel/html/hal/comp.html#_convenience_macros
Do not use hyphens which are reserved for pin names. eg use time_delay.
time_delay could be a pin or parameter so it can be set in your hal file to be more universal.
Yes you are on the right track but I would ensure on_delay is initialised to 0.0 on declaration.
Why don't you make your timer example a complete component that turns a pin on and off every time_delay fperiods as a learning exercise? Something like this;
flash_pin |=1;
time_delay = 0.0;
Install it in your hal file and observe in halshow.
The following user(s) said Thank You: thewho
Please Log in or Create an account to join the conversation.
02 May 2022 20:20 #241877
by andypugh
Replied by andypugh on topic Am I doing this right? (component programming)
The way to do a time delay in a switch is to have a "waiting@ state
switch (state){
...
case 11:
if (something){
state = 12; // waiting state
timer = 10000; // how long to wait
}
break;
case 12:
timer -= fperiod;
if (timer > 0) break;
// Here do things that are meant to happed when the timer expires.
// Should generally only be a change of state, just to keep things
// obvious to future-you
The following user(s) said Thank You: thewho
Please Log in or Create an account to join the conversation.
Time to create page: 0.069 seconds