MartinSant.net

Software Engineering | MicroMachines

  • Airplane
  • Electronics
  • Model Trains
  • Chickens
  • 3D Design
  • German Shepherds
  • Garden
  • Protothrottle

Raspberry Pi and Xbee Series 1

Posted by admin on February 16, 2014
Posted in: Other Stuff.

I’m going down much the same road with my new widgets as I did with the Wixels- depending on the software loaded and the application, a Widget can be a client or controller. A client can be a locomotive, turnout or any other device that is controlled via servos or discrete outputs. The controler can be a hand-held interface and/or a computer. In my case this is my Raspberry Pi, configured as a web server/web sockets host.

To that end, I coded up a quick Xbee interface for the Raspberry Pi in python that works with the datagrams in my set of train/control widgets. It’s extremely minimalistic (of course) but allows you to send standard ‘AT’ commands to the Xbee and also send advanced API datapackets. This code assumes that you have an Xbee module configured with X-CTU. I’m using the Parallax Xbee USB board to do this. You will need to set the interface baud rate of the Xbee to 38400 baud and place the Xbee in API mode. Once configured, move the Parallax board to the Raspberry Pi and that’s it. Destination Xbee modules (configured as above) will receive this data (based on it’s destination address of course) and pass this out the serial port to the host. In this case, the host is (will be) my train widget boards. Once they are available that is, perhaps early March (I hope)

Anyhow, you can now control Train Widgets with the following code or adapt it to your own xbee design. XbeeTransmitDataFrame is the primary control interface. All servo, sound and sensor data uses this fixed length datagram. It’s compact and fast and offers 65K of possible command codes (I’ve implemented 3 so far).

xbeeSendDataQuery is used to do a standard ‘AT’ command using the API mode. For example, you can pass ‘M’ and ‘Y’ to this method and it will return the 16 bit node address of the Xbee. Any of the other AT commands can be used as well but you will have to get the data using serial.read() and know where in the packet the return value and how long it is.

xbeeTransmitDataFrame is used to send the 16 byte packets I’ve made up for my implementation. You can see how these are constructed from the C structures below.


import serial

class xbeeController:
    def __init__(self):
        usbPort = '/dev/ttyUSB0'
        self.sp = serial.Serial(usbPort, 38400)

    def xbeeReturnResult(self, datalength):
        return(self.sp.read(datalength))

    def xbeeDataQuery(self, cmdh, cmdl):
        frame = []
        c0 = ord(cmdl)
        c1 = ord(cmdh)
        frame.append(0x7e)	# header
	frame.append(0)	        # our data is always fixed size
	frame.append(4)         # this is all data except header, length and checksum
	frame.append(0x08)      # AT COMMAND - send Query to Xbee module
	frame.append(0x52)	# frame ID for ack- 0 = disable
	frame.append(c1)	# Command high character
	frame.append(c0)	# low character
	frame.append(0)	        # zero checksum location

	cks = 0;
	for i in range(3,7):	# compute checksum
	    cks = cks + frame[i]

	i = (255-cks) & 0x00ff
	frame[7] = i	        # and put it in the message

	for i in range(0,8):	# send it out the serial port to the xbee
            self.sp.write(chr(frame[i]))
	
    def xbeeTransmitDataFrame(self, dest, data):
        frame = []
        frame.append(0x7e)	# header
	frame.append(0)	        # our data is always fixed size
	frame.append(21)        # this is all data except header, length and checksum
	frame.append(0x01)      # TRANSMIT REQUEST - send Query to Xbee module
	frame.append(0)	        # frame ID for ack- 0 = disable
	frame.append( (dest>>8) & 0x00ff) # Destination address
	frame.append( (dest & 0xff))
        frame.append(0)         # disable ack for fastest transmission

        for i in data:          # move data to transmit buffer
            frame.append(i)
        frame.append(0)         # checksum position

	cks = 0;
	for i in range(3,25):	# compute checksum
	   cks += frame[i]

	i = (255-cks) & 0x00ff
        frame[24] = i

	for i in range(0,25):	# send it out the serial port to the xbee
            self.sp.write(chr(frame[i]))


This is the xbee header information that is in the Widgets. This defines the three control packets I’m sending with the Xbee. These are the 16 bit fixed length packets that ride in the transport area of the above datagram. By keeping them small, I’m getting a 7ms packet transmit time which is very fast.


#define CONTROLLER   0x0000				// XbeeCTRLPacket{}
#define RFIDCOMMAND  0x0010				// XbeeRFIDPacket{}
#define SOUNDCOMMAND 0x0011				// XbeeSOUNDPacket{}
	
typedef struct
{
	uint16_t destinationAddress;		// Xbee destination address for this client
	uint16_t sourceAddress;				// This node's address
	uint16_t commandID;					// 16 bit command ID
	uint16_t Sound0;					// 16 Bits of Sound Triggers
	uint16_t Sound1;
	uint16_t Sound2;
	uint16_t Sound3;
	uint16_t Sound4;
} XbeeSOUNDPacket;
	

typedef struct
{
	uint16_t destinationAddress;		// Xbee destination address for this client
	uint16_t sourceAddress;				// This node's address
	uint16_t commandID;					// 16 bit command ID
	uint16_t RFID0;						// 12 bytes of ascii RFID info
	uint16_t RFID1;
	uint16_t RFID2;
	uint16_t RFID3;
	uint16_t misc1;
} XbeeRFIDPacket;

typedef struct
{
	uint16_t destinationAddress;		// Xbee destination address for this client
	uint16_t sourceAddress;				// This node's address
	uint16_t commandID;					// 16 bit command ID
	uint16_t Servo0;					// Servo 0
	uint16_t Servo1;
	uint16_t Servo2;
	uint16_t Discrete;
	uint16_t misc1;
} XbeeCTRLPacket;


Posts navigation

← Control Widgets
Production Control Widgets →
  • Recent Posts

    • All finished, well almost
    • New Paint
    • Train Layout Rebuild
    • New Computer
    • Airplane Refurb
  • Pages

    • 2D vector drawings into 3D models
    • 3D Printed Figures
    • Android – Reels Game App
    • AVR Attiny 1634 s/w UART
    • Bluetooth Diagram and Descriptions
    • Building a G Scale Turnout
    • Burnley Country Store
    • Flying to York PA
    • New Puppy – Sophie
    • Protothrottle
    • Protothrottle to Airwire Beta
    • Rail Layout Editor
    • Raspberry Pi Zero W Wifi Access Point
    • RPi Android HTML5 Servo Control
    • Steam Engine and Dynamo
    • Tin Can Steam Boiler
    • Wixel Breakout Board
    • CRM C# Autonumber Plugin
    • Microsoft CRM and C#
    • EightWay Game
    • Dice In A Stone Box
    • About Martin
Proudly powered by WordPress Theme: Parament by Automattic.