• 基于视觉识别的自动采摘机器人设计与实现


    一、前言

    1.1 项目介绍

    【1】项目功能介绍

    随着科技的进步和农业现代化的发展,农业生产效率与质量的提升成为重要的研究对象。其中,果蔬采摘环节在很大程度上影响着整个产业链的效益。传统的手工采摘方式不仅劳动强度大、效率低下,而且在劳动力成本逐渐上升的背景下,越来越难以满足大规模种植基地的需求。人工采摘还可能因不规范的操作导致果实损伤,影响商品果率。

    基于视觉识别技术的自动采摘机器人的研发,正是针对这一问题提出的创新解决方案。本项目采用树莓派4B作为主控芯片,因其具有强大的计算能力和丰富的扩展接口,可以方便地集成各种传感器和执行机构,实现对复杂环境下的实时图像采集与处理。

    项目利用百度飞浆(PaddlePaddle)深度学习框架中的目标检测和分类算法,通过安装在机器人上的高清摄像头获取果树图像,并进行实时分析,精准识别出果实的位置、大小以及成熟度等信息。当成功识别到目标果实后,主控系统将根据识别结果快速计算出机械手臂的最佳运动路径,控制其移动至指定位置,以最适宜的方式完成果实的高效、无损采摘。

    基于视觉识别的自动采摘机器人设计与实现项目旨在解决传统农业中人工采摘的瓶颈问题,通过人工智能与自动化技术的深度融合,提高果园管理的智能化水平,降低劳动成本,提高生产效率,从而推动我国乃至全球农业产业向更加智能、高效的现代农业转型。

    image-20240221234847550

    image-20240221234907193

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    【2】设计实现的功能

    (1)视觉识别:借助高性能的摄像头和图像处理算法(本项目采用百度飞浆的目标识别和分类算法),机器人能够捕捉到果园中的果实图像,并准确地从中识别出目标果实。

    (2)定位与导航:在识别到果实后,系统会通过计算果实的空间坐标和距离,确定机械手臂需要到达的精确位置。同时,机器人会根据果园内的环境信息和路径规划算法,自动导航至目标果实附近。

    (3)机械手臂控制:一旦机器人到达目标位置,机械手臂会在系统的精确控制下,自动调整姿态和动作,以轻柔而准确的方式采摘果实。这一过程涉及到复杂的机械动力学和协同控制算法,确保采摘动作的高效和安全。

    (4)果实收集与处理:采摘下来的果实会被机器人收集到专门的容器中,以便后续的分拣、包装和处理。系统还可以对采摘的果实进行数量统计和质量评估,为农业生产提供有价值的数据支持。

    本项目实现的功能是一个完整的自动采摘机器人系统,从视觉识别到机械手臂控制,再到果实收集与处理,形成了一个高效、智能的自动化采摘流程。这不仅大大提高了农业生产的效率和质量,也展示了人工智能技术在现代农业领域的广阔应用前景。

    【3】项目硬件模块组成

    (1)主控板:采用树莓派4B开发板作为整个系统的主控芯片。树莓派是一款功能强大且易于使用的计算机主板,具备高性能的处理器、充足的内存和存储空间,以及丰富的接口和扩展功能,可以满足本项目对计算和控制的需求。

    (2)视觉系统:视觉系统包括高性能的摄像头和图像处理单元。摄像头负责捕捉果园中的图像信息,而图像处理单元则基于百度飞浆的目标识别和分类算法,对图像进行处理和分析,以识别和定位目标果实。

    (3)机械手臂:机械手臂是实现自动采摘的关键部件,由多个关节和执行器组成,可以在三维空间内自由移动和旋转。通过精确的控制算法,机械手臂能够准确地到达目标果实的位置,并执行采摘动作。

    (4)传感器和导航系统:为了实现自动导航和精确定位,项目中还集成了多种传感器和导航系统。这些传感器可以感知环境信息,如距离、方位、障碍物等,而导航系统则根据这些信息规划出机器人的最佳路径。

    (4)电源和供电系统:为了保证机器人的持续工作,项目中还包括了电源和供电系统。电源负责为各个硬件模块提供稳定的电力供应,而供电系统则可以根据实际需要调整电力输出,以满足机器人在不同工作状态下的能耗需求。

    本项目的硬件模块组成包括主控板、视觉系统、机械手臂、传感器和导航系统、电源和供电系统以及其他辅助模块。这些硬件模块相互协作,共同实现了基于视觉识别的自动采摘机器人系统的功能。

    【3】功能总结

    系统集成了先进的视觉识别技术、机械手臂控制技术以及自动导航技术,能够自动识别和定位果园中的目标果实,并通过机械手臂完成采摘动作。整个过程无需人工干预,实现了果园采摘的自动化和智能化。

    功能包括果实的自动识别和定位、机械手臂的自动导航和控制以及果实的自动收集和处理。通过高性能的摄像头和图像处理算法,系统能够准确捕捉和识别目标果实的图像信息;借助精确的导航和控制算法,机械手臂能够自动导航至果实位置并完成采摘;最后,采摘下来的果实会被自动收集并进行后续处理。

    本项目的功能实现不仅提高了果园采摘的效率和准确性,降低了人力成本,同时也为农业生产的现代化和智能化发展提供了新的解决方案和思路。该系统的成功应用将为农业生产带来革命性的变革,推动农业向更高效、更环保、更可持续的方向发展。

    1.2 设计思路

    (1)需求分析:对果园采摘的实际需求进行分析,明确项目需要解决的问题和达到的目标。了解果园的环境特点、果实类型和生长状况,以及采摘作业的流程和要求,为后续设计提供基础依据。

    (2)技术选型:根据需求分析的结果,选择合适的技术方案。选用树莓派4B开发板作为主控芯片,利用其高性能的处理器和丰富的接口资源,实现机器人的控制和管理。同时,采用百度飞浆的目标识别和分类算法,通过视觉系统实现对目标果实的准确识别和定位。

    (3)硬件设计:根据技术选型,设计机器人的硬件结构。包括摄像头的选型和布局,确保能够捕捉到清晰、稳定的图像信息;机械手臂的设计和选型,使其能够适应果园环境和采摘需求;导航和传感器系统的设计和选型,实现机器人的自动导航和精确定位。

    (4)软件设计:编写机器人的控制程序和算法。通过图像处理算法实现对目标果实的识别和定位,将结果传递给导航和控制系统;根据导航和传感器系统提供的信息,规划机器人的运动路径和动作,控制机械手臂完成采摘动作;实现果实的计数、分类和收集等功能,以及数据的存储和传输。

    (5)系统集成与测试:将各个硬件模块和软件程序进行集成,并进行系统测试和调试。确保各个模块之间的通信和协作正常,机器人能够准确识别和采摘目标果实,并实现自动导航和收集等功能。

    1.3 系统功能总结

    功能模块功能描述
    视觉识别- 通过高性能摄像头捕捉果园图像
    - 利用百度飞浆的目标识别和分类算法,识别目标果实
    - 确定果实的空间坐标和距离
    导航与定位- 根据果园环境信息和路径规划算法,自动导航至目标果实附近
    - 集成多种传感器,感知环境信息,如距离、方位、障碍物等
    机械手臂控制- 在系统精确控制下,自动调整姿态和动作,采摘果实
    - 确保采摘动作的高效和安全
    果实收集与处理- 采摘下来的果实被自动收集到专门容器中
    - 对采摘的果实进行数量统计和质量评估
    - 提供数据支持,为农业生产决策提供参考
    通信与监控- 实现远程监控和控制功能

    二、树莓派4B环境搭建

    【1】硬件环境介绍

    树莓派是什么?Raspberry Pi(中文名为“树莓派”,简写为RPi,或者RasPi/RPi)是为学生计算机编程教育而设计,只有信用卡大小的卡片式电脑,其系统基于Linux。

    image-20230222220821492

    【2】资料下载

    第一步,先将树莓派4B需要使用的资料下载下来。

    image-20230222214743788

    【3】准备需要的配件

    (1)准备一张至少32G的TFT卡,用来烧写系统。

    (2)准备一个读卡器,方便插入TFT卡,好方便插入到电脑上拷贝系统

    (3)树莓派主板一个

    (4)一根网线(方便插路由器上与树莓派连接)

    (5)一根type-C的电源线。用自己Android手机的数据线就行,拿手机充电器供电。

    image-20230222215214788

    image-20230222215230700

    image-20230222215246793

    【4】准备烧写系统

    (1)安装镜像烧写工具

    image-20230222215354199

    image-20230222215404779

    (2)格式化SD卡

    将TFT卡通过读卡器插入到电脑上,将TFT卡格式化。

    image-20230222215625025

    image-20230222215701338

    (3)烧写系统

    **接下来准备烧写的系统是这一个系统:**将系统解压出来。

    image-20230222223022944

    然后打开刚才安装好的镜像烧写工具,在软件中选择需要安装的 img(镜像)文件,“Device”下选择SD的盘符,然后选择“Write”,然后就开始安装系统了,根据你的SD速度,安装过程有快有慢。

    注意:从网盘下载下来的镜像如果没有解压就先解压,释放出img文件。

    image-20230222220145324

    下面是烧写的流程:

    image-20230222220325807

    点击YES,开始烧写。

    image-20230222220347360

    烧写过程中:

    image-20230222220422721

    安装结束后会弹出完成对话框,说明安装就完成了,如果不成功,需要关闭防火墙一类的软件,重新插入SD进行安装。

    image-20230222222036811

    需要注意的是,安装完,windows系统下看到SD只有74MB了,这是正常现象,因为linux下的磁盘分区win下是看不到的。 烧录成功后windows系统可能会因为无法识别分区而提示格式化分区,此时**千万不要格式化!不要格式化!不要格式化!**点击取消,然后弹出内存卡,插入到树莓派上。

    image-20230222222207411

    至此,树莓派烧写成功。

    【5】启动系统

    (1)树莓派供电

    由于我买的树莓派开发板不带电源线,就采用Android手机的充电线供电。 使用Type-C供电时,要求电源头的参数要求,电压是5V,电流是3A。

    我的充电器是小米的120W有线快充,刚好满足要求。

    image-20230222221409160

    image-20230222221435491

    (2)启动树莓派(以Type-C供电示例)

    烧写完后把MicroSD卡直接插入树莓派的MicroSD卡插槽,如果有显示器就连接显示器,有DHMI线机也可以连接外接的显示器,有鼠标、键盘都可以插上去,就可以进入树莓派系统了。

    但是,我这块板子就一个主板,什么都没有。就拿网线将树莓派的网口与路由器连接。

    image-20230222223207997

    上电之后,开发板的指示灯会闪烁,说明已经启动。

    (3)查看开发板的IP地址

    现在板子没屏幕,想要连接板子,只能通过SSH远程登录的方式,当前烧写的这个系统默认开机就启动了SSH,所以只要知道开发板的IP地址就可以远程登录进去。

    **如何知道树莓派板子的IP地址?**方法很多,最简单是直接登录路由器的后台界面查看连接进入的设备。

    我使用的小米路由器,登录后台,看到了树莓派的IP地址。

    image-20230222223441177

    (4)SSH方式登录开发板

    当前烧写系统的登录账号和密码如下:

    账号:pi 密码:yahboom
    
    • 1

    打开SSH远程登录工具:PuTTY_0.67.0.0.exe

    image-20230222223700940

    输入IP地址和端口号,点击open。

    image-20230222223752958

    然后输入账号和密码。

    image-20230222223815162

    输入用户名 pi按下回车,然后再输入密码 yahboom。 注意:Linux下为了保护隐私,输入密码是不可见的,你只需要正常输入,按下回车键确定 即可。

    正常情况下,就登录成功了。

    image-20230222223840293

    接下来看看联网情况。 ping一下百度测试互联网是否畅通,因为接下来要在线安装软件包。

    ping www.baidu.com
    
    • 1

    image-20230222224200466

    可以看到网络没有问题。

    提示: 按下 Ctrl + C 可以终止命令行。 这算是Linux基础。

    【6】windows远程登录桌面

    为了方便图形化方式开发,可以使用windows系统通过远程桌面登录树莓派,就可以看到界面了,不过需要先安装工具。

    (1)安装xdrp

    在树莓派的命令行终端输入命令:

    sudo apt-get install xrdp
    
    • 1

    按下回车之后,会弹出确认窗口。输入 y之后,按下回车,继续安装。

    image-20230222224534775

    安装完毕:

    image-20230222224724318

    (2)打开windows远程桌面

    在windows电脑上打开运行命令的窗口,输入mstsc来打开远程桌面。

    image-20230222224920925

    打开远程桌面的窗口:

    image-20230222224953096

    (3)连接树莓派远程桌面

    打开远程桌面后,输入树莓派开发板的IP地址,点击连接。

    image-20230222225040460

    如果弹出窗口,就选择

    image-20230222225121454

    接下来就进入到树莓派开发板的远程桌面的登录窗口了。

    image-20230222225204850

    接下来输入面账号和密码。

    账号:pi 密码:yahboom
    
    • 1

    输入后点击OK按钮登录。

    image-20230222225405070

    正常情况下,就顺利的进入树莓派的桌面了。接下来就可以进行远程桌面开发了。

    image-20230222225519317

    【7】扩展树莓派SD卡可用空间

    树莓派系统默认启动时,树莓派默认没有把整个存储空间拓展到整张卡中,如果需要使用整个SD卡,这时候可以通过人为的把存储空间拓展到整张卡上。

    (1)查看内存使用情况

    打开命令行终端,输入df -h 命令。

    image-20230222225925276

    (2)扩展内存

    <1> 打开树莓派命令行终端输入:

    pi@raspberrypi:~ $ sudo raspi-config
    
    • 1

    <2> 在弹出的命令行里选择Advanced Options

    image-20230222230513705

    <3> 选择第一个选项。

    image-20230222230539460

    <4> 点击确定

    image-20230222230550004

    <5> 点击右边的Finish按钮保存退出。

    确定之后,关闭界面,系统会自动重启,重启之后,使用df命令查看是否扩展成功(我这里插的是32G的SD卡)。

    可以看到,我的系统已经扩展成功了,目前可以内存空间是19G。

    image-20230222230727040

    【8】树莓派连接WIFI

    (1)配置需要连接的WIFI

    点击右上角的数据连接图标,打开WIFI列表,点击想要的WIFI进行连接。

    image-20230302232003214

    输入密码:

    image-20230302232119543

    连接成功后的效果:

    image-20230302232504724

    (2)通过WIFI的IP地址登录远程桌面

    在路由器的后台可以看到,目前树莓派连入了两个IP地址。接下来把网线拔掉,使用WIFI无线也可以直接连接无线桌面,这样就不用插网线了。

    image-20230302232814697

    账号和密码:

    账号:pi 密码:yahboom
    
    • 1

    三、代码设计

    3.1 舵机控制代码(机械手臂控制)

    C语言代码: 使用wiringPi库控制树莓派上的GPIO引脚,实现对舵机的控制。通过servo_rotate()函数可以控制舵机旋转到指定的角度。在main()函数中,使用键盘输入获取目标角度,并调用servo_rotate()函数控制舵机旋转到目标角度。

    舵机的控制方式为PWM脉冲宽度调制,即将角度转换为脉宽值并输出对应的高低电平信号。将舵机信号线连接到GPIO18引脚,通过digitalWrite()函数输出高低电平来控制舵机旋转。

    #include 
    #include 
    
    #define SERVO_PIN 18 // SG90舵机信号线连接的GPIO引脚
    
    void servo_rotate(int angle) {
        int pulse_width = (angle * 11) + 500; // 将角度转换为脉宽值
        digitalWrite(SERVO_PIN, HIGH); // 输出高电平
        delayMicroseconds(pulse_width); // 延时脉宽值对应的时间
        digitalWrite(SERVO_PIN, LOW); // 输出低电平
        delay(20 - pulse_width / 1000); // 延时剩余时间
    }
    
    int main(void) {
        wiringPiSetupGpio(); // 初始化wiringPi库
        pinMode(SERVO_PIN, OUTPUT); // 将舵机信号线接口设为输出模式
    
        while(1) {
            // 从键盘输入目标角度
            printf("Enter the angle to rotate (0-180): ");
            fflush(stdout);
            int angle;
            scanf("%d", &angle);
    
            // 旋转到目标角度
            if(angle >= 0 && angle <= 180) {
                servo_rotate(angle);
            } else {
                printf("Invalid angle! Please enter an angle between 0 and 180.\n");
            }
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    Pyhon代码: 使用RPi.GPIO库来控制树莓派上的GPIO引脚,实现对舵机的控制。通过setup()函数进行初始化设置,并通过set_angle()函数控制舵机旋转到指定的角度。

    main()函数中,使用键盘输入获取目标角度,并调用set_angle()函数控制舵机旋转到目标角度。

    import RPi.GPIO as GPIO
    import time
    
    SERVO_PIN = 18  # SG90舵机信号线连接的GPIO引脚
    
    def setup():
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(SERVO_PIN, GPIO.OUT)
        global servo_pwm
        servo_pwm = GPIO.PWM(SERVO_PIN, 50)  # 创建PWM对象,频率设置为50Hz
        servo_pwm.start(0)  # 启动PWM输出,初始占空比设为0
    
    def set_angle(angle):
        duty_cycle = (angle / 18) + 2.5  # 将角度转换为占空比值
        servo_pwm.ChangeDutyCycle(duty_cycle)
        time.sleep(0.3)  # 等待舵机转到指定角度
    
    def main():
        setup()
    
        while True:
            # 从键盘输入目标角度
            angle = int(input("Enter the angle to rotate (0-180): "))
    
            # 旋转到目标角度
            if 0 <= angle <= 180:
                set_angle(angle)
            else:
                print("Invalid angle! Please enter an angle between 0 and 180.")
    
    if __name__ == '__main__':
        try:
            main()
        finally:
            servo_pwm.stop()  # 停止PWM输出
            GPIO.cleanup()  # 清理GPIO资源
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    3.2 调用算法识别目标

    (1)安装PaddlePaddle和PaddleDetection库:

    • 先安装Python和pip。然后,打开终端并执行以下命令安装PaddlePaddle和PaddleDetection库:

      pip install paddlepaddle paddlepaddle-gpu
      pip install paddlehub
      pip install paddlehub -i https://pypi.tuna.tsinghua.edu.cn/simple
      
      • 1
      • 2
      • 3

    (2)下载预训练模型:

    • 百度飞桨提供了预训练的目标检测模型,可以从PaddleDetection的GitHub页面下载这些模型。选择适合的任务的模型,并将其解压到合适的目录中。

    (3)编写调用代码:

    • 创建一个Python脚本文件,例如detect_fruits.py,并使用以下代码编写脚本:

      import paddlehub as hub
      import cv2
      
      def detect_fruits(image_path, model_path):
          # 加载模型
          module = hub.Module(name='yolov3_mobilenet_v1_coco2017')
          input_dict = {'image': [image_path]}
      
          # 目标检测
          results = module.object_detection(data=input_dict)
      
          # 处理结果
          for result in results:
              if len(result['data']) > 0:
                  for obj in result['data']:
                      label = obj['label']
                      confidence = obj['confidence']
                      left, top, right, bottom = obj['left'], obj['top'], obj['right'], obj['bottom']
                      print(f"Label: {label}, Confidence: {confidence:.2f}")
                      print(f"Bounding Box: ({left}, {top}), ({right}, {bottom})")
      
          # 可视化结果
          img = cv2.imread(image_path)
          for result in results:
              module.visualize(data=result, output_dir='output', score_thresh=0.5, use_visualize=True, visualization=True, plot_bbox=True, save_bbox_txt=True, image=img)
      
      if __name__ == '__main__':
          image_path = 'path/to/your/image.jpg'  # 替换为你的图片路径
          model_path = 'path/to/your/model'  # 替换为你的模型路径
          detect_fruits(image_path, model_path)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30

      在上面的代码中,使用PaddleHub库加载了预训练的yolov3_mobilenet_v1_coco2017模型,并将其应用于指定的图像。然后,处理检测结果并进行输出。最后,使用OpenCV库可视化结果并保存到指定目录中。

    (4)运行脚本:

    • 将目标果实图像放置在与脚本相同的目录下(或根据需要修改图像路径)。然后,在终端中执行以下命令运行脚本:

      python detect_fruits.py
      
      • 1

    脚本将分析图像并输出检测到的目标果实的标签、置信度和边界框。会生成一个带有目标果实标注的图像。

    3.3 机器人小车控制代码

    小车的电机驱动采用L298N模块,连接在GPIO17、GPIO18、GPIO27和GPIO22上。 使用了wiringPi库来控制树莓派上的GPIO引脚,实现对小车电机驱动的控制。通过setup()函数进行初始化设置,并通过forward()backward()turn_left()turn_right()函数控制小车前进、后退和转弯。其中,stop()函数用于停止小车运动。

    #include 
    
    #define MOTOR_ENA_PIN 0  // L298N模块ENA引脚连接的GPIO引脚
    #define MOTOR_ENB_PIN 2  // L298N模块ENB引脚连接的GPIO引脚
    #define MOTOR_IN1_PIN 3  // L298N模块IN1引脚连接的GPIO引脚
    #define MOTOR_IN2_PIN 4  // L298N模块IN2引脚连接的GPIO引脚
    #define MOTOR_IN3_PIN 5  // L298N模块IN3引脚连接的GPIO引脚
    #define MOTOR_IN4_PIN 6  // L298N模块IN4引脚连接的GPIO引脚
    
    void setup() {
        wiringPiSetup();  // 初始化wiringPi库
        pinMode(MOTOR_ENA_PIN, OUTPUT);
        pinMode(MOTOR_ENB_PIN, OUTPUT);
        pinMode(MOTOR_IN1_PIN, OUTPUT);
        pinMode(MOTOR_IN2_PIN, OUTPUT);
        pinMode(MOTOR_IN3_PIN, OUTPUT);
        pinMode(MOTOR_IN4_PIN, OUTPUT);
    }
    
    void forward() {
        digitalWrite(MOTOR_IN1_PIN, HIGH);
        digitalWrite(MOTOR_IN2_PIN, LOW);
        digitalWrite(MOTOR_IN3_PIN, LOW);
        digitalWrite(MOTOR_IN4_PIN, HIGH);
        digitalWrite(MOTOR_ENA_PIN, HIGH);
        digitalWrite(MOTOR_ENB_PIN, HIGH);
    }
    
    void backward() {
        digitalWrite(MOTOR_IN1_PIN, LOW);
        digitalWrite(MOTOR_IN2_PIN, HIGH);
        digitalWrite(MOTOR_IN3_PIN, HIGH);
        digitalWrite(MOTOR_IN4_PIN, LOW);
        digitalWrite(MOTOR_ENA_PIN, HIGH);
        digitalWrite(MOTOR_ENB_PIN, HIGH);
    }
    
    void turn_left() {
        digitalWrite(MOTOR_IN1_PIN, LOW);
        digitalWrite(MOTOR_IN2_PIN, HIGH);
        digitalWrite(MOTOR_IN3_PIN, LOW);
        digitalWrite(MOTOR_IN4_PIN, HIGH);
        digitalWrite(MOTOR_ENA_PIN, HIGH);
        digitalWrite(MOTOR_ENB_PIN, HIGH);
    }
    
    void turn_right() {
        digitalWrite(MOTOR_IN1_PIN, HIGH);
        digitalWrite(MOTOR_IN2_PIN, LOW);
        digitalWrite(MOTOR_IN3_PIN, HIGH);
        digitalWrite(MOTOR_IN4_PIN, LOW);
        digitalWrite(MOTOR_ENA_PIN, HIGH);
        digitalWrite(MOTOR_ENB_PIN, HIGH);
    }
    
    void stop() {
        digitalWrite(MOTOR_ENA_PIN, LOW);
        digitalWrite(MOTOR_ENB_PIN, LOW);
    }
    
    int main() {
        setup();
    
        while (1) {
            // 从键盘输入指令
            char cmd = getchar();
            getchar();  // 忽略回车符
    
            // 根据指令执行动作
            switch (cmd) {
                case 'w':  // 前进
                    forward();
                    break;
                case 's':  // 后退
                    backward();
                    break;
                case 'a':  // 左转
                    turn_left();
                    break;
                case 'd':  // 右转
                    turn_right();
                    break;
                case 'x':  // 停止
                    stop();
                    break;
                default:
                    break;
            }
        }
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    四、总结

    随着农业技术的不断进步,自动化、智能化已成为现代农业生产的重要趋势。本项目通过结合视觉识别技术、机器人技术和自动化控制技术,成功设计并实现了基于视觉识别的自动采摘机器人系统。这一创新性的成果不仅提高了果园采摘的效率和准确性,降低了人力成本,还为农业生产的现代化和智能化发展提供了新的解决方案和思路。

  • 相关阅读:
    【Git】使用git上传项目到github
    不得不会的Oracle数据库知识点(三)
    小程序中的权限设计
    万界星空科技低代码平台云MES系统功能场景
    腾讯数字孪生和To B简介
    Python高光谱遥感数据处理与机器学习实践技术
    【C++】1085:球弹跳高度的计算(信息学奥赛)
    distinct 和 group by有什么区别
    “第六十四天” 字扩展和位扩展,外部存储器
    对接Web Services接口
  • 原文地址:https://blog.csdn.net/xiaolong1126626497/article/details/136337918