So can I use it to proccess sensor data and send the value of the motors to the cortex?
Yes ChristaM this is legal in Vex U. The rule is the motors must be connected to the cortex. The sensor do not need to be directly connected to the cortex.
Could you use this setup to increase the processing power for a VEX robot legally in a HS competition? My first guess is that it provides function and thus is illegal; but I would love to here what others think on this subject. Would you be able to use if it was just recording values?
It is illegal. As would be any form of powering an extra processor.
Co-processors are legal in VEX U (college Vex), and aren’t restricted all that much, the only real limitation is that they cannot have their own integrated battery, and must run off of one of the allowed power sources in VEX U, which includes a third Vex battery for sensors / co-processors.
In HS this is all pretty much not allowed.
Since I’m here writing, I’ll mention that I’m working on writing the code to run this on Linux and PROS atm. The program will self-configure the serial port on Linux, which involves some kind of old modem code which I’m iffy on.
Also I ordered my Logic 8 yesterday ![]()
Forgive me if this is totally wrong (I’m not a programmer but plan to learn after exams and I tried to follow what’s been said so far), but, is it actually necessary to link the cortex and third party processor?
The way I see things, the Cortex is perfectly fine for use in driver control, and the use of the extra processor is needed in auton.
Would it be possible to have the external processor send the desired motor values through the analogue ports of the cortex, and have the cortex simply set the motors to the values coming through these ports? and the digital ports used to start/stop the external processor similarly to pneumatics?
Vex doesn’t forbid the sensors being plugged into something other than the cortex (or so has been said in this thread), so it could be run as if it had the motors plugged in, but simply send the motor values it want’s to output via the cortex’s analogue ports, fulfilling the requirements that the cortex ‘controls’ the motors, and the vexnet
I understand this isn’t setting up the same level of communication being described, but is this a possible alternative? (again, sorry if I’m completely wrong)
You won’t regret it.
Necessary? That depends, what are you trying to do?
If your answer is image processing, the answer is yes. The Cortex is woefully inadequate for such a task.
If you want to make LED’s blink, the answer is no.
It depends.
Yes but if you have 60 seconds of autonomous, that’s like saying you only need a powerful engine and fresh tires for the last 150 laps of the Daytona 500.
Good question. Yes you could absolutely do that.
But, why? Think of all those valuable I/O lines on both the co-processor and the Cortex that you’ve tied up and cannot use now. Think of all the extra wires, etc.
It’s wasteful and unnecessary. Albeit, a simpler system. In CS it is VERY VERY normal to be faced with the classic efficiency vs complexity problem. If you want something to be efficient, time and time again this almost always means that the design is going to get more complex.
So a better answer is this, your solution isn’t right or wrong, it’s just an inefficient but simple solution, while mine is decently complicated but very efficient.
Yes this is true, I fought for this here and here specifically.
Completely correct, the motors and VEXnet are the components that cannot be removed from the Cortex. They must all interface with a stock Cortex, although I’ve established that the plastic casing is fair game.
It’s entirely doable. Don’t feel bad, these are really good question. ![]()
Now I wouldn’t do it. Because I like the crazy complicated, crazy elegant designs. They’re challenging to me and rewarding too.
But I definitely understand why a KISS approach works sometimes. All things considered tho, basic messaging without all the checks over UART isn’t that hard and I do intend to release my code when it’s finished.
-Cody
I’ve not been clear. I meant was two way communication necessary, not was communicating/instructing necessary.
Again, I’ve not been clear. I was meaning, driver control can/will be coded into the cortex and the external computer is only for auton, hence two way communication may not be needed
Simplicity is the exact and only reason. (Although it’d be nice to see your method become simple if/when you succeed and release your code, so best of luck)
Thanks ![]()
I certainly understand the appeal of complex yet rewarding projects. The main difference would be I’ve grown up with a mechanical engineer as a father, so I’ve got more of a knack for mechanical endeavours, like building a toss up descorer for my first year of vex ![]()
Oh that’s good, really good.
Is TWO WAY communication necessary?
Technically yes and no, and sort of. Again it depends on what you’re doing. I want to both command the Cortex and to get data back.
Technically speaking this is doable using a master/slave type dealio like what James has made. But for complicated reasons I’d like to pull the data, and push the commands. For that I need something a little different.
If you just want to control the motors, one way communication is OK, however an acknowledgement would be nice to have, so in this case, I’d use something very much like James’s P3.
Updates…
So I’ve actually been working pretty hard between class work to get this project along. That being said, the project is in a rather messy state right now. I’m not really done, in fact I’m kind of just getting off the ground.
Nevertheless here are two videos of me blabbing for way too long about the project and some of the ideas behind it.
The videos suck, I tried to explain what’s going on alright but things are just everywhere atm.
That being said, the protocol / project is actually getting somewhere, which is really neat. I’ve learned a lot doing this, and as a challenge it’s been lots of fun.
SO here and here are the videos. The latter is newest and therefore way more up to date.
A basic summary of what’s going on…
- I got COBS working
- Spent a whole lot of time getting the POSIX modem crap configured properly
- Eventually settled on a packet format
- Wrote a bunch of the code needed for random stuff
- Bought two of these to make debugging possiable since I could run the code right from Xcode
- Took a good hard look at HDLC
- Decided I didn’t like it, but I did want a sliding-window
- Spent a LOT of time trying to figure out the odds and ends of sliding-window and go-back-to-N ARQ.
- Eventually convinced myself I understood it well enough to try to implement it
- Had a second wave of confusion and frustration (probably due to lack of sleep and thinking way too much)
- Woke up this morning (well it was actually at 9 PM, but all things are relative) and busted out the rest of the basic window code
- Managed to write a basic test which I’m happy with for now
TBD:
- Handle timeouts / resends
- Tune the window size
- Clean up everything
- Figure out how to deal with situations where somehow the clients get out of sync (like if one loses power)
- Write some kind of test that can simulate lost ACK’s and lost packets and power outs, etc. Basically a Chaos Monkey
- Make it work
- Make it do stuff
- Sell out
- Cash in
- Bro down
- etc.
I guess at this point I’m hoping that this can be finished. I’ve figured out what I want to do, and a way to accomplish said goal. What I’m worried about is all the edge cases. All those nasty ways things can go wrong, currently this protocol is crazy brittle. The smallest error would absolutely wreck it.
Fixing that problem is going to be the real challenge.
-Cody
Not sure I see the point of a sliding window in this application. If a message is missed then you probably don’t want to go back and resend that data, suppose it was a motor message, you have probably sent new motor values since the message was lost. Also remember that many messages will want a reply which is not a simple ACK, status messages or asking for sensor values. These are often needed before the code can make further decisions. I’m also not seeing that there is an issue with throughput, ACKs can normally be returned within a very short time of a message being decoded although it all depends on the way the code is written as to how quick that will be. My original P3 implementation would return ACK within 2mS as that was the message action task frequency. Generally there is no need to control motors or ask for status faster than every 10mS.
What is the goal for number of control messages/second?
How many will be control vs status requests?
I’m not saying that understanding and implementing sliding windows is a waste of time, just not sure it’s applicable to a real time controller.
Echo what jpearman says about sliding window. It’s unnecessary unless squeezing maximum possible throughput is a requirement.
Turnaround time for ACKs shouldn’t be an issue with the overall system response times you’re working with. Another way to minimise turnaround time is packing multiple messages in each frame however with real time data sometimes that’s undesirable.
For sending motor values, you’re right resending is a bad idea. But I’m more interested in data transmission atm. I want to know what’s going on inside the robot more than I care to control it remotely right this minute. For that I’d like to resend lost packets (who wants holes in their datasets?).
As for sliding window, it is pretty much overkill. That being said, I do have it working decently well. I’ve been able to nearly max out the UART port in terms of bandwidth with stupidly (100-200) large windows.
But I do see the usefulness in at least a small window. I mean, say you have two tasks doing different things which may or may not be in sequence, what if they both go to send data within the same 2ms window? First one wins, second one gets told the system is busy. So in this case you’re going to have to setup some kind of FIFO anyway, why not use a reasonably sized window as the FIFO?
That being said, this is a good point, some data should be resent (like sensor values, etc) while other data (like motor commands) should probably not be resent.
I’m not 100% sure how I would do that, but even in the case that a packet is lost (which seems very rare from my work thus far, at least over a wire), the retransmission time can easily be under 6ms. Given that motors internally update every 20ms, there’s plenty of opportunity to catch a lost packet between updates.
So, maybe just send everything the reliably and in-order way, using a small window to keep the memory footprint low even knowing that it’s a little overkill?
IDK, I’ve never said “Oh I’d like less bandwidth please.” and at this rate I basically already have the window working with a moderate memory overhead. One could argue that the extra byte needed for the packet numbering is a waste, but I could argue that by doing so I’m 20x’ing the number of packets I can send so who cares.
Besides I’m already looking at Xbee as a next step, and I’m sure once I start sending data over the air that packet loss will become an actual thing.
I just know that a reliable and fast protocol is going to be useful.
So after sleeping my Mac, I woke to discover that my local git repo blew up or something (Xcode refused to commit, for some strange cryptic reason).
After Googling stuff, I made the absolutely amazingly stupid horrible mistake of copying some terminal commands off the internet and running them because someone on StackOverflow made a comment.
Funny thing, doing this has screwed me before. Oh well.
“Hard” reset the repo, and it freaking rolled back to some ancient copy of the code. Thankfully this is a Mac, and I had Time Machine configured correctly so I only lost like an hour of work, v/s days.
MY BAD. So, the bottom line is this code needs to be moved off my computer, so here’s the repo. This is NOT a release, it’s simply a link to my current work in progress.
Those of you who know what you’re doing, and you know who you are, feel free to check out the code. Those who don’t, please don’t bother just yet.
Any good feedback would be appreciated as I’m definitely open to criticism / suggestions.
-Cody
Updates…
- Added unreliable packets (no ACK’s, no retry attempts, etc)
- Rewrote the circular buffer code because of issues
- Added timeout and resend functionality, allowing data to be resent after a packet loss or connection interruption
- Rewrote the test to include two clients sending and receiving simultaneously
- Added a license to the project (Apache 2.0)
- Fixed a thread related issue that was causing the clients to de-sync
All the changes are on GitHub (still extremely experemental).
Details and a short (4 min) demo here.
I’m pretty happy with the state of this right now, I’d like to implement a solution to the syncing issue that will occur if one of the devices goes completely offline (like loses power). Right now the device would restart, assume that it’s on packet #1 and there’s a 7/8 chance that it’ll be out of sync.
A quick fix may be to simply make the system accept ANY packet when it starts up and make that the first starting value. Problem there is, this could happen in the middle of a resend and packets could be lost.
I feel like a better way will be to send a request for place special packet, basically asking the other end for the correct starting place. Or the other end could start pushing place notification packets when the line goes dead.
Not really sure how I want to handle that.
Once I’ve figured this out, and once I remove the cpp bits (mostly replacing cout’s with printf’s), the protocol itself is basically done, but has to be battle tested. In order to do that, other platforms will need to get support.
I’m going to port this to ROBOTC first, probably followed by PROS / ConVEX.
Once ported, I’ll begin the process of writing a series of RPC’s and data oriented commands. This is where things get fun.
-Cody
Hi Cody,
It’s a little hard to follow what constitutes a packet, and how you ‘validate’ the packet in the code. however I’m used to seeing packets defined with a known header byte or word a ‘sync pattern’ followed maybe by an ID / Length byte or counter. Then you could check the first few bytes received and determine how to process the rest of the packet. I don’t know if you’re going for all fixed length packets or not. Xbee uses this type of pattern in their API mode. You seem to be assuming that every read of the port retrieves a complete packet. As you increase transmission speed to max throughput you should see this assumption break down. you will likely see more packets lose sync or so I would expect.
I coded an example home made controller for my PIC using a Mega2560 to read the joystick input and format frames for the PIC which I sent over the Xbee Link configured point to point. I also got data from the PIC to display on the controller LCD. I wanted to take this farther but kinda got distracted by other things.
https://vexforum.com/t/alternate-controller-for-pic/22897/1
Here’s a link if you’d like to see what I did. Also Jame’s provided a more generic version of similar capability here
[https://vexforum.com/showpost.php?p=360741&postcount=179
You’ve probably already seen these but thought I’d bring it up.
I actually picked up a BBB to check out over the year end break, I hope I get some time to play with it. I’m not at all familiar with Linux / Unix programming so I’m not sure how far I’ll get on low level stuff.
Cheers - Kb](https://vexforum.com/showpost.php?p=360741&postcount=179)
I have one on the way as well
Also been spending some quality time with a Microzed (Zynq SOC eval board) recently, have FreeRTOS running nicely along with low level network drivers and a bunch of my generic code for uarts etc.
Hi Kb!
That’s a fairly normal way to do it.
I’ve done something a little different. What I’ve done may be terrible or great, not sure yet. By encoding the body of the packet in COBS, I’ve freed up byte 0x00 for use as a delimiter.
I could have added a 0x00 before and after a packet, but I decided to only add this break byte after each packet.
So basically any byte following a 0x00 is stored into a buffer, bytes are added onto the buffer until a 0x00 is encountered and then the data is tested to see if it conforms to a packet or ACK.
In the case that the data doesn’t validate, it’s thrown out. It’s also thrown out if the first byte (the packet number) isn’t the expected value, UNLESS the first byte if 0xFF which makes the packet as an “unreliable” of numberless packet, in which case it is read and processed.
In Packet.h I’ve shown the makeup of a packet…
Packet Formast:
Reliable packet (will be resent):
---------------------------------------------------------------------------------
| Number | Stuffing | Type | Meta | Length | Data ... | Checksum | Frame (0x00) |
---------------------------------------------------------------------------------
Unreliable packet (will not be ACK'd or resent):
---------------------------------------------------------------------------------
| 0xFF | Stuffing | Type | Meta | Length | Data ... | Checksum | Frame (0x00) |
---------------------------------------------------------------------------------
C4 is currently written to transmit / receive variable length packets.
That’s not true. The update loop reads one byte at a time, until either a packet framing byte is encountered, or until the buffer fills or until there are no more bytes to read.
The buffer is protected from overflow by the loop’s condition, if the loop ever stops from hitting the buffer limit, the if statement just past it will trigger and clear the buffer.
If readVal (num of bytes read) is ever zero, the loop terminates.
And if the last byte read is ever a 0x00, the data is evaluated.
void updatePort(C4Port * port) {
// Attempt to read in however many bytes are left in our packet buffer
while(port->rxLength < PACKET_RAW_MAX_LENGTH) {
ssize_t readVal = read(port->fileDescriptor, port->rxBuffer + port->rxLength, 1);
if(readVal == -1) {
cerr << "read() returned error condition" << strerror(errno) << endl;
break;
} else if(!readVal) break;
++(port->rxLength);
// Did we just receive a packet framing byte?
if(port->rxBuffer[port->rxLength - 1] == FRAME) evaluateRxData(port);
}
// Did we fill the RX buffer?
if(port->rxLength >= PACKET_RAW_MAX_LENGTH) {
// We've overflowed the buffer, clear it - data loss will happen
port->rxLength = 0;
cerr << "ERR: RX Buffer overflow, clearing (data will be lost!)\r\n" << endl;
}
Here’s a link if you’d like to see what I did. Also Jame’s provided a more generic version of similar capability here
[https://vexforum.com/showpost.php?p=360741&postcount=179
You’ve probably already seen these but thought I’d bring it up.
I actually picked up a BBB to check out over the year end break, I hope I get some time to play with it. I’m not at all familiar with Linux / Unix programming so I’m not sure how far I’ll get on low level stuff.
Cheers - Kb](https://vexforum.com/showpost.php?p=360741&postcount=179)
Very cool! I completely and totally want to get into XBee eventually. I’d like to like build a quadcopter sometime, but I don’t really have the money to spare.
Also very cool. Neat board. I don’t know anything about FreeRTOS or how you setup those SOC thingies, so I don’t have much to comment on.
I’m currently visiting family, trying to take things easy. I brought all my stuff to work on C4 but honestly my mind is kind of gone atm after all the calculus 2 crazyness. I mostly just want to relax, be lazy, do nothing, etc.
-Cody
Well I’m not sure why I hadn’t opened packet.h but that does help me understand it better. I will need to look through this when I get a little time off starting this weekend.
Best wishes to you during your time off.
Cheers Kb
Find the money…steal it…whatever. (ok not really)
I built a tricopter and a quadcopter from “scratch” last year. Very fun. I am not a programming mastermind like you so I went with a KK2 board that is able to be flashed with already perfected flight code.
Do it! Lots of fun. You can build a pretty cool one for less than $200.
(not trying to hijack your thread, I just get excited when I read about quadcopters!)