RS-485 트랜시버를 사용한 RS-485 센서와 Modbus 통신
Amazon에서 구입한 RS-485⇔Serial의 통신 변환 보드의 재고가 위험한 경우가 많습니다.
어쨌든 자작할 수 있으면…
소재
환경
배선
아래 그림과 같이 배선합니다.
이번 사용하고 있는 센서가 5V 구동이므로 Mega로부터 그대로 전원을 잡을 수 있었습니다만,
구동 전압이 다른 쪽은 다른 전원을 취해 오는 등 궁리해 주세요.
브레드보드에서 배선한 사진입니다. (더럽고 죄송합니다..)
코드
rs485_test.ino
#include <Arduino.h>
#include <stdio.h>
#define DE_PIN 3
#define RE_PIN 2
byte slaveID = 0x01;
// 各自のRS-485センサーでの命令を記述してください
byte getVolt[] = {slaveID, 0x03, 0x00, 0x16, 0x00, 0x02, 0x25, 0xCF};
// 各自のRS-485センサーでのレスポンス時間に従って書き換えてください
const int modbusTimeout = 30 * 1000;
uint32_t startMillis = 0;
int bytesRead = 0;
byte responseBuffer[20];
unsigned char p[4];
float f = 0;
void setup() {
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
Serial.begin(115200);
Serial1.begin(9600);
Serial.println("setup completed!");
}
void loop() {
transmit_enable();
Serial1.write(getVolt, sizeof(getVolt)/sizeof(getVolt[0]));
Serial1.flush();
startMillis = millis();
Serial.print("write instructions : ");
// iは各自のセンサーの命令バイト数に従って書き換えてください
for(int i=0; i < 8; i++){
Serial.print(getVolt[i], HEX); Serial.print(" ");
}
receive_enable();
while ((Serial1.available() == 0) && ((millis() - startMillis) < modbusTimeout))
{ delay(1UL);}
Serial.println();
if (Serial1.available() > 0){
// バイト数(10)は各自のセンサーのレスポンスバイト数に従って書き換えてください
bytesRead = Serial1.readBytes(responseBuffer, 10);
Serial.print("response frame : ");
if(bytesRead > 0){
// jは各自のセンサーのレスポンスバイト数に従って書き換えてください
for(int j=0; j < 9; j++){
Serial.print(responseBuffer[j], HEX); Serial.print(" ");
}
}
Serial.println();
// ここは私が使用しているセンサーの仕様で記述しています
// 各自のセンサーのレスポンス仕様に従ってresponseBufferから値を取得してください
p[0] = responseBuffer[3];
p[1] = responseBuffer[4];
p[2] = responseBuffer[5];
p[3] = responseBuffer[6];
f = get_float(p); // byte to float
// 値取得ここまで
Serial.print("float value : "); Serial.print(f);
Serial.println();
}
Serial.println();
emptyResponseBuffer(&Serial1);
delay(5 * 1000UL);
}
void transmit_enable() {
digitalWrite(DE_PIN, HIGH);
digitalWrite(RE_PIN, HIGH);
}
void receive_enable() {
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
}
// Byte convert to float
float get_float(unsigned char *p)
{
float value = 0;
unsigned char *valueAddress = (unsigned char*)&value;
*valueAddress = p[1];
valueAddress++;
*valueAddress = p[0];
valueAddress++;
*valueAddress = p[3];
valueAddress++;
*valueAddress = p[2];
return(value);
}
// This empties the serial buffer
void emptyResponseBuffer(Stream *stream)
{
while (stream->available() > 0)
{
stream->read();
delay(1);
}
}
결과
이번에 사용한 명령은 센서의 내부 전압(3.3V)을 반환하는 명령이었습니다.
이와 같이 무사히 응답이 돌아왔다.
요약
일단 기본 통신을 할 수 있었으므로 안심입니다.
보다 간이하게 통신할 수 있도록, 기판 제작에 도전해 가고 싶습니다.
Reference
이 문제에 관하여(RS-485 트랜시버를 사용한 RS-485 센서와 Modbus 통신), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/s_fujii/items/54194d3b86a52b28481f
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
rs485_test.ino
#include <Arduino.h>
#include <stdio.h>
#define DE_PIN 3
#define RE_PIN 2
byte slaveID = 0x01;
// 各自のRS-485センサーでの命令を記述してください
byte getVolt[] = {slaveID, 0x03, 0x00, 0x16, 0x00, 0x02, 0x25, 0xCF};
// 各自のRS-485センサーでのレスポンス時間に従って書き換えてください
const int modbusTimeout = 30 * 1000;
uint32_t startMillis = 0;
int bytesRead = 0;
byte responseBuffer[20];
unsigned char p[4];
float f = 0;
void setup() {
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
Serial.begin(115200);
Serial1.begin(9600);
Serial.println("setup completed!");
}
void loop() {
transmit_enable();
Serial1.write(getVolt, sizeof(getVolt)/sizeof(getVolt[0]));
Serial1.flush();
startMillis = millis();
Serial.print("write instructions : ");
// iは各自のセンサーの命令バイト数に従って書き換えてください
for(int i=0; i < 8; i++){
Serial.print(getVolt[i], HEX); Serial.print(" ");
}
receive_enable();
while ((Serial1.available() == 0) && ((millis() - startMillis) < modbusTimeout))
{ delay(1UL);}
Serial.println();
if (Serial1.available() > 0){
// バイト数(10)は各自のセンサーのレスポンスバイト数に従って書き換えてください
bytesRead = Serial1.readBytes(responseBuffer, 10);
Serial.print("response frame : ");
if(bytesRead > 0){
// jは各自のセンサーのレスポンスバイト数に従って書き換えてください
for(int j=0; j < 9; j++){
Serial.print(responseBuffer[j], HEX); Serial.print(" ");
}
}
Serial.println();
// ここは私が使用しているセンサーの仕様で記述しています
// 各自のセンサーのレスポンス仕様に従ってresponseBufferから値を取得してください
p[0] = responseBuffer[3];
p[1] = responseBuffer[4];
p[2] = responseBuffer[5];
p[3] = responseBuffer[6];
f = get_float(p); // byte to float
// 値取得ここまで
Serial.print("float value : "); Serial.print(f);
Serial.println();
}
Serial.println();
emptyResponseBuffer(&Serial1);
delay(5 * 1000UL);
}
void transmit_enable() {
digitalWrite(DE_PIN, HIGH);
digitalWrite(RE_PIN, HIGH);
}
void receive_enable() {
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
}
// Byte convert to float
float get_float(unsigned char *p)
{
float value = 0;
unsigned char *valueAddress = (unsigned char*)&value;
*valueAddress = p[1];
valueAddress++;
*valueAddress = p[0];
valueAddress++;
*valueAddress = p[3];
valueAddress++;
*valueAddress = p[2];
return(value);
}
// This empties the serial buffer
void emptyResponseBuffer(Stream *stream)
{
while (stream->available() > 0)
{
stream->read();
delay(1);
}
}
결과
이번에 사용한 명령은 센서의 내부 전압(3.3V)을 반환하는 명령이었습니다.
이와 같이 무사히 응답이 돌아왔다.
요약
일단 기본 통신을 할 수 있었으므로 안심입니다.
보다 간이하게 통신할 수 있도록, 기판 제작에 도전해 가고 싶습니다.
Reference
이 문제에 관하여(RS-485 트랜시버를 사용한 RS-485 센서와 Modbus 통신), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/s_fujii/items/54194d3b86a52b28481f
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
일단 기본 통신을 할 수 있었으므로 안심입니다.
보다 간이하게 통신할 수 있도록, 기판 제작에 도전해 가고 싶습니다.
Reference
이 문제에 관하여(RS-485 트랜시버를 사용한 RS-485 센서와 Modbus 통신), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/s_fujii/items/54194d3b86a52b28481f텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)