与arduino的python半双工通信,包括价值检查

时间:2018-09-20 23:04:22

标签: python-2.7 arduino pyserial

我有两个功能块,一个在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()> 

0 个答案:

没有答案