Ok, I have started implementing and testing the serial interface to the Arduino. So far, I have coded the following sequences:
(1) 1/1/pinNumber/analogRate - to write an analog rate to a specific pin
(2) 1/2/pinNumber/digitalState - to write a digital state to a specific pin
(3) 2/1/pinNumber - to read an analog value from a specific pin (via serial)
(4) 2/2/pinNumber - to read the digital state from a specific pin (via serial)
(5) 3/1/servoPin - to read the current pose of a servo from a specific pin (not active)
(6) 3/2/servoPin/servoPose - to write a pose to a servo on a specific pin (not active)
(7) 3/3/servoPin - to detach a servo on a specific pin (not active)
(8) 3/4/servoNumber - to read the pose on a specific servo channel on the maestro
(9) 3/5/servoNumber/servoPWM - to set the pwm pose on a specific servo channel on the maestro
(10) 4/1/lowSweepIR/highSweepIR/speedSweepIR -
At first I had some problems trying to get servos to react. I noticed that the servos were not zeroing at the beginning of the loop. It turns out that my connection to the mini-maestro was not working. After re-seating the connection everything started working correctly.
First test was the 3/5/servoNumber/servoPWM - worked correctly on two different servos (0 - for the Ultrasonic distance sensor, 6 - for the IR distance sensor). I added some instrumentation via the LCD Panel and was able to see what the command was being interpreted as. Servos moved, although there was a delay (I do have a one second feed in there).
Second test was to get the 3/4/servoNumber to work - although I could get some return values, they were not what I was expecting. Need to do a little more homework on return values from the maestro and how I am able to read that through a serial interface. I am getting absolutely nothing back from the Mini-Maestro. I am even using code that I know works with the device (according to websites that have the listings).
Update: Am I up against a hardware problem? If so, what is the least expensive way of implementing what I want. Should I go back to the SSC-32? The resolution in the analog domain was not that great, however, I am no longer using the Maestro to read the values from the IR or Ultrasonic distance sensors.
This is a blog mostly about techie things, what I am doing to my apartment network on the cheap, IOT, 3D Printing, Raspberry Pis, Arduinos, ESP32, ESP8266, Home Automation, Personal Weather Stations, Things That Go Bump in the Night, and some side issues that need discussing. Remember, sometimes the journey to an end is as much fun as the goal achieved!
Showing posts with label Robot SW. Show all posts
Showing posts with label Robot SW. Show all posts
Saturday, April 13, 2013
Saturday, March 30, 2013
Robot Serial Interface Protocol
Based upon a serial interface description that I found at http://forums.trossenrobotics.com/tutorials/how-to-diy-128/complete-control-of-an-arduino-via-serial-3300/, I have decided to try doing the interface in a like manner. I could use firmata but I do not want to program the RPi in python. Here is what I have come up with so far:
Robot Interface Protocol (Serial)
1 - write
1 - digital pin write
"pin number"
"1 for LOW, 2 for HIGH" --> sets pin to value, returns OK
2 - analog pin write
"pin number"
"frequency (0-255)" --> sets pwm on pin to value, returns OK
3 - LCD panel error display
"error number"
2 - read
1 - digital
"pin number" --> returns digital pin value (0 or 1)
2 - analog
"pin number" --> returns analog pin value (0 - 1024)
3 - servo (via Maestro)
1 - read
"servo number" --> returns pwm value
2 - write
"servo number"
"pwm value" --> sets servo to pwm value, returns OK
4 - IR distance sensor (GP2D12 and servo)
1 - set sweep range
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)"
"sample rate in ms" --> returns OK
2 - set IR distance servo
"pwm value" --> returns OK
3 - sample IR distance sensor (raw) --> returns "IR", raw value
4 - sample IR distance sensor (computed) --> returns "IR", computed value
5 - start continuous sample
-->starts sweep back and forth; returns "IR", pwm, computed,
raw at sample rate
6 - stop continuous sample --> returns OK
7 - get statistics at current pwm
"number of samples" --> returns "IR", pwm, mean, sd of computed, mean, sd of raw
8 - display samples on LCD panel
1 - start --> returns OK, starts showing samples on LCD panel
2 - stop --> stops showing samples, clears LCD panel, returns OK
5 - Ultrasonic distance sensor (HC-SR04 and servo)
1 - set sweep range
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)"
"sample rate in ms" --> returns OK
2 - set Ultrasonic distance servo
"pwm value" --> returns OK
3 - sample Ultrasonic distance sensor (raw) --> returns "UL", raw value
4 - sample Ultrasonic distance sensor (computed) --> returns "UL",
computed value
5 - start continuous sample
-->starts sweep back and forth; returns "UL", pwm, computed,
raw at sample rate
6 - stop continuous sample --> returns OK
7 - get statistics at current pwm
"number of samples" --> returns "UL", pwm, mean, sd of computed, mean, sd of raw
8 - display samples on LCD panel
1 - start --> returns OK, starts showing samples on LCD panel
2 - stop --> stops showing samples, clears LCD panel, returns OK
6 - camera pan and tilt servos
1 - set sweep range for pan
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)" --> returns OK
2 - set sweep range for pan
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)" --> returns OK
3 - set camera pan and tilt servos
"pan pwm value"
"tilt pwm value" --> returns OK
4 - start continuous sweep
-->starts sweep back and forth; returns OK
5 - stop continuous sweep --> returns OK
7 - reset all to setup conditions
Robot Interface Protocol (Serial)
1 - write
1 - digital pin write
"pin number"
"1 for LOW, 2 for HIGH" --> sets pin to value, returns OK
2 - analog pin write
"pin number"
"frequency (0-255)" --> sets pwm on pin to value, returns OK
3 - LCD panel error display
"error number"
2 - read
1 - digital
"pin number" --> returns digital pin value (0 or 1)
2 - analog
"pin number" --> returns analog pin value (0 - 1024)
3 - servo (via Maestro)
1 - read
"servo number" --> returns pwm value
2 - write
"servo number"
"pwm value" --> sets servo to pwm value, returns OK
4 - IR distance sensor (GP2D12 and servo)
1 - set sweep range
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)"
"sample rate in ms" --> returns OK
2 - set IR distance servo
"pwm value" --> returns OK
3 - sample IR distance sensor (raw) --> returns "IR", raw value
4 - sample IR distance sensor (computed) --> returns "IR", computed value
5 - start continuous sample
-->starts sweep back and forth; returns "IR", pwm, computed,
raw at sample rate
6 - stop continuous sample --> returns OK
7 - get statistics at current pwm
"number of samples" --> returns "IR", pwm, mean, sd of computed, mean, sd of raw
8 - display samples on LCD panel
1 - start --> returns OK, starts showing samples on LCD panel
2 - stop --> stops showing samples, clears LCD panel, returns OK
5 - Ultrasonic distance sensor (HC-SR04 and servo)
1 - set sweep range
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)"
"sample rate in ms" --> returns OK
2 - set Ultrasonic distance servo
"pwm value" --> returns OK
3 - sample Ultrasonic distance sensor (raw) --> returns "UL", raw value
4 - sample Ultrasonic distance sensor (computed) --> returns "UL",
computed value
5 - start continuous sample
-->starts sweep back and forth; returns "UL", pwm, computed,
raw at sample rate
6 - stop continuous sample --> returns OK
7 - get statistics at current pwm
"number of samples" --> returns "UL", pwm, mean, sd of computed, mean, sd of raw
8 - display samples on LCD panel
1 - start --> returns OK, starts showing samples on LCD panel
2 - stop --> stops showing samples, clears LCD panel, returns OK
6 - camera pan and tilt servos
1 - set sweep range for pan
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)" --> returns OK
2 - set sweep range for pan
"low sweep pwm value (4000 - 8000)"
"high sweep pwm value (4000 - 8000)"
"sweep speed (0.25 us / 10 ms)" --> returns OK
3 - set camera pan and tilt servos
"pan pwm value"
"tilt pwm value" --> returns OK
4 - start continuous sweep
-->starts sweep back and forth; returns OK
5 - stop continuous sweep --> returns OK
7 - reset all to setup conditions
Thursday, March 28, 2013
Distance Calibration and Angle of Same
Ok, here are the current issues:
1. I have two distance sensors on the Lexan plate. One is a GP2D12 ir distance sensor that is supposed to measure some short range distances. The other is a HC-SR04 ultrasonic distance sensor that measures somewhat larger distances. Each of these distance sensors have non-linearity in the values they return.
2. Each of the distance sensors are mounted on servos on either side of the Lexan plate, meaning that the center of rotation is off center from the iRobot Create.
3. When the servos were mounted, I noticed that they were not completely perpendicular to the Lexan plate, nor is the Lexan plate oriented in a perpendicular manner when mounted to the iRobot Create. That means that the angle of rotation needs to be adjusted. In addition, the Lexan plate is somewhat offset from the center of the iRobot Create and may have a rotation effect.
4. There is an area on the plate where each of the distance sensors can rotate to and an area where they cannot, a sector of a circle if you will. There will need to be adjustments to the sweep for each of the distance sensors so that the values they return will be acceptable.
5. Servos have issues in that there are discrete steps that they make rather than a continuous movement. Also, there needs to be a correlation between the pwm value and the angle of rotation for the servos, which may be different in each servo.
The above issues make it difficult to relate the measured values with what is really out there. This post is an attempt to define those issues and point to a solution. The overall requirement is to have measurements be absolute to a specific point, in this case the centroid of the iRobot Create. In order to do this I will have to deal with a number of coordinate systems. To simplify everything, I am going to assume an XY plane (i.e., no Z axis involved here), however I will retain XYZ coordinates for purposes of being able to add them in later. In this case translation is only in the XY plane, rotation is only about the Z axis, and the Z value is always 0. Note that I will assume no scaling. I will use matrix algebra to translate everything into iRobot Create coordinates (assuming that 0,0 is at the center of the Create). So when I take a measurement of a point, it can be translated into the iRobot Create coordinates. So to make it easier we have rotation around the Z axis at an angle psi with translation in the X (Tx) and Y (Ty). Note that normally the translation in Z (Tz) would be zero.
Notice that if there is no rotation, i.e. psi is zero, then cos psi is 1.0 and sin psi is 0.0 which is just a standard identity matrix with the translation parameters imposed. Where to begin:
a. Assume center of Lexan plate is the Lexan plate origin. The centroid of the plate should be an easy calculation, assume normal XY coordinates - measurements should be consistent (i.e., in inches).
b. Assume center of servo rotation is the servo origin. Distance measurements from each distance sensor should be to the servo origin. This simplifies the remaining transformations.
c. Servo -> Lexan coordinates: translate servo origin to Lexan center, rotate about Lexan center to compensate for Servo angle offset, scaling values should be equal to one (no scaling). It should be easy to measure the servo origins in relation to the plate and figure out the translation values. The servo angle offset may be more difficult, in the initial for simplification we can assume 0 degrees.
d. Lexan -> Create coordinates: translate Lexan origin to iRobot Create origin to compensate for plate offset, rotate about iRobot Create origin to compensate for plate rotation offset, scaling values should be equal to one (no scaling).
e. Create -> World coordinates: translate Create origin to World origin, rotate about World origin to get final World coordinates correct. No scaling, probably set the first matrix to an identity matrix for no effect.
Following the normal convention for such things, the final form of the equation is:
1. I have two distance sensors on the Lexan plate. One is a GP2D12 ir distance sensor that is supposed to measure some short range distances. The other is a HC-SR04 ultrasonic distance sensor that measures somewhat larger distances. Each of these distance sensors have non-linearity in the values they return.
2. Each of the distance sensors are mounted on servos on either side of the Lexan plate, meaning that the center of rotation is off center from the iRobot Create.
3. When the servos were mounted, I noticed that they were not completely perpendicular to the Lexan plate, nor is the Lexan plate oriented in a perpendicular manner when mounted to the iRobot Create. That means that the angle of rotation needs to be adjusted. In addition, the Lexan plate is somewhat offset from the center of the iRobot Create and may have a rotation effect.
4. There is an area on the plate where each of the distance sensors can rotate to and an area where they cannot, a sector of a circle if you will. There will need to be adjustments to the sweep for each of the distance sensors so that the values they return will be acceptable.
5. Servos have issues in that there are discrete steps that they make rather than a continuous movement. Also, there needs to be a correlation between the pwm value and the angle of rotation for the servos, which may be different in each servo.
The above issues make it difficult to relate the measured values with what is really out there. This post is an attempt to define those issues and point to a solution. The overall requirement is to have measurements be absolute to a specific point, in this case the centroid of the iRobot Create. In order to do this I will have to deal with a number of coordinate systems. To simplify everything, I am going to assume an XY plane (i.e., no Z axis involved here), however I will retain XYZ coordinates for purposes of being able to add them in later. In this case translation is only in the XY plane, rotation is only about the Z axis, and the Z value is always 0. Note that I will assume no scaling. I will use matrix algebra to translate everything into iRobot Create coordinates (assuming that 0,0 is at the center of the Create). So when I take a measurement of a point, it can be translated into the iRobot Create coordinates. So to make it easier we have rotation around the Z axis at an angle psi with translation in the X (Tx) and Y (Ty). Note that normally the translation in Z (Tz) would be zero.
Notice that if there is no rotation, i.e. psi is zero, then cos psi is 1.0 and sin psi is 0.0 which is just a standard identity matrix with the translation parameters imposed. Where to begin:
a. Assume center of Lexan plate is the Lexan plate origin. The centroid of the plate should be an easy calculation, assume normal XY coordinates - measurements should be consistent (i.e., in inches).
b. Assume center of servo rotation is the servo origin. Distance measurements from each distance sensor should be to the servo origin. This simplifies the remaining transformations.
c. Servo -> Lexan coordinates: translate servo origin to Lexan center, rotate about Lexan center to compensate for Servo angle offset, scaling values should be equal to one (no scaling). It should be easy to measure the servo origins in relation to the plate and figure out the translation values. The servo angle offset may be more difficult, in the initial for simplification we can assume 0 degrees.
d. Lexan -> Create coordinates: translate Lexan origin to iRobot Create origin to compensate for plate offset, rotate about iRobot Create origin to compensate for plate rotation offset, scaling values should be equal to one (no scaling).
e. Create -> World coordinates: translate Create origin to World origin, rotate about World origin to get final World coordinates correct. No scaling, probably set the first matrix to an identity matrix for no effect.
Following the normal convention for such things, the final form of the equation is:
Labels:
Accuracy,
Robot HW,
Robot SW,
Sensors,
Servo Control
Fiddling with a full setup on the Arduino
I decided to go ahead and put together a complete setup of software in the Arduino. I have been developing the interfaces to the servos, ir distance sensor, ultrasonic distance sensor, and LCD serial panel. In the course of the changes, I decided to move the read of the ir distance sensor to the Arduino rather than read it through the Maestro. I may end up changing my mind later. So my setup in the IDE looks something like this:
// Pololu Mini-Maestro 18 Serial Servo Controller
// Power 9v Seperate power supply from Arduino
// GND to GND on the Arduino
// SSC RX pin to Arduino TX pin Pin04
// SSC TX pin to Arduino RX pin Pin03
// Channel 0 - Ultrasonic Distance Sensor Servo
// Channel 2 - Camera Pan Servo
// Channel 4 - Camera Tilt Servo
// Channel 6 - IR Distance Sensor Servo
// GP2D12 IR Distance Sensor
// Power 5v from the Arduino
// GND to GND on the Arduino
// GP2D12 Sensor analog Rx pin to Arduino Analog pin 0
// Parallax 2x16 Serial LCD Panel
// Power 5v from the Arduino
// GND to GND on the Arduino
// LCD Rx pin to Arduino TX pin Pin06
// HC-SR04 Ultrasonic Distance Sensor
// Power 5v from the Arduino
// GND to GND on the Arduino
// HC-SR04 Trig to Arduino TX pin Pin13
// HC-SR04 Echo to Arduino RX pin Pin12
This setup ends up forcing a number of pin definitions as so:
// Define constants
// Serial pins
const int tx_ToSSC=4; ///< Tx pin going to SSC
const int rx_ToSSC=3; ///< Rx pin coming from SSC
const int tx_ToLCD=6; ///< Tx pin going to LCD panel
const int rx_FrmLCD=5; ///< Rx pin coming from LCD panel(nc)
// Digital pins
const int digtx_ToUltraTrig=12; ///< Tx pin going to ultrasonic sensor trig
const int digrx_FrmUltraEcho=13; ///< Rx pin coming from ultrasonic sensor echo
// Channels on SSC
const int chan_ultraservo=0; ///< Channel 0 - Ultrasonic Distance Sensor Servo
const int chan_camerapanservo=2; ///< Channel 2 - Camera Pan Servo
const int chan_cameratiltservo=4; ///< Channel 4 - Camera Tilt Servo
const int chan_irdistservo=6; ///< Channel 6 - IR Distance Sensor Servo
// Analog pins
const int rx_irdistanalog=0; ///< IR Distance Sensor analog Rx
I have gleaned from several sources the code that I need to access each of these items. First up, is my interfaces to the two serial connections needed for the SSC (Maestro) and the LCD panel:
// initalizing serial connections
SoftwareSerial SSC_Serial = SoftwareSerial(rx_ToSSC, tx_ToSSC);
SoftwareSerial LCD_Serial = SoftwareSerial(rx_FrmLCD, tx_ToLCD);
Next up, I have the procedure interface to the SSC that sets a servos pwm value:
// Send a Set servo pwm command to the Maestro.
// Target is in units of quarter microseconds
// so the normal range is 4000 to 8000.
void ssc_cmnd_pwm(unsigned char servo, unsigned int target)
{
SSC_Serial.write(0xAA); //start byte
SSC_Serial.write(0x0C); //device id
SSC_Serial.write(0x04); //command number
SSC_Serial.write(servo); //servo number
SSC_Serial.write(target & 0x7F);
SSC_Serial.write((target >> 7) & 0x7F);
}
Next, I have a few routines for writing information out to the LCD panel:
// display two strings on the LCD panel
void lcd_display_2_str(String myvalue1, String myvalue2) {
delay(100);
LCD_Serial.write(12); // Clear
LCD_Serial.print(myvalue1); // First line
LCD_Serial.write(13); // Form Feed
LCD_Serial.print(myvalue2); // Second line
}
// display string and int value on one line, string on second line on the LCD panel
void lcd_display_2_str_int(String myvalue1, int myvalue, String myvalue2) {
delay(100);
LCD_Serial.write(12); // Clear
LCD_Serial.print(myvalue1); // First line
LCD_Serial.print(myvalue, DEC);
LCD_Serial.write(13); // Form Feed
LCD_Serial.print(myvalue2); // Second line
}
// display integer value on the LCD panel
void lcd_display_int_val(int myvalue) {
delay(100);
LCD_Serial.write(12); // Clear
LCD_Serial.print("val: ");
LCD_Serial.print(myvalue, DEC); // First line
LCD_Serial.write(13); // Form feed
}
Next, I deal with the gp2d12 ir range detector (along with a test):
/*
read_gp2d12_range
Function that reads a value from GP2D12 infrared distance sensor and returns a value in centimeters.
This sensor should be used with a refresh rate of 36ms or greater.
BY: Javier Valencia 2008
float read_gp2d12_range(byte pin)
It can return -1 if something gone wrong.
*/
float read_gp2d12_range(byte pin) {
int tmp;
tmp = analogRead(pin);
if (tmp < 3)
return -1; // invalid value
return (6787.0 /((float)tmp - 3.0)) - 4.0;
}
void test_irdistance()
{
float myval;
myval = read_gp2d12_range(rx_irdistanalog);
Serial.print("ir val: ");
Serial.println(myval);
// LCD_Serial.write(12); // Clear
// LCD_Serial.print("ir val: ");
// LCD_Serial.print(myval, DEC); // First line
// LCD_Serial.write(13); // Form feed
}
Next, I deal with the Ultrasonic distance sensor (HC-SR04):
/*
HC-SR04 Ping distance sensor
VCC to Arduino 5v, GND to Arduino GND
Echo to Arduino pin 13, Trig to Arduino pin 12
more info at: http://goo.gl/kJ8G1
*/
float grab_ultrasonic()
{
int duration;
float distance;
digitalWrite(digtx_ToUltraTrig, LOW);
delayMicroseconds(2);
digitalWrite(digtx_ToUltraTrig, HIGH);
delayMicroseconds(10);
digitalWrite(digtx_ToUltraTrig, LOW);
duration = pulseIn(digrx_FrmUltraEcho, HIGH);
distance = (duration/2) / 29.1;
return distance;
}
void test_ultrasonic()
{
float mydist;
mydist = grab_ultrasonic();
if (mydist >= 200 || mydist <= 0){
Serial.println("Ultra: Out of range");
// LCD_Serial.write(12); // Clear
// LCD_Serial.print("Out of range");
// LCD_Serial.write(13); // Form feed
} else {
Serial.print("Ultra: ");
Serial.print(mydist);
Serial.println(" cm");
// LCD_Serial.write(12); // Clear
// LCD_Serial.print("Out of range");
// LCD_Serial.print(mydist, DEC);
// LCD_Serial.print(" cm");
// LCD_Serial.write(13); // Form feed
}
}
In order to utilize these, I have the following setups:
// run once, when the sketch starts
void setup()
{
// setup pins for serial interface to SSC
pinMode(rx_ToSSC, INPUT);
digitalWrite(tx_ToSSC, HIGH);
pinMode(tx_ToSSC, OUTPUT);
// set SSC serial interface speed
SSC_Serial.begin(9600);
// setup pins for serial interface to LCD
pinMode(rx_FrmLCD, INPUT);
digitalWrite(tx_ToLCD, HIGH);
pinMode(tx_ToLCD, OUTPUT);
// set LCD serial interface speed
LCD_Serial.begin(9600);
// initial clear and backlight for LCD
LCD_Serial.write(12); // Clear
LCD_Serial.write(17); // Turn backlight on
delay(5); // Required delay for response
// set SSC servos to initial state
ssc_cmnd_pwm(chan_ultraservo,6000);
ssc_cmnd_pwm(chan_camerapanservo,6000);
ssc_cmnd_pwm(chan_cameratiltservo,6000);
ssc_cmnd_pwm(chan_irdistservo,6000);
// set Ultrasonic Distance Sensor pins
pinMode(digtx_ToUltraTrig, OUTPUT);
pinMode(digrx_FrmUltraEcho, INPUT);
// setup our serial monitor
Serial.begin(9600);
// wait for settling to happen
delay(1000);
}
Now that I have the initial software coded, I have time to try them out and start to build the interfaces between the Arduino and the sensors/servos. Next up will be results of the testing, followed by dealing with the interface to the RPi.
// Pololu Mini-Maestro 18 Serial Servo Controller
// Power 9v Seperate power supply from Arduino
// GND to GND on the Arduino
// SSC RX pin to Arduino TX pin Pin04
// SSC TX pin to Arduino RX pin Pin03
// Channel 0 - Ultrasonic Distance Sensor Servo
// Channel 2 - Camera Pan Servo
// Channel 4 - Camera Tilt Servo
// Channel 6 - IR Distance Sensor Servo
// GP2D12 IR Distance Sensor
// Power 5v from the Arduino
// GND to GND on the Arduino
// GP2D12 Sensor analog Rx pin to Arduino Analog pin 0
// Parallax 2x16 Serial LCD Panel
// Power 5v from the Arduino
// GND to GND on the Arduino
// LCD Rx pin to Arduino TX pin Pin06
// HC-SR04 Ultrasonic Distance Sensor
// Power 5v from the Arduino
// GND to GND on the Arduino
// HC-SR04 Trig to Arduino TX pin Pin13
// HC-SR04 Echo to Arduino RX pin Pin12
This setup ends up forcing a number of pin definitions as so:
// Define constants
// Serial pins
const int tx_ToSSC=4; ///< Tx pin going to SSC
const int rx_ToSSC=3; ///< Rx pin coming from SSC
const int tx_ToLCD=6; ///< Tx pin going to LCD panel
const int rx_FrmLCD=5; ///< Rx pin coming from LCD panel(nc)
// Digital pins
const int digtx_ToUltraTrig=12; ///< Tx pin going to ultrasonic sensor trig
const int digrx_FrmUltraEcho=13; ///< Rx pin coming from ultrasonic sensor echo
// Channels on SSC
const int chan_ultraservo=0; ///< Channel 0 - Ultrasonic Distance Sensor Servo
const int chan_camerapanservo=2; ///< Channel 2 - Camera Pan Servo
const int chan_cameratiltservo=4; ///< Channel 4 - Camera Tilt Servo
const int chan_irdistservo=6; ///< Channel 6 - IR Distance Sensor Servo
// Analog pins
const int rx_irdistanalog=0; ///< IR Distance Sensor analog Rx
I have gleaned from several sources the code that I need to access each of these items. First up, is my interfaces to the two serial connections needed for the SSC (Maestro) and the LCD panel:
// initalizing serial connections
SoftwareSerial SSC_Serial = SoftwareSerial(rx_ToSSC, tx_ToSSC);
SoftwareSerial LCD_Serial = SoftwareSerial(rx_FrmLCD, tx_ToLCD);
Next up, I have the procedure interface to the SSC that sets a servos pwm value:
// Send a Set servo pwm command to the Maestro.
// Target is in units of quarter microseconds
// so the normal range is 4000 to 8000.
void ssc_cmnd_pwm(unsigned char servo, unsigned int target)
{
SSC_Serial.write(0xAA); //start byte
SSC_Serial.write(0x0C); //device id
SSC_Serial.write(0x04); //command number
SSC_Serial.write(servo); //servo number
SSC_Serial.write(target & 0x7F);
SSC_Serial.write((target >> 7) & 0x7F);
}
Next, I have a few routines for writing information out to the LCD panel:
// display two strings on the LCD panel
void lcd_display_2_str(String myvalue1, String myvalue2) {
delay(100);
LCD_Serial.write(12); // Clear
LCD_Serial.print(myvalue1); // First line
LCD_Serial.write(13); // Form Feed
LCD_Serial.print(myvalue2); // Second line
}
// display string and int value on one line, string on second line on the LCD panel
void lcd_display_2_str_int(String myvalue1, int myvalue, String myvalue2) {
delay(100);
LCD_Serial.write(12); // Clear
LCD_Serial.print(myvalue1); // First line
LCD_Serial.print(myvalue, DEC);
LCD_Serial.write(13); // Form Feed
LCD_Serial.print(myvalue2); // Second line
}
// display integer value on the LCD panel
void lcd_display_int_val(int myvalue) {
delay(100);
LCD_Serial.write(12); // Clear
LCD_Serial.print("val: ");
LCD_Serial.print(myvalue, DEC); // First line
LCD_Serial.write(13); // Form feed
}
Next, I deal with the gp2d12 ir range detector (along with a test):
/*
read_gp2d12_range
Function that reads a value from GP2D12 infrared distance sensor and returns a value in centimeters.
This sensor should be used with a refresh rate of 36ms or greater.
BY: Javier Valencia 2008
float read_gp2d12_range(byte pin)
It can return -1 if something gone wrong.
*/
float read_gp2d12_range(byte pin) {
int tmp;
tmp = analogRead(pin);
if (tmp < 3)
return -1; // invalid value
return (6787.0 /((float)tmp - 3.0)) - 4.0;
}
void test_irdistance()
{
float myval;
myval = read_gp2d12_range(rx_irdistanalog);
Serial.print("ir val: ");
Serial.println(myval);
// LCD_Serial.write(12); // Clear
// LCD_Serial.print("ir val: ");
// LCD_Serial.print(myval, DEC); // First line
// LCD_Serial.write(13); // Form feed
}
Next, I deal with the Ultrasonic distance sensor (HC-SR04):
/*
HC-SR04 Ping distance sensor
VCC to Arduino 5v, GND to Arduino GND
Echo to Arduino pin 13, Trig to Arduino pin 12
more info at: http://goo.gl/kJ8G1
*/
float grab_ultrasonic()
{
int duration;
float distance;
digitalWrite(digtx_ToUltraTrig, LOW);
delayMicroseconds(2);
digitalWrite(digtx_ToUltraTrig, HIGH);
delayMicroseconds(10);
digitalWrite(digtx_ToUltraTrig, LOW);
duration = pulseIn(digrx_FrmUltraEcho, HIGH);
distance = (duration/2) / 29.1;
return distance;
}
void test_ultrasonic()
{
float mydist;
mydist = grab_ultrasonic();
if (mydist >= 200 || mydist <= 0){
Serial.println("Ultra: Out of range");
// LCD_Serial.write(12); // Clear
// LCD_Serial.print("Out of range");
// LCD_Serial.write(13); // Form feed
} else {
Serial.print("Ultra: ");
Serial.print(mydist);
Serial.println(" cm");
// LCD_Serial.write(12); // Clear
// LCD_Serial.print("Out of range");
// LCD_Serial.print(mydist, DEC);
// LCD_Serial.print(" cm");
// LCD_Serial.write(13); // Form feed
}
}
In order to utilize these, I have the following setups:
// run once, when the sketch starts
void setup()
{
// setup pins for serial interface to SSC
pinMode(rx_ToSSC, INPUT);
digitalWrite(tx_ToSSC, HIGH);
pinMode(tx_ToSSC, OUTPUT);
// set SSC serial interface speed
SSC_Serial.begin(9600);
// setup pins for serial interface to LCD
pinMode(rx_FrmLCD, INPUT);
digitalWrite(tx_ToLCD, HIGH);
pinMode(tx_ToLCD, OUTPUT);
// set LCD serial interface speed
LCD_Serial.begin(9600);
// initial clear and backlight for LCD
LCD_Serial.write(12); // Clear
LCD_Serial.write(17); // Turn backlight on
delay(5); // Required delay for response
// set SSC servos to initial state
ssc_cmnd_pwm(chan_ultraservo,6000);
ssc_cmnd_pwm(chan_camerapanservo,6000);
ssc_cmnd_pwm(chan_cameratiltservo,6000);
ssc_cmnd_pwm(chan_irdistservo,6000);
// set Ultrasonic Distance Sensor pins
pinMode(digtx_ToUltraTrig, OUTPUT);
pinMode(digrx_FrmUltraEcho, INPUT);
// setup our serial monitor
Serial.begin(9600);
// wait for settling to happen
delay(1000);
}
Now that I have the initial software coded, I have time to try them out and start to build the interfaces between the Arduino and the sensors/servos. Next up will be results of the testing, followed by dealing with the interface to the RPi.
Labels:
Arduino,
Robot SW,
Sensors,
Servo Control
Wednesday, March 27, 2013
Next Move - Get Arduino SW Working
Connections are in place and now I can settle down to figuring out the software in the Arduino, the breadboard connections for same, and the interface software from the RPi. I still have a number of interfaces that need to be tested:
1. the Ultrasonic Distance sensor needs to be wired up through the breadboard and the interface software needs to be written for the Arduino
2. the IR Distance sensor interface software needs to be written for the Arduino
3. the interface software for the two distance sensor servos needs to be written for the Arduino
4. the interface software for the two camera servos needs to be written for the Arduino
5. a control protocol, including response, needs to be thought up between the RPi and the Arduino and coded on both sides - ultimately this will be used by several Facades in the RPi software
6. a control protocol, including response, needs to be thought up between the RPi and the iRobot Create and coded in the RPi
7. afterwards I can concentrate on more higher level software, including the blackboard.
1. the Ultrasonic Distance sensor needs to be wired up through the breadboard and the interface software needs to be written for the Arduino
2. the IR Distance sensor interface software needs to be written for the Arduino
3. the interface software for the two distance sensor servos needs to be written for the Arduino
4. the interface software for the two camera servos needs to be written for the Arduino
5. a control protocol, including response, needs to be thought up between the RPi and the Arduino and coded on both sides - ultimately this will be used by several Facades in the RPi software
6. a control protocol, including response, needs to be thought up between the RPi and the iRobot Create and coded in the RPi
7. afterwards I can concentrate on more higher level software, including the blackboard.
Labels:
Arduino,
Blackboard,
Robot HW,
Robot SW
Saturday, March 23, 2013
Starting Up Robot SW Build
Over the next few months I will be posting updates on what is going on with the Robot SW build. I intend on building the software from a design at the top which will meet with some experimental software which drives different components at the bottom. Hopefully, they will meet somewhere in the middle correctly. The reason that I need to work on the bottom components is that I need to make sure that I have a sufficient set of facades that will talk to the hardware correctly. I am excited about the prospects and from here on out will try to give a play by play description of what I am up to. I will be using BoUML for the UML design and will document things by posting them here.
Labels:
Robot SW
Wednesday, March 6, 2013
Lower Level Classes for Experiments
In looking at the overall structure of what I want to do with experiments and such, I have come up with the following list of lower level classes that need to be developed:
1. SSC-32 Facade - [HW interface] this will be a collection of routines that will be able to get to the execution points for the SSC-32 servo controller. Specifics:
a. include routines to open / close the connection(s)
b. include routines to read analog and I/O for the digital aspects of the controller
c. include routines to set / read the current pulsewidth of the servo control. since the controls may be made through the Arduino, this facade needs to make sure of being able to proxy the connection to the SSC-32, and this might involve going through the network
2. Pololu Mini-Maestro Facade - [HW interface] this will be a collection of routines that will be able to get to the execution points for the Pololu Mini-Maestro (18) servo controller. Specifics:
a. include routines to open / close the connection(s)
b. include routines to read analog and I/O for the digital aspects of the controller
c. include routines to set / read the current pulsewidth of the servo control
d. since the controls may be made through the Arduino, this facade needs to make sure of being able to proxy the connection to the Pololu Mini-Maestro, and this might involve going through the network
3. Arduino Facade - [HW interface] this collection of routines will utilize the Firmata protocol initially and later will reflect a home grown protocol later on. The purpose is to be able to access most of the functionality of the Arduino through this interface.
a. general interfacing topics for the Arduino is at http://playground.arduino.cc/Main/InterfacingWithHardware.
b. the Firmata information is at http://firmata.org/wiki/Main_Page.
4. Video Facade - [HW interface] this collection of routines will focus on gathering a video stream and/or information about the video including snapshots and setting webcam parameters.
5. Robot Link Facade - [HW interface] this will be a collection of routines that will be able to move data between various CPUs within the Robot and will include connections to external PCs. The reasoning for having this Facade is to be able to grab sensor information from a remote source as necessary.
6. Ultrasound Distance Sensor Proxy - since I will not know in advance of where I will connect the Ultrasound sensor, this will utilize the underlying Facades to control and gather information re the sensor. I want to include calibration routines, setting the servos, reading the sensor, starting/ending sweeps, etc.
7. IR Distance Sensor Proxy - since I will not know in advance of where I will connect the IR distance sensor, this will utilize the underlying Facades to control and gather information re the sensor. I want to include calibration routines, setting the servos, reading the sensor, starting/ending sweeps, etc.
8. Camera Pan/Tilt Proxy - since I will not know in advance of where I will connect the pan and tilt servos, this will utilize the underlying Facades to control the servos. I would like to include setting the position of the servos and reading where the servos are, along with calibration routines.
9. Video Stream Proxy - this will pretty much be an interface point to the video stream, no matter where the webcam(s) are placed. This would include such things as streaming the video between CPUs within the Robot space.
10. Robot Arm Proxy - since I will not know in advance of where I will connect the robot arm servos, this will utilize the underlying Facades to control the servos. I would like to include setting the position of the servos, getting feedback on other sensors (pressure), and reading the servo positions, along with calibration routines.
I think this is a list that will keep me busy for a while getting ready for the main routines to execute the Robot software.
1. SSC-32 Facade - [HW interface] this will be a collection of routines that will be able to get to the execution points for the SSC-32 servo controller. Specifics:
a. include routines to open / close the connection(s)
b. include routines to read analog and I/O for the digital aspects of the controller
c. include routines to set / read the current pulsewidth of the servo control. since the controls may be made through the Arduino, this facade needs to make sure of being able to proxy the connection to the SSC-32, and this might involve going through the network
2. Pololu Mini-Maestro Facade - [HW interface] this will be a collection of routines that will be able to get to the execution points for the Pololu Mini-Maestro (18) servo controller. Specifics:
a. include routines to open / close the connection(s)
b. include routines to read analog and I/O for the digital aspects of the controller
c. include routines to set / read the current pulsewidth of the servo control
d. since the controls may be made through the Arduino, this facade needs to make sure of being able to proxy the connection to the Pololu Mini-Maestro, and this might involve going through the network
3. Arduino Facade - [HW interface] this collection of routines will utilize the Firmata protocol initially and later will reflect a home grown protocol later on. The purpose is to be able to access most of the functionality of the Arduino through this interface.
a. general interfacing topics for the Arduino is at http://playground.arduino.cc/Main/InterfacingWithHardware.
b. the Firmata information is at http://firmata.org/wiki/Main_Page.
4. Video Facade - [HW interface] this collection of routines will focus on gathering a video stream and/or information about the video including snapshots and setting webcam parameters.
5. Robot Link Facade - [HW interface] this will be a collection of routines that will be able to move data between various CPUs within the Robot and will include connections to external PCs. The reasoning for having this Facade is to be able to grab sensor information from a remote source as necessary.
6. Ultrasound Distance Sensor Proxy - since I will not know in advance of where I will connect the Ultrasound sensor, this will utilize the underlying Facades to control and gather information re the sensor. I want to include calibration routines, setting the servos, reading the sensor, starting/ending sweeps, etc.
7. IR Distance Sensor Proxy - since I will not know in advance of where I will connect the IR distance sensor, this will utilize the underlying Facades to control and gather information re the sensor. I want to include calibration routines, setting the servos, reading the sensor, starting/ending sweeps, etc.
8. Camera Pan/Tilt Proxy - since I will not know in advance of where I will connect the pan and tilt servos, this will utilize the underlying Facades to control the servos. I would like to include setting the position of the servos and reading where the servos are, along with calibration routines.
9. Video Stream Proxy - this will pretty much be an interface point to the video stream, no matter where the webcam(s) are placed. This would include such things as streaming the video between CPUs within the Robot space.
10. Robot Arm Proxy - since I will not know in advance of where I will connect the robot arm servos, this will utilize the underlying Facades to control the servos. I would like to include setting the position of the servos, getting feedback on other sensors (pressure), and reading the servo positions, along with calibration routines.
I think this is a list that will keep me busy for a while getting ready for the main routines to execute the Robot software.
Labels:
Robot SW
May Have Found an In-Between Code for Arduino
I had an interesting question for one of the engineers this morning. I asked him if he knew of any remote control for the Arduino in which a command could be sent to the Arduino for execution in lieu of programming the Arduino for a specific purpose. Interestingly enough, I found the Firmata project (http://firmata.org/wiki/Main_Page). This appears to be a protocol based upon the Midi control signals and is geared for micro-controllers of which the Arduino is one. There is a load for the Arduino for the protocol server, and a test program to run from a side computer. All software is available for both sides. In looking through the protocol, it looks like it might do everything that I need it to do for experimentation purposes. Obviously, I would program the Arduino to do specific tasks after I figure out what I need it to do.
Opened up a repository at GitHub
In light of my wanting to get ambitious, I have added a repository at GitHub (https://github.com/linuxweenie/rpiexperiments). I will have the link for this repository to the right of the blog and will be adding software as it becomes available.
Labels:
Robot SW
Thursday, February 28, 2013
Thinking about a distance sensor experiment
Last night I received another distance sensor, Ultrasonic Module HC-SR04 Distance Sensor For Arduino, from Amazon. This is a sensor that is a little more long distance than the IR sensor that I have which has a range of 1-12 inches. Using the two sensors, I now have a short distance and long distance resolution.
I was thinking that I might use the sensors in an experiment on top of the Create that would allow me to figure out the best way to use them. I would like to design a wall follower. Both of the sensors could be used to sweep back and forth, gathering distance/angle data and then take that data to build a model workup of the hallway or room that the Create was in. From that information you could develop a driving routine that would day allow you to follow a wall within 5 inches. Other parts of the routine would be able to react when something was placed in the way of the Create. It would have to make a decision to go around and what would be the best way to do that. I am thinking that the blackboard idea that I have proposed before would be the best option for doing this. My use of the Blackboard would require me to have an overall computational strategy. This is something that would need to be worked on.
I am still out on whether I should interface to an Arduino to control the sweeping sensors however. That seems to be a better way to accomplish the goal. Both of these sensors interface directly with the Arduino, whereas I would have to really think about how I would do this in the RPi. I do have more than one RPi in order to accomplish multiple computer type tasks, but a control processor may be more useful this time around. I could then concentrate on using the RPi to do the decision tasks.
I was thinking that I might use the sensors in an experiment on top of the Create that would allow me to figure out the best way to use them. I would like to design a wall follower. Both of the sensors could be used to sweep back and forth, gathering distance/angle data and then take that data to build a model workup of the hallway or room that the Create was in. From that information you could develop a driving routine that would day allow you to follow a wall within 5 inches. Other parts of the routine would be able to react when something was placed in the way of the Create. It would have to make a decision to go around and what would be the best way to do that. I am thinking that the blackboard idea that I have proposed before would be the best option for doing this. My use of the Blackboard would require me to have an overall computational strategy. This is something that would need to be worked on.
I am still out on whether I should interface to an Arduino to control the sweeping sensors however. That seems to be a better way to accomplish the goal. Both of these sensors interface directly with the Arduino, whereas I would have to really think about how I would do this in the RPi. I do have more than one RPi in order to accomplish multiple computer type tasks, but a control processor may be more useful this time around. I could then concentrate on using the RPi to do the decision tasks.
Tuesday, February 26, 2013
Going to try my hand at a cross-compiler for RPi
I was on the site at Kitware and got some instructions for setting up a cross-compiling platform. I am planning on trying out the instructions tonight and hopefully, I will be able to have a way to compile all of my goodies in the future. I have been longing for something to setup a meaningful toolchain so that I can compile the Robotic SW on a faster platform. That way I should be able to update things as necessary and get it running quickly instead of waiting for a couple of hours for a compile.
Labels:
Robot SW
Thursday, February 21, 2013
Starting to think of the Robotic SW that I will use
So far, I haven't said much about what software will run where in the Robot that I am working on. In the back of my mind, I am intending on learning a bit about some Artificial Intelligence (AI) techniques. The AI technique that I will be using is Blackboard. Imagine for a moment that you have several mathematicians sitting in front of a blackboard trying to solve a math problem. At any one time one of them will get up and put part of the resolution on the board. There is no communication between the mathematicians other than through the blackboard. There might be a secretary who puts the original problem on the board, and perhaps another secretary that records the solution when they are finished. But event the secretaries do not have to communicate with the mathematicians. This is kind of the idea of how a blackboard works.
In my Robot example there would be Knowledge Sources (those elements that do the thinking) that grab sensor information and place it on a global data area (the Blackboard). Other Knowledge Sources would try to make sense of the information and place updates onto the Blackboard which in turn triggers different Knowledge Sources to act. Sometimes the Blackboard information would change so that still different Knowledge Sources would output the information to actuators (wheels, servos, etc.) to act upon the information. In fact, which Knowledge Source goes next could be decided by different Knowledge Sources. This is kind of the idea that I will use.
The pattern for the Blackboard architecture will be based upon a paper, "Two complementary patterns to build multi-expert systems" by Philippe Lalanda. Additional papers will be added as I progress. I do know that whatever I come up with will have to have a distributed capability - my plan was use one RPi as a camera sensor/image processing element, a second RPi to control motors and servos, and a third RPi to do the thinking.
In my Robot example there would be Knowledge Sources (those elements that do the thinking) that grab sensor information and place it on a global data area (the Blackboard). Other Knowledge Sources would try to make sense of the information and place updates onto the Blackboard which in turn triggers different Knowledge Sources to act. Sometimes the Blackboard information would change so that still different Knowledge Sources would output the information to actuators (wheels, servos, etc.) to act upon the information. In fact, which Knowledge Source goes next could be decided by different Knowledge Sources. This is kind of the idea that I will use.
The pattern for the Blackboard architecture will be based upon a paper, "Two complementary patterns to build multi-expert systems" by Philippe Lalanda. Additional papers will be added as I progress. I do know that whatever I come up with will have to have a distributed capability - my plan was use one RPi as a camera sensor/image processing element, a second RPi to control motors and servos, and a third RPi to do the thinking.
Monday, February 18, 2013
Building the ROS Core and OpenCV
I was able to have Presidents Day off and my wife is out to lunch with my daughter. This is a perfect time to get up to date with my RPi things. I decided to load OpenCV and ROS onto one of the 16GB SD cards. I am currently following the instructions on http://www.ros.org/wiki/fuerte/Installation/Debian. The instructions are a little old, but do have some steps for a Wheezy build which is the current Raspbian build on the RPi website. Apparently I performed some of this setup earlier but I don't remember it. I think that I am going to have to start keeping a logbook in order to make sure that I don't repeat myself again. That is probably a good topic for an RPi Tip.
Subscribe to:
Posts (Atom)

