Labels

Thursday, March 28, 2013

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.