cancel
Showing results for 
Search instead for 
Did you mean: 

API-manual for ST Edge AI Developer Cloud generated C file for ISPU

Amith_lal
Associate III

In ST Edge AI Developer Cloud I generated the C library of a ST_LSM6DSO16IS_ispu_wand_dataset with platform selected as ISPU. I got many library files in which the major APIs are in the network.h and its c file. I need an API manual or documentation to apply this in tho my program or an example of implementation is enough.

1 ACCEPTED SOLUTION

Accepted Solutions

Your idea on how to fill the input buffer is correct, however the algo_00 function (where I guess you wrote your code), is executed each time a new sample is generated by the sensor.

So, while it might technically work, you should not loop inside the function with "while(count < STAI_NETWORK_IN_1_SIZE)" and "delay_ms(38);". The code should be something like this:

 

uint32_t class;
float *input = (float *)input_buffers[0];
float *output = (float *)output_buffers[0];
 
input[count + 0] = (float)cast_sint16_t(ISPU_ARAW_X) * ACC_SENS;
input[count + 1] = (float)cast_sint16_t(ISPU_ARAW_Y) * ACC_SENS;
input[count + 2] = (float)cast_sint16_t(ISPU_ARAW_Z) * ACC_SENS;
count += 3;

if (count == STAI_NETWORK_IN_1_SIZE) {
    count = 0;

    stai_return_code res = stai_network_run(net, STAI_MODE_SYNC);
    class = argmax(output, STAI_NETWORK_OUT_1_SIZE); // to find the highest among the 3 output
    cast_float(ISPU_DOUT_06) = output[0];
    cast_float(ISPU_DOUT_08) = output[1];
    cast_float(ISPU_DOUT_10) = output[2];
    cast_float(ISPU_DOUT_12) = class;
}

 

You can define "count" as a static global variable and you should initialize it to 0 in the "algo_00_init" function.

It seems you want to run use data at 26 Hz, so make sure that in the "conf.txt" in your project folder both "acc_odr" and "ispu_irq_rate" are set to 26.

Regarding the output, if you are using MEMS Studio or Unicleo-GUI to display them, make sure to also have a ".json" file as explained in the readme of the generic template here: https://github.com/STMicroelectronics/ispu-examples/tree/master/ism330is_lsm6dso16is/template. This file will tell to the desktop application how to interpret the outputs of the ISPU and display them correctly. The ".json" file must have the same name as the ".ucf" one.

By the way, I see you are starting copying the outputs from ISPU_DOUT_06. I guess this is because you have other data before that. Should that not be the case, you should start from ISPU_DOUT_00, because the ".json" indicates the format for contiguous outputs starting from ISPU_DOUT_00.

Hope this helps solve your problems.

View solution in original post

11 REPLIES 11
Lorenzo BRACCO
ST Employee

Hi @Amith_lal,

thanks for reaching out.

You can refer to the documentation and resources on the GitHub repository for ISPU: https://github.com/STMicroelectronics/st-mems-ispu. In particular, you can use the template specific for the integration of models converted with ST Edge AI, together with a README file explaining the necessary steps: https://github.com/STMicroelectronics/ispu-examples/tree/master/ism330is_lsm6dso16is/template_stedgeai.

