Closed rozrabiak closed 1 year ago
Thanks for these questions. Has been some time since I used it. Some quick answers
Add 3. Depends on the size of the struct. This library has some protocol that has a 48 byte buffer so it should fit in (do not forget overhead etc).. Probably it makes sense to define your own protocol that runs on top of the basic sending of bytes.
Add 5 Checksum XOR is a weak checksum 0.4% chance of missing errors. Better use CRC16 which fails 1 in 65535 or CRC32.
Add 4. Protocol design is pretty difficult to get robust and not loose performance. Read a book about the implementation of TCP/IP which is a very reliable protocol.
Now I test on BlackPill (STM32F401CCU6) using Serial1. Code for STM32 (and code for Arduino nano below):
#include <Arduino.h>
#include <RS485.h>
#define rs485Tx HIGH
#define rs485Rx LOW
#define rs485ReDe PB15
const uint8_t devID = 1;
const char msg[] = "23";
RS485 rs485(&Serial1, rs485ReDe, devID);
int status;
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
rs485.setMicrosPerByte(9600);
delay(2000);
Serial.println("Start");
Serial.println("PCF8574");
}
void loop() {
rs485.send(3, (uint8_t *)msg, strlen(msg));
delay(100);
if(rs485.available() > 0)
{
status = rs485.read();
}
if(status > 1)
{
Serial.print("status ");
Serial.println(status);
}
Serial.print("devID ");
Serial.println(rs485.getDeviceID());
delay(2000);
}
#include <Arduino.h>
#include <RS485.h>
//dla rs485
const uint8_t devID = 3;
#define rs485Tx HIGH
#define rs485Rx LOW
#define rs485ReDe 2
RS485 rs485(&Serial, rs485ReDe, devID);
int status;
const char msg[] = "52";
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
delay(100);
Serial.println("sterownik kurnika");
rs485.setMicrosPerByte(9600);
}
void loop()
{
// put your main code here, to run repeatedly:
if(rs485.available() >0)
{
status = rs485.read();
}
Serial.print("status ");
Serial.println(status); //always 0
Serial.print("devID ");
Serial.println(rs485.getDeviceID());
if(status == 23)
{
rs485.send(1, (uint8_t *)msg, strlen(msg));
}
delay(2000);
}
Communication not working for me. On Arduino Nano "status" always return integer from 1 to 170 not what I send from STM32. No one library for rs485 works between Nano and STM32, I tested 4 libraries :-)
Have nice day!
mmm, getting too late now, can't think properly, sorry.
No one library for rs485 works between Nano and STM32, I tested 4 libraries :-)
I do not have the STM hardware to verify, this library worked between Nano's. to be continued later this week.
Rob, receiving using this code:
if (rs485.receive(ID, arr, len))
{
arr[len] = 0;
Serial.print("RECV:\t");
Serial.print(ID);
Serial.print("\t");
Serial.println((char*) arr);
}
Works with STM32 & Arduino Nano.
Thank's a lot! Have a nice day.
(updated the code tags in your posts)
Works with STM32 & Arduino Nano.
If your problem is solved now, you may close the issue.
Thank's a lot!
you're welcome
My luck was too short... Sending from stm32f4 to arduino nano works great. But when I'm trying to send from NANO to stm32 - stm32 not receiving any data.
So, i just try to add
delay(100);
in function:
void RS485::send(uint8_t receiverID, uint8_t msg[], uint8_t len)
{
uint8_t CHKSUM = 0;
setTXmode(); // transmit mode
delay(100); //ADDED
_stream->write(SOH);
_stream->write(receiverID); // TO
_stream->write(_deviceID); // FROM
_stream->write(len); // LENGTH BODY
_stream->write(STX);
for (int i = 0; i < len; i++)
{
_stream->write(msg[i]);
CHKSUM ^= msg[i]; // Simple XOR checksum.
}
_stream->write(CHKSUM);
_stream->write(ETX);
_stream->write(EOT);
delayMicroseconds((len + 8 + 2) * _microsPerByte); // + 2 to be sure...
delay(100); //ADDED
setRXmode();
}
but it's help only for a few minutes, I don't know why, but after some time - stm32 not receiving any data.. :-( I'm sending data every 1500ms from NANO to stm32.
Any ideas?
[EDIT]: so, I removed
delay(100);
And added (after last write(EOT))
_stream->flush();
and now, from sended 147 messages only 5 was received by stm32 :-(
Are you using a software serial on the STM32 side? RS485 works most reliable with a hardware serial (at least for receive, send() works fine with SWW).
Every node that is not sending should be in the receive mode.
Can you try to get it working with two NANO's?
I'm tired. That was my mistake I'm running code in loop without any millis/delays. Communication works without problems.
But _stream.flush();
- must be in code, without there is no communication.
I'm not using software serial. On STM32 I'm using Serial1 for rs485, Serial for monitor on PC.
On nano I'm sharing Serial for both.
But... when I'm sending structure like below - float values OR integer values are always received as 0.00 or 0 (zero). When I'm trying to send structure with String - program on receiver hangs. Is there any solution?
Thank's a lot for Your patience.
Sender:
struct sendPacket
{
bool ssrState; //ssr relay state
bool socketState; //socket relay state
bool mOkno; //small windows
bool dOkno; //big window
bool mDrzwi; //small door
bool dDrzwi; //big door
float temp = 25.22; //temperature in chicken house
int autoGrzanie = 0; //auto heat
float setTemp = 10;
};
sendPacket _sendPacket;
rs485.send(1, (uint8_t*)&_sendPacket, sizeof(_sendPacket));
Receiver:
struct rcvKurPacket
{
bool ssrState; //ssr relay state
bool socketState; //socket relay state
bool mOkno; //small windows
bool dOkno; //big window
bool mDrzwi; //small door
bool dDrzwi; //big door
float temp; //temperature in chicken house
int autoGrzanie; //auto heat
float setTemp;
};
rcvKurPacket _rcvKurPacket;
if (rs485.receive(ID, arr, len))
{
arr[len] = 0;
rcvKurPacket* dtrs = reinterpret_cast<rcvKurPacket*>(arr);
Serial.print("RECV:\t");
Serial.print(ID);
Serial.print("\t");
Serial.println((char*) arr);
Serial.print("dDrzwi ");
Serial.println(dtrs->dDrzwi);
Serial.print("mDrzwi ");
Serial.println(dtrs->mDrzwi);
Serial.print("mOkno ");
Serial.println(dtrs->mOkno);
Serial.print("dOkno ");
Serial.println(dtrs->dOkno);
Serial.println(dtrs->temp);
}
EDIT:
I try to change buffer size - nothing happens, float are 0.00 :-(
uint8_t _buffer[100]; // internal receive buffer
I'm tired.
Happens to everyone,
But... when I'm sending structure like below - float values OR integer values are always received as 0.00 or 0 (zero). When I'm trying to send structure with String - program on receiver hangs. Is there any solution?
make a HEX dump of what is received to analyze
if (rs485.receive(ID, arr, len))
{
Serial.print(len); // should be 16..20 or so
Serial.print("\t")
for (int i = 0; i< len; i++)
{
if (arr[i] < 0x10) Serial.print(0, HEX);
Serial.print(arr[i], HEX);
Serial.print("\t");
}
Serial.println();
}
you might need to test on both platforms
HEX dump:
16 00 01 01 01 00 01 AE 47 B3 41 FF 00 00 00 7F 43
and sizeof:
arduino nano:
float 4
bool 1
int 2
stm32:
float 4
bool 1
int 4
struct receiving on stm32f4.
EDIT: I try to send float without struct:
float test = 25.47;
rs485.send(1, (uint8_t*)&test, sizeof(test));
and receive:
float* dtrs = reinterpret_cast<float*>(arr);
float floatOut = dtrs[0];
That's works.
Note you have a problem with sending the int. It is different in size on the two platforms.
You can replace int with int32_t which is forced 32 bit.
Way past midnight, to be continued tomorrow
So, I make some tests..
FIRST TRY:
struct sndPacket
{
float temp; //temperature in chicken house
float setTemp = 10; // temperatura zadana
int autoGrzanie = 65; //auto heat
bool mDrzwi; //small door
bool dDrzwi; //big door
};
sndPacket _sndPacket;
void setup()
{
_sndPacket.temp=25;
_sndPacket.setTemp = 32;
_sndPacket.autoGrzanie = 65;
_sndPacket.dDrzwi = true;
_sndPacket.mDrzwi = false;
}
SERIAL MONITOR ON STM32:
00:45:14.947 > dDrzwi 0
00:45:14.947 > mDrzwi 0
00:45:14.947 > 25.00
00:45:14.947 > 32.00
00:45:14.947 > 16777281
bool and int are not correct values.
SECOND TRY:
struct sndPacket
{
float temp; //temperature in chicken house
float setTemp = 10; // temperatura zadana
int autoGrzanie = 65; //auto heat
byte mDrzwi; //small door
byte dDrzwi; //big door
};
sndPacket _sndPacket;
void setup()
{
_sndPacket.temp=25;
_sndPacket.setTemp = 32;
_sndPacket.autoGrzanie=65;
_sndPacket.dDrzwi = 1;
_sndPacket.mDrzwi=0;
}
SERIAL MONITOR ON STM32:
07:57:47.432 > dDrzwi 0
07:57:47.432 > mDrzwi 0
07:57:47.432 > 25.00
07:57:47.432 > 32.00
07:57:47.432 > 16777281
byte and int are not correct.
THIRD TRY:
struct sndPacket
{
byte mDrzwi; //small door
byte dDrzwi; //big door
};
sndPacket _sndPacket;
void setup()
{
_sndPacket.dDrzwi = 1;
_sndPacket.mDrzwi = 0;
}
SERIAL MONITOR ON STM32:
08:02:11.531 > dDrzwi 1
08:02:11.531 > mDrzwi 0
all correct.
FOURTH TRY:
struct sndPacket
{
float temp; //temperature in chicken house
float setTemp = 10; // temperatura zadana
int autoGrzanie = 65; //auto heat
};
sndPacket _sndPacket;
void setup()
{
_sndPacket.temp=25;
_sndPacket.setTemp = 32;
_sndPacket.autoGrzanie=65;
}
SERIAL MONITOR ON STM32:
00:45:14.947 > 25.00
00:45:14.947 > 32.00
00:45:14.947 > 65
all correct.
FIFTH TRY:
struct sndPacket
{
float temp; //temperature in chicken house
float setTemp = 10; // temperatura zadana
int autoGrzanie = 65; //auto heat
float mDrzwi; //small door
int dDrzwi; //big door
};
sndPacket _sndPacket;
void setup()
{
_sndPacket.temp = 25;
_sndPacket.setTemp = 32;
_sndPacket.autoGrzanie = 65;
_sndPacket.dDrzwi = 125;
_sndPacket.mDrzwi = 256;
}
SERIAL MONITOR ON STM32:
08:15:32.351 > dDrzwi 0
08:15:32.351 > mDrzwi 0.00
08:15:32.351 > temp 25.00
08:15:32.351 > setTemp 32.00
08:15:32.352 > autoGrzanie 65
dDrzwi & mDrzwi have incorrect values.
So, buffer size now I have hardcoded to 200:
uint8_t _buffer[200]; // internal receive buffer
and problem still exists. Have a nice day!
Good morning The size of the buffer is not problem. The data is send as a stream of bytes, and every field of the struct starts at a certain position. This position depends on the size of the data types on the specific processor. That is why I said you should use int32 instead of int. That has the same size on all platforms.
Rob! You write about int32_t in comment !! And I forgot about that :-( I change int to int32_t and it's work's! It's time to rest. Bike ride - it's a good idea. Thank's a lot! Have nice day.
As I said before, designing a protocol is harder than most people think.
These are the most common areas that need attention (There are more, check the OSI 7 layers model.)
as discussed here
You have an int32 that you know that is 4 bytes, but in which order are those 4 bytes send (12 possibilities, in real live I have seen 3 or 4 version) This is seen sometimes e.g. in RGB images where colors suddenly swap.
OK and the bytes themselves, are they send MSG or LSB.
Some machines want every variable address at an even address or at an quad (div4) address
Are integers codes as binary (as usual) or as BCD (mainframe) Which char set is used?
Are Gray codes used? (prevents long runs of 0 or 1 bits) Is there an error detection and or correction scheme. Is there a compression scheme?
What is the chance of bit error for this communication line?
Maybe I should add this in a separate document one time.
Rob, my programming skills are very poor. But I like electronics and programming.
What you do for the community, what others do by writing libraries is amazing and deserves great respect, appreciation! Again - thanks for your help!
Rob, my programming skills are very poor. But I like electronics and programming.
I started when I was 8 or so with (hidden) electric switches and lights, and gradually knowledge build up. My first LED survived for 1 millisecond (no resistor) and several have followed, including displays, forgetting the diode near a relay, using wrong pins and debug until morning light etc. Programming is a similar story, "know how" is often "know how not to do things" A favorite quote: "You should make a mistake only once as there are enough others too choose from next time."
Programming is best done with pen and paper, draw the flow of information, timing diagrams etc Decompose the problem into parts and give every part its responsibility. Libraries are sort "software IC's", defining the interface is most important, how things are handled inside is another abstraction layer. Similar for software functions, you define what to put in, and what comes out and how it is implemented comes later.
Again - thanks for your help!
You're welcome
Hi, because I don't know how to add pull request I have some questions.
Maybe fork of this library (probably discontinued) https://github.com/rzeman9/Simple485
Thank's a lot for this work.