【问题标题】:Arduino communication with 3 RS485 devices与 3 个 RS485 设备的 Arduino 通信
【发布时间】:2014-05-19 15:17:31
【问题描述】:

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

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 上的最佳解决方案是什么?这个我试过了,不正确。

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="";
      }
}

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

所有代码:

#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="";
      }
}

已编辑作废:

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或\n

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

所以我需要删除最后一个字符 \0 或 \n 或其他任何内容

【问题讨论】:

  • 它不发送 19 个字符,它发送 20 个字符。额外的一个是换行符,'\n',这就是你知道你得到了整个响应而不必计算的方式。由于您没有阅读它,因此您阅读的下一个字符串将以上一个响应中的换行符开头。
  • 谢谢汉斯,阅读直到\n帮助
  • 如果 read() 正在获取 ASCII 字符和 \n 和/或 NUL 终止,那么您应该编写代码来处理输入字符串,而不是按字节数指定或限制输入。您真的不想“删除最后一个字符 \0 或 \n 或其他任何字符”,而是使用适当的字符串终止符(即 NUL 字符)存储输入。您正在接收规范输入,但试图将其视为原始数据或二进制数据。

标签: serial-port arduino


【解决方案1】:

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

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。

【讨论】:

  • 感谢您的回复。实际上我想读取所有传入的字节并打印它们,但是出了点问题;)最后有终止零\ 0。我要删,怎么办?用编辑过的代码查看编辑过的帖子。
【解决方案2】:

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

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 == '\n'){           //If read char is new line then break.
     break;
      }
      momentas2 += c;       
    }
}

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

  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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多