RS-485 configuation

Hi, I'm trying to get an Arduino to talk to the scalextric C7042 powerbase to allow using the protocoll it supports for talking to computers.

I have done this via a laptop, and once I got the serial port configured it worked fine.

the device uses RS-485 to talk, the protocol is basically transmit 9 bytes, get 15 bytes back, repeat at will.

I have managed to get two Arduino talking over RS-485, using Max485 chips on the handy little modules you can get cheaply on line, and sending the same data back and forth. But so far cannot coax a response from the C7042 - which will talk to a laptop quite well.

I suspect the issue is in the serial port configuration, the required specification is thus:

1 start bit
8 data bits
no parity bit
1 stop bit
19,200 baud.

the code used on the laptop to open the serial port is thus:

    struct termios options;
    #define DEVICE "/dev/tty.usbserial-AI023L0L"
    int FD;
    // try to close the port
    close(FD);
    FD = open(DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (FD <0)
    {
        // Error opening port
        return 1;
    }
    // set back to blocking mode
    if(fcntl(FD, F_SETFL, 0) == -1)
    {
        // Error configuring Port
        return 2;
    }
    
    tcgetattr(FD, &options);
    cfsetispeed(&options, B19200);
    cfsetospeed(&options, B19200);
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;         // 8 bit data
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_lflag = 0;
    options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF);
    options.c_cc[VMIN] = 14;        // read 14 char --> full input packet
    options.c_cc[VTIME] = 1;
    
    if (tcsetattr(FD, TCSANOW, &options) == -1)
    {
        // Error configuring port
        return 3;
    }

this is obviously part of something quite a bit larger, this works

on the arduino the RS-485 module is connected to the Rx & Tx pins and the serial port opened with:

Serial.begin(19200, SERIAL_8N1);

which I think sets the baud rate to 19,200, 8 bit data, no parity and 1 stop bit

I can then use this configuration between two Arduino to talk happily, guessing because they both have the same configuration. tying this to the C7042 leads to the write operation reporting it worked (but then it is easily pleased as its just talking to the Max485 chip). yet the Serial.readBytes() operation times out and returns zero bytes - the C7042 isn't itself responding to what has been sent.

my question is this: is the Arduino serial port configuration in Serial.begin() likely correct/complete or is there another step required somewhere?

I've had a look on line at various tutorials which got the two Arduinos talking after a bit of fiddling sending binary data back and forth well so presumably the hardware etc is working fine meaning its either the configuration, while workable, is wrong for the target device, or there is something wrong in the checksum code - though the same code works fine on a laptop, and is the code lifted from the C7042 specification.

any guidance or references for where would be a good place to go with this most welcome

As you can have more than 2 devices on an RS-485 cable, can you use your laptop as a packet sniffer to monitor the RS-485 messages. That might give you an idea of what is happening on your RS-485 link and whether you have the correct serial parameters.

Also, as RS-485 is differential, it could simply be that your + & - wires are swapped over.

There's an ancient serial port monitor that I've used in the past that displays serial data as hex bytes which might help you as well. You can find the latest version here.

Laptop is a mac which is a pig ear in some ways for things like this.

I suspected the A & B wires could be the other way round, the little board is hooked with a DPDT switch set to make them easy to reverse and thats been tried.

have used the "other" Arduino to see what the first is actually sending and its picking up what I expect it to see, I just suspect thats largely down to both having the same config and it should work whatever that config is, as long as its the same both ends.

I m wondering on getting another module to strip the resistors from to use as a device in the middle to see what it can see, but presumably you get the same issue - if its configured the same it will see stuff if not, it won't.

the C7042 is a curious beastie, while the spec says this is RS-485 there is a bit more to it, the thing has three modes of operation - one where nothing is plugged into it (on this port), one where the display it comes with is plugged in and this mode which is meant to be RS-485.

its not well documented but people wiser than me have found if you use the +12V power line it puts out and draw current from it the thing goes into a different mode - that mode apparently will fry a Max485 chip (and many others), so leaving that line alone. there was a muttering about having to change the termination resistor but others say there is no need..

just really wanting to check I have the serial port actually configured correctly, if it is the problem has to be code (which since it works elsewhere it shouldn't be) or something about the Arduino its not liking

curious to get it working as it means a somewhat expensive laptop can be replaced for my purposes by a somewhat less expensive Arduino

a bit of progress, though its still not actually working - have eliminated a few more things.

have now tried with the SoftwareSerial library as well as the hardware stuff to no effect, added a switch to make swapping the A & B lines easier and swapped the termination resistor for 120 ohms of resistors and a 1k potentiometer to see if that makes a difference, so far nothing.

wondering what Hornby have done to the RS-485 system the documentation neglects to mention

I'm guessing that you have seen this web site. The author provides a link to some Hornby documentation that details the interface.

I had a quick look and it all seems fairly straightforward. There seems to be 2 main variables at play in talking to the unit. (1) you need to get the serial parameters right (baud rate, parity, stop bit etc) and (2) you need to get the checksum calculated correctly.

If you got it to work with the laptop, then you could eliminate the checksum calculation by generating a fixed message on the laptop and then getting the arduino to transmit the exact same 9 byte message - i.e. bypass your checksum calculation.

That should only leave you with the serial port setup parameters to deal with.

BTW, that document says that the unit responds with 14 bytes of data.

I have that doc, yes as supplied it responded with 14, I've since updated the firmware and it now replies with 15, the extra byte being the state of the 8 buttons on the thing, plus allowing for more commands to be sent and generally making it a heck of a lot more useful

thats the plan, I have some RJ-12 sockets on order, plug the laptops cable into an Arduino, record what its actually sending, then have the Arduino send that and see what happens, if that doesn't work then it has to be some sort of serial port configuration issue.

IIRC it took a fair bit of trial and error to get the laptop talking to it - though you have a lot more control over how the serial port works there

specifically the .read() operation can be told to wait until it has 'x' bytes or it times out.

however the hardware is meant to flip into "SNC" mode when its gets the data packet and from past experience thats not happening (in that mode the car controllers no longer drive the car, it passes the controller value out over this link and the computer at the other end sends back the speed to actually dive at - really good for self driving cars etc). the base unit isn't switching into that mode so presumably either it doesn't like the data (which is one angle) or its simply not recognising the connection

Problem is now solved, for the sake of completeness should any other poor lost soul be trying this the wolution that resolved the problem was actually quite simple.

change the 20k pull up and pull down resistors on the Max485 board for 4k7 resistors

that done, with the 120 ohm terminator everything works, nice stable connection.

also after sending to the C7042 powerbase immediately go into Listening mode, this thing replies both fast and once miss it and you are back to square one.

thanks for the help and pointers to all :slight_smile:

1 Like

Glad you got it working. ;D