9 years ago.

Nothing happening with RS485 communication

Hi I'm trying to use an RS485 system to communicate with mbed over a 30m cable. It is tasked with adjusting the position of a servo and reporting an angle derived from accelerometers. I have a usb to rs485 assembly at the computer: http://www.ftdichip.com/Products/Cables/USBRS485.htm And the transceiver linked mentioned in the cookbook https://www.sparkfun.com/products/10124 I think everything is connected as required but apart from a data light on the usb plug at the computer nothing is happening. I've not done anything beyond the usb serial connection before so I suspect I maybe missing something fundemental/obvious, how does the following look? Thanks Robin

  1. include "mbed.h"
  2. include "Servo.h" Servo myservo(p22); Serial pc(p28, p27); AnalogIn z(p20); AnalogIn y(p19); AnalogIn x(p18); int main() { pc.printf("\n\r***\n\rMBED restarted\n\r***\n\ri key sets inclination to 90 degrees\n\rkeys 1, 2 & 3 move actuator to respective positions. \n\rKey 4 increases radius, key 5 reduces it. \n\r"); pc.printf("Ctrl+a then b restarts the system\n\r\n\r"); float position = 0.5; float range = 0.0005; float inclin = 0; float inc_offset = 180; float pipe_mm = 0; float actuator_extension = 0;

while (1) { wait(0.5);

if (pc.readable()) { switch(pc.getc()) { case '1': position = 0.0; break; case '2': position = 0.5; break; case '3': position = 1.0; break; case '4': position -= 0.01; break; case '5': position += 0.01; break; case 'i': inc_offset += (90 - inclin); break;}}

inclin = fmod( ( atan2( (y.read()-0.5)*10, (x.read()-0.5)*10 ) * 180.0 / 3.141592654 ) + inc_offset, 360 );

pipe_mm = 225 + (3.641*(30*position)); actuator_extension = position*30;

pc.printf("Inclination, %.1f degrees", inclin); pc.printf("\r\nActuator position %f", position); pc.printf(" Radial position at 0 degrees, %f mm", pipe_mm); pc.printf(" Actuator extension, %f mm\r", actuator_extension); myservo.calibrate(0.0005, 30.0); myservo = position;

}}

use "<<code>>" and "<</code>"" to make it more readable...

   #include "mbed.h"
    #include "Servo.h" 
Servo myservo(p22); 
Serial pc(p28, p27); 
AnalogIn z(p20); 
AnalogIn y(p19); 
AnalogIn x(p18); 

int main() 
{ 
pc.printf("\n\r***\n\rMBED restarted\n\r***\n\ri key sets inclination to 90 degrees\n\rkeys 1, 2 & 3 move actuator to respective positions. \n\rKey 4 increases radius, key 5 reduces it. \n\r"); 
pc.printf("Ctrl+a then b restarts the system\n\r\n\r"); 

float position = 0.5;
 float range = 0.0005; 
float inclin = 0; 
float inc_offset = 180; 
float pipe_mm = 0;
 float actuator_extension = 0; 

while (1) 
{ 
 wait(0.5);

 if (pc.readable()) { 
  switch(pc.getc()) { 
     case '1': position = 0.0; break; 
     case '2': position = 0.5; break; 
     case '3': position = 1.0; break; 
     case '4': position -= 0.01; break; 
     case '5': position += 0.01; break; 
     case 'i': inc_offset += (90 - inclin); break;
   }
  }

inclin = fmod( ( atan2( (y.read()-0.5)*10, (x.read()-0.5)*10 ) * 180.0 / 3.141592654 ) + inc_offset, 360 );

pipe_mm = 225 + (3.641*(30*position)); actuator_extension = position*30;

pc.printf("Inclination, %.1f degrees", inclin); 
pc.printf("\r\nActuator position %f", position); 
pc.printf(" Radial position at 0 degrees, %f mm", pipe_mm); 
pc.printf(" Actuator extension, %f mm\r", actuator_extension); myservo.calibrate(0.0005, 30.0); myservo = position;

}
}
posted by Raph Francois 23 Apr 2015

2 Answers

9 years ago.

Hi Robin,

I don't have the specific hardware which you talk about, but I think you should first start by looking if you receive anything from the rs485. Try something really simple and look if there is data returned to the pc. It will help me help you.

try sending some data with this function:

#include "mbed.h"

Serial pc(p28, p27);

int main()
{
    while (1) {
        if( pc.readable()) {
            pc.putc(pc.getc());
        }
    }
}

if you get characters which you don't recognize, this would mean that the baudrate you use is not the default mbed one. For this, you will need to find which baudrates fit your need. In the following code I added a few typical baudrates which you could try to switch if you don't know the baudrate of your communication device.

#include "mbed.h"

Serial pc(p28, p27);

int main()
{
pc.baud(4800);
//pc.baud(9600);
//pc.baud(19200);
//pc.baud(38400);
//pc.baud(115200);
    while (1) {
        if( pc.readable()) {
            pc.putc(pc.getc());
        }
    }
}

If these 2 things didn't work, we'll look further into the code, otherwise, let's see with he hardware.

