机智宝 发表于 2016-9-9 18:09:23

【STM32F405+Gokit】之智能楼宇服务机器人

第一章项目总体介绍
    目前,机器人的用途已经渗入到社会生活的方方面面,在工业生产中,机器人可以代替人类完成恶劣环境下的货物搬运以及设备检测等任务。而在人们的日常生活中,智能机器人也发挥了越来越重要的作用。因此,我们设计了基于STM32和Gokit的智能楼宇服务机器人。
   本设计是由以STM32F405为主控的底盘控制系统和STM32F103+ESP8266构成的WiFi控制系统组成的智能楼宇安防机器人。其运动底盘采用四轮驱动的麦克纳姆轮,实现全方位移动的零转角控制,可以迅速调整机器人的运动状态。底盘控制系统主要包括:电源模块、微控制器模块、电机驱动模块、DBUS通讯控制模块等。通过无线遥控器的摇杆可以直接控制机器人前进、后退、左平移、右平移、向左旋转和向右旋转,安保人员坐在室内即可轻松地控制机器人完成安防工作,减轻了安保人员的工作负担,增加了工作乐趣,同时降低了安防工作的成本。
Wifi服务系统由主控部分、传感器部分和显示部分构成,主控部分采用STM32103c8t6+ESP8266构成,传感器部分有3色灯、夏普PM2.5粉尘传感器、雨量传感器、温湿度传感器DHT11和TCRT5000光电传感器构成。MCU主控把采集到的传感器信息上传到机智云的云端,然后云端将信息发送到楼宇内人员的手机端,保安和楼宇内工作人员通过手机APP即可实时获取楼宇外的温湿度、空气质量和雨量。能够判断是否下雨和是否有人在机器人旁通过屏幕查询信息。显示部分使用串口屏显示传感器的信息,并且给来找人和咨询事情的人提供查询信息。通触摸屏设计的多级式菜单设定外来人员的需求信息,增进了人机交互的灵活性。
   最后,本设计实现了一款具有安防功能、能给外来办事人员和楼宇内人员提供帮助的智能楼宇安防服务机器人。它可以直接应用到高校办公大楼,公司楼宇、写字楼和机关办公大楼等,具有很好的实际意义,实现了我们最初的设计目标。
http://club.gizwits.com/data/attachment/forum/201607/22/112047lablx7akba1xayn7.jpg参赛团队:理工ROOT战队(3人)

功能演示:
http://v.youku.com/v_show/id_XMTY2NTM0MzE0OA==.html

回帖可见:WiFi服务系统程序WiFi服务系统程序完整下载 http://club.gizwits.com/static/image/filetype/rar.gif xinchengxu.rar (5.8 MB, 下载次数: 11)

