使用来自串行端口的字符串数据来操作振镜扫描仪在更高的速度下会出错

Using stringdata from serial port to manipulate galvo scanners goes wrong at higher speeds

本文关键字:速度 出错 扫描仪 串行端口 字符串 数据 操作      更新时间:2023-10-16

我正在使用振镜扫描仪来操纵激光。我从串行端口获取数据。此外,我正在将数据发送回串行监视器,在那里我没有任何问题。因此,问题应该是将数据从arduino传输到显示器和振镜驱动程序。如果我在 python 端使用 timesleep=1 秒,它可以工作。但它需要更快。

我已经尝试更改一些延迟并调整波特率。

我使用的Arduino代码:

///// Declaration for laser
#include "Laser.h"
// Create laser instance (with laser pointer connected to digital pin 5)
Laser laser(5);
///// Declaration for the OLED /////
#include "U8glib.h" // LCD Lib
//define ADDRESS 0x3C// address of display
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);
///// Declatation of variables /////
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = "";
int integerFromPC2 = 0;
int integerFromPC3 = 0;
//float floatFromPC = 0.0;
boolean newData = false;

//===============================================
///////////////////////////////
///////////// Setup ///////////
///////////////////////////////

void setup()
{
Serial.begin(9600); //9600 Standard
laser.init();
//laser.resetClipArea();
laser.setScale(1);
//laser.setOffset(0,0);
// assign default color value
if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
u8g.setColorIndex(255);     // white
}
else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
u8g.setColorIndex(3);         // max intensity
}
else if ( u8g.getMode() == U8G_MODE_BW ) {
u8g.setColorIndex(1);         // pixel on
}
else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
u8g.setHiColorByRGB(255,255,255);
}
pinMode(8, OUTPUT);
}

//===============================================
///////////////////////////////
///////////// Loop ////////////
///////////////////////////////
void loop() {
///// OLED: wait for serial /////
u8g.firstPage();
do {
draw();
}
while( u8g.nextPage() );
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
//   because strtok() used in parseData() replaces the commas with 
parseData();
showParsedData();
newData = false;
}
SerToLaser();
//   delay(10);
}

//========================================================
///////////////////////////////
////////// Functions //////////
///////////////////////////////
///// Info before receiving serial information /////
void draw(void) {
u8g.setFont(u8g_font_unifont);
//u8g.setFont(u8g_font_osb21);
u8g.drawStr( 5, 10, "ser_data: NO");
u8g.drawStr( 5, 25, "Laser: OFF");
u8g.drawStr( 5, 45, "x: --");
u8g.drawStr( 65, 45, "y: --");
}
///// Info when receiving serial information & print received values /////
void draw2(void) {
// graphic commands to redraw the complete screen should be placed here
u8g.setFont(u8g_font_unifont);
//u8g.setFont(u8g_font_osb21);
u8g.drawStr( 5, 10, "ser_data: YES");
u8g.drawStr( 5, 25, "Laser:");
u8g.setPrintPos(65, 25); // set position 25,35
u8g.print(messageFromPC); // display laser status
u8g.drawStr( 5, 45, "x:");
u8g.setPrintPos(20, 45); // set position 25,35
u8g.print(integerFromPC2); // display x-coordinate
u8g.drawStr( 65, 45, "y: ");
u8g.setPrintPos(80, 45); // set position 25,35
u8g.print(integerFromPC3); // display y-coordinate

}

void SerToLaser(){
switch (integerFromPC) {
case 1:
{
// int serDataX = Serial.parseInt();
// int serDataY = Serial.parseInt();            
laser.sendtoRaw(integerFromPC2, integerFromPC3);
laser.on();
// picture loop
u8g.firstPage();
do {
draw2();
} while( u8g.nextPage() );
integerFromPC = "";
//delay(200);   ////////////////
break;                                
}
case 0:
{
laser.off();
// int serDataX = Serial.parseInt();
// int serDataY = Serial.parseInt();             
laser.sendtoRaw(integerFromPC2, integerFromPC3);
// picture loop
u8g.firstPage();
do {
draw2();
} while( u8g.nextPage() );
integerFromPC = "";
//delay(200);   ////////////////
break;                                
}
default:
break;
}

}



void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = ''; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() {      // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,",");      // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx);     // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC2 = atoi(strtokIndx);     // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC3 = atoi(strtokIndx);     // convert this part to an integer
//strtokIndx = strtok(NULL, ",");
//floatFromPC = atof(strtokIndx);     // convert this part to a float
}
//============
void showParsedData() {
Serial.print("Laserstatus: ");
Serial.println(messageFromPC);
Serial.print("Statusnumber: ");
Serial.println(integerFromPC);
Serial.print("X: ");
Serial.println(integerFromPC2);
Serial.print("Y: ");
Serial.println(integerFromPC3);
SerToLaser();
}
//============

我使用的 Python 代码:

import serial
import time
import random

ard = serial.Serial('com6',9600,timeout=5)
time.sleep(1.8) # wait for Arduino min 1.8
i = 0
while (i <4096):
# Serial write section
#int r = randint(0,100) 
setX_Coor = i
setY_Coor = 2000

setStatus = 1#random.randint(0,1)
#setX_Coor = random.randint(1000,4095) #63
#setY_Coor = random.randint(1000,4095)#37
ard.flush()
setVal1 = str(setStatus)
setVal2 = str(setX_Coor)
setVal3 = str(setY_Coor)
print ("Python value sent: ")
print (setVal1.encode())
print (setVal2.encode())
print (setVal3.encode())

ard.write(('<').encode())
ard.write(('ON,').encode())
ard.write((',').encode())
ard.write(setVal1.encode())
ard.write((',').encode())
ard.write(setVal2.encode())
ard.write((',').encode())
ard.write(setVal3.encode())
ard.write(('>').encode())

time.sleep(1) # 0.08 is fastest possible value

# Serial read section
msg = ard.read(ard.inWaiting()) # read all characters in buffer
print ("Message from arduino: ")
print (msg)
i = i + 10
else:
print ("Exiting")
#exit()

扫描仪应扫描 y=2000 的线,并将 x 的值从 0 更改为 4095。它完成工作 3 秒,然后 y 值仅比 20 或 1 或一些随机数字 200 ......

乍一看,您似乎正在做很多多余的重绘(这可能很昂贵,我从未使用过u8glib(。 你在主循环的顶部重绘一次,然后由于你的 SerToLaser(( 两次(一次在主循环的底部,一次在 showParsedData(( 中(。 另外(虽然 1 秒一点也不快(,串行显示在 arduino 上非常昂贵,所以你应该节省打印到终端的数量。