[Micropython]TPYBoard v102 DIY照相机
摄像头(CAMERA或WEBCAM)又称为电脑相机、电脑眼、电子眼等,是一种视频输入设备,被广泛的运用于视频会议,安防系统 、图像采集系统、 环境监控 、工业现场过程控制 等方面。本实验用TPYBoard v102以及PTC06 串口摄像头模块DIY一个简易的照相机。
1.所用器材:
l TPYBoard v102 1块
l PTC06 串口摄像头模块1个
l 杜邦线若干
l TF卡1个
l 下载数据线1条
2.TPYBoard v102简介:
TPYBoardv102主控芯片采用STM32F405,M4的内核,168MHZ的最高运行速度,1024KB的Flash,192KB的RAM,内置SD卡槽,最大支持8G内存的内存卡。板载四个LED灯和一个加速度传感器。TPYBoard v102板载30个通用GPIO接口、 2个SPI接口、2个CAN接口、2个I2C接口、 5个USART 接口、 2个ADC接口(精度12bit )、2个DAC接口、1个SWD接口。可与大部分常用传感器模块连接。
3. PTC06 串口摄像头模块简介:
PTC06 串口摄像头模块是一款集图像采集、拍摄控制、数据压缩、串口传输于一体的工业级图像采集处理模块。其内置的高性能数字信号处理芯片实现了对原始图像的高比例压缩。产品图像输 出采用标准 JPEG 格式,可方便地兼容各种图像处理软件;采用 3 线制 TTL 电平 UART 通 信接口,可以方便地实现与单片机或其他微处理器连接。
默认波特率为 115200,其它可选波特率有 9600,19200,38400 和 57600。
其中对于串口控制拍照,读取静态图片的应用中,只需要用到 GND,RX,TX,VCC 这 4 个信号线。 如果是要输出模拟视频的应用,才需要将 CVBS 信号。注意: TX 和 RX 是 3.3v 的 TTL 电平信号。
4.接线方式:
5.实验步骤.
基本原理:TPYboard v102 通过串口与串口摄像头模块(PTC06)进行连接,通过按键控制模块进行拍照,并保存到TF卡中。上电后,等待ToyBoard v102板载绿灯亮起,说明摄像头模块初始化完毕,按一下USR键,控制摄像头进行拍照,蓝灯会闪烁,说明正在传输图片数据,等待蓝灯熄灭后,说明传输完毕。按一下rst键让板子重新加载一下TF卡,打开TF卡就会看到一个新生成的jpeg文件。
6.源代码:
""" #TPYBoard v102 驱动串口摄像头PTC06 拍照并保存到TF卡 #------------------------------------------------------ #作者:山东萝卜电子科技有限公司 #时间:2018年03月15日 """ import pyb from pyb import UART,Switch """ 拍照的基本流程 -------------------- 1.清空图片缓存 2.发送拍照命令 3.获取图片的长度 4.根据长度读取图片数据 使用到的指令与返回的数据格式 ------------------------------- 复位 0x56 0x00 0x26 0x00 返回 0x76 0x00 0x26 0x00 +DSP 版本信息+Init end ------------------------ 清空图片缓存 0x56 0x00 0x36 0x01 0x02 返回 0x76 0x00 0x36 0x00 0x00 ------------------------- 拍照命令 0x56 0x00 0x36 0x01 0x00 返回 0x76 0x00 0x36 0x00 0x00 -------------------------- 读所拍图片的长度 56 00 34 01 00 返回 0x76 0x00 0x34 0x00 0x04 0x00 0x00 XX YY (XX 为高位字节,YY 为低位字节) -------------------------- 读取图片数据 0x56 0x00 0x32 0x0C 0x00 0x0A 0x00 0x00 AA BB 0x00 0x00 XX YY 0x00 0xFF AA BB:起始地址(先高位字节,后低位字节.必须是8的倍数) XX YY:本次读的数据长度(先高位字节,后低位字节) 返回 76 00 32 00 00 FF D8 ....... FF D9 76 00 32 00 00 (完整的JPEG 图片文件是以 FF D8 开始 FF D9 结尾) """ #-----Command---------# initcmd=b'\x56\x00\x26\x00' #复位指令 clearcmd=b'\x56\x00\x36\x01\x02' #清除缓存 photocmd=b'\x56\x00\x36\x01\x00' #拍照 lengthcmd=b'\x56\x00\x34\x01\x00' #获取图片长度 readcmd=b'\x56\x00\x32\x0C\x00\x0A\x00\x00' #获取图片数据 responseCmd=b'\x76\x00\x32\x00\x00'#返回的图片数据固定头和尾 #---------------------------------# isFlag=0#标识是否初始化 isPhoto=0#标识是否发送拍照命令 num=1 f_name='/sd/photo%s.jpeg'#保存的文件名称 nBytes=512#每次读取的字节数 #---------------------------------# uart=UART(4,115200,timeout=100)#串口4 TX-X1 RX-X2 #------将10进制转为16进制字节数组--------# def convert_Data(num): if num>255: num_h=hex(num) if len(num_h)<6: num_h_a=num_h[:3] num_h_b='0x'+num_h[3:] else: num_h_a=num_h[:4] num_h_b='0x'+num_h[4:] byte_num=bytes([int(num_h_a,16),int(num_h_b,16)]) else: byte_num=b'\x00'+bytes([num]) return byte_num #--------------------------------- #函数名:get_photo #描述:获取图片数据 #参数:起始地址、读取长度 #返回:成功返回正常数据,失败返回0 #---------------------------------/ def get_photo(add,readlen): global readcmd,responseCmd cmd=readcmd+add+b'\x00\x00'+readlen+b'\x00\xFF' uart.write(cmd) while uart.any()<=0: continue data=uart.read() #print('data:',data) #print('data[0:5]:',data[0:5]) #print('data[-5:]:',data[-5:]) if data[0:5]==responseCmd and data[-5:]==responseCmd: revdata=data[5:-5] print('revdata:',revdata) else: revdata=0 return revdata #--------------------------------- #函数名:test #描述:USR按键的回调函数。 #按键每按1次拍照1次 #---------------------------------/ def test(): global num,isPhoto pyb.delay(30) if(sw()): sw.callback(None)#正在获取数据时 禁用回调 isPhoto=0 num+=1 pyb.LED(3).on() #清除缓存 uart.write(clearcmd) #等待模块上电完毕 print('wait......') pyb.delay(2800) print('init start.......') uart.write(initcmd) sw=Switch() sw.callback(test) while True: if uart.any()>0: data=uart.read() print('revdata:',data) if isFlag==0: #说明接收的是复位后的信息 if data==b'Init end\r\n': #复位完毕 print('init ok.......') pyb.delay(2000) isFlag=1 pyb.LED(2).on() else: if len(data)>=5: if data[0]==118:#0x76 if data[2]==54:#0x36 if isPhoto==0: #清除缓存返回 print('-----clear buffer ok----') isPhoto=1 uart.write(photocmd) else: #拍照返回 print('-----taking pictures ok----') uart.write(lengthcmd) if data[2]==52:#0x34 print('photo length:',data[7],'-',data[8]) tlen=data[7]*256+data[8] t_c=tlen//nBytes t_y=tlen%nBytes add=0 #256=[0x01,0x00] 512=[0x02,0x00] length=convert_Data(nBytes) name=f_name % str(num) print('filename:',name) for i in range(0,t_c): add=convert_Data(i*nBytes) #每512字节写一次 revdata=get_photo(add,length) if revdata!=0: f=open(name,'a') f.write(revdata) f.close() pyb.LED(4).toggle() print('-------------',i) pyb.delay(100) add=convert_Data(t_c*nBytes) revdata=get_photo(add,convert_Data(t_y)) if revdata!=0: f=open(name,'a') f.write(revdata) f.close() pyb.LED(3).off() pyb.LED(4).off() pyb.delay(100) print('*========================================*') sw.callback(test) else: print('-----data length error-----')