purduesigbots / pros

Source code for PROS kernel: open source C/C++ development for the VEX V5 microcontroller
https://pros.cs.purdue.edu
Other
259 stars 76 forks source link

🐛[BUG] - Pros::Link Issues #620

Open ifndef-define opened 10 months ago

ifndef-define commented 10 months ago

Describe the bug When experimenting with the vexLink system in pros, I came across two issues: 1) When starting a program with a pros::Link device initialized and with two radios connected to the brain, the radio designated as the link radio doesn't initialize (the radio doesn't flash red at 2hz). And when the ov parameter is set to true, the brain black screens and nothing works at all. However, when I start with one radio connected to the brain (ov set to true), it initializes correctly and links with the other radio (with the red-green flashing), and then I connect the other radio back which connects to the controller without any problem. 2) I have not been able to send any data via pros::Link. I have tried numerous ways to send data using the transmit and transmit_raw functions and the respective receive functions to no avail. I even used the exact layout from the pros documentation (except the constructor which is incorrect on the docs) to get data to be sent but it doesn't work.

To Reproduce For the first issue: 1) Connect two radios to the brain 2) Start a program with a pros::Link device constructor 3) Radio does not initialize

The way I got it to work: 1) Connect the link radio only 2) Start a program with a pros::Link device constructor and the ov parameter set to true 3) The radio initializes and connects to another brain with the same initialization as a receiver 4) Connect the second radio back to the brain

Expected behavior Two radios connected to the robot, one designated as a pros::Link radio should initialize at program start, connect and send data to the other brain.

Desktop (please complete the following information):

Addon Feature I do not know if this is possible, but is there a way to switch the initializations of the pros::Link devices? The link at the moment only allows sending data in one direction, but in reality it would be better to be able to send in both by switching the job of transmitter and receiver.

ifndef-define commented 10 months ago

Also would like to add the error values and the code snipet; I used the exact values from the docs. The method is constantly returning EINVAL (Invalid Argument).

Code:

char* result;
char* expected = "Hello!";

data = test_trans.receive((void*)result, sizeof(*expected) * sizeof(expected));
receiveErrorVal = errno;

lcd::print(6, "Data: %d", data);
lcd::print(7, "Error: %d", receiveErrorVal);

Output:

Data; INT32_MAX
Error; 22
phinc23 commented 10 months ago

The link docs need some changes in the meantime here's an example of receiving data currently

// The expected message. Only the size matters.
char expected[] = "Hello!";

// size_t is an unsigned int for things like array size. 
size_t msgSize = sizeof(expected); 

// Where the received message will be stored
char data[msgSize];  // Array with the same size as the expected message. "Hello!" has 7 characters so 7 bytes

// The first parameter is where to store received data (address) second param is the size of the received data 
test_trans.receive(&data, msgSize);

lcd::print(6, "Data: %d", data);

This should work don't have access to testing right now so let me know if there are any problems

size_t: https://pvs-studio.com/en/blog/terms/0044/

Fixed typo.

phinc23 commented 10 months ago

I do not know if this is possible, but is there a way to switch the initializations of the pros::Link devices? The link at the moment only allows sending data in one direction, but in reality it would be better to be able to send in both by switching the job of transmitter and receiver.

This should already be possible. Both receivers and transmitters can receive and transmit data. For example you can have a program where a transmitter transmits a value to a receiver where the value is modified and sent back to the transmitter to be displayed.

pros::Link transmitter(1, "RobotID", pros::E_LINK_TRANSMITTER, true);

transmitter.transmit(&data, size); 
transmitter.receive(&modData, size); 

// Display modified data

And

pros::Link receiver(1, "RobotID", pros::E_LINK_RECIEVER, true);

receiver.receive(&data, size);

// Mod data

receiver.transmit(&modData, size); 
phinc23 commented 10 months ago

The way I got it to work:

  1. Connect the link radio only
  2. Start a program with a pros::Link device constructor and the ov parameter set to true
  3. The radio initializes and connects to another brain with the same initialization as a receiver
  4. Connect the second radio back to the brain

Did some testing and we're looking into this hoping to roll out a fix soon along with a docs update. This method is a temporary solution if you're having problems with dual radios.

ifndef-define commented 10 months ago

Thank you so much for the response! Good to hear that most of the problems were just outdated docs and nothing major code-wise. Ill keep you posted on anything else that I find.

ifndef-define commented 9 months ago

The way I got it to work:

  1. Connect the link radio only
  2. Start a program with a pros::Link device constructor and the ov parameter set to true
  3. The radio initializes and connects to another brain with the same initialization as a receiver
  4. Connect the second radio back to the brain

Did some testing and we're looking into this hoping to roll out a fix soon along with a docs update. This method is a temporary solution if you're having problems with dual radios.

Good news, I found the problem with dual radios. When dealing with radios, the brain prioritizes the radio on a higher # port to be the controller radio and disables the other radios that are connected. When I initially posted this issue, I had it so the link radio was on a port number that was lower than the designated controller radio (ex. link lets say is port 5, and the radio is port 21). Since the link radio is disabled (by the flashing red light at the cable connection) the brain doesn't realize the radio existed at the initialization of the link, thus the problem. The solution is to have the link radio on a higher port number than the controller radio (ex. link on 21 and radio on 5). This works since parameter ov when set to true will override the current radio (configured as a controller radio) long enough for the brain to initialize the second radio (the designated link radio) as another controller radio before the first one turns back as a link radio. I believe this is a firmware-based thing, so a docs note should be good for help with explaining dual radio connections.

Edit: I would also like to add the fact that when I call the link constructor inside a constructor for a class that I created, the brain black screens and nothing initializes. All ports flash red and there is no response from the program.

LinkHelper::LinkHelper() 
{ 
    // This doesn't work. Not even the lcd initializes
    pros::Link linkTransmit(15, "link_key", E_LINK_TRANSMITTER, true);
};