Go Down

Topic: problems interfacing with RS485 (Read 409 times) previous topic - next topic

adwsystems

The sensor works on RS485, you have proved that. So the issue is with the arduino. Use two RS485 modules connect the A/B wires to both. On one module, connect RO to Arduino RX and DE/RE to 5V, on the other connect DI to Arduino TX and ground DE/RE. This forces each module on the arduino to a single purpose and rules out any problem with controlling DE/RE (which you have per the last sketch posted). Let's bypass the problem areas for now and get to something that works. Then we can go back and fix the bandaids later.

You don't need another arduino, you have a RS485-USB converter that you can use to see what is on the A/B lines using the PC.

frichsness

progress :) yay

okay i tried hooking up 2 MAX485's and running one for transmit and one receive, and after ALOT of fidling around, i finaly changed the sketch to only receive serial data and display it on the serial monitor. then i used the RS485 to USB and used the PC to send the 10TR2 command.

that worked, but initially when i switched on the transmit from the arduino, i could only see an echo of the command i sent. it turned out i had to send an ENTER command after the 10TR2, so i switched to Serial1.println and it worked.

but i still cant get it to send and receive from the same module. for some reason even thou i take the wires completely off DE and RE on the transmit module, it still transmits, and i have to connect DE and RE to ground on the receive module in order to get that working.

maybe i just have a bad set of modules, but it seems to me i have to get a small transistor in there to switch the pins to ground when receiving (or remember a fluke tomorrow so i can see if it actualy goes low), in order to get it running on 1 module.

the current code (wire from pin 8 not mounted)
Code: [Select]
void setup() {
  Serial1.begin(9600);
  Serial.begin(9600);
  pinMode(8, OUTPUT);
}
void loop() {
  char getdata='m';
  digitalWrite(8,HIGH);
  Serial1.println("10TR2");
  delay(100);
  digitalWrite(8,LOW);

  if(Serial1.available()){
  
    while(Serial1.available() && getdata!='d')
    {
    getdata=Serial1.read();
    Serial.print(getdata);
    }
    Serial.println(" ");
    }
  delay(1000);
}


output in serial monitor (VV.V DDD TT.T) (V=windspeed D=wind direction T=temperature)
Code: [Select]
*44
10TR2
22:00:57.754 -> 00.1 067 +24.8 5
E*45
10TR2
22:00:58.850 -> 00.0 000 +24.9 5E
*44
10TR2
22:00:59.958 -> 00.0 000 +25.0 5E
*4C
10TR2
22:01:01.023 -> 00.0 000 +25.0 5E
*4C
10TR2
22:01:02.125 -> 00.0 000 +25.1 5
E*4D
10TR2
22:01:03.253 -> 00.0 000 +25.2 5E
*4E
10TR2
22:01:04.348 -> 00.0 000 +25.1 5E


so now at least i am getting some usefull data, just need to see if i can refine it a bit and get rid of that extra module.

then then next big step is going to be to get in transfered to a web server on a raspberry, but thats another headache :)

thanks alot for your help up to now adwsystems, it has realy helped me get on the right track everytime i was straying off the path :)

adwsystems

but i still cant get it to send and receive from the same module. for some reason even thou i take the wires completely off DE and RE on the transmit module, it still transmits, and i have to connect DE and RE to ground on the receive module in order to get that working.
What you should have is:
TX Module:
-DE/RE on Tx module are connected to +5V
-DI connected to Arduino Serial1 Tx
-RO not connected

RX Module:
-DE/RE on the Rx module are connected to ground
-RO connected to Arduino Serial1 Rx
-DI not connected

This will work, I have done this very thing to get my modbus RS-485 network and software working.

Once you connect DE/RE to the Arduino, you now must synchronize the transmit of data while the DE/RE line is high and not go low until everything is transmitted (not as easy as one would hope).

frichsness

just an update :)

