Multithreaded programs

How many teams were able to make mulithreaded programs for the Crio in windriver?
There were no examples of making one, so how did you do it?

My WebDMA project uses multithreading to run the web server on a background thread on the cRIO.

Look at the Task object for easy to use multithreading with objects. It uses the native vxWorks thread API to allow you to create multiple tasks and set their priorities and such.

If you’re familiar with pthreads, vxWorks has a pthreads API that you can use, which is just a wrapper around the native API.

I used the multi-platform boost::thread library with WebDMA, which uses pthreads as the underlying native thread API. Some of my boost patches made it into 1.39, so you might not need to patch it anymore – I haven’t tried 1.39 yet.

WPILib includes nice helper classes that can help you set up multithreading pretty easily. Take a look at Task, Notifier, and Synchronized, in particular.

The WPILib PIDController implementation uses these classes to set up a thread that periodically calculates the next output value. Take a look at PIDController.cpp to see how to use them.

Thank you, I am making a software serial port on the sidecars io pins. I didn’t want to have the bit-banging done in the main software loop :ahh: , which would clutter up all the logic.

planing to use the sparkfun atomic 6dof imu on the robot next year to help with navigating the field for the touchscreen.
it communicates over serial, and we werent allowed to use the serial port this year, so i am basing my decisions on that

http://www.sparkfun.com/commerce/product_info.php?products_id=9184

yes, the cRio can process sensors, but the reduction of analog cord length makes up for the 2bit loss of resolution. the IMU also computes some positioning math internally, so the cRio only has to do one conversion and then can deal with game logic

If I may offer a suggestion:

I think you will find writing a bit-banged serial port driver to run on the cRIO to be incredibly difficult, if not impossible. Serial port timings are very tight - you’d need extensive use of interrupts to make it work, and even then it might not since the digital I/O pins on the sidecar are not directly tied to processor I/O.

Instead, my suggestion is that you modify the 6DOF source code to speak the I2C protocol and wire up the 6DOF to the I2C bus that is already available on the sidecar. This is a non-trivial task as well, but I’m much more confident that you’ll be able to make that work. I think the only thing you’d need from a hardware standpoint is some circuitry to limit the 5v I2C lines coming from the sidecar to the 3.3v that the 6DOF uses (SparkFun has some tutorials on that). At any rate, you’d need that for the serial port to work as well.

the rio wouldn’t have to send anything, only receive. so if i have a very fast loop in a separate thread, could i conceivably catch the data?

thats a great idea except the arduino uses analog pins 5 and 6 for I2C communication, and all 6 pins are used (3 for x y z) (3 for roll pitch yaw)

what about SPI? it was finished for labview but not for windriver

Receiving is actually much harder than sending when writing a bit-banged serial port. I can say this because I wrote my own software serial implementation for the ATmega168 (so I could have 2 UARTs on it).

If your code is just a while() loop running in a task, you need to consider that other tasks will be constantly interrupting you and taking the processor from you (for many milliseconds at a time). So you can’t count on a while() loop to catch the first edge. So, you might be able to use an edge-triggered interrupt, but you have to be ready to sample the I/O line at 1.5 times the bit clock after the edge interrupt. I haven’t looked into the pin change interrupts too closely. I don’t know if your code would actually be running in the CPU’s interrupt handler or if the RTOS catches the interrupt and just sends a signal to your task. If it’s the latter, then it’s very unlikely that you’ll get the interrupt fast enough. Even if it’s the former, you need to know exactly when that first edge occurred so you can know when to sample your first bit, and then you need to loop, waiting precisely 1 bit time, sampling the input pin and looping again until you have all 8 bits. It may be possible, but my point is that it will be incredibly difficult to get all the timing right on a multitasking RTOS. Keep in mind that at 115200 bps (which is what the 6DOF uses), each bit is only 8.7 microseconds long. Usually the scheduler on an RTOS like VxWorks runs at 1, 5, or 10ms, so if your task gets interrupted it’ll be way too long before you get control back.

thats a great idea except the arduino uses analog pins 5 and 6 for I2C communication, and all 6 pins are used (3 for x y z) (3 for roll pitch yaw)

what about SPI? it was finished for labview but not for windriver

SPI might be an option. I haven’t looked into how that works on the cRIO. Alternatively, I think you’d be better off trying to bit-bang I2C on the 6DOF with some of the unused pins. People have done it before; you can find code out on the Internet that might work for you (a quick Google search turned up this which might be promising).

Another option would be to add an additional AVR microcontroller - program that to act as an I2C-to-serial bridge and place it between the 6DOF and the sidecar. You can get pre-made AVR or Arduino boards for <$20 that would probably work well. Still not a trivial programming challenge, but much more straightforward than the bit-banged serial.

Like I said before, it might be possible to get bit-banged serial working on the cRIO, but I think it will be difficult and frustrating. I wouldn’t want to try it myself, but if you really want to then maybe it’s worth a shot. I’m just trying to point out that there might be some other options for you, some of which might offer an easier solution.

how did you get past the weird WPI protocol on the I2C bus?

and are pullup resistors needed, or are they in the sidecar?

I’m not sure what you’re referring to. Are you talking about the limitation that you can only read/write 4 bytes at a time? We just made sure the protocol we used over the I2C bus conformed to the cRIO’s I2C limitations (I don’t believe the limitations are anything related to WPI but rather the FPGA image inside the cRIO).

and are pullup resistors needed, or are they in the sidecar?

The I2C pullup resistors are present in the digital sidecar. In our application they did not seem to be strong enough, so I added additional resistors in parallel to increase the drive current, but you shouldn’t do that unless you determine that to be an issue in your case. The built-in ones will probably be enough if you keep the wires short and/or use shielded cable.

I’m not sure what you’re referring to. Are you talking about the limitation that you can only read/write 4 bytes at a time? We just made sure the protocol we used over the I2C bus conformed to the cRIO’s I2C limitations (I don’t believe the limitations are anything related to WPI but rather the FPGA image inside the cRIO).

ok, it was very hard for us to get our compass to work with it, so we decided not to try to use it.
how should i set up the IMU code? should i send a byte from cRio to arduino
then depending on the byte return a different value? or try to fit as much data into 4 bytes as i can?

The FIRST Developers love feedback. Please post about your experience (preferably in a new thread on this forum or on the usfirst.org forums) so they can try to improve it.

The FIRST Developers love feedback. Please post about your experience (preferably in a new thread on this forum or on the usfirst.org forums) so they can try to improve it.

it turned out to be an endian issue, but we ran out of time to fix our implementation, so we used a lego one instead.