Use V5 Smart Port as Generic Serial Device [PROS]


#1

We are trying to figure out how to use a V5 port as a generic serial port in PROS, and have had little success.

As far as we can see, the main control functions PROS provides are serctl(), and registry_bind_port().
We can see how to bind the port with the second function, but are not sure how to go about reading the serial data from the port.

In the vex api there is a vexGenericSerialRecieve() function, where you pass in the port, and a buffer for the data. However, we cannot find an equivalent function in the PROS api.

Is there an equivalent function in PROS that we aren’t finding? Otherwise, how would we go about receiving data from the port?


Keyboard and Mouse
#2

registry_bind_port is a function for internal use only. You can open a smart port as if it was a file by using standard C file I/O functions though:

FILE* port11 = fopen("/dev/11", "rw");

also note that serctl is also not exposed. Instead, use fdctl with the appropriate command.


#3

Thanks!
I tried the example code using

FILE* port_read = fopen("/dev/21", “r”);

but I can’t read any data from the port…
Is there anything special I need to do to use it as a serial port, right now I’m just using

fread(buf, 1, 256, port_read);

which is not working.

Also, do you know the BAUD rate of the brain? As far as I can find its 1562500, but I’m not sure.
Also also, how would I go about setting the BAUD rate with fdctl, what should I pass as the file parameter?


#4

Ports configured as generic serial will default to 115200 baud.

What type of device are you trying to read from ?


#5

I’m using an arduino with a TTL to RS485 Module


#6

@nickmertin and I were experimenting with generic serial communication and we were able to get it working in VCS, however, were unable to get it working in PROS (we didn’t try RMS). Unfortunately we don’t have continual access to a V5 (we were borrowing one) so we weren’t able to actually figure out why it wouldn’t work in PROS. We were using these RS-485 transceivers with a STM32 Cortex M3 based board.


#7

It’s impossible to read and write data using multiple fopens at the same time. I’ve tested it.
You must at least ensure that they are read or written asynchronously.


#8

From the testing that @Andrew_Strauss and I did, it appears that fopen with mode "rb" puts the internal RS-485 transceiver in reading mode, while the "wb" mode puts it in writing mode. As RS-485 is only half-duplex, there’s no way to (usefully) enable both reading and writing at the same time.

You shouldn’t have to use any special kernel API functions (in either VCS or PROS) to read/write, it should just be via device files (/dev/port## on VCS, /dev/## on PROS). Unfortunately, there appears to some internal issue in the PROS smart device driver that prevents it from working as-is; we’ve been talking to the devs but as of yet haven’t been able to find a solution. I’m going to look into it more when I have time; we’re planning on getting it working in PROS for VEX U.

In the meantime, here is the VCS code that I got working, based on this code from jpearman:

#include <stdio.h>
#include "robot-config.h"
          
using namespace vex;

int main() {
    // IO using stdio
    //**********************
    FILE *fp1, *fp2;
    fp1 = fopen( "/dev/port20", "wb" );
    fp2 = fopen( "/dev/port18", "rb" );
    while(1) {
      if( fp1 != NULL ) {
        fprintf(fp1, "Hello\r\n");
        fflush(fp1);
      }
      if( fp2 != NULL ) {
        char buf[128];
        int nRead = fread( buf, 1, 128, fp2 );
        if( nRead > 0 ) {
          for(int i=0;i<nRead;i++) {
            printf("%02X ", buf[i]);
          }
          printf("\n");
        }
      }
    this_thread::sleep_for(10);
    }
}

#9

Ok, thanks.
Do you know if there’s a way to use the micro USB port on the brain to do serial with an Arduino? Or any way to hikack the pros terminal connection?


#10

You could theoretically use an arduino to grab the serial output from the USB. I say theoretically because afaik it’s only been done so far with small linux computers, like a raspberry pi, but that’s not to say it wouldn’t work.

By default, we have “stream multiplexing” enabled on the serial line, which effectively boils down to the idea that stdout and stderr streams are prefixed with sout and serr. If you want to, this can be disabled using fdctl and the SERCTL_DEACTIVATE macro.

The other thing we do is run the serial streams (including the serial input stream) through COBS, which you’ll almost certainly want to disable (unless you implement a COBS decoder on your client device of course). This can be done with fdctl and the SERCTL_DISABLE_COBS macro.

Once you’ve done that, you should be good to read raw serial data. One caveat is that there’s currently not a way to disable the PROS banner that we display on connection, so you’ll have to deal with that on the receiving end.


#11

Thanks @hotel , I’ll give it a try.

Do you have any idea why reading from a smart port isn’t working?
It’d be a lot easier for us to just go through that since we’ve already got the hardware set up.


#12

Not off the top of my head. As @nickmertin mentioned, we’re still looking into it.

If you are willing to help diagnose, the relevant code is here


#13

Thanks, I took a look but am not sure I can be of much use.
Is there anyway to call vexDeviceGenericSerialReceive directly from user code?

@jpearman Would it be possible to trick the brain into thinking the Arduino is a motor. I.e. the Arduino would wait for a message from the brain, and then send a packet with my data disguised as a reply to motor.get_position()? Or would the V5 brain know it’s not a motor and ignore this?


#14

We strip non-public symbols, so no. edit 2: yes, if you forward declare it

Not unless you can have the Arduino send the same device initialization info to the brain (devices initiate communication)
Edit: see below post for more


#15

No, smart devices communicate at a much higher bit rate and we do now allow that when used as a generic port. In addition, smart devices act as the master, the motor initiates all communication.


#16

If you don’t mind me asking, what are the baud rates allowed when used as a generic port?


#17

So when I call motor.get_position() what is actually happening on the hardware level?
How does the value for position get from the motor to the brain?
All I’m trying to do is send a 16bit number from the Arduino to the brain, so could the Arduino just wrap it’s number in a message to the brain formatted as if it were from a motor, and then read this as if it were from a motor.
So all the PROS user code would be is

Motor m(port);
double valFromArduino = m.get_position();


#18

(not sure if you caught my edit, but you can actually use the SDK function as long as you prototype it)


#19

Great, thanks…
Do you know what the type of the first field should be? I saw device->device_info being passed, but I’m not sure of the type or what the value should be… Is it just the port number?


#20

yea, don’t use the vexDeviceGenericSerialReceive version that takes opaque pointer to an internal structure, use the vexGenericSerialReceive that just needs 0 based index to a port.