2017-03-28 14 views
0

라즈베리 파이에서 IMU 센서 (BNO055)와 통신하기 위해 C# 및 모노를 사용하려고합니다. 내가하는 일과 관계없이 센서를 읽고 쓸 수는 없습니다. 더 많은 경험을 가진 사람이 이것을 할 수있는 적절한 방법이 무엇인지 알 수 있습니까? 감사.C# 직렬 포트 BNO055 센서 통신

초기화 :

private void ConnectToBNO055() 
    { 
     GPIO.Write(ResetPin, true); 
     Task.Delay(650).Wait(); 

     Port    = new SerialPort(); 
     Port.PortName  = PortName; 
     Port.BaudRate  = 115200; 
     Port.Parity   = Parity.None; 
     Port.DataBits  = 8; 
     Port.StopBits  = StopBits.One; 
     Port.Handshake  = Handshake.None; 
     Port.ReadTimeout = 5000; 
     Port.WriteTimeout = 5000; 

     try 
     { 
      Port.Open(); 

      while (!Port.IsOpen) { Task.Delay(1).Wait(); } 

      SetMode(OperationMode.OPERATION_MODE_CONFIG); 

      WriteRegister((byte)PageIDRegisterDefinition.BNO055_PAGE_ID_ADDR, 0, false); 

      byte chipID = ReadRegister((byte)PageRegisterDefinitionStart.BNO055_CHIP_ID_ADDR); 

      if ((byte)I2CAddress.BNO055_ID == chipID) 
      { 
       Reset(); 

       WriteRegister((byte)ModeRegisters.BNO055_PWR_MODE_ADDR, (byte)PowerMode.POWER_MODE_NORMAL); 

       WriteRegister((byte)ModeRegisters.BNO055_SYS_TRIGGER_ADDR, 0x0); 

       SetMode(OperationMode.OPERATION_MODE_NDOF); 

       Connected = true; 
       Console.WriteLine("Connected to IMU."); 

       Console.WriteLine("Calibrating IMU. . ."); 

       BNO055.CalibrationStatus lastCal; 
       BNO055.CalibrationStatus cal = GetCalibrationStatus(); 

       Console.WriteLine("System: " + cal.System.ToString() + ", Magnometer: " + cal.Mag.ToString() + ", Gyroscope: " + cal.Gyro.ToString() + ", Accelerometer: " + cal.Accel.ToString()); 
       while (cal.System != 3 || cal.Mag != 3 || cal.Gyro != 3 || cal.Accel != 3) 
       { 
        Task.Delay(250).Wait(); 

        lastCal = cal; 
        cal = GetCalibrationStatus(); 

        if (cal.Accel != lastCal.Accel || cal.Gyro != lastCal.Gyro || cal.Mag != lastCal.Mag || cal.System != lastCal.System) 
        { 
         Console.WriteLine("System: " + cal.System.ToString() + ", Magnometer: " + cal.Mag.ToString() + ", Gyroscope: " + cal.Gyro.ToString() + ", Accelerometer: " + cal.Accel.ToString()); 
        } 
       } 

       Calibrated = true; 
       Console.WriteLine("IMU Calibrated."); 
      } 
      else 
      { 
       Console.WriteLine("Unable to connect to IMU."); 
      } 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Unable to connect to IMU."); 
     } 
    } 

IO 방법 : 여기

private void WriteRegister(byte address, byte data, bool ack = true) 
    { 
     byte[] writeBuffer = new byte[] { 0xAA, 0x00, address, 1, data }; 
     byte[] response; 
     try 
     { 
      response = WriteData(writeBuffer, ack); 
      if (ack) 
      { 
       if (0xEE01 != (response[0] << 8 | response[1])) 
        throw new Exception(string.Format("WriteRegister returned 0x{0:x2},0x{1:x2}", response[0], response[1])); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(string.Format("WriteRegister error: {0}", ex.Message)); 
     } 
    } 

    private byte ReadRegister(byte register) 
    { 
     byte[] commandBuffer = new byte[] { 0xAA, 0x01, register, 1 }; 
     byte[] readBuffer = new byte[1]; 
     try 
     { 
      readBuffer = ReadData(commandBuffer, 1); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(string.Format("ReadRegister error: {0}", ex.Message)); 
     } 
     return readBuffer[0]; 
    } 

    private byte[] WriteData(byte[] command, bool ack = true, int retries = 5) 
    { 
     byte[] ackBuffer = new byte[2]; 
     bool done = false; 

     while ((!done) && (retries-- > 0)) 
     { 
      Port.Write(command, 0, command.Length); 

      if (ack) 
      { 
       while (Port.BytesToRead != 2) { Task.Delay(1).Wait(); } 
       Port.Read(ackBuffer, 0, 2); 

       done = 0xEE07 != (ackBuffer[0] << 8 | ackBuffer[1]); 
      } 
      else 
       done = true; 
     } 

     if (!done) 
      throw new Exception("WriteData retries exceeded"); 
     return ackBuffer; 
    } 

    private byte[] ReadData(byte[] command, int readLength) 
    { 
     byte[] headerBuffer = new byte[2]; 
     byte[] returnBuffer = new byte[readLength]; 

     Port.Write(command, 0, command.Length); 

     while (Port.BytesToRead != 2) { Task.Delay(1).Wait(); } 
     Port.Read(headerBuffer, 0, 2); 

     if (headerBuffer[0] != 0xBB) 
      throw new Exception(string.Format("ReadData error 0x{0:x2}{1:x2}", headerBuffer[0], headerBuffer[1])); 
     if (headerBuffer[1] != readLength) 
      throw new Exception(string.Format("ReadData error: failed to read {0} bytes. Read {1}", readLength, headerBuffer[1])); 

     while (Port.BytesToRead != readLength) { Task.Delay(1).Wait(); } 
     Port.Read(returnBuffer, 0, readLength); 

     return returnBuffer; 
    } 
+0

직렬 포트 초기화 코드도 표시 할 수 있습니까? – PaulF

+0

및 무엇이 발생합니까? throw 된 예외 중 하나라도 빈 버퍼가 반환 되었습니까? – dlatikay

+0

방금 ​​위에 게시했습니다. ReadData 메서드에서 첫 번째 예외가 throw됩니다. – spugia

답변

0

문제 나 데이터를 즉시 작성 후 센서의 응답을 읽으려고 한 것이 었습니다. 문제를 해결하려면 BytesToRead 속성이 원하는 응답 길이와 같아 지길 기다리는 루프를 추가 한 다음 읽습니다.