前提
就像人类一样,植物也可能染病,比如植物的叶子可能会因真菌或其他病原体而发黄或出现斑点。因此,通过机器学习的力量,可以扫描颜色,然后将其用于训练一个模型,该模型可以检测叶子的颜色并对其健康状态作出判断。
硬件
这个项目主要用Arduino Nano 33 BLE Sense,它之所以被选中主要是它具有一组功能强大的传感器,包括9DoF IMU,APDS-9960(颜色,手势,接近度和亮度),麦克风以及温度/湿度/压力传感器组合。为了使电路板围绕植物的叶子移动并进行测量,将一对步进电机与一对DRV8825驱动器板配合使用。
设置TinyML
对于此项目,列出的针对Arduino Nano 33 BLE Sense on Edge Impulse的内置传感器将不起作用,这意味着将我们必须使用data forwarder而不是serial daemon。
首先,创建一个新项目并将其命名。接下来需要通过Node.js以及NPM来安装EdgeImpulse CLI。然后运行:
npm install -g edge-impulse-cli
如果找不到安装路径,则可能需要将其安装路径添加到PATH环境变量中。接下来,运行
edge-impulse-data-forwarder
并确保其有效,然后按Ctrl + C退出。
颜色识别
APDS-9960的工作原理是:通过物体表面所反射的光线波长来读取颜色。为了与传感器通信,最好安装Arduino APDS9960库,该库可以访问一些有用的功能。
在代码中,首先初始化APDS-9960,然后程序进入循环功能,等待直到有颜色数据出现。如果有读数,则使用
APDS.readColor()
以及与表面的接近程度来读取颜色。每个RGB分量都从0-2 ^ 16-1数转换为其值与总和的比率。
扫描仪
扫描叶子的颜色是通过在两个轴上移动装备以使叶子在车载APDS-9960下方经过的各个位置进行的。通过沿顺时针或逆时针方向旋转丝杠来移动每个轴,以使程序段沿任一方向平移。整个系统是在Fusion 360中设计的,下面是这些设计的一些渲染图:
X轴位于Y轴的顶部,从而使顶部程序段在两个轴上移动。Y轴上有一个附加的V轮,以支撑步进电机的重量。零件是使用PLA打印的,填充量约为45%。
收集数据
当系统首次启动时,步进电机是不知道它的初始位置的,因此我们必须进行原点复位,(可通过限位开关实现)。接下来初始化APDS-9960。有一个定义为两个元素的数组的边界框,它们包含一个框的相对角。在这两个位置之间选择一个随机点,然后将步进器运行到该位置,同时读取它们之间的颜色。
处理和发送颜色信息
如前所述,使用
APDS.readColor()
来读取颜色。计算总和后,将计算百分比,然后通过调用
Serial.printf()
的方法通过USB发送百分比。值用逗号分隔,每个读数用换行符分隔。数据转发器程序接收到数据后,会将其作为带有给定标签(健康或不健康)的训练数据发送到Edge Impulse云端。
训练模型
收集完所有训练数据后,就该建立一个可以区分健康叶子和不健康叶子的模型了。我使用了由三轴时间序列,频谱分析模块和Keras模块组成的脉冲。查看以下屏幕截图可以了解我如何从数据中生成这些功能:
测验
为了测试新模型,这次我收集了一些新的测试数据,这是不健康的。该模型的准确性约为63%,并且在通过一些测试功能后,能够在大多数时间正确地对叶子进行分类。
可以通过添加更多训练数据并减慢训练速度来提高此准确性。
代码
#include 《Arduino_APDS9960.h》#include 《AccelStepper.h》#include 《MultiStepper.h》#include “pinDefs.h” int r, g, b, c, p;
float sum;
AccelStepper xStepper(AccelStepper::DRIVER, STEPPER_1_STEP, STEPPER_1_DIR);
AccelStepper yStepper(AccelStepper::DRIVER, STEPPER_2_STEP, STEPPER_2_DIR);
MultiStepper steppers;// a random location will be chosen within the bounding box
const long boundingBox[2][2] = { {0,0}, {40,40}};
void setup(){ Serial.begin(115200); while(!Serial);
if(!APDS.begin()) { Serial.println(“Could not init APDS9960”); while(1); }
pinMode(X_AXIS_HOMING_SW, INPUT_PULLUP); pinMode(Y_AXIS_HOMING_SW, INPUT_PULLUP); //Serial.println(digitalRead(X_AXIS_HOMING_SW) + digitalRead(Y_AXIS_HOMING_SW)); xStepper.setPinsInverted(X_AXIS_DIR); yStepper.setPinsInverted(Y_AXIS_DIR); xStepper.setMaxSpeed(150); yStepper.setMaxSpeed(150); steppers.addStepper(xStepper); steppers.addStepper(yStepper); homeMotors();}
void loop(){ long randomPos[2]; randomPos[0] = random(boundingBox[0][0], boundingBox[1][0]) * STEPS_PER_MM; randomPos[1] = random(boundingBox[0][1], boundingBox[1][1]) * STEPS_PER_MM; steppers.moveTo(randomPos);
while(steppers.run()) { if(!APDS.colorAvailable() || !APDS.proximityAvailable()){} else { APDS.readColor(r, g, b, c); sum = r + g + b; p = APDS.readProximity();
if(!p && c 》 10 && sum 》= 0) { float rr = r / sum, gr = g / sum, br = b / sum; Serial.printf(“%1.3f,%1.3f,%1.3f
”, rr, gr, br); } } }}
void homeMotors(){ // home x //Serial.println(“Now homing x”); while(digitalRead(X_AXIS_HOMING_SW))
xStepper.move(-1);
// home y //Serial.println(“Now homing y”); while(digitalRead(Y_AXIS_HOMING_SW)) yStepper.move(-1); xStepper.setCurrentPosition(0); yStepper.setCurrentPosition(0);}
原理图
原文标题:Arduino使用TinyML扫描植物的叶子确定植物的健康
文章出处:【微信公众号:FPGA入门到精通】欢迎添加关注!文章转载请注明出处。
责任编辑:haq
全部0条评论
快来发表一下你的评论吧 !