SPI Port on Robot Controller

On the 2006 controller, the PIC micro had the SPI port #2 connected to the Relay outs 5, 6 and 7. With this upcoming season almost upon us, I have thinking about ways to use an SPI port to talk to custom electronics. Not being a programmer, I wonder if any one has written code for such a purpose, ie using the SPI port with the relay outputs of the RC.

I’ve thought about this a bit and I think I decided it won’t work. IIRC, the relay ports go through a buffer so that they get disabled when the RC is disabled, as they are hooked up to the user microprocessor. I doubt it is bidirectional, so I don’t know if this would work.

You should be able to impliment SPI or I2C through bit-bang techniques in software and using the interrupt ports.

imho the port pins are configured to function as GPIO pins in the first place. As relay controls, the pins may be connected to transistors or FETs. Hence they loose the ability to “read” data. The frequeny response would be slower with external components. Not very familiar with the SPI protocol, it may not be possible to implement it. Can give it a try though… but I think its easier using the TTL serial port (I know theres one on the mini RC, not sure about the full size one) and perhaps have a serial-spi bridge using a low-end controller :slight_smile:

Yes, the full sized has a TTL port. Its mainly used by teams for the CMUCam.

I see. so in order to have SPI and TTL serial going to the CMU cam you’d need a low cost dual USART w/ SPI/I2C port microcontroller to do the multiplexing, with an amount of RAM for buffering and addressing. think of “encapsulating” the SPI and CMUcam’s serial data to the IFI :stuck_out_tongue: (no bit banging please!)

(in networking we have 802.1q VLANing… I think some day theres gonna be VUSARTing :eek: )

The following is untested on the RC and provided only as a prototypical example of how you can use the generic I/O lines to do this on your own.

You didn’t indicate what you were intending to interface with, but you need to pay attention to the clock and data line phase relationship as well as recognising that some SPI periphials will have input and output data transitions occurring on opposite clock phases.

In many cases you will find that if your intent is to us a microcontroller’s onboard SPI interface and operate it at relatively high speeds, that by the time you get the byte or word loaded into the SPI shift register, the shift action occurs so quickly (with respect to CPU execution speed) that you really don’t have time to interact with the SPI port on an interrupt basis, because by the time you exited from the interrupt, the SPI shift would be completed, and you’d immediately re-enter your interrupt service routine.

All things considered, you’ll find that bit banging the SPI data on generic I/O pins with a few bytes of data here and there does not take an appreciablly greater period of time than using on board SPI hardware.

If you have larger amounts of data to transfer between CPU’s or perhiphials on a very regular basis (such as the inter-processor communication between the two CPU’s in the RC), then the onboard SPI hardware can be quite helpful.

#include "ifi_aliases.h"

#define MYSPI_CLK	rc_dig_out16
#define MYSPI_DOUT	rc_dig_out17
#define MYSPI_DIN	rc_dig_in18


// call this on init to setup the port I/O as needed

void MySPI_Init(void) {

        MYSPI_CLK = 0;
	digital_io_16 = OUTPUT;
	digital_io_17 = OUTPUT;
	digital_io_18 = INPUT;

}


unsigned char MySPI_ByteIO(unsigned char dat_out) {

unsigned char mask = 0x80;
unsigned char dat_in = 0;

	while (mask) {
		MYSPI_DOUT = (dat_out & mask)?1:0;
		dat_in <<=1;
		if (MYSPI_DIN) {
			dat_in |= 1;
		}
		MYSPI_CLK = 1;
		mask >>= 1;
		MYSPI_CLK = 0;
	
	}
	return(dat_in);

}

All the io lines are noise filtered with RC networks. The io lines that support analog inputs being the most heavily filtered( about 5x the normal digital io lines), the interrupt io pins being the least filtered (about .1x). Be aware that:

	MYSPI_CLK = 1;
	mask &gt;&gt;= 1;
	MYSPI_CLK = 0;

would probably work ok in a bare PIC18F environment, but with the digital lines spec’d to max 50Khz response time (20us?) the above clock pulse will never show up at the IFI controller pin. You’d likely need to add lots of nop delay to wait for the rise time on the pin and also filter it through a schottky or some other type of buffer to clean up the slow rise “pulse” into a real clock edge.

