精华内容
下载资源
问答
  • 行业分类-金融管理-智能钱箱追踪管理系统.zip
  • 行业分类-物流装置-一种物流环节智能追踪分析系统.zip
  • 本小车系统主要基于一片IAP15F2K61S2单片机实现功能。整个系统可分为四个部分,核心控制部分、信息探测部分、动作执行部分和辅助部分。
  • 行业分类-网络游戏-实现基于网络的物件智能追踪的方法.zip
  • 行业分类-设备装置-智能追踪式太阳能百叶窗
  • 行业分类-化学冶金-基于调光膜和舵机的防强光智能追踪保护装置及其方法.zip
  • 行业分类-物理装置-一种网点内智能肢体识别及追踪方法.zip
  • 行业分类-电子电器-一种网点内智能肢体识别及追踪方法.zip
  • 行业分类-电子-一种人体红外追踪智能电风扇.zip
  • 行业分类-电子-关于人体红外追踪智能电风扇的说明分析.rar
  • 行业分类-物理装置-一种集成瞳孔追踪功能的全息智能显示装置及实现方法.zip
  • 行业分类-外包设计-智能柔性包装机.zip
  • 智能车教程(红外、蓝牙、OpenMV追踪

    千次阅读 多人点赞 2019-04-14 03:20:56
    文章目录动手制作一个智能小车小车功能设计你需要懂的知识、你能学到什么材料准备组装小车制作红外小车制作蓝牙小车制作追踪颜色小车将三个功能集成,制作智能小车项目总结 动手制作一个智能小车 小车功能设计 你...

    动手制作一个智能小车教程未完成

    能亲手制作智能车、机器人,大概是我们每一位marker都想实现的事情,那么今天我们就来看看如何制作一辆可以红外、蓝牙控制,并且可以用openmv摄像头实时追踪色块的智能车吧。


    1.小车功能设计

    现在我们手上有一套智能车模型套件、红外遥控器及传感器、蓝牙模块、一块OpenMV摄像头模块。

    • 首先,要快速完成一辆小车的制作,我们可以选用智能车模型套件,直接拼装成智能车,这可以节省我们不少设计的功夫,将精力放在功能实现上面。
    • 其次,我们可以使用红外遥控和红外接收模块,对小车进行红外控制;
    • 再次,我们可以通过蓝牙模块,通过手机app,蓝牙远程遥控智能车;
    • 最后,车子要做到智能,那必不可少的就是图像识别,我们可以使用OpenMV摄像头对颜色进行实时识别和跟踪。

    那就让我们开始实现以上的想法吧,JUST DO IT

    2.应用学到那些知识

    做这个项目之前,你需要有:

    • 一点基础的编程语法知识(任何语言)
    • 一颗耐心和创客的激情

    做完这个项目,你可以掌握:

    • 电机驱动板L298N的使用方法
    • arduino的使用方法
    • 红外模块的使用方法
    • 蓝牙模块HC-05的调试方法
    • 手机控制蓝牙的方法
    • OpenMV摄像头模块颜色识别的方法
    • OpenMV与arduino板子通信的方法

    3.材料准备

    1.智能车部分:模型套件,如下图
    通用智能车模型套件
    2.控制电路部分:如下表

    材料数量
    arduino模块1块
    L298N电机驱动模块1块
    红外接收模块1块
    红外遥控器1件
    蓝牙模块1块
    USB转TTL模块(可选)1块
    OpenMV3 摄像头模块1块
    9-12V电源(博主使用三节18560串联,推荐)1件
    杜邦线若干
    螺丝、螺母、铜柱若干
    热熔胶枪1把
    螺丝刀套件1套
    L298N电机驱动模块1块
    焊烙铁(可选)1件
    剥线钳(可选)1把
    电压表(可选)1件
    android手机(使用软件)1部

    3.摄像头部分:OpenMV摄像头模块,如下图
    在这里插入图片描述

    4.组装小车

    按照说明书装配小车模型。
    电子模块我是如下图安装的,当然大家可以按照自己的习惯安装。
    注意:

    • 导线可以先不接,之后可以根据每一次实现的功能再接
    • 连接OpenMV的支架为博主自行切割的,大家可以动手自己设计支架

    在这里插入图片描述

    小车各模块安装示意图

    在这里插入图片描述

    小车各模块实际安装图

    5.制作红外小车

    准备工作都做好了,那我们开始动手制作最简单的红外小车吧。

    1. 如下图连接杜邦线
      在这里插入图片描述
    红外小车连线图
    1. 电路原理
      1. 红外接收器
      2. L298N电机驱动板
      3. 电源选择
      4. Arduino UNO引脚分类与供电方式
    2. 打开Arduino开发环境并添加库文件,如未安装,点击这里
    3. 上传代码
    //红外小车代码及解释
    #include <IRremote.h>//打开IDE:项目→加载库→添加→搜索IRremote→安装IRredmote库
    int RECV_PIN = 11;//红外接收端口
    IRrecv irrecv(RECV_PIN);
    decode_results results;//结构声明
    
    //==============================
    int Left_motor_back=3;     //左电机后退(IN1)
    int Left_motor_go=4;     //左电机前进(IN2)
    
    int Right_motor_go=9;    // 右电机前进(IN3)
    int Right_motor_back=10;    // 右电机后退(IN4)
    
    void setup()
    {
      //初始化电机驱动IO为输出方式
      pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM)
      pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM)
      pinMode(Right_motor_go,OUTPUT);// PIN 9 (PWM) 
      pinMode(Right_motor_back,OUTPUT);// PIN 10 (PWM)
      pinMode(13, OUTPUT);端口模式,输出
      Serial.begin(9600);   //波特率9600
      irrecv.enableIRIn(); // Start the receiver
    }
    void run()     // 前进
    {
      digitalWrite(Right_motor_go,HIGH);  // 右电机前进
      digitalWrite(Right_motor_back,LOW);     
      digitalWrite(Left_motor_go,HIGH);  // 左电机前进
      digitalWrite(Left_motor_back,LOW);
    }
    
    void brake()         //刹车,停车
    {
      digitalWrite(Right_motor_go,LOW);
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);
      digitalWrite(Left_motor_back,LOW);
    }
    
    void left()         //左转(左轮不动,右轮前进)
    {
      digitalWrite(Right_motor_go,HIGH);    // 右电机前进
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);   //左轮不动
      digitalWrite(Left_motor_back,LOW);
    }
    
    void spin_left()         //左转(左轮后退,右轮前进)
    {
      digitalWrite(Right_motor_go,HIGH);    // 右电机前进
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);   //左轮后退
      digitalWrite(Left_motor_back,HIGH);
    }
    
    void right()        //右转(右轮不动,左轮前进)
    {
      digitalWrite(Right_motor_go,LOW);   //右电机不动
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,HIGH);//左电机前进
      digitalWrite(Left_motor_back,LOW);
    }
    
    void spin_right()        //右转(右轮后退,左轮前进)
    {
      digitalWrite(Right_motor_go,LOW);   //右电机后退
      digitalWrite(Right_motor_back,HIGH);
      digitalWrite(Left_motor_go,HIGH);//左电机前进
      digitalWrite(Left_motor_back,LOW);
    }
    
    void back()          //后退
    {
      digitalWrite(Right_motor_go,LOW);  //右轮后退
      digitalWrite(Right_motor_back,HIGH);
      digitalWrite(Left_motor_go,LOW);  //左轮后退
      digitalWrite(Left_motor_back,HIGH);
    }
    
    //=============================================================================
    //读取各个按键需要用到这段代码
    //=============================================================================
    
    void read_key()
    {
        if(irrecv.decode(&results)){  //如果接收到信息
            Serial.print("code:");
            Serial.println(results.value,HEX);//results.value为16进制,unsigned long
            Serial.print("bits:");
            Serial.println(results.bits);//输出元位数
            irrecv.resume();
          } 
    }
    
    
    
    void loop()
    {
      read_key();
      if(irrecv.decode(&results)){  //如果接收到信息
       switch(results.value){
         case 0xFF18E7:  //前,对应2
           run();
           break;
         case 0xFF4AB5:  //后,对应8
           back();
           break;
         case 0xFF10EF:  //左,对应4
           left();
           break;
         case 0xFF5AA5:  //右,对应6
           right();
           break;
         case 0xFF38C7:  //停止,对应5
           brake();
           break;
         default:
           break;
       }
      irrecv.resume();
      }
    }
    
    1. 测试成果
      在这里插入图片描述
    红外小车实际控制

    6.添加蓝牙控制功能

    1. 如下图连接杜邦线
      在这里插入图片描述
    蓝牙小车连线图
    1. 电路原理及注意
      1. HC-05蓝牙模块原理
      2. 蓝牙模块与Arduino交叉连接(即蓝牙RX连接板子TX、蓝牙TX连接板子RX)
      3. 此处红外模块无需拆下,红外接线对蓝牙功能没有影响,正好同时使用两种功能
    2. 上传代码
    //蓝牙小车代码及解释
    #include <IRremote.h>//打开IDE:项目→加载库→添加→搜索IRremote→安装IRredmote库
    int RECV_PIN = 11;//红外接收端口
    IRrecv irrecv(RECV_PIN);
    decode_results results;//结构声明
    
    //==============================
    int Left_motor_back=3;     //左电机后退(IN1)
    int Left_motor_go=4;     //左电机前进(IN2)
    
    int Right_motor_go=9;    // 右电机前进(IN3)
    int Right_motor_back=10;    // 右电机后退(IN4)
    
    void setup()
    {
      //初始化电机驱动IO为输出方式
      pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM)
      pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM)
      pinMode(Right_motor_go,OUTPUT);// PIN 9 (PWM) 
      pinMode(Right_motor_back,OUTPUT);// PIN 10 (PWM)
      pinMode(13, OUTPUT);端口模式,输出
      Serial.begin(9600);   //波特率9600
      irrecv.enableIRIn(); // Start the receiver
    }
    void run()     // 前进
    {
      digitalWrite(Right_motor_go,HIGH);  // 右电机前进
      digitalWrite(Right_motor_back,LOW);     
      digitalWrite(Left_motor_go,HIGH);  // 左电机前进
      digitalWrite(Left_motor_back,LOW);
    }
    
    void brake()         //刹车,停车
    {
      digitalWrite(Right_motor_go,LOW);
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);
      digitalWrite(Left_motor_back,LOW);
    }
    
    void left()         //左转(左轮不动,右轮前进)
    {
      digitalWrite(Right_motor_go,HIGH);    // 右电机前进
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);   //左轮不动
      digitalWrite(Left_motor_back,LOW);
    }
    
    void spin_left()         //左转(左轮后退,右轮前进)
    {
      digitalWrite(Right_motor_go,HIGH);    // 右电机前进
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);   //左轮后退
      digitalWrite(Left_motor_back,HIGH);
    }
    
    void right()        //右转(右轮不动,左轮前进)
    {
      digitalWrite(Right_motor_go,LOW);   //右电机不动
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,HIGH);//左电机前进
      digitalWrite(Left_motor_back,LOW);
    }
    
    void spin_right()        //右转(右轮后退,左轮前进)
    {
      digitalWrite(Right_motor_go,LOW);   //右电机后退
      digitalWrite(Right_motor_back,HIGH);
      digitalWrite(Left_motor_go,HIGH);//左电机前进
      digitalWrite(Left_motor_back,LOW);
    }
    
    void back()          //后退
    {
      digitalWrite(Right_motor_go,LOW);  //右轮后退
      digitalWrite(Right_motor_back,HIGH);
      digitalWrite(Left_motor_go,LOW);  //左轮后退
      digitalWrite(Left_motor_back,HIGH);
    }
    
    //=============================================================================
    //读取各个按键需要用到这段代码
    //=============================================================================
    
    void read_key()
    {
        if(irrecv.decode(&results)){  //如果接收到信息
            Serial.print("code:");
            Serial.println(results.value,HEX);//results.value为16进制,unsigned long
            Serial.print("bits:");
            Serial.println(results.bits);//输出元位数
            irrecv.resume();
          } 
    }
    
    
    
    void loop()
    {
      read_key();
      if(irrecv.decode(&results)){  //如果接收到信息
       switch(results.value){
         case 0xFF18E7:  //前,对应2
           run();
           break;
         case 0xFF4AB5:  //后,对应8
           back();
           break;
         case 0xFF10EF:  //左,对应4
           left();
           break;
         case 0xFF5AA5:  //右,对应6
           right();
           break;
         case 0xFF38C7:  //停止,对应5
           brake();
           break;
         default:
           break;
       }
      irrecv.resume();
      }
      //蓝牙控制
      if(Serial.available()>0){
          char ch = Serial.read();
          if(ch == '1'){
             //前进
             run();
             Serial.print("前进");
          }else if(ch == '2'){
             //后退
             back();
             Serial.print("后退");
          }else if(ch == '3'){
             //左转
             left();
             Serial.print("左转");
          }else if(ch == '4'){
            //右转
            right();
            Serial.print("右转");
          }else if(ch=='0'){
            //停车
            brake();
            Serial.print("停车");
          }
        }
    }
    
    1. 手机安装蓝牙控制app 1,连接蓝牙,控制小车
      1. 下载安装软件
      2. 小车通电
      3. 打开软件,点击左下角连接小车蓝牙
      4. 控制小车
    2. 测试成果
      在这里插入图片描述
    蓝牙小车实际控制

    7.添加OpenMV颜色追踪功能

    1. 如下图连接杜邦线
      在这里插入图片描述
    2. 电路原理及注意
      1. OpenMV教程参考1参考2(需要先学习)
      2. 此项目是将OpenMV3作为从设备,Arduino作为主设备控制电机的
    3. 上传代码

    Arduino代码

       /*
     * 蓝牙串口指令规定
     * 改变运行模式:红外:I(默认)、蓝牙:B、openmv:O
     * 蓝牙控制参数设置:前进:1、后退:2、左转:3、右转:4、停车:0、油门:5、刹车:6
     */
    #include <IRremote.h>
    #include <Wire.h>
    #define BAUD_RATE 9600
    #define CHAR_BUF 128
    float left_speed = 1.1;
    float right_speed = 1.1;
    char buff[CHAR_BUF] = {0};
    int RECV_PIN = 11;//红外接收端口
    IRrecv irrecv(RECV_PIN);
    decode_results results;//结构声明
    char mode = 'I';  //设置小车运行模式,默认红外模式
    int Left_motor_back=3;     //左电机后退(IN1)
    int Left_motor_go=4;     //左电机前进(IN2)
    int Right_motor_go=9;    // 右电机前进(IN3)
    int Right_motor_back=10;    // 右电机后退(IN4)
    int ENA = 5;      //PWM输入A
    int ENB = 6;      //PWM输入B
    int speed_default = 100;    //0-255之间,小车最低速度为70,最佳速度为100
    char ch;
    bool inverse_left=false;
    bool inverse_right=false;
    
    void setup()
    {
      //初始化电机驱动IO为输出方式
      pinMode(Left_motor_go,OUTPUT); // PIN 5 (PWM)
      pinMode(Left_motor_back,OUTPUT); // PIN 6 (PWM)
      pinMode(Right_motor_go,OUTPUT);// PIN 9 (PWM) 
      pinMode(Right_motor_back,OUTPUT);// PIN 10 (PWM)
      pinMode(ENA,OUTPUT);
      pinMode(ENB,OUTPUT);
      pinMode(13, OUTPUT);端口模式,输出
      Serial.begin(BAUD_RATE);   //波特率9600
      irrecv.enableIRIn(); // Start the receiver
      Wire.begin();
      delay(1000); // 给OpenMV一个启动的时间
    }
    void run()     // 前进
    {
      digitalWrite(Right_motor_go,HIGH);  // 右电机前进
      digitalWrite(Right_motor_back,LOW);     
      digitalWrite(Left_motor_go,HIGH);  // 左电机前进
      digitalWrite(Left_motor_back,LOW);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    void brake()         //刹车,停车
    {
      digitalWrite(Right_motor_go,LOW);
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);
      digitalWrite(Left_motor_back,LOW);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    void left()         //左转(左轮不动,右轮前进)
    {
      digitalWrite(Right_motor_go,HIGH);    // 右电机前进
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);   //左轮不动
      digitalWrite(Left_motor_back,LOW);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    void spin_left()         //左转(左轮后退,右轮前进)
    {
      digitalWrite(Right_motor_go,HIGH);    // 右电机前进
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,LOW);   //左轮后退
      digitalWrite(Left_motor_back,HIGH);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    void right()        //右转(右轮不动,左轮前进)
    {
      digitalWrite(Right_motor_go,LOW);   //右电机不动
      digitalWrite(Right_motor_back,LOW);
      digitalWrite(Left_motor_go,HIGH);//左电机前进
      digitalWrite(Left_motor_back,LOW);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    void spin_right()        //右转(右轮后退,左轮前进)
    {
      digitalWrite(Right_motor_go,LOW);   //右电机后退
      digitalWrite(Right_motor_back,HIGH);
      digitalWrite(Left_motor_go,HIGH);//左电机前进
      digitalWrite(Left_motor_back,LOW);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    void back()          //后退
    {
      digitalWrite(Right_motor_go,LOW);  //右轮后退
      digitalWrite(Right_motor_back,HIGH);
      digitalWrite(Left_motor_go,LOW);  //左轮后退
      digitalWrite(Left_motor_back,HIGH);
      analogWrite(ENA,speed_default);
      analogWrite(ENB,speed_default);
    }
    
    //=============================================================================
    //读取各个按键需要用到这段代码
    //=============================================================================
    
    void read_key()
    {
        if(irrecv.decode(&results)){  //如果接收到信息
            Serial.print("code:");
            Serial.println(results.value,HEX);//results.value为16进制,unsigned long
            Serial.print("bits:");
            Serial.println(results.bits);//输出元位数
            irrecv.resume();
          } 
    }
    
    //=============================================================================
    //处理字符串buff
    //============================================================================
    
    void getCode(){    //buff经过传输,尾部有干扰,故用两个空格分割
      String temp1,temp2;
      String string = String(buff);
      int postion = string.indexOf(" ");
      temp1 = string.substring(0,postion);
      string = string.substring(postion+1,string.length());
      postion = postion = string.indexOf(" ");
      temp2 = string.substring(0,postion);
      left_speed = temp1.toFloat();
      right_speed = temp2.toFloat();
    }
    //=============================================================================
    //PWM模式的小车运动
    //============================================================================
    void openmvrun(){
      if(inverse_left) 
        left_speed=-left_speed;
      if(inverse_right)
        right_speed=-right_speed;
    
      int l_speed = abs(left_speed);
      int r_speed = abs(right_speed);
      
    
       if(left_speed<0){
         digitalWrite(Left_motor_go,LOW);   //左轮后退
         digitalWrite(Left_motor_back,HIGH);
       }else{
         digitalWrite(Left_motor_go,HIGH);//左电机前进
         digitalWrite(Left_motor_back,LOW);
       }
       analogWrite(ENA,l_speed);
    
       if(right_speed<0){
         digitalWrite(Right_motor_go,LOW);  //右轮后退
         digitalWrite(Right_motor_back,HIGH);
       }else{
         digitalWrite(Right_motor_go,HIGH);    // 右电机前进
         digitalWrite(Right_motor_back,LOW);
       }
       analogWrite(ENB,r_speed);
       
       Serial.print(l_speed);
       Serial.print(" ");
       Serial.print(r_speed);
    }
    
    void loop()
    {
      
      if(Serial.available()>0){
          ch = Serial.read();
          if(ch == 'I'){
            //红外模式
            mode = 'I';
          }else if(ch == 'B'){
            //蓝牙模式
            mode = 'B';
          }else if(ch == 'O'){
            //openmv模式
            mode = 'O';
          }
      }
      if(mode == 'I'){     //红外模式控制代码
        //Serial.println("红外模式");
        read_key();
        if(irrecv.decode(&results)){  //如果接收到信息
          Serial.println(results.value);
          switch(results.value){
           case 0xFF18E7:  //前,对应2
             run();
             break;
           case 0xFF4AB5:  //后,对应8
             back();
             break;
           case 0xFF10EF:  //左,对应4
             left();
             break;
           case 0xFF5AA5:  //右,对应6
             right();
             break;
           case 0xFF38C7:  //停止,对应5
             brake();
             break;
           default:
             break;
          }
          irrecv.resume();
        }
      }
    
      if(mode == 'B'){   //蓝牙模式控制代码
        //Serial.println("蓝牙模式");
        char ch1 = '0';
        if(ch == '1'){
             //前进
             run();
             Serial.print("前进");
          }else if(ch == '2'){
             //后退
             back();
             Serial.print("后退");
          }else if(ch == '3'){
             //左转
             left();
             Serial.print("左转");
          }else if(ch == '4'){
            //右转
            right();
            Serial.print("右转");
          }else if(ch=='0'){
            //停车
            brake();
            Serial.print("停车");
          }else if(ch=='5'){
            speed_default +=5;
            ch = ch1;
          }else if(ch=='6'){
            speed_default -=5;
            ch = ch1;
          }
          ch1 = ch;
          Serial.println(speed_default);
      }
    
      if(mode == 'O'){      //openmv模式控制代码
        //Serial.println("openmv模式");
        int32_t temp = 0; 
        Wire.requestFrom(0x12, 2);
        if (Wire.available() == 2) { // got length?  
          temp = Wire.read() | (Wire.read() << 8);
          delay(1); // Give some setup time... 
          Wire.requestFrom(0x12, temp);
          if (Wire.available() == temp) { // got full message? 
            temp = 0;
            while (Wire.available()) buff[temp++] = Wire.read();  
          } else {
            while (Wire.available()) Wire.read(); // Toss garbage bytes.
          }
        } else {
          while (Wire.available()) Wire.read(); // Toss garbage bytes.
        }
      
        //Serial.println(buff);
        getCode();
        //Serial.println(left_speed+"  "+"right_speed="+right_speed);
        //Serial.print(left_speed);
        //Serial.print(" ");
        //Serial.print(right_speed);
        openmvrun();
        delay(1); // Don't loop to quickly.
      }
    }
    

    OpenMV代码

    #car.py
    # Arduino 作为I2C主设备, OpenMV作为I2C从设备。
    #
    # 请把OpenMV和Arduino按照下面连线:
    #
    # OpenMV Cam Master I2C Data  (P5) - Arduino Uno Data  (A4)
    # OpenMV Cam Master I2C Clock (P4) - Arduino Uno Clock (A5)
    # OpenMV Cam Ground                - Arduino Ground
    
    import pyb, ustruct
    import ujson
    from pyb import Pin, Timer
    
    text = "Hello World!\n"
    data = ustruct.pack("<%ds" % len(text), text)
    # 使用 "ustruct" 来生成需要发送的数据包
    # "<" 把数据以小端序放进struct中
    # "%ds" 把字符串放进数据流,比如:"13s" 对应的 "Hello World!\n" (13 chars).
    # 详见 https://docs.python.org/3/library/struct.html
    
    # READ ME!!!
    #
    # 请理解,当您的OpenMV摄像头不是I2C主设备,所以不管是使用中断回调,
    # 还是下方的轮循,都可能会错过响应发送数据给主机。当这种情况发生时,
    # Arduino会获得NAK,并且不得不从OpenMV再次读数据。请注意,
    # OpenMV和Arduino都不擅长解决I2C的错误。在OpenMV和Arduino中,
    # 你可以通过释放I2C外设,再重新初始化外设,来恢复功能。
    
    # OpenMV上的硬件I2C总线都是2
    bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
    bus.deinit() # 完全关闭设备
    bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
    print("Waiting for Arduino...")
    
    
    
    # 请注意,为了正常同步工作,OpenMV Cam必须 在Arduino轮询数据之前运行此脚本。
    # 否则,I2C字节帧会变得乱七八糟。所以,保持Arduino在reset状态,
    # 直到OpenMV显示“Waiting for Arduino...”。
    
    def run(left_speed, right_speed):
        data = str(left_speed)+" "+str(right_speed)+" "
        try:
            #print(data)
            bus.send(ustruct.pack("<h", len(data)), timeout=10000) # 首先发送长度 (16-bits).
            try:
                bus.send(data, timeout=10000) # 然后发送数据
                print("Sent Data!") # 没有遇到错误时,会显示
            except OSError as err:
                pass # 不用担心遇到错误,会跳过
                # 请注意,有3个可能的错误。 超时错误(timeout error),
                # 通用错误(general purpose error)或繁忙错误
                #(busy error)。 “err.arg[0]”的错误代码分别
                # 为116,5,16。
        except OSError as err:
            pass # 不用担心遇到错误,会跳过
            # 请注意,有3个可能的错误。 超时错误(timeout error),
            # 通用错误(general purpose error)或繁忙错误
            #(busy error)。 “err.arg[0]”的错误代码分别
            # 为116,5,16。
    
    #pid.py
    from pyb import millis
    from math import pi, isnan
    
    class PID:
        _kp = _ki = _kd = _integrator = _imax = 0
        _last_error = _last_derivative = _last_t = 0
        _RC = 1/(2 * pi * 20)
        def __init__(self, p=0, i=0, d=0, imax=0):
            self._kp = float(p)
            self._ki = float(i)
            self._kd = float(d)
            self._imax = abs(imax)
            self._last_derivative = float('nan')
    
        def get_pid(self, error, scaler):
            tnow = millis()
            dt = tnow - self._last_t
            output = 0
            if self._last_t == 0 or dt > 1000:
                dt = 0
                self.reset_I()
            self._last_t = tnow
            delta_time = float(dt) / float(1000)
            output += error * self._kp
            if abs(self._kd) > 0 and dt > 0:
                if isnan(self._last_derivative):
                    derivative = 0
                    self._last_derivative = 0
                else:
                    derivative = (error - self._last_error) / delta_time
                derivative = self._last_derivative + \
                                         ((delta_time / (self._RC + delta_time)) * \
                                            (derivative - self._last_derivative))
                self._last_error = error
                self._last_derivative = derivative
                output += self._kd * derivative
            output *= scaler
            if abs(self._ki) > 0 and dt > 0:
                self._integrator += (error * self._ki) * scaler * delta_time
                if self._integrator < -self._imax: self._integrator = -self._imax
                elif self._integrator > self._imax: self._integrator = self._imax
                output += self._integrator
            return output
        def reset_I(self):
            self._integrator = 0
            self._last_derivative = float('nan')
    
    
    #main.py
    # Blob Detection Example
    #
    # This example shows off how to use the find_blobs function to find color
    # blobs in the image. This example in particular looks for dark green objects.
    
    import sensor, image, time
    import car
    from pid import PID
    
    # You may need to tweak the above settings for tracking green things...
    # Select an area in the Framebuffer to copy the color settings.
    
    sensor.reset() # Initialize the camera sensor.
    sensor.set_pixformat(sensor.RGB565) # use RGB565.
    sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
    sensor.skip_frames(10) # Let new settings take affect.
    sensor.set_auto_whitebal(False) # turn this off.
    clock = time.clock() # Tracks FPS.
    
    # For color tracking to work really well you should ideally be in a very, very,
    # very, controlled enviroment where the lighting is constant...
    green_threshold   = (42, 80, 28, 127, -22, 55)   # 颜色阈值,不同物体需要修改
    size_threshold = 2000               #小球距离
    x_pid = PID(p=0.1, i=0.2, imax=30)     # 方向参数p
    h_pid = PID(p=0.01, i=0.1, imax=100)    # 速度参数p
    
    def find_max(blobs):                #找到视野中最大的色块,即最大的小球
        max_size=0
        for blob in blobs:
            if blob[2]*blob[3] > max_size:
                max_blob=blob
                max_size = blob[2]*blob[3]
        return max_blob
    
    while(True):
        clock.tick() # Track elapsed milliseconds between snapshots().
        img = sensor.snapshot() # Take a picture and return the image.
    
        blobs = img.find_blobs([green_threshold])
        if blobs:
            max_blob = find_max(blobs)
            x_error = max_blob[5]-img.width()/2    #色块的外框的中心x坐标blob[5]
            h_error = max_blob[2]*max_blob[3]-size_threshold
            #色块的外框的宽度blob[2],色块的外框的高度blob[3]
            print("x error: ", x_error)   #打印 x 轴误差  用于转弯
            print("h error: ", h_error)   #打印 距离误差  用于速度
            '''
            for b in blobs:
                # Draw a rect around the blob.
                img.draw_rectangle(b[0:4]) # rect
                img.draw_cross(b[5], b[6]) # cx, cy
            '''
            img.draw_rectangle(max_blob[0:4]) # rect
            img.draw_cross(max_blob[5], max_blob[6]) # cx, cy
            x_output=x_pid.get_pid(x_error,1)
            h_output=h_pid.get_pid(h_error,1)    #h_error调整后的值
            print("x_output",x_output)
            print("h_output",h_output)
    
            car.run(-h_output-x_output,-h_output+x_output)
            print(-h_output-x_output,-h_output+x_output)
        else:
            car.run(0,0)
    
    
    
    1. 测试成果
      在这里插入图片描述
    OpenMV颜色追踪小车实际控制

    8.项目总结

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    1. 此款app是根据@单片机菜鸟(博哥)蓝牙小车项目的app基础上修改。博哥在创客、esp8266、软件编程等领域都是令人钦佩的一位技术大拿,有开源精神,向他学习! ↩︎

    展开全文
  • 创客小制作(含源代码)《RFID控制器》,用于智能门禁、物流追踪、控制物品等,基于Arduino 目录创客小制作(含源代码)《RFID控制器》,用于智能门禁、物流追踪、控制物品等,基于Arduino准备RFID简介舵机介绍思路制作...

    创客小制作(含源代码)《RFID控制器》,用于智能门禁、物流追踪、控制物品等,基于Arduino

    准备

    RFID简介

    射频识别即RFID(Radio Frequency IDentification)技术,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需建立机械或光学接触。有低频(125k~134.2K)、高频(13.56Mhz)、超高频,微波等技术。RFID读写器也分移动式的和固定式的,目前RFID技术应用很广,如:图书馆,门禁系统,食品安全溯源等。

    RFID的工作原理:标签进入磁场后,接收解读器发出的射频信号,凭借感应电流所获得的能量发送出存储在芯片中的产品信息(Passive Tag,无源标签或被动标签),或者由标签主动发送某一频率的信号(Active Tag,有源标签或主动标签),解读器读取信息并解码后,送至中央信息系统进行有关数据处理。

    舵机介绍

    舵机是一种位置伺服的驱动器,其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度为1.5ms 的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。经由电路板上的IC 判断转动方向,再驱动无核心马达开始转动,透过减速齿轮将动力传至摆臂,同时由位置检测器送回信号,判断是否已经到达定位。适用于那些需要角度不断变化并可以保持的控制系统。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。一般舵机旋转的角度范围是0 度到180 度。

    思路

    智能门禁

    基于arduino与RFID,可通过RFID技术识别读入IC卡的序号并与设定的序号比较符合则使用舵机打开门禁,由于不同门禁的需要可选择不同的控制器代替舵机,如电磁开关、继电器,红外线发射装置。

    物流追踪
    关于物流跟踪,使用RFID技术识别读入IC卡的序号并报告给系统即可,其他内容本篇文章暂时讨论

    控制物品
    思路与智能门禁类似,可通过RFID技术识别读入IC卡的序号根据设定执行相关操作,如流水线上的两种产品贴上两种不同的无线射频标签,RFID技术识别后执行两种不同的操作(如放入不同流水线中),通过电磁开关、继电器,红外线发射等实现。

    制作

    材料

    1. Arduino
    2. RFID
    3. IC卡
    4. 舵机
    5. 杜邦线

    可选材料

    1. LCD1002(显示)
    2. 继电器
    3. 电磁开关
    4. 红外线发射模块

    接线

    RFID对应Arduino UNO

    RFID模块Arduino UNO
    VCC3.3V
    RST5V
    GNDGND
    MISO12
    MOSI11
    SCK13
    NSS10
    IRQ(不接)

    舵机
    所有的舵机都有外接三根线,分别用棕、红、橙三种颜色进行区分,由于舵机品牌不同,颜色也会有所差异,棕色为接地线,红色为电源正极线,橙色为信号线

    感谢阅读

    持续更新arduino 树莓派 python linux c语言等等
    接到有帮助的话 求点赞👍 求关注❤️ 求分享👥
    有问题可以评论
    点关注,不迷路
    如果有任何错误,如何建议,请批评指教,不胜感激 !

    源代码(三个版本)

    对代码有疑问可评论

    智能门禁

    这里以控制舵机为例子,如有需要显示可加上lcd1602详细可前往我的另一篇博客

    Arduino实践(二)lcd1602使用说明,源码

    /*
    RFID模块  Arduino UNO
    VCC      3.3V
    RST    5V
    GND   GND
    MISO    12
    MOSI   11
    SCK   13
    NSS   10
    IRQ   (不接)
    舵机
    黄色   信号线
    红色   5v
    棕色   地级
    
     */
    
    
    /*舵机*/
    #include <Servo.h>
    #include <SPI.h>
    #include <MFRC522.h>
     
    #define SS_PIN 10
    #define RST_PIN 9
     
    MFRC522 rfid(SS_PIN, RST_PIN); //实例化类
    int relayPin = 6; //继电器引脚
    int key = 7;//按键引脚
    int incomedate = 0;//设置变量
    String refid1="";
    
    // 初始化数组用于存储读取到的NUID 
    byte nuidPICC[4];
    
    
    Servo myservo;  //创建一个舵机控制对象
                              // 使用Servo类最多可以控制8个舵机
    int pos = 90;    // 该变量用与存储舵机角度位置
    void setup() { 
       myservo.attach(8);  // 该舵机由arduino第九脚控制
      pinMode(key,INPUT_PULLUP);//按键为上拉输入
       pinMode(relayPin, OUTPUT);
      Serial.begin(9600);
      SPI.begin(); // 初始化SPI总线
      rfid.PCD_Init(); // 初始化 MFRC522 
    }
     
    void loop() {
      myservo.write(0);
       
      if (digitalRead(key)==LOW) 
       {delay(100);
       if (digitalRead(key)==LOW) incomedate = !incomedate;}
      
        if ((incomedate == 0))
        {
          digitalWrite(relayPin, HIGH);
         
        } 
        else if ((incomedate == 1))
        {
          digitalWrite(relayPin, LOW);
        
        }
     
      // 找卡
      if ( ! rfid.PICC_IsNewCardPresent())
       {    delay(500);
            if ( ! rfid.PICC_IsNewCardPresent())
               {incomedate = 1;
                return;}
        }
     
      // 验证NUID是否可读
      if ( ! rfid.PICC_ReadCardSerial())
        return;
     
      MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
     
      // 检查是否MIFARE卡类型
      if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
        piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
        piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println("不支持读取此卡类型");
        return;
      }
      
      // 将NUID保存到nuidPICC数组
      for (byte i = 0; i < 4; i++) {
        nuidPICC[i] = rfid.uid.uidByte[i];
      }   
      Serial.print("十六进制UID:");
      printHex(rfid.uid.uidByte, rfid.uid.size);
      Serial.println();
      
      Serial.print("十进制UID:");
      printDec(rfid.uid.uidByte, rfid.uid.size);
      Serial.println();
      if((refid1=="1214519892")||(refid1=="73217151153"))    
        {   
          incomedate = 0;
        //判断为真,执行需要的程序。
        Serial.println("已验证");
        myservo.write(pos);        // 指定舵机转向的角度
        delay(3000);                       // 等待15ms让舵机到达指定位置
        myservo.write(0);
          }
        else
        {
          //判断为假,执行需要的程序。
          Serial.println("验证失败");
          }
    
    
      
      // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡
    / rfid.PICC_HaltA();
     
      // 停止读卡模块编码
    /  rfid.PCD_StopCrypto1();
      refid1="";
      /* if (rfid.uid.uidByte, rfid.uid.size==183624630) 
       { incomedate = !incomedate;}
       */
        
       if ((incomedate == 0))
        {
          digitalWrite(relayPin, HIGH);
        
        } 
        else if ((incomedate == 1))
        {
          digitalWrite(relayPin, LOW);
        
        }
    }
      void printHex(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : "");
        Serial.print(buffer[i], HEX);
        refid1+=nuidPICC[i];
      }
    }
      void printDec(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : "");
        Serial.print(buffer[i], DEC);
        
      }
      
    }
    
    

    物流追踪

    /*RFID模块*/
    /*
    
    
    RFID模块  Arduino UNO
    VCC      3.3V
    RST    5V
    GND   GND
    MISO    12
    MOSI   11
    SCK   13
    NSS   10
    IRQ   (不接)
    
     
     */
    
    #include <SPI.h>
    #include <MFRC522.h>
     
    #define SS_PIN 10
    #define RST_PIN 9
     
    MFRC522 rfid(SS_PIN, RST_PIN); //实例化类
     
    // 初始化数组用于存储读取到的NUID 
    byte nuidPICC[4];
     
    void setup() { 
      Serial.begin(9600);
      SPI.begin(); // 初始化SPI总线
      rfid.PCD_Init(); // 初始化 MFRC522 
    }
     
    void loop() {
     
      // 找卡
      if ( ! rfid.PICC_IsNewCardPresent())
        return;
     
      // 验证NUID是否可读
      if ( ! rfid.PICC_ReadCardSerial())
        return;
     
      MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
     
      // 检查是否MIFARE卡类型
      if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
        piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
        piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println("不支持读取此卡类型");
        return;
      }
      
      // 将NUID保存到nuidPICC数组
      for (byte i = 0; i < 4; i++) {
        nuidPICC[i] = rfid.uid.uidByte[i];
      }   
      Serial.print("十六进制UID:");
      printHex(rfid.uid.uidByte, rfid.uid.size);
      Serial.println();
      
      Serial.print("十进制UID:");
      printDec(rfid.uid.uidByte, rfid.uid.size);
      Serial.println();
      
      // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡
      rfid.PICC_HaltA();
     
      // 停止读卡模块编码
      rfid.PCD_StopCrypto1();
    }
     
    void printHex(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : "");
        Serial.print(buffer[i], HEX);
      }
    }
     
    void printDec(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : "");
        Serial.print(buffer[i], DEC);
      }
    }
    

    控制继电器

    /*
    
    
    RFID模块  Arduino UNO
    VCC      3.3V
    RST    5V
    GND   GND
    MISO    12
    MOSI   11
    SCK   13
    NSS   10
    IRQ   (不接)
    
     
     */
    
    
    
    #include <SPI.h>
    #include <MFRC522.h>
     
    #define SS_PIN 10
    #define RST_PIN 9
     
    MFRC522 rfid(SS_PIN, RST_PIN); //实例化类
    int relayPin = 6; //继电器引脚
    int key = 7;//按键引脚
    int incomedate = 0;//设置变量
    String refid1="";
     
    // 初始化数组用于存储读取到的NUID 
    byte nuidPICC[4];
     
    void setup() { 
      pinMode(key,INPUT_PULLUP);//按键为上拉输入
       pinMode(relayPin, OUTPUT);
      Serial.begin(9600);
      SPI.begin(); // 初始化SPI总线
      rfid.PCD_Init(); // 初始化 MFRC522 
    }
     
    void loop() {
       
      if (digitalRead(key)==LOW) 
       {delay(100);
       if (digitalRead(key)==LOW) incomedate = !incomedate;}
      
        if ((incomedate == 0))
        {
          digitalWrite(relayPin, HIGH);
         
        } 
        else if ((incomedate == 1))
        {
          digitalWrite(relayPin, LOW);
        
        }
     
      // 找卡
      if ( ! rfid.PICC_IsNewCardPresent())
       {    delay(500);
            if ( ! rfid.PICC_IsNewCardPresent())
               {incomedate = 1;
                return;}
        }
     
      // 验证NUID是否可读
      if ( ! rfid.PICC_ReadCardSerial())
        return;
     
      MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
     
      // 检查是否MIFARE卡类型
      if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
        piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
        piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println("不支持读取此卡类型");
        return;
      }
      
      // 将NUID保存到nuidPICC数组
      for (byte i = 0; i < 4; i++) {
        nuidPICC[i] = rfid.uid.uidByte[i];
      }   
      Serial.print("十六进制UID:");
      printHex(rfid.uid.uidByte, rfid.uid.size);
      Serial.println();
      
      Serial.print("十进制UID:");
      printDec(rfid.uid.uidByte, rfid.uid.size);
      Serial.println();
      if((refid1=="1214519892")||(refid1=="73217151153"))    
        {   
          incomedate = 0;
        //判断为真,执行需要的程序。
        Serial.println("已验证");
          }
        else
        {
          //判断为假,执行需要的程序。
          Serial.println("验证失败");
          }
    
    
      
      // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡
    / rfid.PICC_HaltA();
     
      // 停止读卡模块编码
    /  rfid.PCD_StopCrypto1();
      refid1="";
      /* if (rfid.uid.uidByte, rfid.uid.size==183624630) 
       { incomedate = !incomedate;}
       */
        
       if ((incomedate == 0))
        {
          digitalWrite(relayPin, HIGH);
        
        } 
        else if ((incomedate == 1))
        {
          digitalWrite(relayPin, LOW);
        
        }
    }
      void printHex(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : "");
        Serial.print(buffer[i], HEX);
        refid1+=nuidPICC[i];
      }
    }
      void printDec(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : "");
        Serial.print(buffer[i], DEC);
        
      }
      
    }
    

    其他相关博客

    Arduino小白入门全解,学习笔记

    Arduino实践(二)lcd1602使用说明,源码

    展开全文
  • 人工智能文献综述

    2017-07-05 09:47:26
    人工智能相关文献
  • 接下来就是要进行更为精准更智能追踪。因此,在接下来的代码演示Demo中我重新设计了几个,一个是PlayObject,这个其实也没有什么新的东西,都是之前已经介绍过的,无非就是速度向量、位置以及移动控制等它的...

    CSDN个人博客地址,凯尔八阿哥栏http://blog.csdn.net/zhangxiao13627093203,转载请注明出处

    接下来就是要进行更为精准更智能的追踪。因此,在接下来的代码演示Demo中我重新设计了几个类,一个是PlayObject,这个类其实也没有什么新的东西,都是之前已经介绍过的,无非就是速度向量、位置以及移动控制等它的代码设计如下:

    </pre><span style="font-size:24px"></span><pre name="code" class="csharp">using UnityEngine;
    using System.Collections;
    
    public class PlayObject : MonoBehaviour
    {
        [HideInInspector]
        public float moveVx;//x方向的分速度
        [HideInInspector]
        public float moveVy;//y方向的分速度
        /// <summary>
        /// 2维坐标(x,y)
        /// </summary>
        public Vector2 Position
        {
            get
            {
                return new Vector2(this.transform.position.x, this.transform.position.y);
            }
        }
        private Vector2 _vHeading;
        /// <summary>
        /// //设置导弹的前进方向的归一化向量m_vHeading
        /// </summary>
        public Vector2 vHeading
        {
            get
            {
                float length = Mathf.Sqrt(moveVx * moveVx + moveVy * moveVy);
                if (length != 0)
                {
                    _vHeading.x = moveVx / length;
                    _vHeading.y = moveVy / length;
                }
                return _vHeading;
            }
        }
        private Vector2 _vSide;
        /// <summary>
        /// 前进方向的垂直向量
        /// </summary>
        public Vector2 vSide
        {
            get
            {
                _vSide.x = -vHeading.y;
                _vSide.y = vHeading.x;
                return _vSide;
            }
        }
    
        /// <summary>
        /// 速度向量
        /// </summary>
        public Vector2 Velocity
        {
            get
            {
                return new Vector2(moveVx, moveVy);
            }
        }
        /// <summary>
        /// 速度标量
        /// </summary>
        public float Speed
        {
            get
            {
                return Mathf.Sqrt(moveVx * moveVx + moveVy * moveVy);
            }
        }
        public float MaxSpeedRate;
        // Use this for initialization
        void Start()
        {
    
    
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
        /// <summary>
        /// 移动物体
        /// </summary>
        /// <param name="speedRate">移动的速度率,一般为1</param>
        /// <param name="isLookAtVelocityVector">是否要这是速度矢量与物体的朝向一致</param>
        public void Move(float speedRate, bool isLookAtVelocityVector)
        {
            this.transform.position += new Vector3(moveVx * Time.deltaTime, moveVy * Time.deltaTime, 0) * speedRate;
            //  Debug.Log("x:" + m_postion.x + "y:" + m_postion.y);
            //调整导弹的朝向是的它和速度矢量合成方向一样
            if (isLookAtVelocityVector)
            {
                LookAtVelocityVector();
            }
        }
        /// <summary>
        /// 使得物体始终朝向矢量速度的方向
        /// </summary>
        void LookAtVelocityVector()
        {
            float zAngles = Mathf.Atan(moveVx / moveVy) * (-180 / Mathf.PI);
            if (moveVy == 0)
            {
                zAngles = moveVx > 0 ? -90 : 90;
                //跟以往的计算角度不同的是,这里加了moveVx==0的独立判断,这样可以在不控制的时候保持原状态
                if (moveVx == 0)
                {
                    zAngles = this.transform.rotation.eulerAngles.z;
                }
            }
    
            if (moveVy < 0)
            {
                zAngles = zAngles - 180;
            }
            Vector3 tempAngles = new Vector3(0, 0, zAngles);
            Quaternion tempQua = this.transform.rotation;
            tempQua.eulerAngles = tempAngles;
            this.transform.rotation = tempQua;
        }
    }
    


     
    

    这样就可以很方便的操作我们的控制对象,作为使用例子我写了一个鼠标点击追踪算法,效果如图所示

    它的核心代码如下:

    <span style="font-size:24px;">using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class AISeek : MonoBehaviour {
        public PlayObject plane;
        public Image Aim;
        public float vecChangeRate;//这个数值越大在目标点的穿梭次数就会越多,一般为1
        public float MaxSpeed;
        public float FleeDistance;
        Vector2 AimPos;
    	// Use this for initialization
    	void Start () {
            AimPos = new Vector2(Aim.transform.position.x, Aim.transform.position.y);
    	
    	}
    	
    	// Update is called once per frame
        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                Aim.transform.position = Input.mousePosition;
                AimPos = new Vector2(Aim.transform.position.x, Aim.transform.position.y);
            }
            Vector2 moveVec = AI_Seek(AimPos);
            float length = Mathf.Sqrt(moveVec.x * moveVec.x + moveVec.y * moveVec.y);
            if (length != 0)
            {
                //   Debug.Log("x:" + moveVec.x + "y:" + moveVec.y);
                plane.moveVx += vecChangeRate * moveVec.x / length;
                plane.moveVy += vecChangeRate * moveVec.y / length;
    
            }
            plane.Move(1, true);
        }
        Vector2 AI_Seek(Vector2 targetPos)
        {
            Vector2 vSeekPos = targetPos - plane.Position;
            vSeekPos = vSeekPos.normalized*MaxSpeed - plane.Velocity;
            return vSeekPos;
        }
    }
    </span>

    它的原理是:首先计算预期的速度,这个速度是智能体在理想化情况下到达目标位置所需的速度,它是从智能体到目标的向量,大小为智能体的最大速度,该方法返回的操控力是所需要的力,当把它加到智能体当前速度向量上就得到预期的速度。所以,你可以简单的从预期速度中减去智能体的当前速度。但是你很快就会发现这个算法的一个问题,就是飞机在到达指定目标位置后并没有停止下来,而是反复的往返穿越目标点,如图所示:

    针对这个问题,我会在下一篇进行讲解,接下来要讲的还是和这个算法直接相关的东西,我必须要先把它讲完。

    有追踪算法,那么肯定也要有反追踪算法,其实它的原理在基于追踪的原理上就显得非常简单了

    <span style="font-size:24px;">   Vector2 AI_UNSeek(Vector2 targetPos)
        {
            Vector2 disPos = plane.Position - targetPos;
            float distance = Mathf.Sqrt(disPos.x * disPos.x + disPos.y * disPos.y);
            if(distance>FleeDistance)
            {
                return Vector2.zero;
            }
            disPos = disPos.normalized * MaxSpeed - plane.Velocity;
            return disPos;
        }</span>
    看看这个代码和上面的AI_Seek(vecter2 targetPos)有什么不一样。我在反追踪代码上面还加了一个距离的判断,也就是当目标和 飞机的距离小于预设的追踪距离的时候就开始追踪,它的效果图如图所示

    展开全文
  • 在基于反汇编的输入路径追踪技术的基础上,结合基于代码覆盖的测试数据生成和基于快照恢复的错误注入技术,将其应用于模糊测试中。提出一种软件安全漏洞自动化挖掘的方法,较好地解决传统模糊技术存在的若干局限。...
  • 随着人们对健康管理意识的提高及老龄化社会的到来,医院仅仅为患者提供疾病治疗的服务已不能满足大众对健康的需求,这就要医院将智能健康管理系统融入到医疗卫生服务体系中,对居民人体健康状况进行长时间监护管理,...

    随着人们对健康管理意识的提高及老龄化社会的到来,医院仅仅为患者提供疾病治疗的服务已不能满足大众对健康的需求,这就要医院将智能健康管理系统融入到医疗卫生服务体系中,对居民人体健康状况进行长时间监护管理,并通过相关的健康信息进行疾病的预分析诊断,为居民提供更深层次的健康管理服务。健康管理服务包括健康人群、亚健康人群、疾病人群,以控制健康危险因素为核心,通过病因预防、临床前期预防、临床预防三级预防并举,实现良性环形运转循环,为居民提供更加系统的健康管理。

    目录

    一、智能健康管理系统介绍

    二、智能健康管理系统优势与价值

    三、智能健康管理系统功能介绍

    四、智能健康管理系统子系统组成

    五、智能健康管理系统特点

    六、智能健康管理系统服务流程

    七、智能健康管理系统发展前景

    正文

    一、智能健康管理系统介绍

    健康管理是一个连续的、长期的、循环往复、始终贯穿的过程,依托互联网+实时健康监测智能穿戴设备+云数据为基础,利用智能健康检测设备、无线通讯、互联网+实体、云计算+人工智能等诸多领域的前沿技术,智能健康管理系统通过对健康大数据的科学运用,为国人提供精准智能健康管理和个体化健康,让每个人都享受到带来的健康生活。为老年人群体、亚健康人群、慢性病患者(高血压、心脏病等)。实现院外监测,对亚健康人群和社区居民健康状况进行集中有效的管理(评估、预测和控制),实现个人对慢性病的早监测、早发现、早诊断和早治疗,实现对老年人和特殊人群的长期有效的病情监控和护理,同时智能健康管理平台为病人建立终身动态电子健康档案。通过物联网和云计算的应用促进健康保健水平的提升,促进资源的高度共享,完善健康保障体系,为医疗改革提供新型的网络化的支撑平台。
    在这里插入图片描述
      二、智能健康管理系统优势与价值

    健康管理是一种对个人及人群的健康危险因素进行全面管理的过程,提供科学的健康指导、健康生活方式的干预,调动其自觉性和主动性,有效地利用有限的资源来达到最大的健康改善效果,保护和促进人类的健康,真正达到防治疾病的发生,提高生命质量、降低医疗费用的目的。

    1、重视“诊前诊后管理”

    将健康检测、健康评估、健康干预、健康服务、健康预防、健康定制、健康生活、健康生态一体化结合。运用云数据、云计算、云服务,为客户健康提供24小时360度全方位商品质的健康服,尤其是慢性病患者、亚健康人群的诊前咨询和诊后追踪的健康管理服务。

    2、以“健康档案”为核心

    以居民个人健康为核心、贯穿整个生命过程,包括个人基本信息、体检信息、疾病档案以及日常生活习惯信息,通过分析健康档案信息变化并提供健康评价服务。

    3、“知识库”的构建

    为服务商提供大数据查询、分析及统计全面了解和掌握会员身体状态,制定专业合理的健康调理,提升会员的信任度,并通过大数据判断目标人群,正确开发、选购更多的健康项目、产品等。

    4、保证客户“长期”管理

    专家团队实时为消费者、服务商提供健康咨询、分析评估、健康促进、跟踪干预、效果评估、持续远程管理监测健康及移动管理监测健康和全面的健康管理解决,建立与客户长期合作关系,保证医疗机构的客源。

    5、有利于“营销说服”

    医疗机构通过系统跟踪患者的体征数据,及时掌握患者的医疗需求,利用电话、短信、微信、移动APP与患者保持联系,向患者推送治疗,引导说服患者重视健康管理,定期到医疗机构体检和治疗。

    6、适合连锁店管理

    健康管理机构服务对象主要是周边居民(客户),服务周期为长期,以服务为主,医疗为辅,其服务可复制性强,能够通过了解居民健康档案,为客户量身定制各种健康管理,吸引客户持续消费。
    在这里插入图片描述
      三、智能健康管理系统功能介绍

    智能健康管理系统的核心是维护健康,焕生汇健康管理专家提出体检向健康管理的“三个转变”:由单纯经营型向学科建设型转变,由疾病检查向整体健康评估转变,由单纯体检向全面健康管理转变。焕生汇健康管理还倡导引入功能医学,使诊疗前移,给大家量身定制营养治疗和生活方式指导。

    1、自动生成回访任务

    平台将自动分析患者所属情况,并提醒健康管理师进行回访;其中包括“首次检测、重大异常、波动异常、半夜检测、频繁检测、一般异常、心律异常、试纸异常”等12种回访任务。提升健康管理师回访效率,保证回访及时性,避免遗漏。

    2、全面记录客户信息

    全方位记录客户的健康消息,收集客户的基本信息、生活习惯、既往病史、家族史等,为健康管理服务提供基础数据的分析。

    3、智能推送健康知识

    可人工定制客户关怀的短信模板、回访模板、疾病和药品知识等,提高系统使用效率和客户服务质量。

    4、一键形成分析报告

    可对接医院体检系统,自动同步客户的体检报告,同时也支持Excel手工导入客户体检报告。可收集客户体检报告,并进行历年报告的对比分析。同时,对于企业团体体检,也可以一键快速生成团体体检分析报告,快速统计分析企业员工健康情况。
    在这里插入图片描述
      四、智能健康管理系统子系统组成

    随着现代生活的发展,越来越多的人的身体都有亚健康的状态出现,个人健康管理软件可以帮助用户检测自己的身体情况,管理个人的身体健康问题,十分实用。

    1、健康档案系统:为客户提供健康管理,个体的健康问题简明、重点突出、条理清楚、便于计算机数据处理和管理等。

    2、健康评估系统:为客户提供健康评估,使个体对健康风险有一个综合认识。认清个人身体健康状态,并进行客户分类并筛选优质客户。

    3、健康干预系统:帮助客户自我康复,浏览客户疾病管理信息,客户个人的健康智能提醒,制定智能化的个人疾病管理。

    4、效果评价系统:收集效果信息,针对不同客户进行不同的诊疗分析。直观展示健康指标的改变。

    5、健康会所外部营销系统:发布会所资讯、产品消息、活动、健康咨询、社交分享, 实现病毒式营销传播、寻找锁定客户。

    6、健康会所内部管理系统:包括咨询预约、医生工作站、仓库管理、后勤管理、检查结果、报表分析。

    7、智能健康管理系统前端产品:支持一体机设备、手环、体质称等。
    在这里插入图片描述
      五、智能健康管理系统特点

    智能健康管理系统的特点是以会员健康档案CRM为核心,以医养结合健康管理为主线,以移动互联网云计算为创新点。全面支持供应商、生产商、销售商、服务商、健康机构、投资商、政府、消费者等以生产商品和提供服务为中心组成的全渠道健康生态管理系统。打破了传统的行业界线,使不同“行业”的企业走到了一起,从而增加各自的市场机会,充分调动企业间资源的相互协调和聚集。

    1、简洁美观的界面,系统平滑流畅的运行体验,独具特色的定制功能,让医护人员在欢快工作之余,提升机构的效益。

    2、全面支持第三方系统集成,与网站、手机APP、多媒体展示台等连成整体,简单易用,性价比高。

    3、软硬件一体化设计,自动获取智能穿戴设备数据并上传云端,根据体征数据自动生成健康管理,并将自动提示客户和服务人员,进行随访与干预。

    4、集成多系统规范化管理,提高内部管理的效率,减少出错机会,降低管理成本。

    5、利用微信、网站、APP等移动互联网工具,对医疗机构进行全方位介绍,提高医疗机构形象和知名度,服务更加有黏性。
    在这里插入图片描述
      六、智能健康管理系统服务流程

    智能健康管理服务的流程是有序开展智能健康管理服务运作和实施的关键因素,按照八个步骤开展服务,使之有条不紊地落实和完成,达到加强自身和客户对智能健康管理服务的管理和质量控制。

    八个步骤分别为:签署客户服务合约、采集健康信息、建立完整健康档案、开展健康风险评估、制定健康干预计划和、实施健康干预、健康动态跟踪、智能健康管理效果评价。

    第一步:签署客户服务合约

    在深入了解健康需求的基础上,依据自身服务能力,尽最大可能满足客户服务要求,讲求实事求是地与客户签署服务合约,按照合约履行工作职责,做到诚信与承认现服务。

    第二步:采集健康信息

    对个人健康信息进行收集,根据个人健康状况有针对性地涉及个性化健康体检项目,安排健康体检后,通过健康信息问卷调查与健康体检数据所采集的健康相关信息,予以汇总分析,是健康风险分享评估的可靠依据。

    第三步:建立完整健康档案

    健康健康档案,是智能健康管理中心所必需的。健康档案是用来记录客户生命体征以及自身所从事过的与健康相关的行为与事件。

    个人健康档案是将整个智能健康管理周期的所有健康信息资料,如服务合约、个人健康档案管理首页、会员服务要求、个人会员服务须知、个人健康信息调查问卷、既往健康体检报告、健康体检项目设计、现实健康体检报告、健康风险评估报告、健康干预计划和、健康干预实施过程记录等进行系统地、完整地管理、以利于客户随时查看和后续干预,为医疗服务提供详实的资料。

    第四步:开展健康风险评估

    针对客户健康危险因素开展相关疾病风险评估,通过健康风险评估对客户的健康状况予以综合判断和评价,预测其为了5-10年内的健康走向,以加强预警提示作用,使客户对自己健康给予高度重视和早起防范,为制订健康干预计划和的量化指标。如生活方式评估报告,卒中因子风险预测评估报告、糖尿病危险因子预测评估报告等。

    第五步:制定健康干预计划和

    根据健康风险评估存在的健康风险来制订其控制目标和降低危险因素的干预计划和。

    首先,要制订干预的目标、方法、时间等。尤其是应确定优先干预解决的健康问题,如亚临床状态的异常指标、生活方式等;制订中期干预解决的健康问题,如单种疾病、生活方式等;制订远期干预解决的健康问题,如多种疾病、生活方式等。

    其次,再制订干预,应包括干预的内容、途径、手段、频率等,如异常指标或单种疾病、多种疾病、生活方式、其他健康问题等;医疗干预包含门诊、会诊、特诊、监测、餐导、跟踪等;生活方式干预包含膳食干预、运动干预、心理干预、行为干预、环境干预等。

    第六步:实施健康干预

    依据智能健康管理干预计划和,有步骤地以多种形式来帮助个人采取行动,纠正不良的生活方式和习惯,控制健康危险因素,实现个人智能健康管理计划的目标。

    在此过程中重视干预计划的实施和执行情况,包括干预的具体内容、干预的手段、频率和时间等,以确保客户主动参与干预的积极性和有效性。

    第七步:健康动态跟踪

    人体是不断变化的,因此对健康的监测、跟踪与干预服务是智能健康管理据服务中的根本之重任。

    通过多种方式跟踪个人执行智能健康管理计划的状况,并定期进行在此评估,给个人提供最新的改善结果,使健康得到有效的管理和维护。更重要的是随时掌握客户的身体变化和健康状况,以不断调整和修订健康干预计划和。

    第八步:智能健康管理效果评价

    在管理过程中对客户的健康状况予以阶段性效果评价和年度效果评价,如单项干预、综合干预效果评价、干预前后生活方式改善评价、行为因素方式改善评价等,以及时了解客户健康状况改善情况,再依据次评价修正调整智能健康管理干预计划和,实施更好的干预服务,最终使客户的健康状况得到有效的改善和促进。
    在这里插入图片描述
      七、智能健康管理系统发展前景

    随着人们生活水平的不断提高和现代社会的快速发展,使越来越多的人开始关注健康管理。国家人口与健康科技发展战略也必须确定为战略前移的方针:即从治疗疾病为主导向保障健康为主导向开始转变,重预防、重保健,维护和促进健康,不得病或少得病的意识和观念不断提高。曾有人说过: “有两样 东西是别人抢不走的,一个是知识,一个是健康。 新兴的健康管理行业将有非常广阔的发展前景。建立一支健康管理专业队伍,对于改善和提高中国国民身体素质,全面建设小康社会有着重要意义。
    在这里插入图片描述

    展开全文
  • 通过安装车载一体机实现机扫车、洒水车等机械化作业车辆的实时位置与作业状态的在线查看与追踪。具体包括实时GIS位置、地址、速度、方向、行驶路线、点火状况等信息,同步实时预警车辆违规行为。根据车辆作业位置,...
  • 忆阻器脑芯片与人工智能

    千次阅读 2020-10-18 17:33:48
    来源:文章转载自期刊《微纳电子与智能制造》作者:陈子龙,程传同,董毅博,张 欢,张恒杰,毛旭瑞,黄北举,谢谢。摘 要现阶段计算与存储分离的“冯·诺依曼”体系在功耗和速率方面已经不能满足人...
  • 基础设施数据库参考建设部城镇建设行业标准CJ/T171-2002《城市环境卫生设施属性数据采集表及数据库结构》的要求进行设计,共包括主次干道、垃圾收集点、垃圾收集站、公共厕所、垃圾处置场、公共场所共六大设施。...
  • 德州仪器C2000及MCU创新设计大赛,低功耗三等奖,低功耗低成本的全球定位追踪器,不含源码,比赛练习案例,创新创业比赛、青春杯、挑战杯、互联网+比赛赛参考,报告模板,技术模仿。适用于教学案例、毕业设计、...
  • 初探AR技术

    千次阅读 多人点赞 2019-10-06 15:36:58
    企业、机构和独立开发人员受益于Wikitude的工具,用于开发适用于Android,iOS,智能手机,平板电脑,智能眼镜的AR应用程序。 功能: 即时跟踪:挖出标记。即时跟踪是使用WikitudeSLAM技术的第一个功能。它可以...
  • vscode安装使用教程

    万次阅读 多人点赞 2018-12-11 19:18:48
    Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性,支持插件...
  • 获取更多资讯,赶快关注上面的公众号吧! 文章目录第十章 蝙蝠算法10.1 介绍10.2 蝙蝠的自然行为概述10.3 蝙蝠算法的数学表达10.4 蝙蝠算法变种10.4.1 混沌...蝙蝠算法(Bat Algorithm,BA)是一种基于群体智能的...
  • 知识追踪模型的应用

    千次阅读 2020-10-20 17:05:20
    近年来,随着在线学习系统在教育环境中越来越普及,在线学习人数越来越多,教育者不可能追踪每一个学习者的知识状态并提供个性化的学习指导;在线学习系统中的知识需要学习者通过各种冗余信息自我查找,导致学习资源...
  • 蓝牙追踪We’ve all done it: you misplace something important and you spend a lot of time (with a lot of stress) backtracking to locate it again. With Bluetooth tracking devices you can make the hunt a...
  • 增强现实AR智能眼镜是当前社会上比较主流的可穿戴AR设备,是除了手机和平板电脑之外最重要的增强现实支撑设备。前面的文章中,我们已经讨论过与光学透视型头戴显示器相关的标定技术,其实增强现实AR智能眼镜就是一种...
  • 网络追踪器介绍

    千次阅读 2020-08-02 14:30:37
    该功能能够告诉访问的网站上运行的是哪一款网络追踪器,还会给用户一个30天的报告,告知在浏览时发现的、已知的网络追踪器,另外,还会显示出这些追踪器来自哪些网站。那么什么是网络追踪器呢?这些网络追踪器又会对...
  • 知识追踪理论入门

    千次阅读 2020-05-23 09:51:17
    what 知识追踪(Knowledge Tracing)是根据学生过去的答题情况对学生的知识掌握情况进行建模,从而得到学生当前知识状态表示的一种技术。便我们能准确地预测学生对于各个...Corbett和Anderson,1995年将BKT引入智能

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,723
精华内容 13,489
关键字:

智能追踪类