@Rink I’ll take a look tomorrow on my L476!
Ok Sir ,
If you need my CubeIDE file then I will give you my project files…but this demo is very important for me .
After some changes , Right now my code give me same ans as studio , but this works only on static buffer , if i give real time sensor data on this buffer then its can’t provide right ans .
@Rink, I thought I had a L476 laying around, but I didn’t Anyway, this is a demo on the DISCO-L475VG in STM32CubeIDE:
Includes
/* Includes ------------------------------------------------------------------*/
#include <edge-impulse-sdk/classifier/ei_run_classifier.h>
#include "main.h"
#include "stm32l475e_iot01_accelero.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
using namespace ei;
/* USER CODE END Includes */
Code
/* USER CODE BEGIN 2 */
ACCELERO_StatusTypeDef s = BSP_ACCELERO_Init();
ei_printf("Accelerometer init result %d\n", s);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
float features[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
for (size_t ix = 0; ix < EI_CLASSIFIER_RAW_SAMPLE_COUNT; ix++) {
uint64_t next_tick = ei_read_timer_us() + (EI_CLASSIFIER_INTERVAL_MS * 1000);
int16_t accel_data[3] = { 0 };
BSP_ACCELERO_AccGetXYZ(accel_data);
features[(ix * EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME) + 0] = static_cast<float>(accel_data[0]) / 100.0f;
features[(ix * EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME) + 1] = static_cast<float>(accel_data[1]) / 100.0f;
features[(ix * EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME) + 2] = static_cast<float>(accel_data[2]) / 100.0f;
// busy-loop until next tick
while (ei_read_timer_us() < next_tick);
}
ei_impulse_result_t result;
signal_t signal;
numpy::signal_from_buffer(features, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
EI_IMPULSE_ERROR res = run_classifier(&signal, &result, false);
ei_printf("run_classifier returned: %d\n", res);
ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
// print the predictions
ei_printf("[");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf("%.5f", result.classification[ix].value);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(", ");
#else
if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {
ei_printf(", ");
}
#endif
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf("%.3f", result.anomaly);
#endif
ei_printf("]\n\n\n");
}
/* USER CODE END 3 */
Ok sir ,
thanks for your help
I will try this demo on my setup .
Hey sir ,
I was trying to run you code on my system but still its gets same result which is not correct.
Hey , Sir
I was thinking , Can I use a standard C++ file on My setup(stm32L4 + lis2dw12)?
Because this is just for testing purposes, Our company final goal is that edge impulse use in a Nordic microcontroller. So How can I use Standard C++ library . Please give me some details or sample code something , I also try your Mbed OS code which is given in GitHub , but still there is so many linking error I got .
@Rink you can but if the model does not work properly on the STM32Cube.AI export it won’t work in the normal C++ export either. Given that your results are always the same I’m still suspecting the buffer to not be filled correctly.
So How can I use Standard C++ library
For STM32Cube.IDE see Need help with porting (STM32 Nucleo)
I also try your Mbed OS code which is given in GitHub , but still there is so many linking error I got .
https://github.com/edgeimpulse/example-standalone-inferencing-mbed? This works out-of-the-box for me on the https://os.mbed.com/platforms/ST-Discovery-L476VG/, compiling with GCC ARM 9 - what linker errors do you see?
janjongboom:~/repos/example-standalone-inferencing-mbed (master) $ mbed compile -t GCC_ARM -m disco_l476vg
[mbed] Working path "/Users/janjongboom/repos/example-standalone-inferencing-mbed" (program)
[Warning] @,: Compiler version mismatch: Have 9.3.1; expected version >= 6.0.0 and < 7.0.0
Building project example-standalone-inferencing-mbed (DISCO_L476VG, GCC_ARM)
Scan: example-standalone-inferencing-mbed
Link: example-standalone-inferencing-mbed
Elf2Bin: example-standalone-inferencing-mbed
| Module | .text | .data | .bss |
|---------------------------------------|------------|----------|-----------|
| [fill] | 146(+0) | 14(+0) | 27(+0) |
| [lib]/c.a | 33532(+0) | 2472(+0) | 89(+0) |
| [lib]/gcc.a | 7196(+0) | 0(+0) | 0(+0) |
| [lib]/m.a | 9976(+0) | 1(+0) | 0(+0) |
| [lib]/misc | 188(+0) | 4(+0) | 28(+0) |
| [lib]/nosys.a | 32(+0) | 0(+0) | 0(+0) |
| [lib]/stdc++.a | 5208(+0) | 8(+0) | 44(+0) |
| edge-impulse-sdk/CMSIS | 15784(+0) | 0(+0) | 0(+0) |
| edge-impulse-sdk/dsp | 3226(+0) | 0(+0) | 0(+0) |
| edge-impulse-sdk/porting | 74(+0) | 0(+0) | 0(+0) |
| edge-impulse-sdk/tensorflow | 15444(+0) | 192(+0) | 0(+0) |
| mbed-os/components | 36(+0) | 0(+0) | 4(+0) |
| mbed-os/drivers | 174(+0) | 0(+0) | 0(+0) |
| mbed-os/hal | 1726(+0) | 8(+0) | 130(+0) |
| mbed-os/platform | 4482(+0) | 260(+0) | 408(+0) |
| mbed-os/rtos | 6854(+0) | 168(+0) | 10324(+0) |
| mbed-os/targets | 11050(+0) | 8(+0) | 966(+0) |
| source/main.o | 9100(+0) | 65(+0) | 4(+0) |
| tflite-model/trained_model_compiled.o | 1288(+0) | 744(+0) | 2832(+0) |
| Subtotals | 125516(+0) | 3944(+0) | 14856(+0) |
Total Static RAM memory (data + bss): 18800(+0) bytes
Total Flash memory (text + data): 129460(+0) bytes
Image: ./BUILD/DISCO_L476VG/GCC_ARM/example-standalone-inferencing-mbed.bin
sir , I Checked my buffer fill with proper data or not , even I also print it.
See this in picture , I printed my buffer data and result … my data continues changes but result cant , and this time I used c++ library instead of Cube-AI.
Hi Rink,
The buffer should contain 600 values. If only 3 are filled that would explain the same results as mentioned by Jan.
Aurelien
sir , actually the buffer have 600 values , but just print first three value for showing variation .
void lis2dw12_read_data_single(void)
{
stmdev_ctx_t dev_ctx;
dev_ctx.write_reg = platform_write;
dev_ctx.read_reg = platform_read;
platform_delay(BOOT_TIME);
lis2dw12_device_id_get(&dev_ctx, &whoamI);
if (whoamI != LIS2DW12_ID)
{
printf(“Device not respond\r\n”);
}
lis2dw12_reset_set(&dev_ctx, PROPERTY_ENABLE);
do
{
lis2dw12_reset_get(&dev_ctx, &rst);
} while (rst);
lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
lis2dw12_int_notification_set(&dev_ctx, LIS2DW12_INT_LATCHED);
lis2dw12_pin_polarity_set(&dev_ctx, LIS2DW12_ACTIVE_LOW);
lis2dw12_pin_int1_route_get(&dev_ctx, &ctrl4_int1_pad);
ctrl4_int1_pad.int1_drdy = PROPERTY_ENABLE;
lis2dw12_pin_int1_route_set(&dev_ctx, &ctrl4_int1_pad);
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT);
lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_10);
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_CONT_LOW_PWR_12bit);
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_SET_SW_TRIG);
memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
lis2dw12_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
acceleration_mg[0] = lis2dw12_from_fs2_lp1_to_mg(data_raw_acceleration[0]);
acceleration_mg[1] = lis2dw12_from_fs2_lp1_to_mg(data_raw_acceleration[1]);
acceleration_mg[2] = lis2dw12_from_fs2_lp1_to_mg(data_raw_acceleration[2]);
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_SET_SW_TRIG);
for(int i =0 ; i< 600 ; )
{
features[i++] = acceleration_mg[0];
features[i++] = acceleration_mg[1];
features[i++] = acceleration_mg[2];
HAL_Delay(10);
}
/* sprintf((char *)p_buf,"%f %f %f \r\n",features[0],features[1],features[2]);
HAL_UART_Transmit(&huart2, (uint8_t )p_buf, sizeof(p_buf),1000);/
}
this is my sensor code , you can see I
fill my features buffer with 600 data values
Hi @Rink,
You’re not reading from the accelerometer in the loop. You should call lis2dw12_acceleration_raw_get
every time to get the new values. Now you’re writing the same value over and over.
see it is inside my int main() function , I put my in while(1) so every time they get updated value even i also checked it
@Rink, it is not:
memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
lis2dw12_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
acceleration_mg[0] = lis2dw12_from_fs2_lp1_to_mg(data_raw_acceleration[0]);
acceleration_mg[1] = lis2dw12_from_fs2_lp1_to_mg(data_raw_acceleration[1]);
acceleration_mg[2] = lis2dw12_from_fs2_lp1_to_mg(data_raw_acceleration[2]);
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_SET_SW_TRIG);
for(int i =0 ; i< 600 ; )
{
// SHOULD READ FROM ACCELEROMETER HERE
features[i++] = acceleration_mg[0];
features[i++] = acceleration_mg[1];
features[i++] = acceleration_mg[2];
HAL_Delay(10);
}
Here you read the accelerometer once and then keep writing those same values. You should update the acceleration_mg
array every time you hit this loop.
hey @janjongboom thanks a lot for helpping me …finally it works … I realize my mistakes
You are right …every time fill same x,y,z data in buffer , I had small change in my code and then it works
Hello sir ,
How can i link all the library(stranded cpp) components (folders) with CMakeList.txt file , can you give me some direction something , I am Working on nrf52840 with Zephyr , and programming with linux terminal.
Hey @Rink, add a CMake rule that finds all .h
, .cc
, .c
, and .cpp
files, and then exclude the edge-impulse-sdk/porting
, utensor
and ei_run_classifier_c.*
files. See:
For an example.
Hello Sir,
as you say ,
CMake rule that finds all .h
, .cc
, .c
, and .cpp
files, and then exclude the edge-impulse-sdk/porting
, utensor
and ei_run_classifier_c.*
files.
I done it , after this I build my code but there are so many errors .
And porting folder file error also ,
so give me some solution , I am working on nrf52840 Dk board , and conding in zephyr os
I was not change any files or folder in your standard sdk just deleting porting , utensor and ei_run_classifier_c.* nothing else .
@Rink here’s an end-to-end example with a Zephyr project: https://docs.edgeimpulse.com/docs/running-your-impulse-locally-zephyr
thanks a lot sir its works well …