http://www.ifirobotics.com/rc.shtml#Specifications
http://www.ifirobotics.com/docs/analog-digital–i-o-rc.pdf

Good catch.

Moving the bit-banged SPI lines to I/O 1-6 would certainly speed things up, but also recognize that the output lines have no series R between the port pin and the capacitor, so now the rate of rise/fall is determined primarily by the CPU’s output gate drive capability which appears to be on the order of 230 ohms sourcing and 70 ohms sinking.

I’m estimating the equivilant output resistance by taking the specified worst case voltage drop at a rated output current for the port pins and calculating the equivilant resistance.

So 1T would be about 230ns right?

So on I/O lines 7-18, with the 10nF cap hanging right on the port pin, 1T would be 2.3us.

Clearly if the SPI port needed to bring data IN, then yes I would limit the input data rate to 40kHz on I/O lines 7-18, and maybe 300kHz on I/O lines 1-6. Assumes 3T (95%) settling times.

For an output only configuration, then rates of 140kHz for I/O 7-18 and 1.45MHz for I/O 1-6 would probably be ok.

I would agree that some circumstances may necessitate the need for a schottky gate might be necessary, but lacking any additional information its hard to comment beyond that.

Along those lines, no matter what the external part or parts may be, that the interconnecting lines should be kept as short as possible, and that the target system either share the same 5V supply, or at least provide a means of protecting against differences between sepearately derived 5V supplies. The input impedance of the IFI appears to be high enough to prevent damage if one system was unpowered, it is still low enough that one could potentially be partially powered from the other via the protection clamping diodes.

Thanks,

Dave,

All the stuff I’ve been doing is bi-directional so I’m constrained by the input delay on paired i/o lines. So yes, if you are only using SDO and don’t care about SDI on the SPI interface then I guess you can quick clock just to get the shifted data out. I’d still put a scope on the line. I never got my stuff to work cleanly and looking at the output pulses guessed that it was becuase they looked more like slow rise sine waves than digital data/clock signals.

Might get away with 2t, which is still ~13%/86% levels?, if using schmitt trigger buffers (why did I say schottky?! before) to clean up the pulses.

Line 1-6 are least filtered because they are the external interrupts lines also. So using them up could mean other issues pop up.

I was looking at using a small dual port ram and address blocking. Each co-processor would have their own dual-port ram chip but only part of the address space would be decoded - say 16 bytes. They would have their data lines tied together so the robot controller can access all the data but wouldn’t know it was reading chunks from different chips. I was using the analog lines for the interface because that was one of the things I wanted to off-load to another processor anyway. Still bit banging, but bit banging bytes! At least that’s the theory.

Bud

It must have been late, because although I knew what you meant, I also gave credit to Schottky rather than Schmitt for the hysteresis you were referring to.

Yes, 2T should be ok, and 3T is conservative.

Whether we consider your dual port ram scenario, or something like an SPI communications path, it would probably be a good idea if one had ready access to a logic analyzer to make sure all of the timing requirements are met. Validating something like that with just a two channel storage scope can be time consuming and may not show you enough to recognize what the problem is.

For something like inter-processor communication, I’d suggest that using the TTL serial port and converting to RS-485 or RS-422 to make multi-drop inter-processor communication that much easier.

As long as one is careful, uses balanced/twisted pairs, properly terminates the line, and perhaps uses shielded (but low capacitance) cabling, there’s no reason that the serial channel couldn’t be run at the highest bit rate possible if low latency was a concern. A high bit rate approach likely means not handling serial communications via interrupt routines, which may be a good thing, or bad thing depending upon your overall design.

If latency isn’t a large concern, then a more conservative bit rate like 9600 or 19200 would probably be better, and use interrupt routines to handle the serial port.

Above all, build a check byte or word into the protocol. CRC’s are better, checksums are ok. I generally keep a count of discarded packets, and find a way to make things like that available for debugging.

This approach is something I’ve been considering to add sensors that would otherwise be more of a challange to add directly to the RC’s I/O and/or to offload the RC by moving some data pre-processing on another CPU.

