paper: Driver Station Encoder Support using the TI LaunchPad

Thread created automatically to discuss a document in CD-Media.

Driver Station Encoder Support using the TI LaunchPad
by: ayeckley

The 2015 Driver Station discontinued support for quadrature encoder inputs via the Cypress pSOC. This paper provides a detailed description for the equivalent functionality using the TI LaunchPad from the 2015 KOP.

This document briefly describes the motivation for and implementation of a quadrature encoder-based operator input for the 2015 Driver Station. This solution uses the TI LaunchPad included in the 2015 KOP. It presents a detailed set of software modifications to the LaunchPad FRC code to enable use of a FANUC CNC encoder wheel. Also included is example LabVIEW code for extracting the encoder data using the roboRIO.

TI LaunchPad Encoder Support.pdf (286 KB)

I think I was able to follow most of this but did have some follow-up questions. Though I’m not as experience in looking at the launchpad code or using eclipse.

Looking at the example code:

P1IE basically enables the interupt
P1IES enables interupt edge select

It appears that we are limited to just P1 and P2,e.g. we could add a second encoder with P2IE and P2IES?

Additionally, to map that to a button 2.2 and 2.7 we could reference bits 2 & 7 respectively?

To output it then could I use the other 16 BITS for the buttons out?

Finally, is there the ability to pass additional encoder counts so long as we did not exceed the current draw of the launchpad?

For example could I run an interrupt on P3 using 3.2 and 3.6?

Would I just implement that by passing an integer vs a float for an axis value?

Thanks for any help, my sum total of knowledge is thus far based upon your team’s paper and Google. (http://courses.cs.washington.edu/courses/cse466/11au/calendar/04-Interrupts-posted.pdf)

Not exactly. It just specifies whether the interrupt occurs on the rising edge or the falling edge of the signal.

It appears that we are limited to just P1 and P2,e.g. we could add a second encoder with P2IE and P2IES?

Yes, or you could just use some of the other inputs from Port 1; there’s no reason that a second encoder would have to go on Port 2 if there are still bits available on Port 1.

Additionally, to map that to a button 2.2 and 2.7 we could reference bits 2 & 7 respectively?

Right. Or 1.2 and 1.7, or 1.2 and 1.3, and so forth. You have complete freedom to use whatever two inputs you like. The only reason we used the inputs that we did was because they were a) available and b) in close proximity to each other on the connector.

To output it then could I use the other 16 BITS for the buttons out?

Assuming that they haven’t been assigned for other purposes, yes. There is nothing saying that you need to use 16 bits either. If 8 bits is enough for your application then I’d try to conserve that resource. Heck, use 7 or 9 if it suits you. There’s nothing saying it has to be on 8-bit boundaries (as long as you handle it accordingly in software).

Finally, is there the ability to pass additional encoder counts so long as we did not exceed the current draw of the launchpad? For example could I run an interrupt on P3 using 3.2 and 3.6?

Yes and no. The current draw of the photo emitters inside the encoders is the driving issue; the total draw of the encoders needs to be less than the maximum current that the voltage regulators on the Launchpad PCB can provide (unless you add additional circuitry). The currents associated with the phase A and B signals between the encoders and the Launchpad are pretty small; the exact value depends upon the type of encoders and the configuration of the Launchpad inputs but they are typically much smaller than the emitter current.

The “no” part of the answer is that (IIRC) this particular MSP430 does not offer interrupts on Port 3. Other than power limitations, there’s no fundamental reason why you couldn’t connect four encoders to Port 1 and another four encoders to Port 2.

Would I just implement that by passing an integer vs a float for an axis value?

I guess it depends. If you’ve run out of “bits” in the HID datastream to use for integers then I suppose that would be your only remaining alternative. Personally I’d try hard to free up those bits from other purposes (e.g. unused buttons) rather than using the axis datatypes. That’s mostly because I am very reluctant to use floating datatypes when using microcontrollers (probably irrationally now, but once upon a time that was a Big Deal).

Very cool! Good work folks! Thank you for sharing this!

So, one more question. (it’s essentially my rookie year so I get unlimited questions right?) How would I run multiple interrupts or Port 1 would I just change different BITs (vs BIT 4 and 5 as shown in your example)?

There are a few different options, and they revolve around whatever software implementation you prefer. Not knowing much about your application, I’d recommend modifying the “new” Port 1 Interrupt Service Routine (ISR) that is shown in the paper rather than adding a new one for Port 2.

Let’s assume that the second encoder will use hardware P1.2 (meaning Port 1, bit 2) for Phase A and P1.3 for Phase B and that the first encoder still uses P1.4 for Phase A and P1.5 for Phase B. The Interrupt Enable register acts in a “logical OR” fashion; if we want the Port 1 Interrupt to occur on the rising edge of P1.2 (encoder 2) OR P1.4 (encoder 1) then we would write P1IE |= (BIT2 + BIT4). We should also make sure that we have already written P1IES &=~(BIT2 + BIT4) to ensure that both are in “rising edge” mode. I think that syntax is valid, but even if it’s not you get the idea.

