NM500 NeuroShield and MPU6050 IMU Test Example
Dependencies: mbed NeuroShield
main.cpp
- Committer:
- nepes_ai
- Date:
- 2020-02-11
- Revision:
- 2:28290f9caf51
- Parent:
- 1:fb672eb52bd6
File content as of revision 2:28290f9caf51:
/****************************************************************************** * NM500 NeuroShield Board and mpu6050 imu Test example * revision 1.1.5, 2020/02/11 * Copyright (c) 2017 nepes inc. * * Please use the NeuroShield library v1.1.4 or later ******************************************************************************/ #include "mbed.h" #include <NeuroShield.h> #include <NeuroShieldSPI.h> #include <mpu6050.h> // for NM500 #define MOTION_REPEAT_COUNT 3 // number of samples to assemble a vector #define MOTION_SIGNAL_COUNT 8 // d_ax, d_ay, d_az, d_gx, d_gy, d_gz, da, dg #define MOTION_CAPTURE_COUNT 20 #define DEFAULT_MAXIF 500 NeuroShield hnn; MPU6050 mpu(0x68, PB_9, PB_8); // SDA:(D14=PB_9) SCL(D15=PB_8) <= SB143/SB138 must close for I2C on A4/A5 and SB147/SB157 must open!!! Serial pc(USBTX, USBRX); DigitalOut sdcard_ss(D6); // SDCARD_SSn DigitalOut arduino_con(D5); // SPI_SEL int16_t ax, ay, az, gx, gy, gz; uint8_t learn_cat = 0; // category to learn uint8_t prev_cat = 0; // previously recognized category uint16_t dist, cat, nid, nsr, ncount; // response from the neurons uint16_t prev_ncount = 0; uint16_t fpga_version; int16_t min_a = 0xFFFF, max_a = 0, min_g = 0xFFFF, max_g = 0, da = 0, dg = 0; // reset, or not, at each feature extraction uint8_t vector[MOTION_REPEAT_COUNT * MOTION_SIGNAL_COUNT]; // vector holding the pattern to learn or recognize void mpu6050Calibration() { int i, j; long sum_ax = 0, sum_ay = 0, sum_az = 0, sum_gx = 0, sum_gy = 0, sum_gz = 0; int mean_ax, mean_ay, mean_az, mean_gx, mean_gy, mean_gz; int ax_offset, ay_offset, az_offset, gx_offset, gy_offset, gz_offset; for (i = 0; i < 100; i++) { mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); } for (j = 0; j < 5; j++) { for (i = 0; i < 100; i++) { mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); sum_ax += ax; sum_ay += ay; sum_az += az; sum_gx += gx; sum_gy += gy; sum_gz += gz; } mean_ax = sum_ax / 100; mean_ay = sum_ay / 100; mean_az = sum_az / 100; mean_gx = sum_gx / 100; mean_gy = sum_gy / 100; mean_gz = sum_gz / 100; // MPU6050_GYRO_FS_1000 : offset = (-1) * mean_g // MPU6050_ACCEL_FS_8 : offset = (-0.5) * mean_a ax_offset = (-mean_ax) / 2; ay_offset = (-mean_ay) / 2; az_offset = (-mean_az) / 2; gx_offset = -mean_gx; gy_offset = -mean_gy; gz_offset = -mean_gz; // set mpu.setXAccelOffset(ax_offset); mpu.setYAccelOffset(ay_offset); mpu.setZAccelOffset(az_offset); mpu.setXGyroOffset(gx_offset); mpu.setYGyroOffset(gy_offset); mpu.setZGyroOffset(gz_offset); } } void extractFeatureVector() { int i; int16_t min_ax, min_ay, min_az, max_ax, max_ay, max_az; int16_t min_gx, min_gy, min_gz, max_gx, max_gy, max_gz; uint32_t norm_ax, norm_ay, norm_az, norm_gx, norm_gy, norm_gz; int32_t d_ax, d_ay, d_az, d_gx, d_gy, d_gz; int32_t da_local, dg_local; mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); max_ax = min_ax = ax; max_ay = min_ay = ay; max_az = min_az = az; max_gx = min_gx = gx; max_gy = min_gy = gy; max_gz = min_gz = gz; for (i = 0; i < MOTION_CAPTURE_COUNT; i++) { mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); if (ax < min_ax) min_ax = ax; else if (ax > max_ax) max_ax = ax; if (ay < min_ay) min_ay = ay; else if(ay > max_ay) max_ay = ay; if (az < min_az) min_az = az; else if (az > max_az) max_az = az; if (gx < min_gx) min_gx = gx; else if (gx > max_gx) max_gx = gx; if (gy < min_gy) min_gy = gy; else if (gy > max_gy) max_gy = gy; if (gz < min_gz) min_gz = gz; else if (gz > max_gz) max_gz = gz; } d_ax = max_ax - min_ax; d_ay = max_ay - min_ay; d_az = max_az - min_az; d_gx = max_gx - min_gx; d_gy = max_gy - min_gy; d_gz = max_gz - min_gz; da_local = d_ax; if (d_ay > da_local) da_local = d_ay; if (d_az > da_local) da_local = d_az; dg_local = d_gx; if (d_gy > dg_local) dg_local = d_gy; if (d_gz > dg_local) dg_local = d_gz; norm_ax = d_ax; norm_ax = norm_ax * 255 / da_local; norm_ay = d_ay; norm_ay = norm_ay * 255 / da_local; norm_az = d_az; norm_az = norm_az * 255 / da_local; norm_gx = d_gx; norm_gx = norm_gx * 255 / dg_local; norm_gy = d_gy; norm_gy = norm_gy * 255 / dg_local; norm_gz = d_gz; norm_gz = norm_gz * 255 / dg_local; for (i = 0; i < MOTION_REPEAT_COUNT; i++) { vector[i * MOTION_SIGNAL_COUNT] = norm_ax & 0x00ff; vector[(i * MOTION_SIGNAL_COUNT) + 1] = norm_ay & 0x00ff; vector[(i * MOTION_SIGNAL_COUNT) + 2] = norm_az & 0x00ff; vector[(i * MOTION_SIGNAL_COUNT) + 3] = norm_gx & 0x00ff; vector[(i * MOTION_SIGNAL_COUNT) + 4] = norm_gy & 0x00ff; vector[(i * MOTION_SIGNAL_COUNT) + 5] = norm_gz & 0x00ff; if (da_local >= 4096) vector[(i * MOTION_SIGNAL_COUNT) + 6] = 0xff; else vector[(i * MOTION_SIGNAL_COUNT) + 6] = ((da_local >> 4) & 0x00ff); if (dg_local >= 4096) vector[(i * MOTION_SIGNAL_COUNT) + 7] = 0xff; else vector[(i * MOTION_SIGNAL_COUNT) + 7] = ((dg_local >> 4) & 0x00ff); } } int main() { int input_key[2]; arduino_con = LOW; sdcard_ss = HIGH; wait(0.5); if (hnn.begin() != 0) { fpga_version = hnn.fpgaVersion(); if ((fpga_version & 0xFF00) == 0x0000) { printf("\n\n#### NeuroShield Board (Board v%d.0 / FPGA v%d.0) ####\n", ((fpga_version >> 4) & 0x000F), (fpga_version & 0x000F)); } else if ((fpga_version & 0xFF00) == 0x0100) { printf("\n\n#### Prodigy Board (Board v%d.0 / FPGA v%d.0) ####\n", ((fpga_version >> 4) & 0x000F), (fpga_version & 0x000F)); } else { printf("\n\n#### Unknown Board (Board v%d.0 / FPGA v%d.0) ####\n", ((fpga_version >> 4) & 0x000F), (fpga_version & 0x000F)); } printf("\nStart NM500 initialzation...\n"); printf(" NM500 is initialized!\n"); printf(" There are %d neurons\n", hnn.total_neurons); } else { printf("\n\nStart NM500 initialzation...\n"); printf(" NM500 is not connected properly!!\n"); printf(" Please check the connection and reboot!\n"); while (1); } // initialize mpu6050 printf("\nStart MPU-6050 initialization...\n"); mpu.initialize(); // set gyro & accel range mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_1000); mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_8); // verify connection for (int i = 0; i < 10; i++) { if (mpu.testConnection()) { printf(" MPU-6050 is connected successfully\n"); break; } else if (i == 9) { printf(" MPU-6050 connection failed\n"); printf(" Please check the connection and reboot!\n"); while (1); } wait(0.1); } // wait for ready printf(" Trying to calibrate. Make sure the board is stable and upright\n"); // reset offsets mpu.setXAccelOffset(0); mpu.setYAccelOffset(0); mpu.setZAccelOffset(0); mpu.setXGyroOffset(0); mpu.setYGyroOffset(0); mpu.setZGyroOffset(0); mpu6050Calibration(); // end message printf(" MPU-6050 calibration is complete!!\n\n"); printf("Move the board horizontally or vertically...\n"); printf("Type '1' and enter, to learn up <-> down motion\n"); printf("Type '2' and enter, to learn left <-> right motion\n"); printf("Type '0' and enter, to learn by category 0\n"); // main loop while (1) { if (pc.readable()) { input_key[0] = input_key[1]; input_key[1] = pc.getc(); if (input_key[1] == 0x0D) { // enter key learn_cat = input_key[0] - '0'; if (learn_cat < 3) { printf("Learning motion category %d\n", learn_cat); for (int i = 0; i < 5; i++) { extractFeatureVector(); ncount = hnn.learn(vector, MOTION_REPEAT_COUNT * MOTION_SIGNAL_COUNT, learn_cat); if (ncount != prev_ncount) { prev_cat = learn_cat; prev_ncount = ncount; } } printf("Neurons=%d\n", ncount); } } } else { // recognize extractFeatureVector(); hnn.classify(vector, MOTION_REPEAT_COUNT * MOTION_SIGNAL_COUNT, &dist, &cat, &nid); if (cat != 0xFFFF) { prev_cat = cat; if (cat & 0x8000) printf("Motion #%d (degenerated)\n", (cat & 0x7FFF)); else printf("Motion #%d \n", cat); } else if (prev_cat != 0xFFFF) { prev_cat = cat; } } } }