综合项目——智能分类垃圾桶

一、讲在前面

之前做过许多项目,也写了许多工程代码,但是一直没能好好整理,导致我每做一个新的项目就跟重头开始似的,为了更好进行代码资料的管理,我决定开辟这个博客,作为我资料整理的开始。

-------------------------------------------分割线---------------------------------------

最近刚结束了一个特别折磨人的项目设计,这个项目设计的题目是智能分类垃圾桶,其中需要进行机械设计制图、安卓开发板代码编写、FPGA代码设计、MCU代码设计等等。我在其中负责FPGA开发板代码和STM32开发板代码的编写,秉承记录的目的和开源的初心,我将更新一个系列的博文进行MCU端代码和FPGA端代码的介绍,供大家一起学习进步,不足之处望补正。

二、博文介绍

在该系列博文,我会按照MCU代码和FPGA代码的顺序进行介绍,此次介绍MCU端的代码。

三、MCU代码框架

3.1代码框架分析

此次项目选择的控制平台是意法半导体出产的stm32L476RGT6系列的集成控制主板。板上集成了ST-LINK烧录器、Arduino接口等资源,引出了I2C、SPI、串口、ADC等管脚资源(正经人谁用硬件I2C和SPI不是),可谓是资源丰富,但是又有许多无用之处。

我们的MCU需要做的就是利用以上的板载资源,设计一个控制系统、对整个智能分类垃圾桶系统进行控制,这个控制系统应该包含以下几个功能:

(1)与安卓开发板进行通信;
(2)与FPGA开发板进行通信;
(3)读取TCS34725颜色传感器数据和VL6180距离传感器数据;
(4)向广和通L610物联网通信主板发送AT指令,进而向阿里云发送垃圾桶事件;
(5)用户服务程序,用于对用户预留的接口,用户在该任务里对垃圾桶的逻辑进行设计;
(6) 开发者调试,串口打印垃圾桶属性和数据任务,用于垃圾桶维修者对垃圾桶进行维护。

3.2代码框架设计

根据以上的分析,我们需要实现6个任务,其中5个为常用任务,一个为调试维护任务。为此,我在我的MCU代码框架中开辟6个任务,对整个控制系统进行管理。下面附上一张代码框架图,有需要可以拷贝,但是请标注来源或者自己根据我的框架搭建一个类似的:

在上面介绍中,我提到了任务管理的概念,那么我运用的任务管理方法是什么呢?没错,聪明的你一定猜到了,我运用的是时间片的管理方法。在代码中,我开启定时器3作为任务管理的时钟,对任务资源进行调度,对时间片管理不熟悉的伙伴可以自行百度哦。也许有人会问,为什么不运用操作系统进行任务的管理。emmm…其实刚开始的时候是有用FreeRtos编写的版本的啦,不过效果不好,被我摒弃了。如果有想要的伙伴,我根据反响,考虑专门出一篇博文介绍FreeRtsos系统下的任务管理介绍,欢迎大家在评论区积极发言哦!行了,扯了这么多蛋,接下来该进入正题了——各个任务代码的介绍。

四、各部分代码详解

4.1代码主循环

以下的主循环中运行着整个系统的全部任务,函数中的参数代表任务循行的频率的倒数,单位时ms。

  while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */data_read_task(5);           //传感器数据读取fpga_com_task(10);         //与FPGA通信Android_com_task(60);      //与上位机通信L610_task(200);             //与L610通信user_service_task(10);     //用户服务程序#if DBUGdbug_task(100);         //开发者调试
#endif  }

4.2传感器数据读取任务

我们需要读取的传感器数据有两种,TCS34725颜色传感器数据和VL6180距离传感器数据。这两个传感器数据的读取协议采用IIC(不了解IIC的同学这边建议百度),具体初始化和读取方法网上有许多例程,我在这里不再赘述,只挑选几个比较重要的函数进行讲解,下面贴上代码:

4.2.1传感器初始化