If you download the CLI tool, ST Edge AI Core (https://www.st.com/en/development-tools/stedgeai-core.html), it includes additional documentation which you may find useful, such as documentation of the APIs.

By next week we plan to also upload additional material regarding specifically the ISPU wand example on the same GitHub repository: https://github.com/STMicroelectronics/st-mems-ispu/tree/master/model_zoo/ispu_wand .

Let me know if you need anything else.

Thank you for sharing the details.The shared information helped me to generate a ml file for ISPU and added that to template_stedgeai. I followed the document README.md. But after that I got some confusion about providing the input and getting the output from the example project. How can I use the output to get the prediction from it.

Screenshot from 2024-07-02 21-51-52.png

@Federica Bossi 

The template is already allocating the memory buffers necessary to store the inputs and outputs and is communicating the location (addresses) of such buffers to the network library in the "init_network" function in "main.c", so that when you call the "stai_network_run" function to run the inference, the network will already know where to get the inputs and where to store the outputs.

For the inputs, what you need to do is to actually fill in the buffer with the correct input data, which depends on your model. Say that your input is composed of 10 float values, you can reinterpret the buffer as an array of float values with a simple cast:

 

float *input = (float *)input_buffers[0];

 

where input_buffers contains the pointers to the preallocated input buffers. If your network has only one input (it is usually the case), you will have to use input_buffers[0] (indicated the first input buffer).

Now you can access and assign the values:

 

input[0] = ...
input[1] = ...
input[2] = ...
...
input[9] = ...

 

What you assign to every single value depends on your application and how the input is generated starting, for example, from the sensor data (you can refer to the examples at https://github.com/STMicroelectronics/ispu-examples/tree/master/ism330is_lsm6dso16is for how to access sensor data).

After running the inference, the output of the network will already be stored in the output buffer, but you will have to again interpret it correctly based on your knowledge of the shape and format of the output of your model. Information about format and shape of both inputs and outputs is available in the "network.h" generated file. However, keep in mind that you still need to know what each value represents.

So, say your model has two 8-bit signed integer values as output, you can access them as follows:

 

int8_t *output = (int8_t *)output_buffers[0];

output[0] // first output value
output[1] // second output value

 

you can then use the output for further processing or you can copy the values to the ISPU output registers. You can do the latter with something like this:

 

cast_sint8_t(ISPU_DOUT_00) = output[0];
cast_sint8_t(ISPU_DOUT_00_B) = output[1];

 

I hope this clarifies your doubts.

I'm getting output as i give input. But the output is not correct. I'm thinking is there any problem in my generated model as I'm not an ML expert .So is there any example to generate machine learning model for ISPU(tensorflowlite or keras)?

nikkiharrisss
Associate

Hello

 

Yes, the ST Edge AI Developer Cloud has the examples and documentation for using the created C library. What you can do is as follows:

1. Go to the documentation part of the ST Edge AI Developer Cloud.
2. Look for the ST_LSM6DSO16IS_ispu_wand_dataset-specific guidance.
3. Example implementations and an API handbook ought to be included in the documentation.
4. You can also browse the ST community forums or get in touch with support if you need more help.

Please do not hesitate to ask for more assistance!

 

Regards

Nikki Harris

Provident Botanico

https://www.providentbotanico.org.in/
Amith_lal
Associate III

If you provide the implementations and an API handbook it will be very helpful.When will this be updated?

Hi @Amith_lal, we will soon have a full tutorial online, plus material to use the ISPU wand model, if that is what you are interested in.

I will let you know as soon as everything is available.

Amith_lal
Associate III

Ok thank you for your consideration.

If my model is for activity recoginision using accelerometer 3 axis with 3 output classes and the data parameters is defined as

/****************************************************************/

#define STAI_NETWORK_IN_1_FORMAT       (STAI_FORMAT_FLOAT32)

#define STAI_NETWORK_IN_1_SHAPE          {1,26,3}

#define STAI_NETWORK_IN_1_BATCH           (1)

#define STAI_NETWORK_IN_1_HEIGHT         (26)

#define STAI_NETWORK_IN_1_CHANNEL      (3)

#define STAI_NETWORK_IN_1_RANK             (2)

#define STAI_NETWORK_IN_1_SIZE               (78)

#define STAI_NETWORK_IN_1_SIZE_BYTES (312)

/****************************************************************/

#define STAI_NETWORK_OUT_1_FORMAT          (STAI_FORMAT_FLOAT32)
#define STAI_NETWORK_OUT_1_SHAPE             {1,3}
#define STAI_NETWORK_OUT_1_BATCH             (1)
#define STAI_NETWORK_OUT_1_CHANNEL        (3)
#define STAI_NETWORK_OUT_1_RANK               (1)
#define STAI_NETWORK_OUT_1_SIZE                ((3))
#define STAI_NETWORK_OUT_1_SIZE_BYTES  (12)

/****************************************************************/

I think I should provide the input as 

int count=0;
uint32_t class;
float *input = (float *)input_buffers[0];
float *output = (float *)output_buffers[0];
 
while(count < STAI_NETWORK_IN_1_SIZE){
    input[count + 0] =(float)cast_sint16_t(ISPU_ARAW_X) * ACC_SENS;
    input[count + 1] =(float)cast_sint16_t(ISPU_ARAW_Y) * ACC_SENS;
    input[count + 2] =(float)cast_sint16_t(ISPU_ARAW_Z) * ACC_SENS;
    count += 3;
    delay_ms(38);
    if (count == STAI_NETWORK_IN_1_SIZE){
        stai_return_code res = stai_network_run(net, STAI_MODE_SYNC);
        class = argmax(output,STAI_NETWORK_OUT_1_SIZE); //to find the highest among the 3 output
        cast_float(ISPU_DOUT_06)   =(float)output[0];
        cast_float(ISPU_DOUT_08)   =(float)output[1];
        cast_float(ISPU_DOUT_10)   =(float)output[2];
        cast_float(ISPU_DOUT_12)   =(float)class;
    }
}

But I'm not getting a proper output .