关于串口:Arduino与3个RS485设备通信

Arduino communication with 3 RS485 devices

我正在为一篇学生的期末论文做这个项目。它很容易,但我就是想不出怎么做。我在一个 arduino 上有 RPM 计数器和 RS232 通信。 RPM 计数器工作正常,但通信不正常。
我有 3 个 RS485 设备 > RS485/RS232 转换器 > RS232/TTL > Arduino。
接收前。第二个设备信息我必须发送"02READ"。下面的示例,使用超级终端完成。

1
2
3
4
5
6
7
8
9
02READ
02ST,GS,    0.00,kg
002READ
02ST,GS,    0.00,kg
002READ
02ST,GS,    0.00,kg
002READ
02ST,GS,    0.00,kg
0

似乎设备正在发送终止0,所有消息都是02ST,GS, 0.00,kg。它的 19 个字节,对吧?要求 3 个设备然后打印它们以将它们记录在 pc 上的最佳解决方案是什么?这个我试过了,不正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
void READ03(){
      mySerial.println("03READ");
    while (mySerial.available()) {
     delay(10);
          if (mySerial.available() >0) {
        char c = mySerial.read();
        readString += c;}
        }
        if (readString.length() == 19) {
      momentas3 = readString;
      readString="";
      }
}

我必须去循环并收集传入的数据。但我不知道该怎么做:(太伤心了……

所有代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <SoftwareSerial.h>
#include <MegunoLink.h>
/*
Baltas   +
Raudonas -
Pinout:
============= TCRT1 =============
Juodas       -  GND
Geltons      -  POSSITIVE
Pilkas       -  SIGNAL
============= TCRT2 =============
Rudas        -  GND
Oranzinis    -  POSSITIVE
Zydras       -  SIGNAL
============= TCRT3 =============
Zalias       -  GND
raudonas     -  POSSITIVE
Baltas       -  SIGNAL
*/
//Software serial for 485 communication : Tx = pin 9, Rx = pin 8.
SoftwareSerial mySerial(9,8);
TimePlot MyPlot;
//CONSTANTS:
//Pin number for Vishay Telefunken Opto-reflecting TCRT1000 sensors:
Message MyCSVMessage("Stendas");
#define TCRT1                12    
#define TCRT2                11  
#define TCRT3                10

String readString;
String momentas1;
String momentas2;
String momentas3;
//Number of pulse changes per revolutuion:
long PulsesPerRevolution1 = 78;
long PulsesPerRevolution2 = 192;
long PulsesPerRevolution3 = 82;
long minute = 60;
//VARIABLES:
//Number of pulses counted:
long           PulseCount1=0;      
long           PulseCount2=0;      
long           PulseCount3=0;      
//Calculated rotations per minute:
long        Rpm1       =0;      
long        Rpm2       =0;      
long        Rpm3       =0;
//Time saved to compare
unsigned long TimeOld    =0;
//Achieved signals saved:
boolean       Status1    =0;      
boolean       Status2    =0;      
boolean       Status3    =0;      
//Signals saved to compare:
boolean       StatusOld1 =0;      
boolean       StatusOld2 =0;      
boolean       StatusOld3 =0;

void setup() {
  //Begin serial communication with BAUD rate 9600bps:
  Serial.begin(9600);
  mySerial.begin(57600);

  //Set input pins for TCRT1000:
  pinMode(TCRT1, INPUT);          
  pinMode(TCRT2, INPUT);          
  pinMode(TCRT3, INPUT);          

  MyPlot.SetTitle("Greicio matavimas");
  MyPlot.SetXlabel("Laikas");
  MyPlot.SetYlabel("Greitis");
  MyPlot.SetSeriesProperties("Rpm", Plot::Magenta, Plot::Solid, 2, Plot::Square);
}

void loop() {
  //

  //Read and save TCRT1000 status:
  Status1=digitalRead(TCRT1);      
  Status2=digitalRead(TCRT2);      
  Status3=digitalRead(TCRT3);      
    //Compare current status with the previous one
    //If changed, then increment the counting:
  if (StatusOld1!=Status1){
    StatusOld1=Status1;
    PulseCount1++;
  }
  if (StatusOld2!=Status2){
    StatusOld2=Status2;
    PulseCount2++;
  }  
  if (StatusOld3!=Status3){
    StatusOld3=Status3;
    PulseCount3++;
  }  
  //Compare time if it exceeds 1s:
  if (millis()-TimeOld>=1000){
   //Get data from RS485:
   READ01();
   READ02();
   READ03();
   //Calculate RPM:
    Rpm1=PulseCount1*minute/PulsesPerRevolution1;
    Rpm2=PulseCount2*minute/PulsesPerRevolution2;
    Rpm3=PulseCount3*minute/PulsesPerRevolution3;
   //Print RPM
    MyCSVMessage.Begin();
    Serial.println(String(Rpm1) +"," + String(momentas1));
    Serial.println(String(Rpm2) +"," + String(momentas2));
    Serial.println(String(Rpm3) +"," + String(momentas3));
    MyCSVMessage.End();
    MyPlot.SendData("Rpm1", Rpm1);
    MyPlot.SendData("Rpm2", Rpm2);
    MyPlot.SendData("Rpm3", Rpm3);

   //reset the counting and time
    TimeOld=millis();
    PulseCount1=0;
    PulseCount2=0;
    PulseCount3=0;    
  }
}
 //Get data from RS485:
void READ01(){
    readString="";
     mySerial.println("01READ");
    while (mySerial.available()) {
     delay(10);
          if (mySerial.available() >0) {
        char c = mySerial.read();
        readString += c;}
        }
        if (readString.length() == 19) {
      momentas1 = readString;
      readString="";
      }
}
void READ02(){
    readString="";
     mySerial.println("02READ");
    while (mySerial.available()) {
     delay(10);
          if (mySerial.available() >0) {
        char c = mySerial.read();
        readString += c;}
        }
        if (readString.length() == 19) {
      momentas2 = readString;
      readString="";
      }
}
void READ03(){
    readString="";
     mySerial.println("03READ");
    while (mySerial.available()) {
     delay(10);
          if (mySerial.available() >0) {
        char c = mySerial.read();
        readString += c;}
        }
        if (readString.length() == 19) {
      momentas3 = readString;
      readString="";
      }
}

编辑过的虚空:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void READ03(){
  while (mySerial.available()){
    mySerial.read();
  }
    mySerial.println("03READ");
    momentas3="";
    delay(20);

    while (mySerial.available()) {
      char c = mySerial.read();
      momentas3 += c;
     }
    // momentas3 = readString;
    //momentas3.setCharAt(momentas3.length() - 1, '\\0');  
}

它返回正确的数据,但最后有 \\\\\\\\0 或 \\\\
在字符串的末尾

1
2
3
4
{MESSAGE:Stendas|DATA|
0,01ST,GS,    0.03,kg
 0,02ST,GS,    0.00,kg
 0,03ST,GS,    0.00,kg

所以我需要删除最后一个字符 \\\\\\\\0 或 \\\\
或者不管它是什么


经过艰苦的尝试,我得到了同事的帮助。我们都找到了解决方案:
添加了带有注释的正确代码。感谢 Hans Pasant 和 Joachim Isaksson 的提示!!!
正确答案是阅读到 '\\
' (新行) char 来了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void READ02(){
  while (mySerial.available()){ // Flush read buffer
    mySerial.read();
  }
    mySerial.println("02READ"); // Send command for second device
    momentas2="";
    delay(20);                  // Wait some time
    while (mySerial.available()) { //While there is data count it to string
     char c = mySerial.read();
     if (c == '\
'){           //If read char is new line then break.
     break;
      }
      momentas2 += c;      
    }
}

并重新处理字符串以获取我需要的数据,以存储第二个和第三个','之间的数据。

1
2
3
4
5
6
7
8
9
  String between2ndAnd3rd(String myString) {
  int pirmas = myString.indexOf(',');
  int antras = myString.indexOf(',', pirmas+1);
  int trecias = myString.indexOf(',', antras+1);
  int ketvirtas = myString.indexOf(',', trecias+1);

  String newStr = myString.substring(antras+1, trecias);
  return newStr;
}

如果你真的想每次都读取固定大小的 19 字节,你可以这样做(原谅我生疏的 arduino 技能,你可能需要纠正我)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void READ01() { momentas1 = READ("01READ"); }
void READ02() { momentas2 = READ("02READ"); }
void READ03() { momentas3 = READ("03READ"); }

String READ(String toSend) {

   mySerial.println(toSend);

   String buffer ="";
   int i = 0;
   while (i < 19)
   {
      while (!Serial.available()) { /* Busy wait for next byte */ }
      buffer += Serial.read();
   }
   buffer.Trim();
   return buffer;
}

应该用来自该设备的 19 字节数据填充相应的 read_buffer。