与Arduino和Python的慢速串行通信
在我的一个项目中,我必须从一个连接到Sony Spresense Arduino板的相机上拍照,该板通过USB端口连接到我的电脑。我在Arduino和串行通信方面不是很有经验,事实上一点也没有,所以我请求一些帮助 我想从相机中读取数据,该数据以十六进制形式从Arduino通过串口发送到我的计算机。以给定的波特率开始,由Python程序处理,以收集十六进制代码,纠正它(出现了一些打印错误,现已解决),并将其转换为JPEG图像。 我能够做到这一点,但我的程序中Python从Arduino收集数据的串行通信部分速度非常慢,需要34秒才能以115200的波特率获得一个“仅”100KO的图像(我不知道对于Arduino来说这是否太难处理)。如果我试图增加这个数字,收集到的十六进制代码会显示一些错误,并且图像无法转换。我也可以更改图像的像素分辨率,但我希望能够处理高清图片 具体来说,这是Arduino的代码,我没有找到其他方法从相机获取数据(Spresense库中没有设计用于串行通信的函数)。相关部分在末尾:与Arduino和Python的慢速串行通信,python,arduino,hex,jpeg,spresense,Python,Arduino,Hex,Jpeg,Spresense,在我的一个项目中,我必须从一个连接到Sony Spresense Arduino板的相机上拍照,该板通过USB端口连接到我的电脑。我在Arduino和串行通信方面不是很有经验,事实上一点也没有,所以我请求一些帮助 我想从相机中读取数据,该数据以十六进制形式从Arduino通过串口发送到我的计算机。以给定的波特率开始,由Python程序处理,以收集十六进制代码,纠正它(出现了一些打印错误,现已解决),并将其转换为JPEG图像。 我能够做到这一点,但我的程序中Python从Arduino收集数据的串
#include <SDHCI.h>
#include <stdio.h> /* for sprintf */
#include <Camera.h>
#define BAUDRATE (115200)
/**
* Print error message
*/
void printError(enum CamErr err)
{
Serial.print("Error: ");
switch (err)
{
case CAM_ERR_NO_DEVICE:
Serial.println("No Device");
break;
case CAM_ERR_ILLEGAL_DEVERR:
Serial.println("Illegal device error");
break;
case CAM_ERR_ALREADY_INITIALIZED:
Serial.println("Already initialized");
break;
case CAM_ERR_NOT_INITIALIZED:
Serial.println("Not initialized");
break;
case CAM_ERR_NOT_STILL_INITIALIZED:
Serial.println("Still picture not initialized");
break;
case CAM_ERR_CANT_CREATE_THREAD:
Serial.println("Failed to create thread");
break;
case CAM_ERR_INVALID_PARAM:
Serial.println("Invalid parameter");
break;
case CAM_ERR_NO_MEMORY:
Serial.println("No memory");
break;
case CAM_ERR_USR_INUSED:
Serial.println("Buffer already in use");
break;
case CAM_ERR_NOT_PERMITTED:
Serial.println("Operation not permitted");
break;
default:
break;
}
}
void CamCB(CamImage img)
{
/* Check the img instance is available or not. */
if (img.isAvailable())
{
/* If you want RGB565 data, convert image data format to RGB565 */
img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
}
else
{
Serial.print("Failed to get video stream image\n");
}
}
/**
* @brief Initialize camera
*/
void setup()
{
CamErr err;
/* Open serial communications and wait for port to open */
Serial.begin(BAUDRATE);
while (!Serial)
{
; /* wait for serial port to connect. Needed for native USB port only */
}
/* begin() without parameters means that
* number of buffers = 1, 30FPS, QVGA, YUV 4:2:2 format */
Serial.println("Prepare camera");
err = theCamera.begin();
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/* Start video stream.
* If received video stream data from camera device,
* camera library call CamCB.
*/
Serial.println("Start streaming");
err = theCamera.startStreaming(true, CamCB);
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/* Auto white balance configuration */
// Serial.println("Set Auto white balance parameter");
err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/* Set parameters about still picture.
* In the following case, QUADVGA and JPEG.
*/
Serial.println("Set still picture format");
// err = theCamera.setStillPictureImageFormat(
// CAM_IMGSIZE_QUADVGA_H,
// CAM_IMGSIZE_QUADVGA_V,
// CAM_IMAGE_PIX_FMT_JPG);
//err = theCamera.setStillPictureImageFormat(320, 240, CAM_IMAGE_PIX_FMT_JPG);
err = theCamera.setStillPictureImageFormat(CAM_IMGSIZE_QUADVGA_H, CAM_IMGSIZE_QUADVGA_V, CAM_IMAGE_PIX_FMT_JPG);
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/**
* @brief Take picture with format JPEG per second
*/
/******** Affichage serie ********/
/* une ligne de vide et l'image */
Serial.println(" ");
CamImage img = theCamera.takePicture();
/* Check availability of the img instance. */
/* If any error was occured, the img is not available. */
if (img.isAvailable())
{
/*Indicateur de debut img : FFD8FF (Magic number of the jpeg format) */
for(int i=0;i<img.getImgSize();i++)
{
Serial.print(*(img.getImgBuff()+i),HEX); //img.getImgBuff() gets the data address of the picture, so the * before.
Serial.print(";");
}
/*End indicator : FFD9FF (Magic number of jpeg format) */
}
}
void loop()
{
// put your main code here, to run repeatedly:
sleep(1);
}
如果你有任何想法或任何建议,以加快这一进程,我接受它。我听说到处都有一些流控制和缓冲区的故事,但当我试图找到与我的情况相关的东西时,我完全不知所措。提前感谢。这里不太可能有什么问题,但是您应该真正使用上下文管理器来处理Python代码中的所有文件对象。这只是一个猜测-与Pi相比,Arduino的内部内存非常少。我认为,对于图像所需的处理速度,Arduino根本不够好。对于类似的东西,我会直接将相机连接到Pi,然后从那里进行图像处理。这不太可能是一个问题,但您应该真正使用上下文管理器来处理Python代码中的所有文件对象。这只是一个猜测-与Pi相比,Arduino的内部内存非常少。我认为,对于图像所需的处理速度,Arduino根本不够好。对于类似的东西,我会直接将相机连接到Pi,然后从那里进行图像处理。
## Serial collecting the data of the picture taken by the camera
import serial
from serial import Serial
import binascii
import string
from PIL import Image
import time
start_time = time.time()
ser = serial.Serial('COM3', baudrate=115200, timeout=1)
# writing the data in a text file
data = open("data.txt", "w")
data.write(str(ser.readlines()))
## Correcting the data
data = open("data.txt", "r")
string = str(data.readlines())
# spliting the string into a list
# I chose to use the ";" to split the different hex couples in the Arduino program
tab=string.split(";")
tab[0] = 'FF'
tab.pop(-1)
N = len(tab)
# correcting the arguments that are not couples :
# Indeed, when Arduino encounter a couple starting with a 0,
# it omits it, so I have to add it back manually
for i in range(N):
if len(tab[i]) == 1:
tab[i] = '0' + tab[i]
newdata = open("newdata.txt", "w")
# writing the new data in a text file
for s in tab:
newdata.write(s)
newdata.close()
data.close()
## Converting the hex data into a JPEG file
file = open("newdata.txt", "r")
data= file.read()
# conversion
data = binascii.a2b_hex(data)
# creation of the JPEG file
with open('imagenew.jpg', 'wb') as image_file:
image_file.write(data)
file.close()
img = Image.open('imagenew.jpg')
img.show()
print("--- %s seconds ---" % (time.time() - start_time))