6回答

1收藏

[原创] 【Curie Nano试用】 A5.Curie神经元算法库--CurieNeurons

DFROBOT DFROBOT 6972 人阅读 | 6 人回复 | 2017-05-16

CurieNeurons,即Curie神经元。Neurons能通过示例学习,不用编程,可以通过数据离线学习。
general vision提供了两个版本可供下载,免费版和收费19美刀的专业版。
下载地址:http://www.general-vision.com/software/curieneurons/


为了尝鲜我们先体验一下免费版吧,
CurieNeurons.zip (1.08 MB, 下载次数: 25)

相关的文档:
Curie Final ppt.pdf (9.29 MB, 下载次数: 14)

TM_CurieNeuronsLibrary.pdf (490.75 KB, 下载次数: 10)

TM_NeuroMem_API.pdf (363.66 KB, 下载次数: 8)

TM_NeuroMem_Technology_Reference_Guide.pdf (627.26 KB, 下载次数: 12)






详细的信息可以看文档里的介绍,这里我们就直接切入正题了。
需要的材料很简单,Curie Nano板和一块AD Keyborad板。
这个AD Keyborad DFROBOT商城有卖,不过太贵了买不起,好在提供原理图,我手工做了一个。
5个按键只占用一个模拟IO口,很巧妙的设计。





这里VCC接3.3V,IO口接A5。