For serial debugging, I’ve used software products by “Front Line Test Equipment” http://www.fte.com for about 15 years. Sometimes the simplicity of their old DOS based “Serial Test” product coupled with an old laptop, is easier than the complexity of the newer, Windows based stuff, but those products are very good as well, and you can build your own protocol decoders to make the display of your own serial protocol that much easier.

As I’m getting a bit far afield from the origional poster’s question, I’ll cut the async discussion here and if anyone wants to pick that up, a new thread is probably best.

Thanks,

After the fourth post, I really don’t understand what’s going on here.

Where can I find an introduction to whatever topic is being discussed, especially the last few posts by dcbrown and Dave K.?

Thanks in advance,
Robinson

They’ve moved off into the technical details of how the controller is wired, the electronics involved, and some signal theory, I think. Not really “programming” anymore.

If you visit the IFI site and look for the pdf file:

It shows resistors and capacitors conditioning all the io pins of the robot controller. These are between the PIC18F chip and the external pins we can attach to. They’re essentially a low pass filter, high frequency noise gets gobbled up by the capacitor. In almost all cases, programmers won’t care that they are there… actually they will be happy because these automatically filter off glitches and debounce stuff and the like for you.

When programming, if an external sensor sets a 1 or 0 on the input line of the controller, the PIC chip won’t see that 1 or 0 for a while. How long it takes for the 0 to be seen as a 1 depends on the RC constant which introduces a delay expressed at tau (t). The wiki page shows the rise/fall times and how many (t) time periods it takes to reach a specific voltage percentage. Tau is R*C.

In practice all this means if you turned an output on and off and on and off etc. very quickly - nothing would happen externally, the on/off transitions are spaced too closely together.

Similarly, if there is an external sensor that is generating very small width pulses it is possible they could be missed because they were filtered off. We’re talking 10us or so for inputs, less for outputs.

The whole purpose of the RC network filter in the first place is to take care of the ambient noise picked up on all the attached sensor cables. For the most part, programmers don’t care… until. Until we try to use the digital io as a serial data line for communication. In that case we want to know how fast can we pump data bits out one of the digital lines without being filtered off.

The resulting “pulses” since they have long rise and decay times don’t look like pulses at all when they are small - much more rounded. This can cause problems when interfacing to raw external digital logic parts which often have requirements of max rise/fall times. To clean them up you can use schmitt triggers which, … well read the wiki:

Bud

The origional post questioned how to do SPI (a synchronous Serial Periphial Interface) with the Robot controller. At the time I responded, I didn’t notice that the origional post was a few months old, but the origional question really hadn’t been fully explored, so I thought that I’d follow up with a quick example of how one can build interfaces like that with some relatively simple code, and provided some example code that I thought others might find useful.

dcbrown followed up with the correct observation that the RC (resistor capacitor) filtering on the user I/O lines limit the transition rates of the lines, and related personal experience in trying to interface a dual port RAM to the controller for the purpose of tying the RC to one or more other co-processing computers.

Aside from some follow up discussion on the timing considerations one needs to consider, and how to analyze them, I expanded on DC’s train of thought in tying co-processing or other I/O devices to the RC and suggested that using an async serial port is much easier to debug.

“chips” with SPI interfaces on them will typically accept moderate to high clock speeds (100’s of kHz to several MHz) and can be a very convienent way to expand the capabilitys of a small microcontroller, such as the one used in the IFI RC, without tying up a lot of the I/O pins on the processor itself.

The RC is flexible enough that if you don’t consider both the software as well as hardware ramifications when choosing how to interface a more complex periphial to the controller, then you may be setting yourself up for more work than you bargained for… especially if you don’t have the proper tools (which could be hardware, software, or a combination thereof) to debug the problem.

dcbrown rightly raised the real world impacts that the hardware RC filtering IFI added were relevant to the discussion and highlight the fact that the software folks need to understand enough about the hardware to take such factors into considersation… likewise, hardware designers need to understand enough about the ramifications of their descisions such that the software doesn’t become impossible to impliment.

The bottom line is that interfacing devices with SPI interfaces to the RC is both possible and practical as long as you are careful to consider all of the requirements.

If anyone is interested in more details related to interfacing an SPI device, we can go deeper into the details if you like.

I hope this helps…

Thank you both for taking the time to explain this, dcbrown and Dave K.

Robinson