第二章 系统硬件设计2.1 车体结构设计    移动底盘的运行结构有多种,目前常用的有轮式、履带式、腿式以及上述几种结构的结合。轮式以及履带式底盘主要适用于地理环境较为平坦、少有坑洼的地面。具有控制方式简单、运行速度快、运行平稳以及噪音小等优点。而腿式步行式的底盘适用的地理环境就较为复杂多样,但是由于控制算法复杂,对机械结构有着较高的要求,并且移动速度较为缓慢,目前的实际应用还不是特别广泛。综合考量本文系统的使用环境以及使用条件,本文中系统的底盘选择轮式运行方式,为了实现全方位移动方式的零度转角,本文底盘采用四轮驱动的麦克纳姆轮如图2-1所示。采用麦克纳姆轮的优点是可以实现底盘前行、横移、斜行、旋转及其组合等运动方式。由此底盘非常适合转运空间有限、作业通道狭窄的楼宇、船舱以及机舱等环境。图2-1 麦克纳姆轮    麦克纳姆轮设计车轮旋转时成45度排列的自由滚子与地面接触,地面会给予车轮与转轴夹45度的摩擦力,此摩擦力可分为X分量与Y分量,籍由车轮的正反转或停止,改变XY分量力的方向,可以调整底盘做各种方式的移动。而单独的麦克纳姆轮无法实现全方位移动,需要至少四个才能组成全方位移动平台,本文所采用的四个麦克纳姆轮全方位移动平台如图2-2所示,图中车轮斜线表示车轮轮缘与地面接触滚子的偏置角度。图2-2 底盘车轮配置图2.2 底盘控制系统设计
2.2.1 主控单元   本系统选用STM32F405RGT6芯片作为底盘移动平台的中央控制器,完成传感器信息收集、电机控制、外部通信扩展等任务。STM32F405RGT6是ST公司推出的以高性能的ARM Cortex-M3内核的32位RISC的内核的芯片。工作最高频率可达84MHz,能实现高速运算。处理器具有3种低功耗模式和灵活的时钟控制机制,可根据系统设计要求对其进行合理的优化。工作电压可以在2.0-3.3V之间,在3.3V的供电电压下,其典型的小号电流仅为1.4µA。
2.2.2 电机驱动模块
2.2.2.1 底盘驱动电机的选择    本设计中为了保证全方位移动方式的零度转角,采用四轮单独驱动,可以灵活调节任意一个麦克纳姆轮的运行方式,从而可以灵活控制移动平台的任意角度位移。移动平台的驱动电机有步进电机和直流电机两种。本设计中选用直流电机作为底盘移动平台的驱动电机,直流电机具有优良的速度控制性能,具体来说,它有以下几点优点:具有较大的转矩,从而能够克服传动装置的摩擦转矩和负载转矩;具有较快的响应能力,可以适应复杂的速度变化和控制信号的变换;电机的负载特性硬,有较大的过载能力,确保运行速度不受负载冲击的影响,增加系统的可靠性;直流电机空载力矩大,在控制系统发出停转的同时可以立即响应,并且可以产生相当大的力矩阻止移动平台由于惯性继续移动;直流电机相对其他电机来说运动起来平稳,而且噪音小。2.2.2.2电机控制方式    直流电机的转速控制方法可以分为两类:调节励磁磁通的励磁控制方式和调节电枢电压的电枢控制方法。而由于励 磁控制方法在低速模式时磁极极易饱和,所以调速范围有限,而在高速模式下,由于经常换向,换向火花较大,造成控制时动态响应较差。本文采用的电机驱动方式是电枢控制方式,通过输出PWM脉宽调制PWM电平来控制电动机的电枢电压,实现调速功能。由于一般的微控制器都可以输出PWM脉冲电平,所以容易在微控制器上实现此种控制方式。2.2.2.3电机驱动模块    本文中移动平台使用直流电机实现其运动的能力,需要进行前进、后退、横向以及斜向的移动方式。直流电机在此运行的状态下工作所消耗的电压和电流都比较大,其正反转的改变需要通过改变所加电压的极性实现。在实际使用中,本设计中采用的是AQMH3615NS直流电机驱动模块来实现电机的驱动。AQMH3615NS的功能特点是:支持电机电压9-36V,有欠压保护功能;最大持续负载电流12A(不加散热);拥有类似L298的驱动逻辑,可三线控制调速、正反转以及刹车;支持满PWM输出,还可直接使用按键控制正反转,PWM的有效范围0.1%-100.0%;接口具有ESD防护。如图2-3所示为电机驱动模块的各个部分的功能。(a)模块正面                   (b)模块背面图2-3 电机驱动模块各个部分功能电机驱动模块电源接口、电机接口以及控制信号接口的连接方式如图2-4所示,当使用外部PWM调速时,IO2/IO3分别控制电机的正反转和刹车,PWM引脚接微控制器的PWM输出,用于电机的调速。而控制电机正反转及刹车的电平逻辑如表2-1所示。表2-1 控制信号逻辑
IO2IO3PWMOUT1/OUT2输出
00X刹车
11X悬空
101全速正转
011全速反转
10PWM正转调速
01PWM反转调速

    在PWM为100%时需要先刹车0.1S以上再给反转信号,否则电机的反向电动势可能导致电源电压突变使驱动芯片进入保护状态而导致错误运行,对于非满PWM状态,如果要改变电机的转动方向,最好也先刹车0.1S以上再给反转信号,以免导致电源电压有较大波动。图2-4 电机驱动模块接线图Gokit main函数流程图
