91495


### 目的

現在，C#を用いてセンサ値を400Hzで取得するプログラムを作成しています．  
現在は，マイコン側から9bytesのデータをシリアルを通じてc#側で取得するようなプログラムを作成しています．

### 現在

9bytesの内，はじめの1byteは0xFFを送り，c#側では読み込んだ初めの1byteが0xFFであれば，センサ値を配列に入れ替えるようなプログラムを組んでおります．

c#側では，button１が押された場合に，データの読み取りを行うようにして，別のボタンによってfragを入れ替えるようなプログラムを書いております．  
また，マイコン側ではfloat型のデータをシリアルで送るために，共用体を用いてfloat型をint型として送信しています．

### 質問

質問は，c#側でのserial.Readのタイミングや方法を教えていただきたいです．  
現在のプログラムでは，全く異なるデータが取得されてしまいます．  
ただ，マイコン側がデータを正しく送信していることは別のプログラムで確認しましたので，特にc#について改善点を教えていただきたいです．

以下にコードを示します．

c#

[code]

    //一部抜粋です.
    public static class Condition
            {
                public static string[,] condition = new string[6, 2];// Modifiable
                public static int clicked_num = 0;
                public static int[] index_num = new int[6];
                public static bool frag = false;
    
            }
    public static class Data_t
            {
                public static float[,] data = new float[50000, 2];
            }
    
    private void button1_Click(object sender, EventArgs e)
            {
                button3.Enabled = true;
                button1.Enabled = false;
                Condition.frag = true;
                if (Condition.clicked_num < 6)
                {
                    int count = 0;
                    while (Condition.frag)
                    {
                        //dataの読み取りと配列に値渡し
                        //System.Console.WriteLine("test_now1");
                        byte[ ] buffer = new byte[9];
                        //System.Console.WriteLine("test_now2");
                        serialPort1.Read(buffer, 0, buffer.Length);
                        //System.Console.WriteLine("test_now3");
                        if (buffer[0] == 0xff)
                        {
                            float tmp1 = BitConverter.ToSingle(buffer,0);
                            float tmp2 = BitConverter.ToSingle(buffer, 4);
                            //System.Console.WriteLine("get_value");
                            Data_t.data[count, 0] = tmp1;
                            Data_t.data[count, 1] = tmp2;
                            System.Console.WriteLine(tmp1.ToString() + ","+tmp2.ToString());
                            count++;
                        }
                        
                        Application.DoEvents();
                    }
                }
                else
                {
                    label1.Text = "FINISH";
                    button3.Enabled = false;
                    serialPort1.DiscardOutBuffer();
                    serialPort1.DiscardInBuffer();
                    serialPort1.Close();
                }
            }
    
           private void button3_Click(object sender, EventArgs e)
            {
                Condition.frag = false;
                button1.Enabled = true;
                button3.Enabled = false;
            }
    
[/code]

また，マイコン側のプログラムは以下です．

[code]

    #include <Arduino.h>
    #include <rhio-LIS2HH12.h>
    #define ODR 200
    float x, y, z;
    float mx,mz;
    //https://gitlab.com/rhombio/rhio-libraries/rhio-LIS2HH12
    LIS2HH12 lis = LIS2HH12();
    
    bool frag = false;
    
    union float2int{
      float value;
      int i;
    };
    
    void setup() {
      // put your setup code here, to run once:
    
      Serial.begin(115200);
      Serial.println("LIS2HH12 example");
      lis.begin();
      lis.setBasicConfig();
      lis.setFrequency(80);//400Hz
    }
    
    void loop() {
      unsigned long pre = micros();
      
      lis.getAccelmG(&x,&y,&z);
      union float2int X;
      union float2int Z;
      X.value = x;
      Z.value = z;
      
      Serial.write(0xFF);
      Serial.write(X.i>>24 |0x00);
      Serial.write(X.i>>16 |0x00);
      Serial.write(X.i>>8 | 0x00);
      Serial.write(X.i&0xFF);
      Serial.write(Z.i>>24|0x00);
      Serial.write(Z.i>>16|0x00);
      Serial.write(Z.i>>8|0x00);
      Serial.write(Z.i&0xFF);
      
      while(micros()-pre<2500);
    }
    
[/code]

以上です．お手数ですがご回答お願いいたします．


CC BY-SA 4.0
2022-10-07T15:48:09.047
91491
2022-10-08T04:13:25.370
2022-10-07T16:23:12.097
3060
37633
question
c# arduino esp32
C#を用いてシリアルでセンサ値取得


Floatへの配列を入れる所で、スタートを間違えていました。  
はじめの1byteを読みとばす必要があります


CC BY-SA 4.0
2022-10-07T23:10:35.520
91492
2022-10-07T23:10:35.520
37633
91491
answer


シリアル通信は1バイトごとの通信にため、複数バイトで1つのデータをやりとりしたい場合、  
どこが始まりでどこが終わりなのか判断する必要があります。  
一般的にこれを実現するために、始まりはSTX(0x02)、終わりはETX(0x03)とし、その間に送信したいデータを挟みます。当然データの中にSTX,ETXと同じ値があるとおかしくなりますので、データの中にSTX,ETXと同じデータが無いように工夫する必要があります。  
一番簡単な方法はデータを文字列に変換し、受信側で元のデータに戻すことです。  
C#のシリアル受信は、DataReceivedイベントを使用し、その中でデータを取得します。  
DataReceivedイベントは複数回発生することがありますので、それを考慮して、受信する必要があります。

STX,ETXでの受信の例

[code]

    string RXSerialBuff;
            
    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        string receivedData = "";
        try {
            //receivedData = this.serialPort1.ReadLine();
            int rbyte = this.serialPort1.BytesToRead;
    
            for (int i = 0; i < rbyte; i++) {
                int tmp = this.serialPort1.ReadChar();
                char ctmp = (char)tmp;
                RXSerialBuff += ctmp;
    
                if (ctmp == '\02') {
                    RXSerialBuff = "";
                }
                if (ctmp == '\03') {
                    receivedData = RXSerialBuff;
                    RXSerialBuff = "";
                    
                    // ここで受信データの処理
    
                }
            }
        }
        catch (Exception ex) {
        }
        
    }
    
[/code]


CC BY-SA 4.0
2022-10-08T04:13:25.370
91495
2022-10-08T04:13:25.370
24490
91491
answer