日知录(15):记药盒的串口通信
十月中旬有一个答辩要去做,原本有点懈怠了,可想了想不能错过每个可以全力以赴的机会,所以硬着头皮继续刚。
我涉及到的主要是树莓派与arduino 的串口通信。想要实现的功能是在传送带上的药片经过颜色识别,输出的返回值,经过串口通信,传递给arduino,进而驱动舵机进行相应的转动。
作为这次小PI首次出山的记录篇,就把所有结构控制方面都给整理一遍。
答辩结束了,感觉这次自己偏控制方向多一点,只是因为对python的理解没有很到位,所以到了后面我就打下手了。
1进药–传送带部分
1.1齿轮减速
解决的是arduino带动小齿轮,经过减速比1:6之后带动传送带转动。
这部分用的是黄色香蕉电机,电机驱动板是L298N,简单的控制了一下,就Ok了。
此处参考如何用L298N电机驱动模块与Arduino实现PWM调速
这个链接是关于用L298N给直流电机调速用的。
把跳线帽去掉之后,内侧或外侧,一个接数字引脚,一个接5V引脚。如果调速效果不明显,可能是ENA那两个引脚接反了,此处带动同步带的效果不明显。
期间还用了28BYJ-48步进电机和ULN2003驱动器板试试,结果可能我不太会调速,Arduino - 28BYJ-48步进电机+ULN2003驱动模块
参考这篇文章,里面写到的是,一般是15r/min,带动同步带轮的效果没有之前的好。
所以就采用小的黄色电机了。
1.2颜色识别
解决的是颜色识别,对opencv有了更深点的认识,cv.waitkey()内更改帧频,从而让识别不那么卡顿。之前因为加了cv.waitkey(5000)之后识别窗口一直很卡。之后修改了之后识别速度可以了。不过想实现的是一个物体识别过后有一个计数功能,这里倒是有点难度。
关于C++和python两个版本,可能在修改过程有所不同,所以C++运行效果还不错,python就有点卡。
要给 C++写一个主函数,这样方便调用吧。
这个部分目前决定还是用电脑上的C++来实现。用python还是有点困难。
问了很多人,也知道问题所在,但是不知道怎么修改。看我前面发了那么多学习python的博客,可一旦涉及到实操,就显得有点拙劣了。
这个问题是比较广泛性的,就是当摄像头在以 一定帧频获取实时图像时,再都对图像进行处理,再用函数进行判断,这个处理的过程较长,比如是0.5s。但摄像头每秒获取几十张实时图像,处理速度跟不上获取速度,所以在显示窗口一直停在了第一帧。可以尝试用延时:cv2.waitKey()或者 time.sleep(),效果大概是可以持续运行十几秒,之后又卡在了某一帧上。
同时,在编写python的时候,由于它是交互式语言,而且是从第一行执行到最后一行,没有涉及函数,所以整体执行速度会比较慢。当一个程序在电脑上面可以运行,但换了别的设备后就出现卡顿。第一可能是硬件的问题,比如显卡,CPU处理之类的;第二可以考虑将C++程序改为python时,考虑其语言本身的特点,结合函数调用,(这个我要查一下资料)。
以我目前的python 水平暂时还没办法解决这个问题,总是后知后觉的,也是这次才刚学会PWM的调速精髓,这是我去年一直追着某位学长问的问题啊。不过这样成长的速度好像太慢了,尽量在这之后也深入研究一下。
用python3实现raspberry pi(树莓派)两路舵机摄像头控制程序
树莓派4B 引脚图
使用OpenCV调用摄像头检测人脸并截图-Python
2.出药—串口通信
2.1 药品分拣–导轨+舵机双门
树莓派与arduino的串口通信。and 万物从点灯开始,点灯会了,别的大体都触类旁通。通信的结果是还行。不过我想实现那种就是通过我这边的发送多个不同的信号,让arduino的if判断进行哪一个控制。可以实现串口通信了,但存在一定的延时。
用Python脚本控制LED灯的开关并获取光强值
此处是亲测的一个树莓派通过发送三个信号给arduino,并且arduino进行信号接收和返回的一个程序。
树莓派部分的代码:
arduino部分的代码:
存在的延迟效果如下:
在第二次对串口输入1,第一二次的返回结果才一起出现。
贴一个亲测有效的链接。
两大开源硬件之树莓派与Arduino的USB串口通讯
TypeError: unicode strings are not supported,的解决办法:
添加encode()方法
这个部分最后由于树莓派python处理图像太慢,就直接用电脑进行颜色识别并且对于arduino进行串口通信控制舵机,进行两个门的关闭。
2.2 药品弹出–舵机控制+LCD显示屏
使用Arduino连接一个LCD显示屏
显示屏主要是显示药片进入后的数量,以及出药后的当前药片数量。所以这是一个非常庞大的串口通信过程。识别完颜色之后,显示屏要显示药片数量,并且控制舵机门的转动。之后接上8266的定时器和蜂鸣器,当指定吃药时间到达后,先移动到指定地点,蜂鸣器响起,再根据红外信号,是否有人靠近,靠近后,就驱动另外3个舵机进行药品弹出。omg,突然觉得这上面一块arduino也不够了。那就是 电脑----arduino-----esp8266.5个舵机可以用一个舵机控制板来驱动,再带上那些附加功能,不得了,果然是一个庞大的工程,而且我们目前还没完成。只是断章取义演示了一遍。
3.一些弯路实验
这是一个循序渐进的过程,原本我还不会用面包板呢,也是这次学会的,面包板+Pi+点灯,之后用arduino+面包板+点灯。之后先断电,再给硬件电路连好之后上电。通过树莓派与Arduino的通信之后控制LED灯,下一步再试试控制舵机。
3.1继电器
根据不同的串口信号进行不同的控制
因为树莓派–>arduino—>舵机,arduino给舵机的电流太低了,要加一个继电器,用以放大电流。首先看一个是
arduino的继电器实验,
注意要先理解继电器的电路原理。一个电磁继电器,单刀双掷开关进行高压电路和低压电路的连接。
接下来进行继电器控制一个LED的实验,这个部分并不难。主要就是要有一个合适的外接电源,如果太大,就加电阻,保证比如LED灯的安全电压是3.3V,过载就会烧掉。我已经因为自己单纯的电路知识少点了两个LED以及两个arduino了,冒过烟,烫过手,焊过锡,这弯路走的够多了。之后用arduino+继电器+SG90舵机的连接,我还是没想明白,舵机的信号线接给了arduino。继电器只当做是一个开关的话,那也没什么关系吧。之前是通过继电器的开闭控制LED的亮灭,那舵机应该同理。就只相当于在arduino与舵机之间多加了一个控制的开关吧。
2.外接电源
朋友说可以加个外接电源。那个是面包板电源,输出5/12V,接在了5V上面,所以可能是强行给arduino5V了吧。
在加了面包板电源之后,树莓派与arduino之间的通信已经ok。可以有返回值,也可以有舵机转动。
整体想法如下:
明天上午给实现吧。
3.蜂鸣器
贴一个链接
有源蜂鸣器与无源蜂鸣器有什么区别?
arduino控制蜂鸣器播放《小星星》
4.esp8266 暂未实现
ESP32 arduino 天气显示 后台可控制 定时消息提示 图片提示
使用ESP8266加蜂鸣器,做一个定时闹钟
5.舵机控制板
PCA9685控制8路SG90舵机实现四足机器人行走
6. 舵机
arduino:舵机的驱动
4.整体实现
5.1 LCD
使用Arduino连接一个LCD显示屏
参考如上。
也可以显示变量。
将"100"修改成变量i,j,k,即可显示变量。
lcd.setCursor(0,0);lcd.write(byte(0)); lcd.print(i);lcd.write(byte(1));lcd.print(j);lcd.write(byte(2));lcd.print(n);5.2 舵机
调整好舵机的初始位置,进行旋转设置
5.3 颜色识别
5.3.1 无计数C++
#include<tchar.h> #include<math.h> #include<Windows.h> #include<string.h> #include "opencv2/opencv.hpp" #include <iostream> #include <stdio.h> #include <vector> #include<opencv2/highgui/highgui_c.h> #define UNIT_PIXEL_W 0.00009234375 #define UNIT_PIXEL_H 0.0000925 using namespace std; using namespace cv;int main() {int i = 0;int a, b, c;a = b = c = 0;Mat frame, frame2, frame3;int k;VideoCapture capture;capture.open(0);if (!capture.isOpened()) {printf("The camera is not opened.\n");return EXIT_FAILURE;}for (;;){i = 0;capture >> frame;if (frame.empty()) {printf("The frame is empty.\n");break;}medianBlur(frame, frame, 3);Mat grayImage;cvtColor(frame, frame2, COLOR_BGR2HSV);for (;;){if (i == 0) {inRange(frame2, Scalar(78, 43, 46), Scalar(99, 255, 255), grayImage);//青}if (i == 1) {inRange(frame2, Scalar(100, 43, 46), Scalar(124, 255, 255), grayImage);//蓝}if (i == 2) {inRange(frame2, Scalar(0, 43, 46), Scalar(10, 255, 255), grayImage);//红}vector<vector<cv::Point>> contours;vector<cv::Point> maxAreaContour;findContours(grayImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);drawContours(grayImage, contours, -1, Scalar(0, 0, 255), 2, 8);double maxArea = 0;for (size_t i = 0; i < contours.size(); i++) {double area = fabs(contourArea(contours[i]));if (area > maxArea) {maxArea = area;maxAreaContour = contours[i];}}// 轮廓外包正矩形 Rect rect = boundingRect(maxAreaContour);rectangle(frame, rect, Scalar(255, 0, 0), 2, 8);// 计算成像宽/高 //绘制外接矩形中心点double x = (rect.x + rect.width + rect.x) / 2;double y = (rect.y + rect.height + rect.y) / 2;circle(frame, Point(x, y), 1, Scalar(0, 0, 255), 1, LINE_8, 0);if (rect.width > 10){k = 1;break;}else {k = 0;i++;continue;}if (i == 2 && k == 1)break;}switch (i) {char disk[50];case 0:a++;sprintf_s(disk, "greee%d", a);putText(frame, disk, Point(5, 20), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 255, 0), 1, 8);break;case 1:b++;sprintf_s(disk, "blue%d", b);putText(frame, disk, Point(5, 20), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255, 0, 0), 1, 8);break;case 2:c++;sprintf_s(disk, "yullow%d", c);putText(frame, disk, Point(5, 20), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0,0, 255), 1, 8);break;}imshow("Frame", frame);imshow("Gray", grayImage);if ((waitKey(10) & 0XFF) == 27) break;}destroyAllWindows();capture.release();return EXIT_SUCCESS; }5.3.2 计数C++
#include<tchar.h> #include<math.h> #include<Windows.h> #include<string.h> #include "opencv2/opencv.hpp" #include <iostream> #include <stdio.h> #include <vector> #include<opencv2/highgui/highgui_c.h> #define UNIT_PIXEL_W 0.00009234375 #define UNIT_PIXEL_H 0.0000925 using namespace std; using namespace cv;HANDLE hCom; //全局变量,串口句柄int serial_open(LPCWSTR COMx, int BaudRate) {hCom = CreateFile(COMx, //COM1口 GENERIC_READ | GENERIC_WRITE, //允许读和写 0, //独占方式 NULL,OPEN_EXISTING, //打开而不是创建 0, //重叠方式FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED (同步方式设置为0)NULL);if (hCom == INVALID_HANDLE_VALUE){printf("打开COM失败!\n");return FALSE;}SetupComm(hCom, 1024, 1024); //输入缓冲区和输出缓冲区的大小都是1024 DCB dcb;GetCommState(hCom, &dcb);dcb.BaudRate = BaudRate; //设置波特率为BaudRatedcb.ByteSize = 4; //每个字节有8位 dcb.Parity = NOPARITY; //无奇偶校验位 dcb.StopBits = ONESTOPBIT; //一个停止位SetCommState(hCom, &dcb); //设置参数到hComPurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓存区 / return TRUE; } int serial_write(char lpOutBuffer[]) //同步写串口 {DWORD dwBytesWrite = sizeof(lpOutBuffer);COMSTAT ComStat;DWORD dwErrorFlags;BOOL bWriteStat;ClearCommError(hCom, &dwErrorFlags, &ComStat);bWriteStat = WriteFile(hCom, lpOutBuffer, dwBytesWrite, &dwBytesWrite, NULL);if (!bWriteStat){printf("写串口失败!\n");return FALSE;}for (size_t i = 0; i < dwBytesWrite / 4; i++)printf("should be write %x \n", lpOutBuffer[i] - '0');PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);return TRUE; }void Serial_close(void) //关闭串口 {CloseHandle(hCom); }int main() {char going_write[100];serial_open(_T("COM3"), 9600);int jinb =0, chub = 0;int jing = 0, chug = 0;int jinr = 0, chur = 0;char disxj[50], disxc[50];int i = 0;int a, b, c;a = b = c = 0;Mat frame, frame2, frame3;int k;VideoCapture capture;capture.open(1);char disx[50];if (!capture.isOpened()) {printf("The camera is not opened.\n");return EXIT_FAILURE;}for (;;){i = 0;capture >> frame;if (frame.empty()) {printf("The frame is empty.\n");break;}medianBlur(frame, frame, 3);Mat grayImage;cvtColor(frame, frame2, COLOR_BGR2HSV);for (;;){if (i == 0) {inRange(frame2, Scalar(100, 43, 46), Scalar(124, 255, 255), grayImage);//蓝}if (i == 1) {inRange(frame2, Scalar(78, 43, 46), Scalar(99, 255, 255), grayImage);//青}if (i == 2) {inRange(frame2, Scalar(0, 43, 46), Scalar(10, 255, 255), grayImage);//红}if (i == 3) {inRange(frame2, Scalar(0, 0, 0), Scalar(180, 255, 46), grayImage);//黑}vector<vector<cv::Point>> contours;vector<cv::Point> maxAreaContour;findContours(grayImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);drawContours(grayImage, contours, -1, Scalar(0, 0, 255), 2, 8);double maxArea = 0;for (size_t i = 0; i < contours.size(); i++) {double area = fabs(contourArea(contours[i]));if (area > maxArea) {maxArea = area;maxAreaContour = contours[i];}}// 轮廓外包正矩形 Rect rect = boundingRect(maxAreaContour);rectangle(frame, rect, Scalar(255, 0, 0), 2, 8);// 计算成像宽/高 //绘制外接矩形中心点double x = (rect.x + rect.width + rect.x) / 2;double y = (rect.y + rect.height + rect.y) / 2;circle(frame, Point(x, y), 1, Scalar(0, 0, 255), 1, LINE_8, 0);//镜头中心点double x2 = (frame.rows) / 2;double y2 = (frame.cols) / 2;Rect rect2(0, 0, x2, y2);circle(frame, Point(x2, y2), 1, Scalar(0, 255, 0), 1, LINE_8, 0);double x3 = x - x2;if (rect.width > 10&&i!=3){if (x < x2){switch (i) {case 0:jinb = 1;break;case 1:jing = 1;break;case 2:jinr = 1;break;}}if (x >= x2){switch (i) {case 0:if(jinb==1)chub = 1;break;case 1:if(jing==1)chug = 1;break;case 2:if(jinr==1)chur = 1;break;}}k = 1;break;}else {k = 0;i++;continue;}if (i == 2 && k == 1)break;}switch (i){case 0:if (jinb == 1 && chub == 1){a++;jinb = 0;chub = 0;}printf("message send to MCU:");going_write[0] = 'a';serial_write(going_write);break;case 1:if (jing == 1 && chug == 1){b++;jing = 0;chug = 0;}printf("message send to MCU:");going_write[0] = 'b';serial_write(going_write);break;case 2:if (jinr == 1 && chur == 1){c++;jinr = 0;chur = 0;}printf("message send to MCU:");going_write[0] = 'c';serial_write(going_write);break;case 3:break;}char disk[50];sprintf_s(disk, "blue %d", a);putText(frame, disk, Point(5, 20), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255, 0, 0), 1, 8);//sprintf_s(disxj, "jinb%d", jinb);//putText(frame, disxj, Point(5, 40), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255, 0, 0), 1, 8);//sprintf_s(disxc, "chub%d", chub);//putText(frame, disxc, Point(5, 60), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255, 0, 0), 1, 8);sprintf_s(disk, "green %d", b);putText(frame, disk, Point(5, 80), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 255, 0), 1, 8);//sprintf_s(disxj, "jing%d", jing);//putText(frame, disxj, Point(5, 100), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 255, 0), 1, 8);//sprintf_s(disxc, "chug%d", chug);//putText(frame, disxc, Point(5, 120), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 255, 0), 1, 8);sprintf_s(disk, "red %d", c);putText(frame, disk, Point(5, 140), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 0, 255), 1, 8);//sprintf_s(disxj, "jinr%d", jinr);//putText(frame, disxj, Point(5, 160), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 0, 255), 1, 8);//sprintf_s(disxc, "chur%d", chur);//putText(frame, disxc, Point(5, 180), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(0, 0, 255), 1, 8);imshow("Frame", frame);imshow("Gray", grayImage);if ((waitKey(10) & 0XFF) == 27) break;}capture.release();destroyAllWindows();}5.3.3无计数python延时
import numpy as np import cv2 import timeblue_lower = np.array([100, 43, 46]) blue_upper = np.array([124, 255, 255]) green_lower = np.array([26, 43, 46]) green_upper = np.array([34, 255, 255]) red_lower = np.array([0, 43, 46]) red_upper = np.array([10, 255, 255]) cap = cv2.VideoCapture(1)cap.set(3, 320) cap.set(4, 240) a = b = c = 0 while 1:i = 0ret, frame = cap.read()# frame = cv2.GaussianBlur(frame, (5, 5), 0)hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)while 1:if i == 0:mask = cv2.inRange(hsv, blue_lower, blue_upper) # 蓝if 1 == i:mask = cv2.inRange(hsv, green_lower, green_upper) # 黄if i == 2:mask = cv2.inRange(hsv, red_lower, red_upper) # 红cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]if len(cnts) > 0:# 寻找面积最大的轮廓并画出其最小外接圆cnt = max(cnts, key=cv2.contourArea)(x, y), radius = cv2.minEnclosingCircle(cnt)cv2.circle(frame, (int(x), int(y)), int(radius), (255, 0, 255), 2)# 找到物体的位置坐标,获得颜色物体的位置,可以来控制小车的转向print(int(x), int(y))k = 1breakelse:k = 0i = i + 1continueif i == 0:a = a + 1disk = "blue%d" % (a)print(disk)cv2.putText(frame, disk, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)if i == 1:int_b = b + 1disk = "yellow%d" % (b)print(disk)cv2.putText(frame, disk, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)if i == 2:int_c = c + 1disk = "red%d" % (c)print(disk)cv2.putText(frame, disk, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)cv2.imshow('frame', frame)cv2.imshow('mask', mask)if cv2.waitKey(5) & 0xFF == 27:breakcv2.waitKey(1000) # 500 =0.5s cap.release() cv2.destroyAllWindows()5.3.4 计数python
import numpy as np import cv2jinr = 0 chur = 0 k = 0 blue_lower = np.array([100, 43, 46]) blue_upper = np.array([124, 255, 255]) green_lower = np.array([26, 43, 46]) green_upper = np.array([34, 255, 255]) red_lower = np.array([0, 43, 46]) red_upper = np.array([10, 255, 255]) dark_lower = np.array([0, 0, 0]) dark_upper = np.array([10, 255, 46]) cap = cv2.VideoCapture(0) cap.set(3, 320) cap.set(4, 240) a = b = c = 0 while 1:i = 0ret, frame = cap.read()hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)while 1:if i == 0:mask = cv2.inRange(hsv, blue_lower, blue_upper) # 蓝if i == 1:mask = cv2.inRange(hsv, green_lower, green_upper) # 黄if i == 2:mask = cv2.inRange(hsv, red_lower, red_upper) # 红if i == 3:mask = cv2.inRange(hsv, dark_lower, dark_upper) # 黑cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]h, w ,ch= frame.shapex2 = h / 2y2 = w / 2if len(cnts) > 0 & i <= 3:# 寻找面积最大的轮廓并画出其最小外接圆cnt = max(cnts, key=cv2.contourArea)(x, y), radius = cv2.minEnclosingCircle(cnt)cv2.circle(frame, (int(x), int(y)), int(radius), (255, 0, 255), 2)cv2.circle(frame, (int(x), int(y)), 1, (250, 0, 0), 2)print(int(x), int(y))if x < x2:if i == 0:jinb = 1if i == 1:jing = 1if i == 2:jinr = 1if x >= x2:if i == 0:chub = 1if i == 1:chug = 1if i == 2:chur = 1k = 1breakelse:k = 0i = i + 1continueif i == 2 & k == 1:breakif i == 0:if jinb == 1 & chub == 1:a = a + 1jinb = 0chub = 0disk = "blue%d" % aprint(disk)cv2.putText(frame, disk, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)diskj = "jinblue%d" % jinbprint(diskj)cv2.putText(frame, diskj, (5, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)diskc = "chublue%d" % chubprint(diskc)cv2.putText(frame, diskc, (5, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)# 串口:if i == 1:if jing == 1 & chug == 1:b = b + 1jing = 0chug = 0disk = "yellow%d" % bprint(disk)cv2.putText(frame, disk, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)diskj = "jingreen%d" % jingprint(diskj)cv2.putText(frame, diskj, (5, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)diskc = "chugreen%d" % chugprint(diskc)cv2.putText(frame, diskc, (5, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)# 串口:if i == 2:if jinr == 1 & chur == 1:c = c + 1jinr = 0chur = 0disk = "yellow%d" % cprint(disk)cv2.putText(frame, disk, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)diskj = "jinred%d" % jinrprint(diskj)cv2.putText(frame, diskj, (5, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)diskc = "chured%d" % churprint(diskc)cv2.putText(frame, diskc, (5, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)# 串口:if i == 3:breakcv2.imshow('frame', frame)cv2.imshow('mask', mask)if cv2.waitKey(5) & 0xFF == 27:breakcap.release() cv2.destroyAllWindows()总结
以上是生活随笔为你收集整理的日知录(15):记药盒的串口通信的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Android利用Cookie实现码源登
- 下一篇: 上海域格LTE模块CLM920_JC3贴