HI @Eoin ,
Here is my Project ID: 371696
Context: I am using process MITDB ECG results where the signals are broken down intro 3 windows. Each window is process with Kurtosis and Skewness formula and saved into a csv file. Each row consist of 3kurtosis value followed by 3 skewness value. Noisy data are labelled as 0 and non-noisy as 1. There is no time series involved and i just want to strictly use Edge classification function to deploy into my MCU(NRF52840DK) to determine and show my professor that it can run and return a classification value.
// Zpehyr 3.1.x and newer uses different include scheme
#include <version.h>
#if (KERNEL_VERSION_MAJOR > 3) || ((KERNEL_VERSION_MAJOR == 3) && (KERNEL_VERSION_MINOR >= 1))
#include <zephyr/kernel.h>
#else
#include <zephyr.h>
#endif
#include "edge-impulse-sdk/classifier/ei_run_classifier.h"
#include "edge-impulse-sdk/dsp/numpy.hpp"
#include <nrfx_clock.h>
extern "C" int engzee(const short int, int);
const short int input_arry[] = {...} // 45000+ hardcoded data points
int peak_indices[5000];
int engzee(const short int *input_arry, int *output_arry)
{
int filter, time = 0, slopecrit, sign, maxslope = 0, nsig, nslope = 0, qtime, maxtime, t0,
t1, t2, t3, t4, t5, t6, t7, t8, t9;
int s2 = 500;
int scmin = 200;
int scmax = 2000;
int ms160 = 40;
int ms200 = 50;
long temp, t, found, counter = 0, counter1 = 0;
t9 = t8 = t7 = t6 = t5 = t4 = t3 = t2 = t1 =
input_arry[0]; // v[0] contains channel 1 signal, v[1] contains channel 2 signal
do {
filter = (t0 = input_arry[counter]) + 4 * t1 + 6 * t2 + 4 * t3 + t4 - t5 - 4 * t6 -
6 * t7 - 4 * t8 - t9;
// printf("This is s2: %d\n", s2); // This value is 500
// printf("This is scmin: %d\n", scmin); //This value is 200
// printf("This is scmax: %d\n", scmax); // THis value is 2000
if (time % s2 == 0) {
if (nslope == 0) {
slopecrit -= slopecrit >> 4;
if (slopecrit < scmin) {
slopecrit = scmin;
}
} else if (nslope >= 5) {
slopecrit += slopecrit >> 4;
if (slopecrit > scmax) {
slopecrit = scmax;
}
}
}
if (nslope == 0 && abs(filter) > slopecrit) {
nslope = 1;
maxtime = ms160;
sign = (filter > 0) ? 1 : -1;
qtime = time;
}
if (nslope != 0) {
if (filter * sign < -slopecrit) {
sign = -sign;
maxtime = (++nslope > 4) ? ms200 : ms160;
} else if (filter * sign > slopecrit && abs(filter) > maxslope) {
maxslope = abs(filter);
}
if (maxtime-- < 0) {
if (2 <= nslope && nslope <= 4) {
slopecrit += ((maxslope >> 2) - slopecrit) >> 3;
if (slopecrit < scmin) {
slopecrit = scmin;
} else if (slopecrit > scmax) {
slopecrit = scmax;
}
// temp = strtim("i"); //This corresponds to which sample is
// on currently.
found = temp - (time - qtime) - 4;
// printf("QRS found: %ld\n", found);
output_arry[counter1] = counter;
counter1++;
time = 0;
} else if (nslope >= 5) {
// Artifact detected
}
nslope = 0;
}
}
t9 = t8;
t8 = t7;
t7 = t6;
t6 = t5;
t5 = t4;
t4 = t3;
t3 = t2;
t2 = t1;
t1 = t0;
time++;
counter++;
// printf("Current sample: %ld \n", counter);
// printf("-----\n");
} while (counter < 451390); // Total number of samples is 451389. Should correspond to about
// 250hz sampling.
printf("Number of peaks: %ld\n", counter1);
return counter1;
}
static const float features[] = {
22.0309, 21.9531, 23.1694, 3.9961,4.1067, 4.2041
// copy raw features here (for example from the 'Live classification' page)
// see https://docs.edgeimpulse.com/docs/running-your-impulse-locally-zephyr
};
int raw_feature_get_data(size_t offset, size_t length, float *out_ptr) {
memcpy(out_ptr, features + offset, length * sizeof(float));
return 0;
}
int main() {
int k;
// This is needed so that output of printf is output immediately without buffering
setvbuf(stdout, NULL, _IONBF, 0);
#ifdef CONFIG_SOC_NRF5340_CPUAPP
// Switch CPU core clock to 128 MHz
nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1);
#endif
printk("Edge Impulse standalone inferencing (Zephyr)\n");
if (sizeof(features) / sizeof(float) != EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE) {
printk("The size of your 'features' array is not correct. Expected %d items, but had %u\n",
EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, sizeof(features) / sizeof(float));
return 1;
}
ei_impulse_result_t result = { 0 };
while (1) {
// the features are stored into flash, and we don't want to load everything into RAM
signal_t features_signal;
features_signal.total_length = sizeof(features) / sizeof(features[0]);
features_signal.get_data = &raw_feature_get_data;
// invoke the impulse
EI_IMPULSE_ERROR res = run_classifier(&features_signal, &result, true);
printk("run_classifier returned: %d\n", res);
// TODO
if (res == 0) {
k = engzee(input_arry, peak_indices);
} else {
return 1;
}
if (res != 0) return 1;
printk("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
#if EI_CLASSIFIER_OBJECT_DETECTION == 1
bool bb_found = result.bounding_boxes[0].value > 0;
for (size_t ix = 0; ix < result.bounding_boxes_count; ix++) {
auto bb = result.bounding_boxes[ix];
if (bb.value == 0) {
continue;
}
printk(" %s (%f) [ x: %u, y: %u, width: %u, height: %u ]\n", bb.label, bb.value, bb.x, bb.y, bb.width, bb.height);
}
if (!bb_found) {
printk(" No objects found\n");
}
#else
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
printk(" %s: %.5f\n", result.classification[ix].label,
result.classification[ix].value);
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
printk(" anomaly score: %.3f\n", result.anomaly);
#endif
#endif
k_msleep(2000);
}
}