示例代码:
  1. /*
  2. Name:                CurieNeurons_andIMU2.0.ino
  3. Created:        7/21/2016 11:08:34 AM
  4. Author:        HansYang
  5. */


  6. #include <CurieIMU.h>
  7. #include <BMI160.h>
  8. #include <CurieNeurons.h>
  9. #include <stdlib.h>
  10. #define DEBUG1
  11. #define ACC_FEATURE_ONLY
  12. #define MANUAL_SCALING

  13. #ifdef ACC_FEATURE_ONLY
  14. #define SAMPLENBR 3  
  15. #else
  16. #define SAMPLENBR 6
  17. #endif // ACC_FEATURE_ONLY

  18. #define MAX_SAMPLING_TIME 3000//ms
  19. #define SAMPLING_INTERVAL 50//ms
  20. #define MAX_VECTOR_LEN 60//MAX_SAMPLING_TIME/SAMPLING_INTERVAL

  21. #define DOWNSAMPLER_SEGS 10

  22. //ADkeyboard
  23. int adc_key_val[5] = { 850,900, 940, 960, 980 };
  24. #define NUM_KEYS 5
  25. int adc_key_in;
  26. int key = -1;

  27. //CurieNeurons
  28. CurieNeurons hNN;
  29. int cat, prevcat;
  30. int dist, nid;

  31. //IMU data
  32. int16_t ax, ay, az;
  33. int16_t gx, gy, gz;

  34. int minax, minay, minaz, maxax, maxay, maxaz;
  35. int mingx, mingy, mingz, maxgx, maxgy, maxgz;
  36. int Sax, Say, Saz, Sgx, Sgy, Sgz;

  37. //Others
  38. uint64_t timer;
  39. short vector_len;
  40. byte vector[MAX_VECTOR_LEN*SAMPLENBR];
  41. byte pattern[SAMPLENBR * 17];
  42. byte learnflag;

  43. void feature_extraction(byte* src_vector, int src_len, byte *dst_vector)
  44. {
  45.         int seg_len = src_len / (DOWNSAMPLER_SEGS * SAMPLENBR);
  46.         double res[17 * SAMPLENBR];
  47.         for (int icol = 0; icol < SAMPLENBR; icol++)
  48.         {
  49.                 int sum = 0;
  50.                 for (int i = 0; i < src_len; i++)
  51.                 {
  52.                         sum += src_vector[i*SAMPLENBR + icol];
  53.                 }
  54.                 //mean
  55.                 int aver = sum / src_len;
  56.                 int e = 0;
  57.                 int mad = 0;
  58.                 //int rms = 0;
  59.                 //byte max = src_vector[icol];
  60.                 //byte min = src_vector[icol];
  61.                 int ratiocount[5] = { 0 };
  62.                 for (int i = 0; i < src_len; i++)
  63.                 {
  64.                         e += (src_vector[i*SAMPLENBR + icol] - aver)*(src_vector[i*SAMPLENBR + icol] - aver);
  65.                         mad += abs(src_vector[i*SAMPLENBR + icol] - aver);
  66.                         //rms += src_vector[i*SAMPLENBR + icol] * src_vector[i*SAMPLENBR + icol];
  67.                         //if (src_vector[i*SAMPLENBR + icol] > max)
  68.                         //        max = src_vector[i*SAMPLENBR + icol];
  69.                         //if (src_vector[i*SAMPLENBR + icol] < min)
  70.                         //        min = src_vector[i*SAMPLENBR + icol];
  71.                         if (src_vector[i*SAMPLENBR + icol] <= 200)
  72.                         {
  73.                                 if (src_vector[i*SAMPLENBR + icol] <= 150)
  74.                                 {
  75.                                         if (src_vector[i*SAMPLENBR + icol] <= 100)
  76.                                         {
  77.                                                 if (src_vector[i*SAMPLENBR + icol] <= 50)
  78.                                                 {
  79.                                                         ratiocount[4]++;
  80.                                                 }
  81.                                                 else
  82.                                                         ratiocount[3]++;
  83.                                         }
  84.                                         else
  85.                                                 ratiocount[2]++;
  86.                                 }
  87.                                 else
  88.                                         ratiocount[1]++;
  89.                         }
  90.                         else
  91.                                 ratiocount[0]++;
  92.                 }
  93.                 //standard deviation
  94.                 res[icol] = sqrt(e / (src_len - 1)) * 2;
  95.                 //MAD
  96.                 res[icol + 1 * SAMPLENBR] = mad / src_len * 2;
  97.                 //RMS
  98.                 //res[icol + 3 * SAMPLENBR] = sqrt(rms / src_len);
  99.                 for (int i = 0; i < 5; i++)
  100.                 {
  101.                         res[icol * 5 + 6 + i] = 0;//ratiocount[i];// * 255 / src_len;
  102.                 }

  103.                 for (int iseg = 0; iseg < DOWNSAMPLER_SEGS; iseg++)
  104.                 {
  105.                         int sum = 0;
  106.                         for (int ismp = 0; ismp < seg_len; ismp++)
  107.                         {
  108.                                 int offset = icol + (iseg * seg_len + ismp)*SAMPLENBR;
  109.                                 sum += (int)src_vector[offset];
  110.                                 src_vector[offset] = 0;
  111.                         }
  112.                         res[20 + icol * DOWNSAMPLER_SEGS + iseg] = sum / seg_len;
  113.                 }
  114.         }

  115.         for (int i = 0; i < SAMPLENBR * 17; i++)
  116.         {
  117.                 pattern[i] = (int)(res[i] + 0.5) * 0x00FF;
  118.         }

  119. #ifdef DEBUG1
  120.         Serial.print("\n");
  121.         for (int i = 0; i < SAMPLENBR*17; i++)
  122.         {
  123.                 Serial.print(pattern[i]);
  124.                 Serial.print("\t");
  125.         }
  126.         //Serial.print("\n");
  127. #endif // DEBUG1

  128. }

  129. int get_key(unsigned int input)        //1 2 3 4 5
  130. {
  131.         int k;
  132.         for (k = 0; k < NUM_KEYS; k++)
  133.         {
  134.                 if (input < adc_key_val[k])
  135.                 {
  136.                         return k + 1;
  137.                 }
  138.         }
  139.         if (k >= NUM_KEYS)
  140.                 k = -1;  // No valid key pressed
  141.         return k + 1;
  142. }

  143. void read_data_once()
  144. {
  145.         CurieIMU.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  146.         /*int R = sqrt(ax*ax + ay*ay + az*az);

  147.         double tX = acos(ax / R);
  148.         double tY = acos(ay / R);
  149.         double tZ = acos(az / R);

  150.         ax = ax - 8192 * cos(tX);
  151.         ay = ay - 8192 * cos(tY);
  152.         az = ax - 8192 * cos(tZ);*/
  153.         
  154.         vector[vector_len*SAMPLENBR + 0] = (byte)(((ax - minax) * 255 / Sax) & 0x00FF);
  155.         vector[vector_len*SAMPLENBR + 1] = (byte)(((ay - minay) * 255 / Say) & 0x00FF);
  156.         vector[vector_len*SAMPLENBR + 2] = (byte)(((az - minaz) * 255 / Saz) & 0x00FF);
  157. #ifndef ACC_FEATURE_ONLY
  158.         vector[vector_len*SAMPLENBR + 3] = (byte)(((gx - mingx) * 255 / Sgx) & 0x00FF);
  159.         vector[vector_len*SAMPLENBR + 4] = (byte)(((gy - mingy) * 255 / Sgy) & 0x00FF);
  160.         vector[vector_len*SAMPLENBR + 5] = (byte)(((gz - mingz) * 255 / Sgz) & 0x00FF);
  161. #endif // !ACC_FEATURE_ONLY               

  162.         /*vector[vector_len*SAMPLENBR + 0] = ax;
  163.         vector[vector_len*SAMPLENBR + 1] = ay;
  164.         vector[vector_len*SAMPLENBR + 2] = az;
  165. #ifndef ACC_FEATURE_ONLY
  166.         vector[vector_len*SAMPLENBR + 3] = gx;
  167.         vector[vector_len*SAMPLENBR + 4] = gy;
  168.         vector[vector_len*SAMPLENBR + 5] = gz;
  169. #endif // !ACC_FEATURE_ONLY                */

  170.         if (vector_len < (MAX_VECTOR_LEN - 2)*SAMPLENBR ) {
  171.                 vector_len++;
  172.                 Serial.print("*");
  173.         }
  174.         else
  175.         {
  176.                 Serial.print("O");
  177.         }
  178. }

  179. // the setup function runs once when you press reset or power the board
  180. void setup() {
  181.         Serial.begin(9600);
  182.         while (!Serial);

  183.         Serial.print("CurieNeurons initializing...");
  184.         hNN.begin();
  185.         hNN.forget();
  186.         Serial.println("Done");

  187.         Serial.print("CurieIMU initializing...");
  188.         CurieIMU.begin();
  189.         Serial.println("Done");

  190.         Serial.println("Initializing IMU device...");
  191.         CurieIMU.begin();

  192.         // use the code below to calibrate accel/gyro offset values
  193.         Serial.println("Internal sensor offsets BEFORE calibration...");
  194.         Serial.print(CurieIMU.getXAccelOffset());
  195.         Serial.print("\t"); // -76
  196.         Serial.print(CurieIMU.getYAccelOffset());
  197.         Serial.print("\t"); // -235
  198.         Serial.print(CurieIMU.getZAccelOffset());
  199.         Serial.print("\t"); // 168
  200.         Serial.print(CurieIMU.getXGyroOffset());
  201.         Serial.print("\t"); // 0
  202.         Serial.print(CurieIMU.getYGyroOffset());
  203.         Serial.print("\t"); // 0
  204.         Serial.println(CurieIMU.getZGyroOffset());

  205.         Serial.println("About to calibrate. Make sure your board is stable and upright");
  206.         delay(2000);

  207.         // The board must be resting in a horizontal position for
  208.         // the following calibration procedure to work correctly!
  209.         Serial.print("Starting Gyroscope calibration...");
  210.         CurieIMU.autoCalibrateGyroOffset();
  211.         Serial.println(" Done");
  212.         Serial.print("Starting Acceleration calibration...");
  213.         CurieIMU.autoCalibrateXAccelOffset(0);
  214.         CurieIMU.autoCalibrateYAccelOffset(0);
  215.         CurieIMU.autoCalibrateZAccelOffset(1);
  216.         Serial.println(" Done");

  217.         Serial.println("Internal sensor offsets AFTER calibration...");
  218.         Serial.print(CurieIMU.getXAccelOffset());
  219.         Serial.print("\t"); // -76
  220.         Serial.print(CurieIMU.getYAccelOffset());
  221.         Serial.print("\t"); // -2359
  222.         Serial.print(CurieIMU.getZAccelOffset());
  223.         Serial.print("\t"); // 1688
  224.         Serial.print(CurieIMU.getXGyroOffset());
  225.         Serial.print("\t"); // 0
  226.         Serial.print(CurieIMU.getYGyroOffset());
  227.         Serial.print("\t"); // 0
  228.         Serial.println(CurieIMU.getZGyroOffset());

  229.         Serial.println("Enabling Gyroscope/Acceleration offset compensation");
  230.         CurieIMU.setGyroOffsetEnabled(true);
  231.         CurieIMU.setAccelOffsetEnabled(true);

  232.         CurieIMU.setAccelerometerRange(4);
  233.         //hNN.GCR(128);                        //LSUP distance
  234.         //hNN.MAXIF(600);

  235. #ifdef MANUAL_SCALING

  236.         minax = minay = minaz = maxax = maxay = maxaz = -32768;
  237.         mingx = mingy = mingz = maxgx = maxgy = maxgz = 32767;
  238.         Sax = Say = Saz = Sgx = Sgy = Sgz = 65535;

  239. #else
  240.         Serial.println("\nAssessing the amplitude of motions...Press any key to continue");
  241.         adc_key_in = analogRead(5);
  242.         while (adc_key_in > 980)
  243.         {
  244.                 adc_key_in = analogRead(5);
  245.                 CurieIMU.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  246.                 if (ax>maxax) maxax = ax; if (ax<minax) minax = ax;
  247.                 if (ay>maxay) maxay = ay; if (ay<minay) minay = ay;
  248.                 if (az>maxaz) maxaz = az; if (az<minaz) minaz = az;
  249.                 if (gx>maxgx) maxgx = gx; if (gx<mingx) mingx = gx;
  250.                 if (gy>maxgy) maxgy = gy; if (gy<mingy) mingy = gy;
  251.                 if (gz>maxgz) maxgz = gz; if (gz<mingz) mingz = gz;
  252.         }
  253.         Sax = maxax - minax;
  254.         Say = maxay - minay;
  255.         Saz = maxaz - minaz;
  256.         Sgx = maxgx - mingx;
  257.         Sgy = maxgy - mingy;
  258.         Sgz = maxgz - mingz;
  259.         Serial.print("\nSa :\t"); Serial.print(Sax); Serial.print(","); Serial.print(Say); Serial.print(","); Serial.print(Saz);
  260.         Serial.print("\nSg :\t"); Serial.print(Sgx); Serial.print(","); Serial.print(Sgy); Serial.print(","); Serial.println(Sgz);
  261. #endif

  262.         timer = 0;
  263.         prevcat = 0x7FFF;
  264.         learnflag = 0;

  265.         Serial.print("The program will begin in 2 seconds...\n");
  266.         delay(2000);
  267.         Serial.println("Start.");


  268. }

  269. // the loop function runs over and over again until power down or reset
  270. void loop() {

  271.         timer = millis();
  272.         adc_key_in = analogRead(5);
  273.         key = get_key(adc_key_in);

  274.         if (key!=0)
  275.         {
  276.                 learnflag = key;
  277.                 read_data_once();
  278.         }
  279.         else if (learnflag != 0)
  280.         {
  281.                 read_data_once();
  282.                 feature_extraction(vector, vector_len, pattern);
  283.                 //downsampler_means(vector, vector_len, pattern, SAMPLENBR*DOWNSAMPLER_SEGS);
  284. #ifdef DEBUG
  285.                 Serial.print("\n");
  286.                 for (int i = 0; i < SAMPLENBR*DOWNSAMPLER_SEGS; i++)
  287.                 {
  288.                         Serial.print(pattern[i]);
  289.                         Serial.print("\t");
  290.                 }
  291.                 Serial.print("\n");
  292. #endif //DEBUG
  293.                 if (learnflag != 5)
  294.                 {
  295.                         hNN.learn(pattern, SAMPLENBR * 17, learnflag);
  296.                         Serial.print("\nLearned motion #");
  297.                         Serial.print(learnflag);
  298.                         Serial.println("once, please repeat.");
  299.                 }
  300.                 else
  301.                 {
  302.                         int res = hNN.classify(pattern, SAMPLENBR * 17, &dist, &cat, &nid);
  303.                         cat &= 0x00FF;
  304.                         if (res != 0)
  305.                         {
  306.                                 Serial.print("\nMotion Detected. #"); Serial.println(cat);
  307.                         }
  308.                         else
  309.                         {
  310.                                 Serial.println("\nMotion Unknow.");
  311.                         }
  312.                 }
  313.                 learnflag = 0;
  314.                 vector_len = 0;
  315.         }
  316.         while ((millis() - timer) < SAMPLING_INTERVAL);
  317. }
