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,所有消息都是
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。