Jump to content
OMRON Forums

How to guarantee the time in sending the command?


LimingDeng

Recommended Posts

Dear All,

 

I am using Turbo PMAC2A PC/104 to control a robot,the PMAC connect the upper computer by ISA bus. The O.S of the computer is ubuntu10.04 kernel 2.6.32-122-rtai.

 

The upper computer is responsible for generat the position velocity and send them to the rotary buffer in PMAC. Because the robot require a quick response to the environment, thus a long delay are not permitted. Actually, we send the position every 10ms, and we want to guarantee that the rotary buffer should not hungry and also not too much comand lines remaining in the buffer, therefore, I initial two command lines in the rotary buffer.

 

I test it two times, and each were taken half an hour. and repeated 181000 times calling the following functions to send command to PMAC, in the most of time, the send PVT time are small ,however in the 44390 while loop(in first test ) it takes more than 100ms , and in the 30298while loop(In second test),it takes 95ms , also almost 3 to 8 while loops exceed 5 ms, which will cause the hungry of rotary buffer and are not permitted in my system.

 

Functions to send to PMAC

//This file shows the function add position and velocity to Rotary buffer, and the function for sending command to PMAC.

void PMAC::RotaryBufferAddPositionVelocityLine(int* pos_m,int* vel_m)
{

       char cmd[256];
       char value[15];
       string answ;

       strcpy(cmd,"OPEN ROT");//NOTE:Should change to coordinate system.
       SendCmd(cmd);

   strcpy(cmd,"X");//From strcat change to strcpy
   sprintf(value, " %d", pos_m[0]);
   strcat(cmd,value);
   strcat(cmd,":");
   sprintf(value, " %d", vel_m[0]);
   strcat(cmd,value);

   strcat(cmd," Y");
   sprintf(value, " %d", pos_m[1]);
   strcat(cmd,value);
   strcat(cmd,":");
   sprintf(value, " %d", vel_m[1]);
   strcat(cmd,value);
       SendCmd(cmd);

       strcpy(cmd,"CLOSE");
       SendCmd(cmd);
}

void PMAC::SendCmd(char* cmd)
{
   if(pmac_get_response(pmac_dev, cmd) == -ENODEV)
       printf("No device found\n");
   return;
}

 

Why it happens ,How to fix it?

Any available advice are appreciated!

 

Thanks in advances!

Link to comment
Share on other sites

  • Replies 2
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

Dear all,

I have test 6 times and each time will have 181000 while loop,in my program ,each loop should execute within 10ms. The following table shows the number of send command which exceed 10ms ,between two send command it took about 5 minutes, and seems "regular".

sendCMD whileNUM TestNUM

95ms 30298 1 In test 1 only one send

96ms 29837 2

92ms 60811 2 In test 2 two send command

92ms 30850 3 In test 3 four send command …

100ms 61318 3

98ms 92161 3

92ms 122696 3

93ms 43207 4 In test 4 four send command …

96ms 73498 4

98ms 103933 4

92ms 134266 4

98ms 29719 5 In test 5 only one

92ms 29793 6

100ms 60295 6 In test 6 three…

94ms 90804 6

The following table shows the 10 largest terms of SendCmd in Test6.

test6.png.7d512498fda716efe42b8c6bb7bccd85.png

//This is what I used to send comand to PMAC
void PMAC::SendCmd(char* cmd)
{
if(pmac_get_response(pmac_dev, cmd) == -ENODEV)
	rt_printk("No device found\n");
return;
}

//This is a part of core thread code to get position and send position to PMAC
/*START HARD REAL TIME*/
static char opener[]="OPEN ROT\0";
static char closer[]="CLOSE\0";
MyPMAC.SendCmd(opener);
    rt_make_hard_real_time();
       RTIME period;
       period=nano2count(1e7);//10ms to clock ticks.
       t_read_start=rt_get_cpu_time_ns();
	rt_task_make_periodic(TrjSend_task,rt_get_time(),period);
        //Argument is measured in clock ticks.
