完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、机械结构设计
1.Solidworks建模 示例:采用双层履带结构 2.建模的不足以及改进 1.挡板的添加 从上履带识别后,移交至第二层履带时。会出现飞出去的情况导致分类失败,于是我们在履带两侧以及垃圾桶整体四周加上挡板。这样情况大大改善。 挡板: 2.履带防滑 当进行调试过程中,如果出现瓶子、电池等容易滚的物体,很容易在投掷过程中滚下去导致无法实现识别。为此,我们决定在履带上用胶水粘上小突起,经检验这样能很好解决这个问题。 3.整体实物 二、视觉识别部分 1.引入库 代码如下(示例): from __future__ import absolute_import from __future__ import division from __future__ import print_function import argparse import io import time import numpy as np #import picamera import cv2 import RPi.GPIO as GPIO #import tensorflow as tf from PIL import Image from tflite_runtime.interpreter import Interpreter 2.识别部分 代码如下: def load_labels(path): with open(path, 'r') as f: return {i: line.strip() for i, line in enumerate(f.readlines())} def set_input_tensor(interpreter, image): tensor_index = interpreter.get_input_details()[0]['index'] input_tensor = interpreter.tensor(tensor_index)()[0] input_tensor[:, :] = image def classify_image(interpreter, image, top_k=1): """Returns a sorted array of classification results.""" set_input_tensor(interpreter, image) interpreter.invoke() output_details = interpreter.get_output_details()[0] output = np.squeeze(interpreter.get_tensor(output_details['index'])) # If the model is quantized (uint8 data), then dequantize the results if output_details['dtype'] == np.uint8: scale, zero_point = output_details['quantization'] output = scale * (output - zero_point) ordered = np.argpartition(-output, top_k) return [(i, output) for i in ordered[:top_k]] def main(): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument( '--model', help='File path of .tflite file.', required=True) parser.add_argument( '--labels', help='File path of labels file.', required=True) args = parser.parse_args() labels = load_labels(args.labels) #interpreter = tf.lite.Interpreter(args.model) interpreter = Interpreter(args.model) interpreter.allocate_tensors() _, height, width, _ = interpreter.get_input_details()[0]['shape'] #with picamera.PiCamera(resolution=(640, 480), framerate=30) as camera: #camera.start_preview() cap = cv2.VideoCapture(0) #擷取畫面 寬度 設定為640 cap.set(cv2.CAP_PROP_FRAME_WIDTH,640) #擷取畫面 高度 設定為480 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) key_detect = 0 times=1 while (key_detect==0): ret,image_src =cap.read(0) frame_width=image_src.shape[1] frame_height=image_src.shape[0] cut_d=int((frame_width-frame_height)/2) crop_img=image_src[0:frame_height,cut_d:(cut_d+frame_height)] image=cv2.resize(crop_img,(224,224),interpolation=cv2.INTER_AREA) start_time = time.time() if (times==1): results = classify_image(interpreter, image) elapsed_ms = (time.time() - start_time) * 1000 label_id, prob = results[0] print(labels[label_id],prob) num=int(label_id) cv2.putText(crop_img,labels[label_id] + " " + str(round(prob,3)), (5,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 1, cv2.LINE_AA) times=times+1 if (times>1): times=1 cv2.imshow('Detecting....',crop_img) if cv2.waitKey(1) & 0xFF == ord('q'): key_detect = 1 cap.release() cv2.destroyAllWindows() if __name__ == '__main__': main() 以上基于tenserflow,tenserflow适合在树莓派上跑,但是如果数据集过大就会崩溃(我们就是因为这个原因,止步于省赛)建议数据集采样图片时控制在2000张左右,不然会崩 三、上下位机通信方式: 1.高低电平通信: 最开始因为下位机仅仅需要接受树莓派识别结果,而结果种类只有四种,于是乎最开始想到的是:树莓派往gpio写高低电平,stm32浮空输入电平结果,通过排列组合进行通信。源码如下: communicate.h: #define Type_2 PEin(10)// PF13 #define Type_3 PEin(11)// PF14 #define Type_4 PEin(12)// PF15 #define Type_5 PEin(13)// PF16 #define Nothing 0 #define hazardous_waste 1 #define other_waste 2 #define Recyclable_waste 3 #define Kitchen_waste 4 void communicate_Init(void);//初始化 int adjust(void); communicate.c: void communicate_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10 |GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOE, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5 GPIO_SetBits(GPIOE,GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13); //PB.5 输出高 } int adjust(void){//判断函数 delay_ms(10);//防抖 if(Type_2==0&&Type_3==1&&Type_4==1&&Type_5==1)//第一个树莓派io输出低电平为可回收 return Recyclable_waste; if(Type_2==1&&Type_3==0&&Type_4==1&&Type_5==1)//第二个io输出低电平为有害垃圾 return hazardous_waste; if(Type_2==1&&Type_3==1&&Type_4==0&&Type_5==1)//第三个输出低电平为其他 return other_waste; if(Type_2==1&&Type_3==1&&Type_4==1&&Type_5==0)//第四个输出低电平为厨余垃圾 return Kitchen_waste; return 0; } 1.2高低电平树莓派部分: GPIO.setmode(GPIO.BCM) GPIO.setup(2,GPIO.OUT) GPIO.setup(3,GPIO.OUT) GPIO.setup(4,GPIO.OUT) GPIO.setup(17,GPIO.OUT) if num == 0: GPIO.output(2,GPIO.HIGH) GPIO.output(3,GPIO.HIGH) GPIO.output(4,GPIO.HIGH) GPIO.output(17,GPIO.HIGH) print('') elif num == 1: GPIO.output(2,GPIO.LOW) GPIO.output(3,GPIO.HIGH) GPIO.output(4,GPIO.HIGH) GPIO.output(17,GPIO.HIGH) print('可回收垃圾') elif num == 2: GPIO.output(2,GPIO.HIGH) GPIO.output(3,GPIO.LOW) GPIO.output(4,GPIO.HIGH) GPIO.output(17,GPIO.HIGH) print('有害垃圾') elif num == 3: GPIO.output(2,GPIO.HIGH) GPIO.output(3,GPIO.HIGH) GPIO.output(4,GPIO.LOW) GPIO.output(17,GPIO.HIGH) print('其他垃圾') elif num == 4: GPIO.output(2,GPIO.HIGH) GPIO.output(3,GPIO.HIGH) GPIO.output(4,GPIO.HIGH) GPIO.output(17,GPIO.LOW) print('厨余垃圾') else: GPIO.output(2,GPIO.HIGH) GPIO.output(3,GPIO.HIGH) GPIO.output(4,GPIO.HIGH) GPIO.output(17,GPIO.HIGH) 2.stm32串口通信部分: void u***_communicate(void){ u16 t; u16 len; if(USART_RX_STA&0x8000){//防抖 delay_ms(100); delay_ms(100); if(USART_RX_STA&0x8000) { len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 printf("rn您发送的消息为:rnrn"); for(t=0;t USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束 } } } } int USB_adjust(void){ u***_communicate(); if(USART_RX_BUF[0]=='0'){ USART_RX_STA=0; return Nothing ;//没有垃圾 } if(USART_RX_BUF[0]=='1'){ USART_RX_STA=0; return Recyclable_waste ; }//可回收 if(USART_RX_BUF[0]=='2'){ USART_RX_STA=0; return hazardous_waste ; }//有害 if(USART_RX_BUF[0]=='3'){ USART_RX_STA=0; return other_waste;}//可回收垃圾 if(USART_RX_BUF[0]=='4'){ USART_RX_STA=0; return Kitchen_waste;}//厨余垃圾 USART_RX_STA=0; return EOF;//错误标志位 } 提示:这里对文章进行总结: 例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。 四、下位机电机驱动部分 1.电机:涡轮蜗杆电机(履带负载较大,不可直接用步进直流电机) 驱动:l298N(12V) //.h #ifndef __MOTOR_H #define __MOTOR_H #include "sys.h" #define IN_1 PFout(1)// PB5 #define IN_2 PFout(2)// PE5 #define IN_3 PFout(3)// PB5 #define IN_4 PFout(4)// PE5 #define ZHENGXIANG 0 #define FANXIANG 1 #define STOP 2 void motor_Init(void);//初始化 void zongxiang_run(u16 model); void hengxiang_run(u16 model); void _delay_s(u16 s); void stop(void); void Recyclable_waste_work(void);//可回收3号 void hazardous_waste_work(void);//有害垃圾1号 void other_waste_waste_work(void);//其他垃圾2号 void Kitchen_waste_waste_work(void);//厨余垃圾4号 #endif //.c #include "motor.h" #include "delay.h" #define ZHENGXIANG 0 #define FANXIANG 1 #define STOP 2 void motor_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOF, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5 } void hengxiang_run(u16 model){ switch(model){ case ZHENGXIANG : { IN_3=0; IN_4=1; break; } case FANXIANG :{ IN_3=1; IN_4=0; break; } case STOP:{ IN_3=1; IN_4=1; break; } } } void zongxiang_run(u16 model){ switch(model){ case ZHENGXIANG : { IN_1=0; IN_2=1; break; } case FANXIANG :{ IN_1=1; IN_2=0; break; } case STOP:{ IN_1=1; IN_2=1; break; } } } void _delay_s(u16 s){ int i; for(i=0;i<=s;i++) delay_ms(1000); } void Recyclable_waste_work(void){//可回收3号 hengxiang_run(FANXIANG); zongxiang_run(FANXIANG); _delay_s(5); zongxiang_run(STOP); hengxiang_run(STOP); _delay_s(1); } void hazardous_waste_work(void){//有害垃圾1号 zongxiang_run(ZHENGXIANG); hengxiang_run(FANXIANG); _delay_s(5); zongxiang_run(STOP); hengxiang_run(STOP); _delay_s(1); } void other_waste_waste_work(void){//其他垃圾2号 hengxiang_run(ZHENGXIANG); zongxiang_run(ZHENGXIANG); _delay_s(5); zongxiang_run(STOP); hengxiang_run(STOP); _delay_s(1); } void Kitchen_waste_waste_work(void){//厨余垃圾 hengxiang_run(ZHENGXIANG); zongxiang_run(FANXIANG); _delay_s(5); zongxiang_run(STOP); hengxiang_run(STOP); _delay_s(1); } void stop(void){ zongxiang_run(STOP); hengxiang_run(STOP); } |
|
|
|
2.有关于延时的改进:
本人在调试时发现keil环境中:delay_ms(1000)和delay_ms(3000)差别不大 竟然有一下发现: void _delay_s(u16 s){ int i; for(i=0;i<=s;i++) delay_ms(1000); }//明显好于s*delay_ms(1000) 3.stm32主函数: int main(void) { // u16 adcx; // float temp; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 LCD_Init(); Adc_Init(); //ADC初始化 POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,50,200,16,16,"Elite STM32"); LCD_ShowString(60,70,200,16,16,"ADC TEST"); LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(60,110,200,16,16,"2015/1/14"); //显示提示信息 POINT_COLOR=BLUE;//设置字体为蓝色 LCD_ShowString(60,130,200,16,16,"ADC_CH0_VAL:"); LCD_ShowString(60,150,200,16,16,"ADC_CH0_VOL:0.000V"); motor_Init(); while(1) { if(adjust()){ delay_ms(200); delay_ms(200); switch(adjust()){ case hazardous_waste:{//有害垃圾分类 hazardous_waste_work(); _delay_s(5); break;} case other_waste :{//其他垃圾分类 other_waste_waste_work(); _delay_s(5); break;} case Recyclable_waste :{//可回收垃圾分类 Recyclable_waste_work(); _delay_s(5); break;} case Kitchen_waste :{//厨余垃圾分类 Kitchen_waste_waste_work(); _delay_s(5); break;} default :{ //没垃圾 stop(); break;} } } } } 五、炸电机: 在调试过程中,我们炸了六个电机驱动,弄坏了一个步进电机原因:一夜炸了六个电机驱动,我们依次排查电路接线、程序,最后竟然是电池的原因!!! |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
568浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 16:04 , Processed in 0.960939 second(s), Total 47, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号