Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Program call delay - C & Linux

I'm working on new hardware for active prosthetic legs. My system has a BeagleBone Black RevC embedded computer and some custom boards. The BeagleBone Black (BBB) runs Debian Linux.

I wrote a C console app to talk to my other boards from Linux. From the terminal I can send command like "./plan execute_1 set_pid_gains 10 50 0" to change the gains of a control loop running on my motor driver. The "plan" function is written in C. It sends the message via SPI.

The program works fine on its own, I can send all the commands I want. However, when we started testing it from Python (using Popen to call the C program) we realised that it wasn't executing as fast as we wanted.

To replicate and isolate the problem I wrote a shell script (fxa_test_z_1) that sends 3 commands on my network:

#!/bin/bash
# Places FlexSEA in Impedance control mode
# Use with care!

# Set control mode to 'z' (4)
./plan execute_1 set_control 4

# Current loop gains:
./plan execute_1 set_current_gains 10 50 0

# Choose from one of these:
./plan execute_1 set_z_gains 1 0 0
echo "FlexSEA in Stiffness mode"

There is a 14ms delay between each function (measured with an oscilloscope). I ran many small experiments to isolate the problem. Opening & closing the SPI port, sending SPI commands and parsing the agv[] are not the problem. If I call them multiple times in the same program call the delay is in the order of 700us between each serial packet.

Calling "nice -n -19 ./fxa_test_z_1" didn't change anything.

==

What can I do to make those function calls happen faster? Is there any hope I can get them to go sub-ms?

Right now I'm trying to avoid doing major modifications to my code as we want to test our control loops tomorrow.

Thanks!

Jeff

like image 819
JFDuval Avatar asked Aug 11 '26 07:08

JFDuval


1 Answers

You can make it faster by having plan do more work before it has to be run again. Starting a process is a lot of work, so you don't want to do it more often than necessary.

To have plan do more work, you can feed it a list of commands on stdin or from a file. The tricky part is then parsing each line to extract individual commands and parameters. Since your existing code already reads commands from argv, it's easy enough to parse the commands into an argv-like array using strtok:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_COMMAND_LEN 256
#define MAX_ARGS 64
char *fake_argv[MAX_ARGS];  /* For compatibility with existing parser. */
const char *delims = " \n";

int main(int argc, char *argv[])
{
    char command[MAX_COMMAND_LEN];

    while( fgets(command, sizeof(command), stdin) )
    {
        int fake_argc = 0;
        fake_argv[fake_argc] = strtok(command, delims);
        while( fake_argv[fake_argc] != NULL )
        {
            fake_argv[++fake_argc] = strtok(NULL, delims);      
        }

        { int i;  /* debug print... you can remove this block */
          printf("Handling command: [%s], argc %d\n", command, fake_argc);
          for( i = 0; i < fake_argc; ++i ) { printf("  arg: [%s]\n", fake_argv[i]); }
        }
        /* ... do the stuff you were already doing except now with fake_argv */
    }

    return 0;
}

Then your bash script can just be a set of lines that you feed your program:

./plan << END_COMMAND_LIST
execute_1 set_control 4
execute_1 set_current_gains 10 50 0
execute_1 set_z_gains 1 0 0
END_COMMAND_LIST

Now the plan process is created once and it runs 3 commands before exiting.

like image 129
indiv Avatar answered Aug 14 '26 07:08

indiv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!