Maxim

Hi Maxim I focused the hardware as it became apparent that I had missed the rts, however after struggling to make progress I was looking to go through my code from the start. What should the following do?

#include "mbed.h"
 
Serial pc(p28, p27);
 
int main()
{
    while (1) {
        if( pc.readable()) {
            pc.putc(pc.getc());
        }
    }
}

Am I right in thinking this is intended to take characters from the computer keyboard, give them to the mbed, and then repeat the to the computer, showing in terminal? I get a send light flickering at the computer end but nothing coming back to the terminal. I know the mbed system is ok because I test it thorough the usb from time to time. Am I perhaps missing something in the terminal set-up? Thanks Robin

posted by Robin Hague 30 Apr 2015
9 years ago.

Have you used 120Ohm resistor between A and B of the 2 devices ?

This is how RS485 needs to works...

http://i.stack.imgur.com/TT2By.jpg

And also RS485 is Half Duplex , so you have to tell to the driver when it can send datas and when it can receive datas...

if you look at the datasheet from sparkfun https://cdn.sparkfun.com/datasheets/BreakoutBoards/RS485_Breakout_v10.pdf

You can see that there is an rts pin that is connected to the DE (Data Enable) and not RE (Receive Enable) pins of the drivers. So they works with an inverse logic. When DE is High RE is Low and when DE is Low RE is high. This is by this way you can state the drivers to send or receive datas.

You need to use an DigitalOut Pin from your mbed and connect it to the rts.

So from everytime you need to send datas through the drivers youMUST first set the digitalout pin to High Level and then set it to low level when you want to receive datas...

As we don't know about your schematics, it's not easy to help you about that. Can you provide more informations ?

Best regards

That look like the issue, I've got the resistors in but am not driving the RTS pin. I'll set that up next. (and thanks or the <<code>> <</code>>, I was wondering about that!)

posted by Robin Hague 23 Apr 2015

Ok hardware seems to be there, with the addition of an RTS line the system is feeding characters back to the PC. But it is not showing everything as expected, and it doesn't appear to be accepting the commands from the key board. The code now looks like the following, any issues jump out?

#include "mbed.h"
#include "Servo.h"
Servo myservo(p22);
Serial pc(p28, p27);
DigitalOut rts (p26);
AnalogIn z(p20);
AnalogIn y(p19);
AnalogIn x(p18);
int main() {
pc.printf("\n\r*************\n\rMBED restarted\n\r*************\n\ri key sets inclination to 90 degrees\n\rkeys 1, 2 & 3 move actuator to respective scanning positions. \n\rKey 4 increases radius, key 5 reduces it. \n\r");
pc.printf("Ctrl+a then b restarts the system\n\r\n\r");
float position = 0.5;
//float range = 0.0005;
float inclin = 0;
float inc_offset = 180;
float pipe_mm = 0;
float actuator_extension = 0;  
pc.baud(9600);  
    while (1) {
        wait(1.5);
        
        rts = 0;
        
        if (pc.readable()) {
            switch(pc.getc()) {
                case '1': position = 0.0; break;
                case '2': position = 0.5; break;
                case '3': position = 1.0; break;
                case '4': position -= 0.01; break; 
                case '5': position += 0.01; break;
                case 'i': inc_offset += (90 - inclin); break;}}

               
        inclin = fmod(
        (
        atan2(
        (y.read()-0.5)*10, (x.read()-0.5)*10
        ) * 180.0 / 3.141592654 
        ) + inc_offset, 360
        );
        
        pipe_mm = 225 + (3.641*(30*position));
        actuator_extension = position*30;

       rts = 1;
        pc.printf("Inclination, %.1f degrees", inclin);
        //pc.printf("\r\nActuator position %f", position);
        pc.printf(" Radial position at 0 degrees, %f mm", pipe_mm);
        pc.printf(" Actuator extension, %f mm\r", actuator_extension);
        myservo.calibrate(0.0005, 30.0); 
        myservo = position;        
        
        }}

posted by Robin Hague 23 Apr 2015

" But it is not showing everything as expected"... what do ypu mean ? Can you read the printf functions back to the PC ? Are the results bad ?

Try to put rts=0; before the wait statement. On other way, the pc.readable will be ok for only few micro seconds as there is only 3 lines of calculus before the rts=1;

It must works as you wrote but you have to be very very very quick ;o)

posted by Raph Francois 23 Apr 2015

Thanks Raph, given the half duplex nature of RS485 I reckoned that it was going to be best to use an RPC system to have the computer command the mbed. Either to request the output that I had printing here, or indeed to just collect the analogin and do all the calculation in Python on the pc. Not that any of that is working as the cookbook describes, it's so demoralising when thing don't match up to the instructions!

posted by Robin Hague 29 Apr 2015

Ok, accidentally shorted the tx/rx lines between the mbed and the rs485 breakout board and that makes the system start writing to the terminal (which was otherwise inactive). Should there be another resistor on the mbed serial pins? I've never seen mention of this otherwise. Still never managed to send something back to the mbed.

posted by Robin Hague 01 May 2015