Use V5 Smart Port as Generic Serial Device [PROS]

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?

Ports configured as generic serial will default to 115200 baud.

What type of device are you trying to read from ?

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

@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.

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.

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);
    }
}
1 Like

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?

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.

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.

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

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?

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

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.

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

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();

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

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?

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.

2 Likes

Max theoretical baud tate is 921600, however, as baud rates are not derived from a standard oscillator (typically something like 18.432MHz would be used for standard rates) there will be an error between actual baud rate and the requested baud rate, in the case of 921600, perhaps 3%. So your millage will vary depending on how accurate the device you are communicating with is. At lower baud rates the error drops to become largely insignificant.

1 Like

Ok, thanks for the information.