creating socket based rt component
27 Sep 2016 12:42 #80990
by wn007
creating socket based rt component was created by wn007
I have been using Linux CNC for a couple of years now with great success. I am currently attempting to use halcompile to create an RT Component. The only job this component has is to receive a trigger and then read/request data from a socket. I can get it to compile and it does "see" the declared HAL Pins of the component. It just does not respond. I have placed printf statements within the code and nothing shows up in the terminal when running linuxcnc from the command line. I think it has to do with the initialization or permissions?
Not sure how to init, other than using the EXTRA_SETUP option?
I will be posting the code shortly.
Not sure how to init, other than using the EXTRA_SETUP option?
I will be posting the code shortly.
Please Log in or Create an account to join the conversation.
27 Sep 2016 12:54 #80992
by andypugh
Replied by andypugh on topic creating socket based rt component
The simplest and easiest explanation for this would be if the component has not been added to a thread.
Unless you are sure that the socket data request is thread-safe and will never wait you might be better off writing your component as a user-space rather than realtime component.
Unless you are sure that the socket data request is thread-safe and will never wait you might be better off writing your component as a user-space rather than realtime component.
The following user(s) said Thank You: wn007
Please Log in or Create an account to join the conversation.
27 Sep 2016 13:15 #80998
by wn007
Replied by wn007 on topic creating socket based rt component
Here is the code. I really would like to get this working. I have already written and tested with a python based HAL userspace component. The issue is the trigger timing is hit and miss at the feed rate I am using. Sometimes it misses trigger points. I can say that the data is returned within 50 to 100 milliseconds after the trigger. So not sure if that qualifies as thread safe or if there is another way to achieve the same result using RT.
component rtTelnet;
pin in bit trigger_;
pin out float xOffset_;
pin out bit hardTrigger_;
function _;
option extra_setup;
license "GPL"; // indicates GPL v2 or later
;;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int n, sock,sock2, len;
char buf[50000];
struct sockaddr_in cmts;
struct sockaddr_in server;
char *user = "user1\r\n";
char *pwd = "123\r\n";
char *cmd = "trigger\r\n";
char buffer[256];
EXTRA_SETUP()
{
cmts.sin_family = AF_INET;
cmts.sin_port = htons( 23 );
cmts.sin_addr.s_addr = inet_addr("192.168.2.5");
sock = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock < 0 ) {
perror("Socket creation error!");
exit (EXIT_FAILURE);
}
if ( connect( sock, (struct sockaddr *) &cmts, sizeof( cmts ) ) < 0 ) {
perror("Connect process error!");
exit (EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_port = htons( 20000 );
server.sin_addr.s_addr = inet_addr("192.168.2.5");
sock2 = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock2 < 0 ) {
perror("Socket creation error!");
exit (EXIT_FAILURE);
}
if ( connect( sock2, (struct sockaddr *) &server, sizeof( server ) ) < 0 ) {
perror("Connect to server process error!");
exit (EXIT_FAILURE);
}
n = read(sock,buffer,255);
bzero(buffer,256);
len = strlen(user);
n = send(sock, user, len, 0);
n = read(sock,buffer,255);
bzero(buffer,256);
len = strlen(pwd);
n = send(sock, pwd, len, 0);
n = read(sock,buffer,255);
printf("rtTelnet Init ok...");
return(0);
}
FUNCTION(_) {
if(trigger_){
hardTrigger_ = true;
bzero(buffer,256);
len = strlen(cmd);
n = send(sock, cmd, len, 0);
printf("Trigger sent...");
}
}
component rtTelnet;
pin in bit trigger_;
pin out float xOffset_;
pin out bit hardTrigger_;
function _;
option extra_setup;
license "GPL"; // indicates GPL v2 or later
;;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int n, sock,sock2, len;
char buf[50000];
struct sockaddr_in cmts;
struct sockaddr_in server;
char *user = "user1\r\n";
char *pwd = "123\r\n";
char *cmd = "trigger\r\n";
char buffer[256];
EXTRA_SETUP()
{
cmts.sin_family = AF_INET;
cmts.sin_port = htons( 23 );
cmts.sin_addr.s_addr = inet_addr("192.168.2.5");
sock = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock < 0 ) {
perror("Socket creation error!");
exit (EXIT_FAILURE);
}
if ( connect( sock, (struct sockaddr *) &cmts, sizeof( cmts ) ) < 0 ) {
perror("Connect process error!");
exit (EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_port = htons( 20000 );
server.sin_addr.s_addr = inet_addr("192.168.2.5");
sock2 = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock2 < 0 ) {
perror("Socket creation error!");
exit (EXIT_FAILURE);
}
if ( connect( sock2, (struct sockaddr *) &server, sizeof( server ) ) < 0 ) {
perror("Connect to server process error!");
exit (EXIT_FAILURE);
}
n = read(sock,buffer,255);
bzero(buffer,256);
len = strlen(user);
n = send(sock, user, len, 0);
n = read(sock,buffer,255);
bzero(buffer,256);
len = strlen(pwd);
n = send(sock, pwd, len, 0);
n = read(sock,buffer,255);
printf("rtTelnet Init ok...");
return(0);
}
FUNCTION(_) {
if(trigger_){
hardTrigger_ = true;
bzero(buffer,256);
len = strlen(cmd);
n = send(sock, cmd, len, 0);
printf("Trigger sent...");
}
}
Please Log in or Create an account to join the conversation.
27 Sep 2016 13:38 #81000
by andypugh
Replied by andypugh on topic creating socket based rt component
50mS is _way_ too long for a component that is called every 1mS.
What you will need to do is write the code so that every time it is called it basically asks "has the data come in yet" and immediately exits if the answer is "no"
You may not see the result of "printf" in the realtime code. Realtime components can only print to the kernel log (if you are using RTAI rather than uspace).
You should try to only use functions from rtapi. (including rtapi_print)
linuxcnc.org/docs/2.7/html/man/man3/rtapi_print.3rtapi.html
The list of rtapi_* commands is near the bottom of here:
linuxcnc.org/docs/2.7/html/
What you will need to do is write the code so that every time it is called it basically asks "has the data come in yet" and immediately exits if the answer is "no"
You may not see the result of "printf" in the realtime code. Realtime components can only print to the kernel log (if you are using RTAI rather than uspace).
You should try to only use functions from rtapi. (including rtapi_print)
linuxcnc.org/docs/2.7/html/man/man3/rtapi_print.3rtapi.html
The list of rtapi_* commands is near the bottom of here:
linuxcnc.org/docs/2.7/html/
Please Log in or Create an account to join the conversation.
27 Sep 2016 15:09 #81003
by wn007
Replied by wn007 on topic creating socket based rt component
I am using the PREEMPT-RT version of linuxcnc. I stripped down my code to the basics and like you said earlier it does not look as though is is being added to a thread. I can see the new component in the Hal Config within Axis. Is there something I am missing in the code as far as initializing or something else?
Thanks again for your replies.
Thanks again for your replies.
Please Log in or Create an account to join the conversation.
27 Sep 2016 15:17 #81004
by andypugh
Replied by andypugh on topic creating socket based rt component
You need the "addf" in the HAL file.
Please Log in or Create an account to join the conversation.
27 Sep 2016 15:17 #81005
by wn007
Replied by wn007 on topic creating socket based rt component
Figured it out. I did forget to add to the servo thread . Thanks for the advice on how to write the code so it is thread safe.
Please Log in or Create an account to join the conversation.
Time to create page: 0.074 seconds