复制代码
编译示例代码并上传到Curie Nano中,打开串口工具,并将开发板平放等待陀螺仪自动校准。如图所示:


动作学习:
按住黄色、绿色、蓝色或者红色按键做动作,动作完成松手。黄色对应动作1,绿色对应动作2,蓝色对应动作3,红色对应动作4。
每种动作可以多做几次,这样识别的准确率会高一些。
下图是我按住黄色按键1和绿色按键2完成的动作识别。


识别动作:
按住中间的白色按键5,做出刚才的动作,程序会识别属于刚才的哪个动作。
如下图所示,如果做出的动作不是刚才的两种之一会显示未知。


动作的采样时间可以在以下的语句修改,但是时间越来复杂度也就越高,识别的准确率也就越低。

程序说明:
在这个过程中,主要是采用按键按下作为动作的开始,松开表示动作的结束,再将采样的动作进行数据分析,再由CurieNeurons神经网络进行学习。识别动作的方式同理。

关注下面的标签,发现更多相似文章
分享到:
回复

使用道具 举报

回答|共 6 个

倒序浏览

沙发

slotg

发表于 2017-5-16 23:40:39 | 只看该作者

这个有意思,感谢分享。
板凳

噗噗熊

发表于 2017-5-17 09:37:23 | 只看该作者

这个好有意思!
地板

我叫逗逗

发表于 2017-5-17 09:46:19 | 只看该作者

楼主什么时候买收费版,不知道收费版可不可以共享?
5#

limale

发表于 2017-5-17 09:46:28 | 只看该作者

slotg 发表于 2017-5-16 23:40
这个有意思,感谢分享。

谢谢支持              
6#

limale

发表于 2017-5-17 09:47:21 | 只看该作者

噗噗熊 发表于 2017-5-17 09:37
这个好有意思!

这个板子确实有好多好玩的地方。
7#

limale

发表于 2017-5-17 09:50:17 | 只看该作者

我叫逗逗 发表于 2017-5-17 09:46
楼主什么时候买收费版,不知道收费版可不可以共享?

看了一下介绍,专业版识别算法准确率高一些。楼主没有这方面的需求,暂时不会考虑买专业版。
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条