//传感器初始化
void sensor_init()
{//读取TOF模块IDtof_name = VL6180X_Read_ID();  //读取TOF模块的IDwhile(tof_name != 0xBE)            //根据模块不同型号和焊接工艺选择IDtof_name = VL6180X_Read_ID();   //循环读取TOF模块的IDinit_flag = VL6180X_Init();      //tof模块的初始化HAL_Delay(300);                  //延时一段时间等待初始化完成TCS34725_Setup();                //颜色识别模块设置TCS34725_Enable();                //颜色识别模块使能TCS34725_Read(TCS34725_ID,&TSC_name,1);   //读取颜色识别模块IDwhile(TSC_name != 0x44)                    TCS34725_Read(TCS34725_ID,&TSC_name,1); //循环读取颜色识别模块的ID}

这里需要注意的是传感器的ID,我用的距离传感器的ID是0XBE,别的同系列的距离传感器数据有0XB4的,如果程序卡在这个初始化循环里有可能是传感器ID设置的问题,对其进行修改即可。颜色传感器ID没什么大问题。代码注释在上面都有。

4.2.2传感器数据读取主体函数

由于我的整个程序运用的是时间片的管理方法,因此在进行函数的封装时,特别要注意的一个参数时任务运行的事件,原则上给定的任务运行时间只要大于任务的实际运行时间即可,但出于对各个任务实时性需求的不同,我们一般会把实时性需求比较大的任务给的运行频率更大。传感器数据更新实时性要求比较高,我们给定的运行频率比较大,有200HZ。

//传感器数据读取任务,频率200HZ
void data_read_task(uint32_t period)
{if(task_count[DATA_READ_TASK] >= period){range = VL6180X_Read_Range();                        //读取距离数据HAL_Delay(1);                                       //延时等待light = VL6180X_Read_Lux(VL6180X_ALS_GAIN_1_25); //读取光强数据HAL_Delay(1);                                       //延时等待TCS34725_GetRawData(&my_color.CLE,&my_color.RED,&my_color.GRE,&my_color.BLU); //读取颜色传感器的颜色数据HAL_Delay(1);                                     //延时等待voice_range = soner_getdistance();                   //超声波距离数据获取task_count[DATA_READ_TASK] = 0;}
}

4.3广和通L610通信模块通信任务

广和通通信模块遵循的是TCP传输协议,我们通过串口1向物联网通信主板发送AT指令,可以控制MCU与阿里云云端的通信(阿里云与广和通L610通信模块的相关使用如果有不清楚的根据反响将出一篇博客介绍)。内容比较简单,就是串口发送相关AT指令,值得注意的几个点就是,在发送的数据结尾加上回车和换行,在代码中体现为\r\n,还有就是字符串中的双引号注意要用ASSIC的表达方式,正常双引号表达方式是“ ,ASSIC的表达方式是\ 加上"。

4.3.1广和通通信模块连接阿里云配置

int K ;
void L610_init()
{//配置阿里云服务器char *strx;Config_para();            //配置阿里云服务参数strx = strstr((const char*)RECEIVE,(const char*)"OK");while(strx == NULL){K++;    if(K>=6)           //防止程序卡死,配置命令发送超过6次之后跳出初始化循环{break;}Config_para();            //配置阿里云服务参数strx = strstr((const char*)RECEIVE,(const char*)"OK");HAL_Delay(300);}//以下为oled数据显示配置,可以选择注释
//      if(K>=6)
//      {//          OLED_Clear_part();
//          OLED_ShowString(20,5,(uint8_t *)"L610 ERROR!",16 );
//          HAL_Delay(3000);
//      }
//      else
//      {//          OLED_Clear_part();
//          OLED_ShowString(16,5,(uint8_t *)"L610 SUCCESS!",16 );
//          HAL_Delay(3000);
//
//      }
}

4.3.2广和通物联网通信模块运行主体函数

以下代码块不仅包含广和通的通信部分,还包含oled的刷新部分。

int j;
void L610_task(uint32_t peirod)
{if(task_count[L610_TASK] >= peirod){Config_para();         //配置阿里云服务参数//垃圾桶各项属性和数据显示 if(frame == 1){OLED_Clear_part();OLED_ShowString(5,5,(uint8_t *)"type :",8 );OLED_ShowString(5,7,(uint8_t *)"state:",8 );if(sevo_step == 1)OLED_ShowString(60,7,(uint8_t *)"complete",8 );elseOLED_ShowString(60,7,(uint8_t *)"onging",8 );if(RX_DATA_FROM_FPGA == '1'){OLED_ShowString(60,5,(uint8_t *)"RB1",8 );}else if(RX_DATA_FROM_FPGA == '2'){OLED_ShowString(60,5,(uint8_t *)"RB2",8 );}else if(RX_DATA_FROM_FPGA == '3'){OLED_ShowString(60,5,(uint8_t *)"RB3",8 );}else if(RX_DATA_FROM_FPGA == '4'){OLED_ShowString(60,5,(uint8_t *)"RB4",8 );}else{OLED_ShowString(60,5,(uint8_t *)"NULL",8 );}frame = -frame;}else{OLED_Clear_part();OLED_ShowString(5,5,(uint8_t *)"range:",8 );OLED_ShowNum(60,5,range,3,8);OLED_ShowString(5,7,(uint8_t *)"remain:",8 );OLED_ShowNum(60,7,voice_range,3,8);frame = -frame;}//超声波数据作为垃圾余量的参考数据if(voice_range<=6)   {OLED_Clear_part();OLED_ShowString(6,5,(uint8_t *)"full sent:",8 );Send_data((char *)"\"hello\"");}//上位机发送呼叫管理员指令     if(AS_call_manager == 1){OLED_Clear_part();OLED_ShowString(6,5,(uint8_t *)"calling sent:",8 );for(j=0;j<=20;j++)Send_data_call((char *)"\"hello\"");AS_call_manager = 0;}//用户模式和DBUG模式切换显示  if(dbug_flag == 0){OLED_ShowString(92,2,(uint8_t *)"USER",8 );  }elseOLED_ShowString(92,2,(uint8_t *)"DBUG",8 );task_count[L610_TASK] = 0; }}

以上就是此次的更新内容,剩余的与FPGA通信部分和与上位机的通信部分过于庞大,咱们下次介绍,这次先把代码贴上,有不清楚的可以下面评论留言哦。

上位机通信部分:主要是数据收发和协议约定

//与上位机通信,运行频率(1000/60)HZ
void Android_com_task(uint32_t peroid)
{if(task_count[COM_TO_Andr] >= peroid){//接收上位机数据HAL_UART_Receive_IT(&huart4,&RX_DATA[0],1);//根据上位机指令选择调试模式和用户模式if(RX_DATA[0] == 'G'){           dbug_flag = Android_DBUG;RX_DATA[0] = 0;} else if(RX_DATA[0] == 'U'){dbug_flag = Android_USER;RX_DATA[0] = 0;}range_temp = (uint8_t) voice_range;if(dbug_flag == Android_USER){if(range <= 100){TX_DATA[0] = 'l';
//                  TX_DATA[1] = 1;HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}//用户模式下从上位机收到b,表示当前可以进行投放if(( RX_DATA[0] == 'b' || time_cmd == 1)&&(garbage_complete == 1) )   {RX_DATA[0] = 0;AS_cmd = 1;}if((RX_DATA[0] == 'a') && (AS_call_manager == 0)){AS_call_manager = 1;RX_DATA [0] = 0;}//当识别到垃圾,并且上位机发送投放指令之后,返回当前垃圾中类给上位机if((garbage_complete == 0)&&(sevo_cmd_type == GARBAGE_1))     //垃圾1{TX_DATA[0] = 'k';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);TX_DATA[0] = 61;                     //距离标号HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}                     else if((garbage_complete == 0)&&(sevo_cmd_type == GARBAGE_2))  //垃圾2{TX_DATA[0] = 'i';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);TX_DATA[0] = 62;                     //距离标号HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}else if((garbage_complete == 0)&&(sevo_cmd_type == GARBAGE_3))   //垃圾3{TX_DATA[0] = 'o';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);TX_DATA[0] = 63;                     //距离标号HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}else if((garbage_complete == 0)&&(sevo_cmd_type == GARBAGE_4))   //垃圾4{TX_DATA[0] = 'v';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);TX_DATA[0] = 64;                     //距离标号HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);  }else{  TX_DATA[0] = 't';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}}else if(dbug_flag == Android_DBUG){if(RX_DATA[0] == 'M')                //测试电机{RX_DATA[0] = 0;for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 126;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 144;   //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 21;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 15;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 9; //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 15;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}}else if(RX_DATA[0] == 'f')         //测试距离,回传距离数据{if(range == 0)TX_DATA[0] = 'h';               //如果距离数据收不到,给上位机发送NelseTX_DATA[0] = 'l';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);RX_DATA[0] = 0;}else if(RX_DATA[0] == 'g')           //测试颜色,回传当前识别到的垃圾种类{if(sevo_cmd_type == GARBAGE_1){//                  TX_DATA[0] = 'h';    TX_DATA[0] = 'k';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}else if(sevo_cmd_type == GARBAGE_2){//                  TX_DATA[0] = 'h';    TX_DATA[0] = 'i';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}else if(sevo_cmd_type == GARBAGE_3){//                  TX_DATA[0] = 'h';    TX_DATA[0] = 'o';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}else if(sevo_cmd_type == GARBAGE_4){//                  TX_DATA[0] = 'h';    TX_DATA[0] = 'v';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}else                   //表示当前没有识别到垃圾{
//                  TX_DATA[0] = 'h';    TX_DATA[0] = 't';HAL_UART_Transmit_IT(&huart4,&TX_DATA[0],1);}RX_DATA[0] = 0;}}task_count[COM_TO_Andr] = 0;}}

FPGA通信部分:用到了三级状态机

int i;
uint8_t ongoing1,ongoing2,ongoing3,ongoing4;
//与FPGA通信任务,频率5HZ
void fpga_com_task(uint32_t period)
{if(task_count[COM_TO_FPGA] >= period){//舵机运动状态机if(sevo_cmd_type == GARBAGE_1 || ongoing1 ==1)     //类型1的垃圾{if(sevo_step == 1)                               //状态1,垃圾投放进入预备状态{if(sevo_cmd == 1){                            //收到指令之后,开始投放垃圾sevo_cmd  = 0;                           //指令归0,防止重复进入该状态ongoing1 = 1;for(i=0;i<5000;i++)                      //控制水平舵机旋转到固定位置{    TX_DATA_TO_FPGA = 21;              //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF); }TX_DATA_TO_FPGA = 15;                 //舵机1旋转控制量,水平舵机停止旋转HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//              HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);for(i=0;i<30000;i++);sevo_step = 2;                           //舵机1动作完毕,进入舵机2动作状态}}else if(sevo_step == 2)                           //控制竖直舵机旋转,开始投放{     for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 134;               //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 144;           //舵机2旋转控制量  HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                      HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}sevo_step = 3;                         //舵机1停止水平旋转,开始俯仰}else if(sevo_step == 3)                           //舵机进入归位状态动作{for(i=0;i<5000;i++)                      //舵机1归位{TX_DATA_TO_FPGA = 9;   HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<3000;i++){TX_DATA_TO_FPGA = 15;                //舵机2归位HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);garbage_complete = 1;}ongoing1 = 0;                            //指示投放完毕sevo_step =1;                          //完成倾倒动作之后,状态回归垃圾投放预备状态}}else if(sevo_cmd_type == GARBAGE_2|| ongoing2 ==1)          //类型2的垃圾{if(sevo_step == 1){if(sevo_cmd == 1){sevo_cmd  = 0;ongoing2 = 1;for(i=0;i<9300;i++){TX_DATA_TO_FPGA = 23; //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF); }TX_DATA_TO_FPGA = 15; //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//              HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);sevo_step = 2;          //舵机1开始水平旋转}}else if(sevo_step == 2){for(i=0;i<8000;i++){TX_DATA_TO_FPGA = 122;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<8000;i++){TX_DATA_TO_FPGA = 144;   //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}sevo_step = 3;         //舵机1停止水平旋转,开始俯仰}else if(sevo_step == 3){for(i=0;i<9300;i++){TX_DATA_TO_FPGA = 7;   //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}sevo_step =1;          //完成倾倒动作之后,舵机2归位TX_DATA_TO_FPGA = 15;   //电机回转HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//              HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);garbage_complete = 1;ongoing2 = 0;}}else if(sevo_cmd_type == GARBAGE_3|| ongoing3 ==1)         //类型3的垃圾{if(sevo_step == 1){if(sevo_cmd == 1){sevo_cmd  = 0;ongoing3 = 1;for(i=0;i<5000;i++){TX_DATA_TO_FPGA = 9;  //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF); }TX_DATA_TO_FPGA = 15; //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//              HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);sevo_step = 2;          //舵机1开始水平旋转}}else if(sevo_step == 2){for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 126;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0X5);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 144;   //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0X5);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}sevo_step = 3;         //舵机1停止水平旋转,开始俯仰}else if(sevo_step == 3){for(i=0;i<5000;i++){TX_DATA_TO_FPGA = 21;  //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}TX_DATA_TO_FPGA = 15;  //电机回转HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//              HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);garbage_complete = 1;sevo_step =1;         //完成倾倒动作之后,舵机2归位ongoing3 = 0;}}else if(sevo_cmd_type == GARBAGE_4|| ongoing4 ==1)           //类型4的垃圾{if(sevo_step == 1){if(sevo_cmd == 1){sevo_cmd  = 0;ongoing4 = 1;for(i=0;i<9000;i++){TX_DATA_TO_FPGA = 9;  //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF); }for(i=0;i<2000;i++){TX_DATA_TO_FPGA = 15;   //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}sevo_step = 2;         //舵机1开始水平旋转}}else if(sevo_step == 2){for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 126;    //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<6000;i++){TX_DATA_TO_FPGA = 144;   //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}sevo_step = 3;         //舵机1停止水平旋转,开始俯仰}else if(sevo_step == 3){for(i=0;i<8700;i++){TX_DATA_TO_FPGA = 21;  //舵机2旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}for(i=0;i<2000;i++){TX_DATA_TO_FPGA = 15;    //舵机1旋转控制量HAL_UART_Transmit(&huart3,&TX_DATA_TO_FPGA,1,0XF);
//                  HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);}
//              HAL_UART_Receive(&huart3,&RX_DATA_FROM_FPGA,1,0XF);garbage_complete = 1;sevo_step =1;         //完成倾倒动作之后,舵机2归位ongoing4 = 0;}}task_count[COM_TO_FPGA] = 0;}}

综合项目——智能分类垃圾桶相关推荐

  1. 计算机本科毕业设计-智能分类垃圾桶

    文章目录 1. 前言 2. 系统定义 2.1 硬件装置 2.2 软件功能模块 2.2.1 环境依赖 2.2.2 软件模块 3. 详细设计 3.1 硬件设计 3.1.1 硬件零件型号 3.1.2 智能垃 ...

  2. 基于ArduinoUNO的LD3320语音识别+SYN6288语音合成的智能分类垃圾桶

    文章目录 写在前面 器件 连接 部分代码 运行结果 小结 写在前面 接上一篇文章,这次是集合了语音识别+语音合成(就是语音播报实现一种反馈)+SG90舵机实现垃圾桶的开与闭,给出上篇文章链接,如果对L ...

  3. 硬件篇:基于微信小程序的智能分类垃圾桶(详细介绍)

    硬件选择 因为我们需要实现的主要功能是控制四个垃圾桶的开合,所以舵机是必不可少的,至于用什么来控制舵机,我直接就选择了51单片机(因为我只学了51),明确了主要的硬件,进一步细化目标,用微信小程序通过 ...

  4. 基于pytorch的人工智能分类垃圾桶

    Hello,大家好,作者终于考完研了,现在开始更新自己以前的科研项目来供大家一起学习参考,开源共享,作者github网址:https://github.com/czzq1999,欢迎加油一起学习,一起 ...

  5. 无法获取 dpkg 前端锁_济南一小区分类垃圾桶上了锁?闲置不用惹居民质疑

    齐鲁晚报·齐鲁壹点记者 任玉停 目前,济南正在大力推行垃圾分类,不少社区也陆续引进了智能分类垃圾桶等相关设备.然而,家住市中区鲁能领秀城27区的业主李先生向齐鲁晚报·齐鲁壹点反映称,小区里的分类垃圾桶 ...

  6. 树莓派python交互界面实例_树莓派综合项目2:智能小车(二)tkinter图形界面控制...

    一.介绍 树莓派综合项目2:智能小车(一)四轮驱动中,实现了代码输入对四个电机的简单控制,本章将使用Python 的图形开发界面的库--Tkinter 模块(Tk 接口),编写本地运行的图形界面,控制 ...

  7. 树莓派综合项目2:智能小车(三)无线电遥控

    一.介绍   阅读本篇文章前建议先参考前期文章:   树莓派基础实验34:L298N模块驱动直流电机实验   树莓派综合项目2:智能小车(一)四轮驱动   树莓派综合项目2:智能小车(二)tkinte ...

  8. 树莓派综合项目2:智能小车(二)tkinter图形界面控制

    一.介绍   阅读本篇文章前建议先参考前期文章:   树莓派基础实验34:L298N模块驱动直流电机实验   树莓派综合项目2:智能小车(一)四轮驱动   树莓派综合项目2:智能小车(一)四轮驱动中, ...

  9. arduino智能闹钟_【Arduino综合项目】小闹钟

    小闹钟项目 在额济纳支教这一年,给孩子们上了很多Arduino开发的课,也带他们完成了几个Arduino综合项目,下面陆续把这些小项目放上来,欢迎围观~~~非科班出身,C语言学的不好,望各路大神批评指 ...

最新文章

  1. python怎么做折线图_python怎么画折线图
  2. java多线程3.设计线程安全类
  3. Fragment生命周期与Fragment执行hide、show后的生命周期探讨
  4. poco c++ 开发指南_掌握这个框架,你将会开发通杀全平台的万能爬虫
  5. POJ - 3278 Catch That Cow 简单搜索
  6. [国嵌笔记][036][关闭MMU和CACHE]
  7. Python面向对象(类的成员之属性)
  8. OJ1027: 判断水仙花数
  9. 队列处理器 WorkQueueT
  10. Godot 2D 和 3D 游戏引擎
  11. GDBT、AdaBoost、XGBoost提升算法解析
  12. 中山大学计算机学院离散数学,《离散数学》课程习题与解答(2011级使用)中山大学计算机科学系_推荐.pdf...
  13. MIT 18.01 单变量微积分总结
  14. oracle 建表sql语句,oracle 建表sql语句
  15. PcShare远程控制
  16. 如何引用阿里云矢量图标库
  17. 中国裁判文书网全网最新爬虫分析
  18. NeoKylin(中标麒麟)6.5 更新yum源
  19. 计算机辅助设计和辅助制造简称,计算机辅助设计与制造
  20. Python 网络爬虫及数据可视化

热门文章

  1. DOTA版设计模式——命令
  2. 如何避开JavaScript浮点数计算精度问题(如0.1+0.2!==0.3)
  3. 第一章 电路模型和电路定律(习题解析)
  4. 电路习题解答 第一章 1-1、1-2
  5. 牛逼了!菜鸟也能用Python演奏一段钢琴曲
  6. Android的微信智能心跳方案
  7. 【leetcode】2022.1.2 消除游戏
  8. [C/C++]员工考勤记录 - 2019校招编程刷题
  9. Vue3 +TypeScript 引入 BabylonJs(Vue3实现3D)【一篇文章精通系列】
  10. 锐捷RSE-CLOUD云开课了