The ISR itself gets a little more complicated since we now have to figure out why it got called: was it P1.2 or was it P1.4? The most straightforward (but not the only) way to do that is to check the status of the Port 1 Interrupt Flag Register (P1IFG) so see which bit is set; if Bit 4 is set then we know it was the first encoder that got us there; else it had to have been the second encoder. Once that’s determined, then the only remaining task would be to look at the corresponding Phase B input for that encoder and increment/decrement it’s associated counter (you’ll need two now, after all) accordingly. You’ll also need to move the P1IV=0 statement to the end of the ISR otherwise you’ll never be able to figure out which flag was originally set.

Caution: There is a bit of a “gotcha” when working with the Interrupt Flags. As soon as you read the Interrupt Flag register in any way, the highest priority pending interrupt flag bit will automatically be cleared. In this situation, P1.2 is a higher priority than P1.4; for that reason, it’s most intuitive to check P1.2 first. Actually, you may find it easiest to preserve a copy the P1IFG register and work from that instead. That way you don’t care if the P1IFG register is changing.

A lot of this info is buried in the MSP430F5529 User’s Guide, which is a mind-boggling 1,145 pages long. The relevant stuff for this discussion begins on p405. That being said, if you really want to learn about the MSP430 family that is the document to go to. It’s a great little microcontroller but doesn’t seem to get the love that the Atmel products do. If you really get into a bind with this we can help, but it probably won’t be until after Week 5 since we’re currently up to our proverbial armpits in robot design changes. Good luck!

Thanks again for the reply. We are in a frenzy as well as our regional is next week.

That being said from a Labview post programming of the Launchpad, do you know of anyway I can read what the Launchpad is outputting to the USB port of the driver station (pre-processing).

Would I just use a USB sniffer? Additionally, IIRC if I put the reading routine in a custom dashboard I should be able to run it and check it’s operation without having to connect the robot (real or otherwise simulated) right?

I spent a good amount of time on it last night and may post some snippets later on if I don’t make more progress after looking at the user guide.

Cheers!

I’m not sure I understand the question. Are you asking if there’s a way to access the raw USB datastream from the LaunchPad, without going thru the roboRio first? I’m afraid I don’t know the answer to that. My recollection is that in past years this was not possible, although we never attempted exactly what you are describing (since the Enhanced I/O gave us everything we needed). With the new control system architecture that may have changed. If it could be done I’m confident it would require writing a Custom Dashboard (as I think you are suggesting).

That is what I was thinking - and since I have a custom dashboard was attempting to just put the custom Labview code with indicators on the “custom” tab of the dashboard to output the buttons and the encoder count.

I figured since I could see the buttons lighting up at the bottom of the driver station and in my custom dashboard I should be able to read that input without actually running “main.vi” to either a live robot or a simulated robot (to help out my old and wheezing processor).

I’m not seeing the button outputs though and when I tried to tie into the data stream that is on the standard dashboard project I was not getting anything from the Launchpad (My process is 1 encoder then modify to get a 2nd and if I have any hair and patience left maybe a 3rd).

