Data System


TRAM has always used the concept of a PIC processor on board the trolley transmitting data over a RF modem to a data system at a fixed location -- usually near the middle of the track.  This is essentially the 1990 vision...


The first PIC version used the TAOS board with two PIC processors.  One handled the PTU module (?) and the other collected data and sent it over a radio module.  I  later built my own board dedicated to the specific sensors that TRAM used.  After lots of mods as TRAM evolved, I created a second board in 2008 with 8 independent UARTS that could handle a variety of sensors (3.3, 5, and 12V power, RS-232 or TTL output).  I believe that all of these version have used the PIC18F252.  (Ned Chamberlin picked a useful CPU for TAOS!)  I soon found that the radios I had selected were not the best choice.  I also have had to add more strange modifications:

  • A power daughter board (12V -> 3.3V) on the power board to supply the high current needed by the Novatel GPS
  • A custom solid-state relay board on the power board since stock relays had limited life and failed in the "on" position.
  • A daughter board just with a TTL logic gate to supply the drive current needed for the power relay
  • A second PIC (PIC24F32K) as a front-end to the IMU to reduce the baud rate from 115.2 to 19.2Kbaud (since the PIC couldn't keep up and dropped characters at 115.2).  Needed to use the PIC24 to get two independent UARTs (and needed 2 UARTs since baud rates are different).  Since this circuit is on a proto board, I haven't drawn it up electronically.  The pin connections are in the table below. [21 Mar 2014: Changed also to format data to hex and only transmit message ID FF.]
    Note that I have added a header to this board for connections and a second header just to secure the board mechanically.
  • Removed all on-board radios and simply wire to an XBee daughter board.  Have also used a Bluetooth module connected this way for lab testing.
Edge Connector Pin PIC Pin Function (comments)
10 1 !MCLR (programming; connected through 10K? pull-up resistor to Vcc)
9 2 PGEC2 (programming)
8 3 PGED2 (programming)
7 4 U2Tx (from this board, to TRAM data system serial port)
6 5 U2Rx (unused)
5 6 U1Rx (to this board, from IMU)
20 11 U1Tx (unused)
16 15 SCK1 (from TRAM)
15 16 SDO1 (to TRAM)
14 17 SDI1 (from TRAM)
13 18 !SS1 (from TRAM)
12 19 Gnd
11 20 Vcc (with bypass capacitor to Gnd) [3.3V]



TRAM started using WIT2410 2.4GHz point-to-point radios.  Later I tried HAC-UEM 433 MHz radios, thinking that the lower frequency would better transmit through trees. Not only didn't it work very well, it also turned out to be an illegal frequency in the US.  I later tried XBee radios both at 915MHz (XBP09-DMSIT-156) and 2.4GHz (XBP24-DMSIT-250) and haven't noticed a significant difference.  I'm now using a pair of XBP09's for the trolley and have another pair of XBP24's if needed (was using with for the power supply before direct-connecting it).

Settings for the XbeePro Radios:

All: (to enter command mode, send "+++", wait for "OK", times out of command mode after 10(?) seconds)

  ATBD 7 (115k; ATBD 3 for 9600)

  ATRO 0 (send each character; default is 3 for packetizing)

  ATPL 4 (max power in field; ATPL 0 in lab; Doesn't work for XBP09s?)

  ATWR (save settings)

  ATDH, ATDL as appropriate:

Part Use Antenna ID,H ID,L
XBP09-DPSIT-156 Trolley SMC-RP, long whip 0013A200 40677B29
XBP09-DPSIT-156 retired connector broke ~5/2014 0013A200 40677B0B
XBP09-DPSIT-156 New: Trolley base SMC-RP, long whip 0013A200 40A65088
XBP09-DPSIT-156 New:spare SMC-RP 0013A200 40A6507F
XPB24-DMSIT-250 former Lambda base SMC-RP, short whip 0013A200 403AB60C
XPB24-DMSIT-250 former Lambda SMC-RP, in box, short whip 0013A200 40080994
XPB24-DMUIT-250 test wire whip 0013A200 4056236F
XPB24-DMUIT-250 test wire whip 0013A200 40562370


The PIC code mostly just polls each serial port for characters.  As it gets characters, it fills a separate buffer for each port.  If a termination character is found, it copies the entire message to an output queue and prepends the port number.  Before polling every port, it also checks if the user has entered a command (listed below).  A 10Hz interrupt is used to grab the speed counter and set up A/D sampling.  After each serial port scan, these values (if available) also are copied to the output queue.  An interrupt on the radio transmit UART flushes the output queue.

I've tried to make this code reasonably efficient, for example by making a table-driven binary-to-hex converter.

With this flow, all channel processing must be accomplished before the input UART 4-byte FIFO is filled.  I found that the IMU at 115.2kbaud was too fast for the PIC to keep up, so I added a second PIC to read its data at 115.2kbaud and echo it back out at 19.2kbaud.  Another oddity of the IMU is that it is in binary and sends several types of record (with variable message lengths).  Special code runs, now in the second PIC, to create hex characters of these data so that they may be parsed like the other TRAM sensors.  I was able to get the PICs to talk using SPI (see "nidas8.c" and "cristafe4"), but this didn't improve data transfer and made the code clumsier.  Also, I should note that the message types are included in the hex translation and have been added to the .xml to parse each of these records.  C code for this front-end PIC is attached. Note that this version has error checking commented out, since it appears to introduce even more errors into the data stream (rejecting entire packets if one byte has an error).

Update (8/2015): Changed to VN100 IMU from Crista, since the VN has a more flexible output (sample rate and baud rate).  Can't run both together, so have removed the "IMU" PIC and wired the Crista directly into its own Xbee radio that goes into another GuruPlug input.

Flow chart:



Infinite loop

Execute command, if present

Loop over serial ports

If new character, add to buffer

If character is end-of-line, prepare to send by adding wrapper and appending to output buffer

If speed counter value available

Adjust speed contoller duty cycle

Prepare to send counter value

Prepare to send duty cycle value

If A/D reading available

Set up for next A/D conversion

Prepare to send last A/D reading

Interrupt service routine (avoids calling subroutines within this ISR to save time):

2ms timer:

Loop over serial ports

If byte available, stuff into buffer

if 100ms has passed

Grab speed counter value

Send one character of VN prompt for P&T values

Prepare first A/D conversion


If output buffer has character, send next character

The trolley PIC is programmed to respond to several commands typed by an operator (via minicom, or equivalent) over the serial radio link to the trolley.  These are:
S Stop (motor off)
G Go (motor on)
+ Increase speed setpoint
- Decrease speed setpoint
C Calibrate TCM [somewhat involved -- move entire trolley through 3D rotations]
c Stop TCM calibration
R Start CO2 (rarely needed now that I figured out correct setting!)
0 Set XBee radio power low (lab testing)
4 Set XBee radio power high (in field)



I can't remember the first version of the TRAM data system -- probably simple logging on a laptop using minicom.  For NIWOT07/09, I used a laptop running pre-NIDAS software to collect trolley data in the same manner as ASTER data.  For BAO12, I ran NIDAS on a laptop.  I now have a GuruPlug running NIDAS that is even easier to start up.  My current .xml configuration is attached.  Note that data come in through only two serial ports (connected to a USB adaptor).  One serial port is connected to the radio receiving trolley data.   Data from the different sensors on the trolley are identified with a 1:, 2:, 3:, etc. prefix, indicating which PIC board serial port the data came from.  Some special data sources on the PIC have other prefixes.  These are listed below.  The other DSM serial port is direct connected to the Lambda power supply.

Prefix Input Source Data Rate
0 U6 TCM 9600/12V/RS232 10
1 U7 SHT 9600/3.3V/TTL 2?
2 U8 CO2 9600/12V/RS232 10 settable
3 U9 Sonic 9600/12V/RS232 10 settable
4 U2 not used (had been RFID?)  
5 U3 IMU 115200->19200/5V/RS232 10
6 U4 GPS 9600/3.3V/TTL 10 settable
7 U5 PAR 9600/3.3V/TTL 2?
8 A0 Voltage 10
9 A1 Current 10
A A4 Position counter 10
C   Echos manual commands, plus ! at power up sporratic
D   Power control PWM duty cycle 10

My intent for multiple trolleys is either to multiple pairs of radios, or to use incorporate a trolley ID in the Prefix above, e.g. 1A:xxx, 37:xxx.  I'd need something similar with the commands: 1G, 2S, etc.

A third USB serial port also is used for a fixed GPS receiver (one of the old ASTER Garmin GPS35s) used as the time source for chrony to set the GuruPlug clock.  This is not ideal, since USB data polling limits the PPS accuracy to about 100us.  At some point, I'll try using the GuruPlug's built-in UART port for the GPS, but will have to figure out how to get the PPS signal from a DIO line.  In this case, I'll go back to the old Lassen GPS (which supplies 3.3V-level signals, is smaller, and can be powered directly from the GuruPlug).

Useful links:

My GuruPlug documentation on EOL's Software Engineering Wiki.

chrony documentation (especially 3.2.3, configuration parameters)

gpsd how-to