温湿度处理流程图PM2.5传感器处理流程图雨量传感器处理流程图关键程序void PM25_Read(uint8_t *dust,uint8_t *temp1,uint8_t *yuliang)
{
      float temp,pm25,rainval;
      //*temp1=Get_Adc(5);
      GPIO_ResetBits(GPIOA,GPIO_Pin_7);
      Delay_us(280);
      temp=(float)Get_Adc(5)*(3.3/4096);
      Delay_us(40);
      GPIO_SetBits(GPIOA,GPIO_Pin_7);
      Delay_us(9680);
      rainval=(float)Get_Adc(4)*(3.3/4096);
      //temp=(float)Get_Adc(5)*(3.3/4096);
      pm25=temp*344-99;
      *temp1=pm25;
      //PM2.5计算空气质量AQI,分为0-5一共6个等级
      if(pm25<35)
                *dust=0;
      if(pm25>=35 && pm25<75)
                *dust=1;
      if(pm25>=75 && pm25<150)
                *dust=2;
      if(pm25>=150 && pm25<250)
                *dust=3;
      if(pm25>=250&& pm25<500)
                *dust=4;
      if(pm25>=500)
                *dust=5;
      
      //雨量等级计算
      if(rainval>=3)
                *yuliang=0;//没有雨
      if(rainval>=1.6 && rainval<3)
                *yuliang=1;//小雨
      if(rainval>=1 && rainval<1.6)
                *yuliang=2;//中雨
      if(rainval>=0 && rainval<1)
                *yuliang=3;//大雨
      //*dust=temp*344-99;
      //*dust=temp;
      //*yuliang=temp2;
}
void GizWits_GatherSensorData(void)
{
      ReadTypeDef.Infrared = IR_Handle();
      //ReadTypeDef.rain = RAIN_Handle();
      //ReadTypeDef.rain=0;
    printf("rain=%d \r\n",ReadTypeDef.rain);
      DHT11_Read_Data(&curTem, &curHum);
      ReadTypeDef.Temperature = (curTem + lastTem) /2;
      ReadTypeDef.Humidity = (curHum + lastHum)/2;

      ReadTypeDef.Temperature = ReadTypeDef.Temperature + 13;//Temperature Data Correction
      lastTem = curTem;
      lastHum = curHum;
      printf("Temperature=%d \r\n",ReadTypeDef.Temperature);
      printf("Humidity=%d \r\n",ReadTypeDef.Humidity);
      //ReadTypeDef.test = 0;
      //ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3;
    //iol_temp = ADC_ConvertedValueLocal*344-99;
      //PM_25_handle();
      //ReadTypeDef.dustVal = 3;
      PM25_Read(&ceshiVal,&ceshi11,&ceshi22);
      Delay_ms(10);
      printf("zhi=%d \r\n",ceshi11);
      printf("dianya=%d \r\n",ceshiVal);
      printf("rain11=%d \r\n",ceshi22);
      ReadTypeDef.dustVal=ceshiVal;
      ReadTypeDef.rain=ceshi22;
      //printf("shangchuan=%d \r\n",ReadTypeDef.dustVal);
      //xintianjia
      chuanshu_buf=0xFF;
      //chuanshu_buf=0xFF;
      chuanshu_buf=curTem;
      chuanshu_buf=curHum;
      chuanshu_buf=ReadTypeDef.rain;
      chuanshu_buf=ceshi11;
      
      

int main(void)
{
      uint8_t p0_control_buf;
      //uint8_t flag=0;
      uint8_t t=0;
      
      SystemInit();      
      HW_Init();
      Printf_SystemRccClocks();
      SW_Init();               
      while(1)
      {
                KEY_Handle();               
                GizWits_MessageHandle(p0_control_buf, sizeof(WirteTypeDef_t));
                if(p0Flag == 1)
                {
                        memcpy((uint8_t *)&WirteTypeDef, p0_control_buf, sizeof(WirteTypeDef_t));
                        GizWits_ControlDeviceHandle();
                        GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
                        p0Flag =0;
                }
      if(gaterSensorFlag != 0)
      {
            GizWits_GatherSensorData();
                        printf("shangchuan=%d \r\n",ReadTypeDef.dustVal);
            gaterSensorFlag = 0;
      }
      
               
                for(t=0;t<5;t++)
                        {
                              UART1_Send_DATA(chuanshu_buf);
                              
                        }
               
               
               
      GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 0);
      }
}
void UpdateUI()
{
      if(current_screen_id==0)//Îı¾ÉèÖúÍÏÔʾ
      {
         uint8 k1,k2,k4;
         k1 = jieshou_buffer;
         k2 = jieshou_buffer;
         k4 = jieshou_buffer;

          SetTextValueInt32(0,1,k1);//µ±Ç°µçÁ÷
          SetTextValueInt32(0,3,k2);//ζÈ
          if(jieshou_buffer == 0)
            {
               SetTextValue(0,4,"ûÓê");
            }
          else if(jieshou_buffer == 1)
         {
               SetTextValue(0,4,"СÓê");
          }
         else if(jieshou_buffer == 2)
             {
                   SetTextValue(0,4,"ÖÐÓê");
            }
          else if(jieshou_buffer == 3)
          {
                SetTextValue(0,4,"´óÓê");
         }

   SetTextValueInt32(0,5,k4);
    ++test_value;
   }
}
int main()
{
      qsizesize = 0;
      uint32 timer_tick_last_update = 0; //上一次更新的时间

      /*配置时钟*/
      Set_System();
      /*配置串口中断*/
      Interrupts_Config();
      /*配置时钟节拍*/
      systicket_init();

      /*串口初始化,波特率设置为115200*/
      UartInit(115200);

      /*清空串口接收缓冲区*/
      queue_reset();

      /*延时等待串口屏初始化完毕,必须等待300ms*/
      delay_ms(300);

      while(1)
      {
                size = queue_find_cmd(cmd_buffer,CMD_MAX_SIZE); //从缓冲区中获取一条指令      
                if(size>0)//接收到指令
                {
                        ProcessMessage((PCTRL_MSG)cmd_buffer, size);//指令处理
                }               


                if(update_en&&timer_tick_count-timer_tick_last_update>=TIME_100MS)
                {
                        update_en = 0;
                        timer_tick_last_update = timer_tick_count;                        

                        UpdateUI();
                }

      }
}
extern uint8 jieshou_buffer;
void USART2_IRQHandler(void)
{
      
    if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
                        
    {
            USART_ClearITPendingBit(USART2,USART_IT_RXNE);
            if(isFramestart == 1)
             {
                                 
                   jieshou_buffer= USART_ReceiveData(USART2);
                  if(bianliang>3)
                      {
                              bianliang=0;
                              isFramestart = 0;
                     }   
             }
       else
         {   
                  
             if(USART_ReceiveData(USART2) == 0xFF)
                         {
                                        isFramestart = 1;
                         }
      }
    }
         
}
页: [1]
查看完整版本: 【STM32F405+Gokit】之智能楼宇服务机器人