That being said I am looking to see if there’s a way I can “see” what’s happening along the process to troubleshoot. (Similar to my cheap way of putting “Alert(‘here’);” when doing poor man’s javascript troubleshooting to see where the process is breaking down.

I see three critical places I would like to check thus far.

1 - Can I tell what software is actually loaded on the Launchpad? (Validate the software install) Currently when I use the little debug button I am getting HW stops where I have a steady red LED and I have to restart the Launchpad via unplugging/plugging it in. When setting the OPTION2 and OPTION3 flag it does show with the appropriate # of buttons afterwards via a Labview Custom DB.

2 - Is the Launchpad actually calculating a value for “encoder_count” and what is it? (Can I see this by using a tool in CCS?)

3 - What is the Launchpad sending via “gamepadReportTX.buttons”?
(Could I see this on my laptop with another tool? I would guess that I could use the LabView Custom Dashboard for this)

I know that’s a bit lengthy but hopefully clears things up.

Also if I wanted to use say P1.3 and P1.2 would I need to delete them from the “Indicators” section of “OPTION1” in hal.c and replace two of the dummy inputs after P1.4 in the buttons section? e.g.

#define NUM_BUTTONS 32
#define NUM_INDICATORS 9

{GPIO_PORT_P1, GPIO_PIN4},
{GPIO_PORT_P1, GPIO_PIN3},
{GPIO_PORT_P1, GPIO_PIN2},
… dummy inputs …

Thanks again for explaining this. If it would be easier I can provide a phone #.

Kurt

I do not know if the HID data is transmitted from the driver station to the dashboard but I do not think it is. What are you planning on using the encoders for?

Another way you can consider for transmitting the data is to use serial on the dashboard and keep the HID to the driver station. The LaunchPad has a USB hub, so the debugger chip can also act as a USB <–> Serial bridge, and you can look at both the HID and the serial stream at the same time. You will just need to write software on the dashboard to detect and decode the serial stream.

The plan is to use it for arm control. The robot has the equivalent of a human arm from the shoulder to the wrist with the same joints. The plan is to have a scale version at the driver station to use to control it’s movement so it’s less clumsy than say driving a backhoe. (sp?)

I’ll have to take a look at the reading in the serial stream (I assume it’s more complicated than the standard create a constant for “USB0” …)

As I was meandering through the code this afternoon I had this random thought. It looks the axis values are defined in “USB_gamepad.h” source such that they are contained in the data structure “USB_GamepadReportTx”.

https://github.com/TI-FIRST/MSP430-Gamepad/blob/master/USB_app/USB_gamepad.h

If I look at that it appears that *.ax, *.ay, etc are all 16bit integers. Could I modify the code from https://github.com/TI-FIRST/MSP430-Gamepad/blob/master/hal.c (line 517)

from: “gamepadReportTx.ax = Convert8Bit(ADC12_A_getResults(ADC12_A_BASE, ADC12_A_MEMORY_12));”
to “gamepadReportTx.ax = encoder_count;” as that would allow me in essence to have up to 8 x 16BIT signed integers in my HID data stream?

(gamepadReportTx is defined on line 151 to type USB_GamepadReportTX from the first linked file.)

I would then just need to see how LV views/processes that data converting it into a float with the range -1.0 to 1.0 but my guess would be by dividing it by 2^15 …

Am I totally off base here or is my lack of sleep starting to pay off?

I believe that would work.

Are you are using an incremental encoder to develop this? How are you planning on getting an absolute value for the arms?

Big Picture Thought first: If you are intending to control a jointed arm, it might make more sense to use potentiometers and the analog inputs on the Launchpad instead of quadrature encoders. You wouldn’t have to modify the default FRC Launchpad code to do that. You could just go directly to the Ax, Ay, Az etc. inputs.

Right, the encoders will still be “live” even if the roboRio code is not running, and you should see flashing virtual LEDs on the DS corresponding to the buttons that have been “stolen” for the encoder (unless you remove them from the “raw” button datastream, which we didn’t). We’ve found that seeing the button states is very useful for diagnostic purposes.

I’m not seeing the button outputs though and when I tried to tie into the data stream that is on the standard dashboard project I was not getting anything from the Launchpad.

That sounds consistent with previous years then; you’d may have to transmit that data back to a Custom Dashboard from the roboRIO using the Smart Dashboard/Network Table feature.

1 - Can I tell what software is actually loaded on the Launchpad? (Validate the software install) Currently when I use the little debug button I am getting HW stops where I have a steady red LED and I have to restart the Launchpad via unplugging/plugging it in.

Perhaps a breakpoint is set? Unlike the roboRIO, code on the Launchpad doesn’t/can’t run in RAM - just Flash memory. Whenever you hit Debug, it’s overwriting the old Flash contents with the new. About the only way to know what’s currently loaded into Flash would be via the checksum.

2 - Is the Launchpad actually calculating a value for “encoder_count” and what is it? (Can I see this by using a tool in CCS?)

In theory you should be able to see the value using the Variables tab in Debug mode, but for some reason that didn’t work for us (even thought it’s declared as a STATIC). What you might try instead is setting breakpoints at places of interest within the ISR to see what it “thinks” it’s doing.

Could I see this on my laptop with another tool? I would guess that I could use the LabView Custom Dashboard for this

Dunno, sorry.

Also if I wanted to use say P1.3 and P1.2 would I need to delete them from the “Indicators” section of “OPTION1” in hal.c and replace two of the dummy inputs after P1.4 in the buttons section?

I don’t have the info re: the original OPTION1 configuration handy at the moment, but in general yes - if OPTION1 configures those as outputs (indicators) they you’d need to change them to inputs (buttons) instead. Maybe that’s what’s going wrong.

I’ve got your email address; I’ll try to drop you a line later tonight. It might be best if you .zip up your code for me to take a look at. I’ll bring a Launchpad and two encoders home to work with.

I also was pushing for the potentiometer solution but it met with much resistance based upon the idea that it would be less precise.

In any case I have posted the code in .zip file here. I commented out some ideas I had and tried to run it as pure to your example.

https://onedrive.live.com/redir?resid=94CA3E1384343D7D!1159&authkey=!AM07Cq1eGOhWI68&ithint=file%2czip

Here’s some screen shots below of the HW Breakpoints

https://onedrive.live.com/redir?resid=94CA3E1384343D7D!1161&authkey=!AA4CMGMs51QfiRg&v=3&ithint=photo%2CPNG

https://onedrive.live.com/redir?resid=94CA3E1384343D7D!1162&authkey=!AFazyP60oTKPuko&v=3&ithint=photo%2CPNG

[email protected]

I was planning on resetting to a known home position to re-zero required. When doing so I would re-zero the encoders on the robot and essentially us the current encoder count from the launchpad as the new 0 ref point.

I also was pushing for the potentiometer solution but it met with much resistance

:wink: