DSpace robot - Software

NOTE: this is a work in progress - stuff is missing, code hasn't all been tested - check back to see what's changed

Change List

Introduction

The robot controller board has had at least 3 different revisions, it will probably change in the future - the C++ classes in robot.h provide a way to hide those differences so that code can be portable from one platform to another (and hopefully to future platforms) - the main thing we're trying to hide here is which pin numbers on the chip are wired to which sensor plug or motor.

Getting the software

When you installed the arduino support software you also installed the code and include files, periodically we'll release new version so please watch our front page

To make sure that you've installed the correct software here's a sample of code for a simple robot using the library. If it compiles all should be installed correctly

Sensor ports

Each port has 2 unique data pins and 1 shared pin (SDA - hardware i2c data)

Some pins in some port may be shared with other board function - check out the description for your board (or look at the board schematic), to see which pins do what and what limitations there might be - Pin0 is usually an analog pin., Pin2 is often shared with several ports.

Raw ports

You can create a raw port for a sensor by declaring an object to represent it:


	RobotSensor  s(0);	// make an object for sensor port 0

Pins on a sensor port are named with the symbols 'Pin0', 'Pin1' and 'Pin2' (case is important)

Before reading or waggling the pins on a sensor port you need to tell the hardware how you are going to use the port - you do this with the PinMode() method:


	s.PinOut(Pin0, INPUT);		// pin 0 is an input
	s.PinOut(Pin1, OUTPUT);		// pin 1 is a digital output
	s.PinOut(Pin2, INPUT_PULLUP);  // pin 2 is an input with a pullup resistor

Now you can read and write the digital values on a port - for example in this example we can read a digital value (1 for a high voltage, 0 for a low voltage) on pin 0 and copy it to pin 1:


	int v = s.DigitalRead(Pin0);
	s.DigitalWrite(Pin1, v);

Or we can read an analog value from the analog pin on a port - we get a value between 0 and 1023 representing a voltage between 0 an 5 volts:


	int a = s.AnalogRead();

Single pin ports

If all you need to use from a port is just one pin you can create a single port object so that you can use the port's pins independently:


	RobotSensor1Pin		p0(0, Pin0);	// pin 0 of sensor port 0
	RobotSensor1Pin		p1(3, Pin2);	// pin 2 of sensor port 3

You can access pins the same way as you do for simple ports but don't have to specify the pin number:


	int v = p0.DigitalRead();
	p1.DigitalWrite(v);

Derived ports

Micro Switches

A MicroSwitchRobotSensor is a RobotSensor1Pin for use when you have a microswitch connected between a sensor's pin and ground - it has a single method On() that returns true if the switch is pressed:


	MicroSwitchRobotSensor m(3, Pin1);  // on port 3 pin 1

	if (m.On()) {
		// do something

DIP Switches

The 3 way DIP switch on the board has 1 switch for the main power and two for general use - these switches share pins with sensors - check the list of shared pins to find out which ones - turn the switches to off if they are used for something else. It's particularly useful to use a switch to disable the motors (or restart your program) so that your robot doesn't walk off the table while you're trying to program it.

	
	DIPSwitchRobotSensor	enable(2);	// dip switch number 2

	if (enable.On()) {
		.....

Driving LEDs

You can attach an LED to any single pin - use a current limiting resistor from +5v - the AVR microprocessor can only sink a small current so choose a resistor and LED that will not damage the chip - limit current to a few milliamps.


	LEDRobotSensor	led(5, Pin1); // pin1 of port 5

	int v;
	led.On();
	Led.Off();
	led.On(v);	// on or of depending on v

Driving external circuits

You can drive higher current circuits, relays, etc with a transistor - use a series resistor if you're driving a bipolar transistor


	TransistorRobotSensor	led(5, Pin1); // pin1 of port 5

	int v;
	led.On();
	Led.Off();
	led.On(v);	// on or of depending on v

Servos

Servos are small motor devices often used for radio controlled devices - they are driven by 3 wire circuits - power, ground and signal. The signal is a simple pulse 1-2milliseconds in length - it needs to be continually repeated many times a second.

We provide a servo control class that generates these pulses for you:


	ServoRobotSensor  servo(5, Pin1);	// use pin 1 on port 5 for a servo

	servo.Pulse(128);			// move servo to middle
	servo.InterPulse();			// wait minimum time
	servo.Pulse(255);			// move servo to one extreme

You must structure you program to periodically call Pulse() on each servo in the system (put it in the Arduino loop() ) - Pulse takes a value from 0-255 with 128 representing the middle position. A static method InterPulse() represents the time you must wait before sending another pulse - if you are doing something else that takes a lot of time (at least 19mS) then you don't need to call it - if you are writing pulses to multiple servos you only need to wait once.

If instead of directly connecting a servo to a sensor port you are using one of the three servo connectors then you can use the ServoRobot object passing in the servo number 1-3:


	ServoRobot	servo(3);		// user servo SERVO3

I2c devices

I2C aka TWI ('two wire interface') is a standard way to talk to devices - any two pins can be turned into a data pin and a clock pin. Several devices can be on the same I2C bus, or you can have multiple buses.

The I2CRobotSensor class is a simple 'bit-banged' I2C master only implementation - it uses the internal AVR pullup resistors - if you want to run fast, or have errors, add a 1k pullup resistor to the data pin.

Some knowledge of how I2C works is needed to use this class - best to look at some of the working examples for real devices:


	I2CRobotSensor	i2c(3);		// use port 3 as an i2c port
	unsigned char data[10];

	const unsigned char ADDRESS = 0x34;
	i2c.WriteAddress(ADDRESS, 0x56);		// write 1 byte 0x56 to a device
	i2c.WriteAddress(ADDRESS, 0x56, 0x78);		// write 2 bytes 0x56 0x78 to a device
	i2c WriteArray(ADDRESS, &data, 10);		// write 10 bytes from data[]
	v = i2c.ReadAddress(ADDRESS);			// read 1 byte from a device
	v = i2c.ReadAddress(ADDRESS, 0x45);		// read 1 byte from a device after sending a byte
	count = i2c.ReadArray(ADDRESS, &data, sizeof(data));// read bytes into an array - returns number of bytes read
	count = i2c.ReadArray(ADDRESS, 0x45, &data, sizeof(data));// read bytes into an array after sending a byte

Motor abstraction classes

We also have a dual H-bridge motor controller - it can control a pair of DC motors or a single stepper motor. We provide a class that represents a motor, and a class that represents two motors for driving a platform - use one or the other, but not both.


	RobotMotor	motor(0);// motor controller for motor 0
	
	motor.Forwards();	// turn motor forwards
	motor.Backwards();	// turn motor backwards
	motor.Stop();		// stop motor (leave it free to turn)
	motor.Brake();		// stop motor (with dynamic braking)

	RobotDrive	drive;	// both motors

	drive.Stop();		// stop
	drive.Forwards();	// move both motors forwards
	drive.Backwards();	// move both motors backwards
	drive.Left();		// spin left
	drive.Right();		// spin right
	drive.LeftPivot();	// pivot left (brake inner motor)
	drive.RightPivot();	// pivot right (brake inner motor)