Set Multiple targets via usb (libusb_submit_transfer)

Hi!
Setup:
Mini Maestro 24.
OS - Linux.

Is it possible to set the Multiple targets for a contiguous block of channels via libusb_submit_transfer or libusb_bulk_transfer?
Now I use libusb_control_transfer(…), but it is very slow (about 70 ~ 100 milliseconds to 24 requests).

/* >== 0 ms */
libusb_control_transfer(handle,0x40,(BYTE)REQUEST_SET_TARGET,target,servo_0,(BYTE)0,0,(u16)2000);
libusb_control_transfer(handle,0x40,(BYTE)REQUEST_SET_TARGET,target, servo_1,(BYTE)0,0,(u16)2000);
...
libusb_control_transfer(handle,0x40,(BYTE)REQUEST_SET_TARGET,target,servo_22,(BYTE)0,0,(u16)2000);
libusb_control_transfer(handle,0x40,(BYTE)REQUEST_SET_TARGET,target,servo_23,(BYTE)0,0,(u16)2000);
/* >== 70-100 ms */

Thank you and sorry for my english.

Hello,

I expect libusb_submit_transfer to work much better for you. I have not tried the asynchronous functions under linux, but that is what I would recommend.

You could also use the Set Multiple Targets serial command, which might be slightly faster since it uses a bulk endpoint, if that does not work for some reason.

-Paul

Hello,
Could you show an example of isochronous data transfer for set multiple targets for Windows or another operating system

Thank you and sorry for my English.

Hello,

The Maestro does not support any isochronous transfers. Did you give up on using libusb_submit_transfer to do control transfers?

-Paul

libusb_submit_transfer (LIBUSB_TRANSFER_TYPE_CONTROL) is not very suitable.
Response time between the first and last servo about 40 ~ 20 ms.

Now I am using serial interface (command 0x9F).

Hello,

I am surprised that libusb_submit_transfer took so long. If you could post that version of the code here in a form that we could compile ourselves, I would be interested in trying it out over here some time to see if I can make it faster. My understanding is that it does not take that long under Windows, though I am not sure that we have ever measured it.

-Paul

The code itself works off an average of 100 nanoseconds ( in for(BYTE i=0;i<=23;i++){…} ).
But until all the data will be read by the controller, between the beginning of the movement first and 24 th servo is 40 ~ 20 ms.

[code]struct libusb_transfer *u_trans[24];
unsigned char buffer [24][LIBUSB_CONTROL_SETUP_SIZE + 1];
for(BYTE n=0;n<=30;n++)
{
for(BYTE i=0;i<=23;i++)
{

				u_trans[i] = libusb_alloc_transfer(0);
				if (!u_trans) 
				{
					printf("!!!");
					exit(1);
				}
				u_trans[i]->flags=LIBUSB_TRANSFER_FREE_TRANSFER;

				libusb_fill_control_setup(buffer[i],0x40,(BYTE) REQUEST_SET_TARGET,((n%3)*2000)+4000,i,0);
				libusb_fill_control_transfer(u_trans[i],handle,buffer[i],NULL,NULL,1000);
				libusb_submit_transfer(u_trans[i]);
			}
			usleep(500000);
		}

[/code]

Can you describe how you are measuring “the beginning of the movement first and 24 th servo”?

-Paul

I take a digital multi-channel oscillograph, connect it to the first and last channel of the Mini-Maestro24 controler.
Execute my program.
The difference between the beginning of change of a PWM signal (first and last channel) is a difference of response of servomotors.

Just to be sure, are you talking about an oscilloscope or some other kind of equipment? Is it possible for you to post a picture of the measurement?

I would like to try running your code, but it is not a good test if I have to guess what the rest of it is. Can you post the entire code along with a Makefile or compilation command so that I can give it a try? You can post them all together in a .zip if that is easiest.

-Paul

Yes, I meant the oscilliscope.
Archive with the project in the attachments.

p.s. Works only with mini-maestro 24.
pololucontrol_usbsubmittransfer_sample-0.1.tar.gz (379 KB)

mak and Paul, I have a suggestion that might make this code faster: you should allocate all of the transfer memory ahead of time. So make an initialization loop before your other loop and move the “u_trans[i] = libusb_alloc_transfer(0);” line there.

You can probably go further than that and it might make it a bit faster: you can probably move most of your code in to the initialization loop… the only code that needs to be in the lower loop is the one that computes the targets for the servos and puts them in to the setup packet struct, because nothing else about your transfers needs to be changed.

–David

It will not work with LIBUSB_TRANSFER_TYPE_CONTROL (only with LIBUSB_TRANSFER_TYPE_INTERRUPT)

I have found a method! Approximately in 2 hours I will write results.

It perfectly works!

/* 
struct libusb_device_handle *handle = libusb_open_device_with_vid_pid(...);

 */

if(libusb_kernel_driver_active(handle,1)==1) //Determine if a kernel driver is active on an interface.
{
	if(libusb_detach_kernel_driver(handle,1)!=0) //Try to detach a kernel driver from an interface.
	{
		printf("Cant detach_kernel_driver\n");
		exit(1);
	}
}
if(libusb_claim_interface(handle,1)!=0) //Claim an interface on a given device handle.
{
	printf("Cant claim\n");
}

struct libusb_transfer *u_trans;

unsigned char m_command[] = {0x9F, 0x18, 0x00, 0x20, 0x1F, 0x70, 0x2E,
	0x40, 0x3E, 0x20, 0x1F, 0x70, 0x2E, 0x40, 0x3E, 0x20, 0x1F, 
	0x70, 0x2E, 0x40, 0x3E, 0x20, 0x1F, 0x70, 0x2E, 0x40, 0x3E,
	0x20, 0x1F, 0x70, 0x2E, 0x40, 0x3E, 0x20, 0x1F, 0x70, 0x2E, 
	0x40, 0x3E, 0x20, 0x1F, 0x70, 0x2E, 0x40, 0x3E, 0x20, 0x1F, 
	0x70, 0x2E, 0x40, 0x3E}; // The prepared SerialInterface command for Mini-Maestro 24

u_trans = libusb_alloc_transfer(0);
if (!u_trans) 
{
	printf("!!!");
	exit(1);
}
u_trans->flags=LIBUSB_TRANSFER_FREE_TRANSFER;

libusb_fill_bulk_transfer(u_trans,handle,/*(2 | LIBUSB_ENDPOINT_OUT)*/ 0x2, m_command,sizeof(m_command),
                          NULL,NULL,1000);

libusb_submit_transfer(u_trans);

if(libusb_release_interface(handle,1)==0)
{
	printf("Cant release_interface\n");
}
if(libusb_kernel_driver_active(handle,1)==0)
{
	if(libusb_attach_kernel_driver(handle,1)!=0)
	{
		printf("Cant attach_kernel_driver\n");
	}
}

Years later… can you post your full code? I can’t get yours to work )with commented out parts filled in properly).