while(!getExitTrj()){
t_while_start=rt_get_cpu_time_ns();
count++;//To show the number of while loop;

	rt_sem_signal(positionReq_sem);//Give up semaphore!
	rt_sem_wait(syncGeneratorSender_sem);	//wait for Traj Generator
	/****************************** Timing ******************************************/
	t_ask_sem=rt_get_cpu_time_ns();
	/********************************************************************************/
	//To get the pos and vel from Trj
	for(j=0 ; j		{
		thread_rtmutex_lock(g_SharedTrjInfo.pcsTrj[j]);
		if(g_SharedTrjInfo.MyTrj[j].NextSegment(pos,vel,time) != -1)
		{
			thread_rtmutex_unlock(g_SharedTrjInfo.pcsTrj[j]);
			positions[j] = pos;
			velocities[j] = vel;
			oldpos[j] = pos;
			oldvel[j] = vel;
		}
		else
		{
			thread_rtmutex_unlock(g_SharedTrjInfo.pcsTrj[j]);
			positions[j] = oldpos[j];
			velocities[j] = oldvel[j];
		}

	}
//Finish to get the position and velocity 
	char cmd[256];
	string answ;
	thread_rtmutex_lock(csPMAC);
	t_start = rt_get_cpu_time_ns();
	sprintf(cmd,"X %d: %d Y %d:%d",positions[0],velocities[0],positions[1],velocities[1]);
	//Put the position and velocity to the command.
	t_PVT_M=rt_get_cpu_time_ns();
	MyPMAC.SendCmd(cmd);//Send the position and velocity to the rotary buffer of PMAC.
	t_PVT_M0=rt_get_cpu_time_ns();
	thread_rtmutex_unlock(csPMAC);
t_wait_start = rt_get_cpu_time_ns();
rt_task_wait_period();
t_while_end=rt_get_cpu_time_ns();

rt_printk("%d,%.3f,%.3f ,%.3f, %.3f,%.3f,%.3f, %.3f\n",count,(t_ask_sem-t_while_start)/1E3,(t_start-t_ask_sem)/1E3,(t_PVT_M-t_start)/1E3,(t_PVT_M0-t_PVT_M)/1E3,(t_wait_start-t_PVT_M0)/1E3,(t_while_end-t_wait_start)/1E3,(t_while_end-t_while_start)/1E3);
//	rt_print_to_screen,rt_printk
}//Finish the while loop 
   MyPMAC.SendCmd(closer);
   t_end2= rt_get_cpu_time_ns();
   rt_printk("The while loop takes %f ms\n\n",(t_end2-t_read_start)/1E6/count);//To caculate the average time that the every while loop takes.

 

Can anyone help me?

 

Thanks in advance.

Link to comment
Share on other sites

I have found that the get response function are implemented by the following code.If we can change it to real time. It should solve my problem!

 

//The name of this file is pcommx.c, and the following code is part of  function I would use.
int pmac_get_response(int device, char *buf)
{
if(!ISDEVICEOPEN(device))
	return -ENODEV;

pmac[device].ext.status = COMM_OK;
ioctl(pmac[device].node, IOCTL_MOTION_FLUSH_PORT);
ioctl(pmac[device].node, IOCTL_MOTION_FLUSH_MEM);
pmac_send_line(device, buf);
return pmac_get_line(device, buf);
}

int pmac_send_line(int device, char *buf)
{
int result;
if(!ISDEVICEOPEN(device))
	return -ENODEV;
switch(pmac[device].ascii_mode){
	case BUS:
		result = pmac_bus_send_line(device, buf);
		break;
	case DPR:
		result = pmac_dpr_send_line(device, buf);
		break;
}
return result;
}
int pmac_bus_send_line(int device, char *buf)
{
if(!ISDEVICEOPEN(device))
	return -ENODEV;

strncpy(pmac[device].ext.buffer, buf, 256);
ioctl(pmac[device].node, IOCTL_MOTION_WRITELN_PORT, &pmac[device].ext);
return 0;
}

 

It seems that the only function should change to real time is ioctl().

I have found a similiar problem and begining to solve it according to the mial list.

http://mail.rtai.org/pipermail/rtai/2009-June/021718.html

And I change my code as follows:

/*****************************Change from here*****************************/
//For real time.
#include 
#define MY_LXRT_EXT // I just copy this from mail list,I do not know whether is correct!
#define RT_IOCTL 1

static inline int rt_ioctl(int dev,int req, void* ptr)
{
  struct { long dev, long req, void *ptr ;} arg={dev,req,ptr};
  return rtai_lxrt(MY_LXRT_EXT, SIZARG, RT_IOCTL, &arg).i[LOW];
}
/***************************The change end here***************************/

/****************************************For real time response**********************************************/
int rt_pmac_get_response(int device, char *buf)
{
if(!ISDEVICEOPEN(device))
	return -ENODEV;

pmac[device].ext.status = COMM_OK;
rt_ioctl(pmac[device].node, IOCTL_MOTION_FLUSH_PORT);
rt_ioctl(pmac[device].node, IOCTL_MOTION_FLUSH_MEM);
rt_pmac_bus_send_line(device, buf);// For I use ISA bus of my device. The first time I did not chane this .
return pmac_get_line(device, buf);
}
/************************************************The End*****************************************************/

/****************************For real time***********************************/
int rt_pmac_bus_send_line(int device, char *buf)
{
if(!ISDEVICEOPEN(device))
	return -ENODEV;
strncpy(pmac[device].ext.buffer, buf, 256);
rt_ioctl(pmac[device].node, IOCTL_MOTION_WRITELN_PORT, &pmac[device].ext);
return 0;
}
/****************************For real time***********************************/

 

The makefile is:

# The headers are taken from the kernel

INCLUDEDIR = /usr/src/linux-headers-2.6.32-122-rtai/include/
LIBDIR= /usr/lib

libpcommx.so.1.0.0: pcommx.o
gcc -g -shared -Wl,-soname,libpcommx.so.1 -o libpcommx.so.1.0.0 pcommx.o -lc

pcommx.o: pcommx.c pcommx.h
gcc -g -fPIC -c -I $(INCLUDEDIR) pcommx.c

all: libpcommx.so.1.0.0

#test: Test.c
#gcc -g Test.c -o test -L. -lpcommx -I$(INCLUDEDIR)

install:
install -c pcommx.h $(INCLUDEDIR)/linux
install -c libpcommx.so.1.0.0 $(LIBDIR)
ln -s $(LIBDIR)/libpcommx.so.1.0.0 $(LIBDIR)/libpcommx.so.1
ln -s $(LIBDIR)/libpcommx.so.1 $(LIBDIR)/libpcommx.so

clean:
rm -f *.o *.so* $(LIBDIR)/libpcommx.* 
rm -f $(INCLUDEDIR)/linux/pcommx.h

 

The readme is

lib  #contain library for pmac

LIBRARY INSTALLATION:
1 In lib/Makefile
 Change $(INCLUDEDIR) to target machine include dir
2 Run make in lib directory as
 make
 make install

 

I remember that the first time I successfully finished these steps, but when I turn to the project file , it shows undefined reference to 'rt_pmac_get_response'. The first time I did not change the pmac_send_line(device, buf) to rt type. So I changed it, then I started the step again. Unfortun ately, it shows the following errors:

root@sjtu-desktop:/home/sjtu/pmac_driver-installed/lib_mod_new# make
make: Warning: File `pcommx.c' has modification time 2.6e+02 s in the future
gcc -g -fPIC -c -I /usr/src/linux-headers-2.6.32-122-rtai/include/ pcommx.c
pcommx.c:14:23: error: rtai_lxrt.h: No such file or directory
pcommx.c: In function ‘rt_ioctl’:
pcommx.c:20: error: expected identifier or ‘(’ before ‘long’
pcommx.c:20: warning: no semicolon at end of struct or union
pcommx.c:20: warning: excess elements in struct initializer
pcommx.c:20: warning: (near initialization for ‘arg’)
pcommx.c:20: warning: excess elements in struct initializer
pcommx.c:20: warning: (near initialization for ‘arg’)
pcommx.c:21: error: expected expression before ‘,’ token
pcommx.c:21: error: ‘SIZARG’ undeclared (first use in this function)
pcommx.c:21: error: (Each undeclared identifier is reported only once
pcommx.c:21: error: for each function it appears in.)
pcommx.c:21: error: ‘LOW’ undeclared (first use in this function)
pcommx.c: In function ‘rt_pmac_get_response’:
pcommx.c:302: error: too few arguments to function ‘rt_ioctl’
pcommx.c:303: error: too few arguments to function ‘rt_ioctl’
make: *** [pcommx.o] Error 1
root@sjtu-

 

What should I do now?

 

Any advice are appreciated!

Thanks!

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.

×
×
  • Create New...