我有两个功能块,一个在Python中,另一个在Arduino(嵌入式C)中。 Python端通过“一次”(即一行代码)通过PySerial发送了一堆参数,并继续发送这些参数,直到从ARD读回的数据与发送的数据匹配为止。
Arduino端获取命令(开始读取传入的参数,并将其解析为全局变量。 如果全局变量尚未从其初始值更新,它将通过串行消息发送适当的错误。 如果全局变量已更新,它会将新值的格式发送给Python,希望该格式与最初发送的字符串相同(提示;此值应与最初从Python发送/接收的字符串匹配)。 该过程应继续进行,直到读取了从Python发送的正确的终止字符(通过串行)为止。
我要注意的两件事; 1)我的所有错误消息都被触发,因此全局变量永远不会更新 ->此外,“解析”操作中的Print语句未显示,因此永远不会进入该循环。
2)在Python端,当我查看终端(IDLE)中的错误消息时,我看到消息有时会丢失0〜3个前几个字符。
为什么我会在Python端丢失数据? 有没有更有效的方法来实施这种反馈/控制?
Arduino:
void receiveSetup(){
/*-------------------------------------------------------------------------------------
Receive Setup File parameters from Python
-------------------------------------------------------------------------------------*/
// Wait for outgoing serial data to complete
Serial.flush();
//while ((Serial.available() > 0) && (Serial.available() != 0)) {} // Wait for incoming data to be of Zero bytes in number.
// Courtesy of <http://forum.arduino.cc/index.php?topic=225329.msg1810764#msg1810764>
byte bytesRecvd = 0;
const char startMarker = '{';
const char endMarker = '}';
bool readInProgress = false;
bool newDataFromPC = false;
// Used for <receiveSetup()> and <parseData()>
const byte buffSize = 80;
char inputBuffer[buffSize];
while(1){
// Receive data from PC and save it into <inputBuffer>
if(Serial.available() > 0){
char x = Serial.read();
Serial.print("<1234 [");
Serial.print(x);
Serial.println("]>");
if(x == "|"){
break;
}
if (x == endMarker) {
readInProgress = false;
newDataFromPC = true;
Serial.println(inputBuffer); // WATCH
inputBuffer[bytesRecvd] = 0;
//parseData();
// Parse data
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(inputBuffer,","); // get the first part - the string: return the index at which ',' is found
gv.numSensors = atoi(strtokIndx);
//Serial.print(gv.numSensors);
strtokIndx = strtok(NULL, ",");
gv.vdd0min = atof(strtokIndx);
//Serial.print(gv.vdd0min); // Vdd min
strtokIndx = strtok(NULL, ",");
gv.vdd0max = atof(strtokIndx);
//Serial.print(gv.vdd0max); // Vdd max
strtokIndx = strtok(NULL, ",");
gv.vin0min = atof(strtokIndx);
//Serial.print(gv.vin0min); // Vin min
strtokIndx = strtok(NULL, ",");
gv.vin0max = atof(strtokIndx);
//Serial.print(gv.vin0max); // Vin max
strtokIndx = strtok(NULL, ",");
gv.iin0min = atof(strtokIndx);
//Serial.print(gv.iin0min); // Iin min
strtokIndx = strtok(NULL, ",");
gv.iin0max = atof(strtokIndx);
//Serial.print(gv.iin0max); // Iin max
strtokIndx = strtok(NULL, ",");
gv.voqmin = atof(strtokIndx);
//Serial.print(gv.voqmin); // Vout min
strtokIndx = strtok(NULL, ",");
gv.voqmax = atof(strtokIndx);
//Serial.print(gv.voqmax); // Vout max
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
gv.psMin = atof(strtokIndx);
//Serial.print(gv.psMin);
strtokIndx = strtok(NULL, ",");
gv.psMax = atof(strtokIndx);
//Serial.print(gv.psMax);
strtokIndx = strtok(NULL, ",");
strcpy(gv.testType, strtokIndx); // copy it to lvc_x0; copy char ref of index to char array destination
//Serial.println(gv.testType);
// End of <parseData()>
}
if(readInProgress) {
inputBuffer[bytesRecvd] = x;
bytesRecvd ++;
if (bytesRecvd == buffSize) {
bytesRecvd = buffSize - 1;
}
}
if (x == startMarker) {
bytesRecvd = 0;
readInProgress = true;
}
/*
if(strstr(inputBuffer,"|")){
break;
}*/
/*
if(strstr(x,"|")){
break;
}*/
/*
else{
Serial.println(x);
}*/
}
// Check at end; if Globals unchanged, ERROR.
if(gv.numSensors == 0){
Serial.println("<29 Parameter <numSensors> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.vdd0min == 0.001){
Serial.println("<33.1 Parameter <vdd0min> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.vdd0max == 0.001){
Serial.println("<33.2 Parameter <vdd0max> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.vin0min == 0.001){
Serial.println("<33.3 Parameter <vin0min> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.vin0max == 0.001){
Serial.println("<33.4 Parameter <vin0max> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.iin0min == 0.001){
Serial.println("<33.5 Parameter <iin0min> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.iin0max == 0.001){
Serial.println("<33.6 Parameter <iin0max> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.voqmin == 0.001){
Serial.println("<33.7 Parameter <voqmin> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.voqmax == 0.001){
Serial.println("<33.8 Parameter <voqmax> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.psMin == 0.001){
Serial.println("<34 Parameter <psMin> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
if(gv.psMax == 0.001){
Serial.println("<35 Parameter <psMax> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
int foo = 0;
for(int p = 0; p<40; p++){
if(gv.testType[p] != 0){
++foo;
}
}
if(foo == 0){
Serial.println("<36 Parameter <testType> has not been updated properly, please check code>");
Serial.flush(); // Wait for outgoing data to finish
}
/*
if(gv.testType==""){
Serial.println("36 Parameter <testType> has not been updated properly, please check code");
Serial.flush(); // Wait for outgoing data to finish
}*/
if((gv.numSensors==0) && (gv.vdd0min==0.001) && (gv.vdd0max==0.001) && (gv.vin0min==0.001) && (gv.vin0max==0.001) && (gv.iin0min==0.001) && (gv.iin0max==0.001) && (gv.voqmin==0.001) && (gv.voqmax==0.001) && (gv.psMin==0.001) && (gv.psMax==0.001) && (foo==0)){
Serial.println("<37 ERROR>"); // If NONE of the vars updated
Serial.flush(); // Wait for outgoing data to finish
}
else if((gv.numSensors!=0) && (gv.vdd0min!=0.001) && (gv.vdd0max!=0.001) && (gv.vin0min!=0.001) && (gv.vin0max!=0.001) && (gv.iin0min!=0.001) && (gv.iin0max!=0.001) && (gv.voqmin!=0.001) && (gv.voqmax!=0.001) && (gv.psMin!=0.001) && (gv.psMax!=0.001) && (foo>0)){
//Serial.println("38 GOOD"); // Null term char, ACK2
Serial.print("{");
Serial.print(gv.numSensors);
Serial.print(",");
Serial.print(gv.vdd0min);
Serial.print(",");
Serial.print(gv.vdd0max);
Serial.print(",");
Serial.print(gv.vin0min);
Serial.print(",");
Serial.print(gv.vin0max);
Serial.print(",");
Serial.print(gv.iin0min);
Serial.print(",");
Serial.print(gv.iin0max);
Serial.print(",");
Serial.print(gv.voqmin);
Serial.print(",");
Serial.print(gv.voqmax);
Serial.print(",");
Serial.print(gv.psMin);
Serial.print(",");
Serial.print(gv.psMax);
Serial.print(",");
Serial.print(gv.testType);
Serial.println("}");
Serial.flush(); // Wait for outgoing data to finish
//break;
if(Serial.read() == "|"){
break; // We want to read-back the data until we match our settings
}
}
}
Serial.flush(); // Wait for outgoing data to finish
}
Python的一面;
# Send SetupFile parameters as 1d Arrays until ACK2 received
def sendSetup():
global numSensors
global vdd0min
global vdd0max
global vin0min
global vin0max
global iinmin
global iinmax
global voutmin
global voutmax
global psMin
global psMax
global testType
ard.reset_output_buffer()
ard.write("*PARAM" + '\r\n') # Let the user click a button to update the variables....? [TBD]
#time.sleep(2)
done = False
lva_output = []
while done == False:
try:
# Send ||SensorSetup first||
# Send ||WaveformSetup 2nd||
### Redacted.
# Send ||OtherSetup 3rd/last||
lva_output = ("{%i,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%s}" % (numSensors,vdd0min,vdd0max,vin0min,vin0max,iin0min,iin0max,voqmin,voqmax,psMin,psMax,testType)).encode('utf-8')
#print(lva_output)
print(ard.write(lva_output + '\r\n'))
except:
print("28 Error while sending data-param...")
else:
# Check for satisfaction from ARD
while(1):
lvx = 0
while(lvx == 0):
lvx = ard.in_waiting
# End while-loop
if(ard.in_waiting > 0):
ACK2 = ard.readline().strip("\n")
ard.reset_input_buffer()
if('38 GOOD' in ACK2) or (lva_output in ACK2):
### ARD is not acting-upon this char, best we can do here is to break simultaneously.
lvc_x = "|"
ard.reset_output_buffer()
ard.write(lvc_x + '\r\n')
print("38.5 Setup received, acknowledged, and confirmed!")
done = True
break
elif '37 ERROR' in ACK2:
print("39 Error updating setup variables on ARD")
break
else:
print(ACK2)
# End if-else
else:
break # If no incoming data, stop checking and try sending again?
# End if-else case
# End while-loop
# End try-catch
# End while-loop
# End <sendSetup()>