mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.4.0 RS485
This commit is contained in:
parent
623a49ac56
commit
5c04d36920
@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.4.0] - 2023-12-18
|
||||
- fix **write(array, length)**
|
||||
- add two examples (ack_nack + controller)
|
||||
- updated experimental protocol, still experimental
|
||||
- update readme.md
|
||||
- minor edits
|
||||
|
||||
----
|
||||
|
||||
## [0.3.0] - 2023-12-05
|
||||
- Fix #15 - use flush() instead of calculation.
|
||||
- remove **setMicrosPerByte()** and **getMicrosPerByte()**
|
||||
|
@ -113,15 +113,21 @@ In 0.2.5 this protocol has been tested and some bugs in the receive parser
|
||||
have been fixed. It still is experimental and it needs more testing.
|
||||
|
||||
The library functions are:
|
||||
- **void send(uint8_t receiverID, uint8_t msg[], uint8_t len)**
|
||||
- **size_t send(uint8_t receiverID, uint8_t msg[], uint8_t len)**
|
||||
- send a buffer of given length to a receiver.
|
||||
- **bool receive(uint8_t &senderID, uint8_t msg[], uint8_t &len)**
|
||||
- receive a packet, senderID identifies the sender.
|
||||
|
||||
Two wrappers:
|
||||
- **size_t send(uint8_t receiverID, char msg[], uint8_t len)**
|
||||
- send a buffer of given length to a receiver.
|
||||
- **bool receive(uint8_t &senderID, char msg[], uint8_t &len)**
|
||||
- receive a packet, senderID identifies the sender.
|
||||
|
||||
Current implementation limits messages up to 48 bytes (hardcoded buffer size)
|
||||
which is in many cases enough.
|
||||
|
||||
See two example sketches.
|
||||
See example sketches.
|
||||
|
||||
|
||||
## Operation
|
||||
|
@ -2,7 +2,7 @@
|
||||
// FILE: RS485.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 30-okt-2017
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.4.0
|
||||
// PURPOSE: Arduino library for RS485 modules (MAX485)
|
||||
// URL: https://github.com/RobTillaart/RS485
|
||||
|
||||
@ -20,7 +20,8 @@ RS485::RS485(Stream * stream, uint8_t sendPin, uint8_t deviceID)
|
||||
_deviceID = deviceID;
|
||||
|
||||
pinMode(_sendPin, OUTPUT);
|
||||
setRXmode(); // receiver mode ==> _sendPin == LOW
|
||||
// default receiver mode ==> _sendPin == LOW
|
||||
setRXmode();
|
||||
}
|
||||
|
||||
|
||||
@ -87,12 +88,14 @@ size_t RS485::write(char * array, uint8_t length)
|
||||
// smallest and slightly fastest.
|
||||
size_t RS485::write(uint8_t * array, uint8_t length)
|
||||
{
|
||||
uint8_t n = 0;
|
||||
setTXmode(); // transmit mode
|
||||
size_t n = 0;
|
||||
for (uint8_t i = 0; i < length; i++)
|
||||
{
|
||||
n += _stream->write(array[i]);
|
||||
yield();
|
||||
}
|
||||
setRXmode(); // receiver mode
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -146,25 +149,29 @@ size_t RS485::write(uint8_t * array, uint8_t length)
|
||||
// EOT end of transmission
|
||||
//
|
||||
|
||||
void RS485::send(uint8_t receiverID, uint8_t msg[], uint8_t len)
|
||||
size_t RS485::send(uint8_t receiverID, uint8_t msg[], uint8_t len)
|
||||
{
|
||||
size_t n = 0;
|
||||
uint8_t CHKSUM = 0;
|
||||
|
||||
setTXmode(); // transmit mode
|
||||
_stream->write(SOH);
|
||||
_stream->write(receiverID); // TO
|
||||
_stream->write(_deviceID); // FROM
|
||||
_stream->write(len); // LENGTH BODY
|
||||
_stream->write(STX);
|
||||
n += _stream->write(receiverID); // TO
|
||||
n += _stream->write(_deviceID); // FROM
|
||||
n += _stream->write(len); // LENGTH BODY
|
||||
n += _stream->write(STX);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
_stream->write(msg[i]);
|
||||
n += _stream->write(msg[i]);
|
||||
CHKSUM ^= msg[i]; // Simple XOR checksum.
|
||||
}
|
||||
_stream->write(CHKSUM);
|
||||
_stream->write(ETX);
|
||||
_stream->write(EOT);
|
||||
n += _stream->write(CHKSUM);
|
||||
n += _stream->write(ETX);
|
||||
n += _stream->write(EOT);
|
||||
_stream->flush();
|
||||
setRXmode(); // receive mode
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@ -276,6 +283,17 @@ bool RS485::receive(uint8_t &senderID, uint8_t msg[], uint8_t &msglen)
|
||||
}
|
||||
|
||||
|
||||
size_t RS485::send(uint8_t receiverID, char msg[], uint8_t len)
|
||||
{
|
||||
return send(receiverID, (uint8_t *)msg, len);
|
||||
}
|
||||
|
||||
|
||||
bool RS485::receive(uint8_t &senderID, char msg[], uint8_t &len)
|
||||
{
|
||||
return receive(senderID, (uint8_t*) msg, len);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -3,7 +3,7 @@
|
||||
// FILE: RS485.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 30-okt-2017
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.4.0
|
||||
// PURPOSE: Arduino library for RS485 modules
|
||||
// URL: https://github.com/RobTillaart/RS485
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include "Arduino.h"
|
||||
#include "ASCII_CONTROL.h"
|
||||
|
||||
#define RS485_LIB_VERSION (F("0.3.0"))
|
||||
#define RS485_LIB_VERSION (F("0.4.0"))
|
||||
|
||||
|
||||
class RS485 : public Stream
|
||||
@ -41,14 +41,19 @@ public:
|
||||
uint8_t getMode() { return digitalRead(_sendPin) == HIGH; };
|
||||
|
||||
|
||||
// EXPERIMENTAL
|
||||
// - use at own risk.- (for 0.3.0)
|
||||
// EXPERIMENTAL
|
||||
// - in a derived class?
|
||||
// - use at own risk
|
||||
// send ASCII encoded messages from one master to multiple clients.
|
||||
// msg[] = 32..127
|
||||
// len = 1..48 ?
|
||||
void send(uint8_t receiverID, uint8_t msg[], uint8_t len);
|
||||
// len = 1.. 48 (internal receive buffer is 50)
|
||||
size_t send(uint8_t receiverID, uint8_t msg[], uint8_t len);
|
||||
bool receive(uint8_t &senderID, uint8_t msg[], uint8_t &len);
|
||||
|
||||
// EXPERIMENTAL
|
||||
size_t send(uint8_t receiverID, char msg[], uint8_t len);
|
||||
bool receive(uint8_t &senderID, char msg[], uint8_t &len);
|
||||
|
||||
|
||||
private:
|
||||
Stream * _stream;
|
||||
@ -56,7 +61,7 @@ private:
|
||||
uint8_t _deviceID = 0;
|
||||
uint16_t _microsPerByte = 1000;
|
||||
|
||||
// EXPERIMENTAL (for 0.3.x)
|
||||
// EXPERIMENTAL
|
||||
uint8_t _bidx = 0;
|
||||
uint8_t _buffer[50]; // internal receive buffer
|
||||
};
|
||||
|
@ -0,0 +1,68 @@
|
||||
// FILE: RS485_master_ACK_NACK.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/RS485
|
||||
|
||||
// This is the code for a master (to be used with slave example)
|
||||
// Best is it to use on a MEGA or another board with multiple hardware Serials.
|
||||
// The master should be connected with one slave e.g. an UNO
|
||||
//
|
||||
// The application is (too) simple,
|
||||
// if the slave receives a printable char it returns an ACK
|
||||
// else an NACK
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RS485.h"
|
||||
|
||||
const uint8_t sendPin = 4;
|
||||
const uint8_t deviceID = 0;
|
||||
|
||||
// use a 2nd Serial port.
|
||||
// RS485 rs485(&Serial2, sendPin, deviceID);
|
||||
RS485 rs485(&Serial, sendPin, deviceID);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(38400);
|
||||
while (!Serial);
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("RS485_LIB_VERSION: ");
|
||||
Serial.println(RS485_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (Serial.available())
|
||||
{
|
||||
char c = Serial.read();
|
||||
rs485.setTXmode();
|
||||
rs485.write(c);
|
||||
rs485.setRXmode();
|
||||
}
|
||||
|
||||
if (rs485.available())
|
||||
{
|
||||
uint8_t answer = rs485.read();
|
||||
switch (answer)
|
||||
{
|
||||
case ACK:
|
||||
Serial.println(" ACK");
|
||||
break;
|
||||
case NAK:
|
||||
Serial.println(" NAK");
|
||||
break;
|
||||
default:
|
||||
Serial.print("0x");
|
||||
if (answer < 16) Serial.print("0");
|
||||
Serial.println(answer, HEX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,86 @@
|
||||
// FILE: RS485_master_controller.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/RS485
|
||||
|
||||
// This is the code for a master (to be used with slave example)
|
||||
// Best is it to use on a MEGA or another board with multiple hardware Serials.
|
||||
// The master should be connected with one slave e.g. an UNO
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RS485.h"
|
||||
|
||||
const uint8_t sendPin = 4;
|
||||
const uint8_t deviceID = 0;
|
||||
|
||||
// use a 2nd Serial port.
|
||||
// RS485 rs485(&Serial2, sendPin, deviceID);
|
||||
RS485 rs485(&Serial, sendPin, deviceID);
|
||||
|
||||
|
||||
// for receiving (must be global)
|
||||
uint8_t ID;
|
||||
uint8_t arr[32];
|
||||
uint8_t len;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(38400);
|
||||
while (!Serial);
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("RS485_LIB_VERSION: ");
|
||||
Serial.println(RS485_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (Serial.available())
|
||||
{
|
||||
char c = Serial.read();
|
||||
switch(c)
|
||||
{
|
||||
// digital read
|
||||
case '2':
|
||||
rs485.send(1, "DR2", 3);
|
||||
break;
|
||||
case '3':
|
||||
rs485.send(1, "DR3", 3);
|
||||
break;
|
||||
case '4':
|
||||
rs485.send(1, "DR4", 3);
|
||||
break;
|
||||
|
||||
// digital write
|
||||
case 'H':
|
||||
rs485.send(1, "DW7H", 4);
|
||||
break;
|
||||
case 'L':
|
||||
rs485.send(1, "DW7L", 4);
|
||||
break;
|
||||
|
||||
// analog read
|
||||
case 'A':
|
||||
rs485.send(1, "AR0", 3);
|
||||
break;
|
||||
case 'B':
|
||||
rs485.send(1, "AR1", 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if (rs485.receive(ID, arr, len))
|
||||
// {
|
||||
// arr[len] = 0;
|
||||
// Serial.print("RECV:\t");
|
||||
// Serial.print(ID);
|
||||
// Serial.print("\t");
|
||||
// Serial.println((char*) arr);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,57 @@
|
||||
// FILE: RS485_slave_controller.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/RS485
|
||||
|
||||
// This is the code for a master (to be used with slave example)
|
||||
// Best is it to use on a MEGA or another board with multiple hardware Serials.
|
||||
// The master should be connected with one slave e.g. an UNO
|
||||
//
|
||||
// The application is (too) simple,
|
||||
// if the slave receives a printable char it returns an ACK
|
||||
// else an NACK
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RS485.h"
|
||||
|
||||
const uint8_t sendPin = 4;
|
||||
const uint8_t deviceID = 0;
|
||||
|
||||
// use a 2nd Serial port.
|
||||
// RS485 rs485(&Serial2, sendPin, deviceID);
|
||||
RS485 rs485(&Serial, sendPin, deviceID);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(38400);
|
||||
while (!Serial);
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("RS485_LIB_VERSION: ");
|
||||
Serial.println(RS485_LIB_VERSION);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (rs485.available())
|
||||
{
|
||||
char c = rs485.read();
|
||||
|
||||
if (isPrintable(c))
|
||||
{
|
||||
rs485.write(ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
rs485.write(NAK);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,29 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
# selected only those that work
|
||||
platforms:
|
||||
- uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266 # does not support A1 analog
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
@ -0,0 +1,92 @@
|
||||
// FILE: RS485_slave_controller.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo
|
||||
// URL: https://github.com/RobTillaart/RS485
|
||||
|
||||
// This is the code for a master (to be used with slave example)
|
||||
// Best is it to use on a MEGA or another board with multiple hardware Serials.
|
||||
// The master should be connected with one slave e.g. an UNO
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RS485.h"
|
||||
|
||||
const uint8_t sendPin = 4;
|
||||
const uint8_t deviceID = 0;
|
||||
|
||||
// use a 2nd Serial port.
|
||||
RS485 rs485(&Serial, sendPin, deviceID);
|
||||
|
||||
|
||||
// for receiving (must be global)
|
||||
uint8_t ID;
|
||||
uint8_t buffer[32];
|
||||
uint8_t len;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(38400);
|
||||
while (!Serial);
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("RS485_LIB_VERSION: ");
|
||||
Serial.println(RS485_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (rs485.receive(ID, buffer, len))
|
||||
{
|
||||
buffer[len] = 0;
|
||||
// DIGITAL READ
|
||||
if (strcmp((char*)buffer, "DR2") == 0)
|
||||
{
|
||||
int value = digitalRead(2);
|
||||
sprintf((char*)buffer, "DR2: %d", value);
|
||||
}
|
||||
else if (strcmp((char*)buffer, "DR3") == 0)
|
||||
{
|
||||
int value = digitalRead(3);
|
||||
sprintf((char*)buffer, "DR3: %d", value);
|
||||
}
|
||||
else if (strcmp((char*)buffer, "DR4") == 0)
|
||||
{
|
||||
int value = digitalRead(4);
|
||||
sprintf((char*)buffer, "DR4: %d", value);
|
||||
}
|
||||
|
||||
// DIGITAL WRITE
|
||||
else if (strcmp((char*)buffer, "DW7H") == 0)
|
||||
{
|
||||
digitalWrite(7, HIGH);
|
||||
sprintf((char*)buffer, "DW7: H");
|
||||
}
|
||||
else if (strcmp((char*)buffer, "DW7L") == 0)
|
||||
{
|
||||
digitalWrite(7, LOW);
|
||||
sprintf((char*)buffer, "DW7: L");
|
||||
}
|
||||
|
||||
// ANALOG READ
|
||||
else if (strcmp((char*)buffer, "AR0") == 0)
|
||||
{
|
||||
int value = analogRead(A0);
|
||||
sprintf((char*)buffer, "AR0: %d", value);
|
||||
}
|
||||
else if (strcmp((char*)buffer, "AR1") == 0)
|
||||
{
|
||||
int value = analogRead(A1);
|
||||
sprintf((char*)buffer, "AR1: %d", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf((char*)buffer, "INVALID");
|
||||
}
|
||||
rs485.send(ID, buffer, strlen((char*)buffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/RS485"
|
||||
},
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=RS485
|
||||
version=0.3.0
|
||||
version=0.4.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=RS485 library for Arduino.
|
||||
|
Loading…
Reference in New Issue
Block a user