managed to get the whole thing simplified to the point of having only 1 RS485 module and the code cleaned up a bit.

but as you said getting the timing right was quite a bit of trail and error, i finally got it working at 7ms transmit time. with 6ms the 2 of the command string was missing every 3-4 loops, and at 9 it didn't  switch to receive before the sensor sent it's data, so i would only get the last bit of the string.

it helped a lot to have the RS485 to USB in the circuit and monitoring that with putty.

but if anyone wants it later here is the final code i am using.
Code: [Select]
void setup() {
  Serial1.begin(9600);
  Serial.begin(9600);
  pinMode(2, OUTPUT);
}
void loop() {
  char getdata='m';
  digitalWrite(2,HIGH);
  Serial1.println("10TR2");
  delay(7);
  digitalWrite(2, LOW);

  if(Serial1.available()){
 
    while(Serial1.available() && getdata!='d')
    {
    getdata=Serial1.read();
    Serial.print(getdata);
    }
    Serial.println(" ");
    }
  delay(980);
}

adwsystems

#19
Oct 11, 2018, 01:02 pm Last Edit: Oct 11, 2018, 01:03 pm by adwsystems
I hate timers. You need to find out if there is a way to detect when the transmit is done. From a library I did not write, I think this is the command you need when using Serial1.

while (!(UCSR1A & (1 << TXC1)));

I would leave the line is receive by default, and change to transmit using the above code to determine when to change back to receive.

frichsness

#20
Oct 11, 2018, 01:08 pm Last Edit: Oct 11, 2018, 01:11 pm by frichsness
I hate timers. You need to find out if there is a way to detect when the transmit is done. From a library I did not write, I think this is the command you need when using Serial1.

while (!(UCSR1A & (1 << TXC1)));

I would leave the line is receive by default, and change to transmit using the above code to determine when to change back to receive.

hmmm interesting i will try to look into that, the sensor has a responce time of <5ms according to the manual.

but i have been playing around with the things i have learned a bit, and adapted the code to run on a nano with software serial. so 1 arduino nano and 1 MAX485, not sure i can make it a smaller package in any way.

is there any way to "filter out" the start bit, checksum and endbit from the serial.print ?

00.1 022 +24.4 5E*48

here is the code for the nano, added led for transmit
Code: [Select]

#include <SoftwareSerial.h>

#define SSerialRX        10 
#define SSerialTX        11 
#define SSerialTxControl 3   
#define RS485Transmit    HIGH
#define RS485Receive     LOW
#define Pin13LED         13

SoftwareSerial RS485Serial(SSerialRX, SSerialTX);

void setup()
{
  Serial.begin(9600);
  pinMode(Pin13LED, OUTPUT);
  pinMode(SSerialTxControl, OUTPUT);
  digitalWrite(SSerialTxControl, RS485Receive);
  RS485Serial.begin(9600);
}

void loop()
{
  char getdata='m';
  digitalWrite(Pin13LED, HIGH);
  digitalWrite(SSerialTxControl, RS485Transmit);
  RS485Serial.println("10TR2");
  delay(7);
  digitalWrite(Pin13LED, LOW);
  digitalWrite(SSerialTxControl, RS485Receive);     
 
  if (RS485Serial.available())
  {
     while(RS485Serial.available() && getdata!='d')
     {
        getdata=RS485Serial.read();
        digitalWrite(Pin13LED, HIGH);
        Serial.print(getdata);       
        digitalWrite(Pin13LED, LOW);
     }
    Serial.println(" ");
  }
  delay(980);
}

adwsystems

If you are going to SoftwareSerial, be ready for a whole other set of problems. AltSoftSerial is better but still has it drawbacks. The Adruino Micro is another option, as it features a serial connection for the computer and a separate hardware UART. Technically it is listed as having one UART, but actually has two serial connections and neither are software based.

frichsness

then that might be a better option, since i definatly need a serial connection to get the data onto a raspberry later on

Go Up