ArcTuRus v1.0 walkthrough build

I got distracted for a few years, okay, maybe 15, if I'm honest.  Wow, where did that time go?  I learnt a lot about computer software in all shapes and sizes, a lot about classic cars (as well as how to do MIG welding - it's not "that" much different to soldering, honest) and how to make things that keep your curiosity interested.

Back in 2000, I had money, too much of it, if memory serves me correctly.  It didn't last long, naturally.  But, the one thing that I did do right was to get hold of a SONY AIBO ERS-111 robot dog.  My word, it felt like the future had arrived.


Things happened and the AIBO got boxed back up and lived in the attic until a few weeks ago.  I then dusted off my 1/2 worked on Arduino "robots" (they'd been sitting on a spare desk for the past 3years) and I decided to see how much the technology had moved on.  Turns out, not really all that much, but enough to now be more interesting....

Keeping the AIBO in mind, I did a bit of research at DFRobot.com and made a few purchases, as well as the Sparkfun WiFi shield.  I reckoned that I could make a modern day AIBO using an Arduino and some shields, but not just match the AIBO, but to exceed it.















I ordered a few things from DFRobot.com:
  • RoMeo Arduino with motor controllers
  • PIXY object recognition camera
  • Ultrasonic sensor
  • SHARP IR sensor
  • Speech shield
  • WiDo IoT arduino

(The WiDo is for a future project connecting to Node.RED, so we'll ignore that for now)


I setup the PIXY camera to detect different objects:

 
The code output just shows the different objects being detected, outputting the X,Y co-ordinates and the width/heights too.  This can be used to work out if the object is getting closer or moving further away.  Something we'll come back too at a later date.


Here's me training the PIXY to detect multiple different coloured objects:

It's pretty amazing, 50 frames a second, the rate it detects moving these objects about is pretty awesome.  (I had to use the 'white thing' pen to help me to take the screenshot! hence my arm is in the photo!)


After playing with the PIXY for a while, I decided I should concentrate my efforts on the Ultrasonic and Infrared sensors.

The RoMeo arduino board has built in motor controllers, so I hooked them up so that if the sensors detected something within a specific distance, such as 15cm we would detect this and change the motor controller servos to move either left or right to avoid the detected object.




I then had a little play with the Speech shield


Due to the power demands and the number of pins used by the RoMeo arduino, using one board was proving to be problematic.  So, I decided to use two, instead.  One for the "higher brain functions" and one for the "lower brain functions".

I purchased some BLE (Bluetooth) shields and set them up to be master and slave and to auto-connect to each other on power up.
Why do this?  So, that the two arduinos can talk to each other.


RoMeo #1 will do the sensor detecting, when it is within range a call is made to the BLE shield to make the speech shield say something (and trigger the motor controller servo to move left or right).  At the moment, RoMeo #1 still controls the motor controller servos, for v1.1 of the code, I'll switch it to be Romeo #2 that does the speech and motor controllers

A side effect of using the BLE shields is that I could connect my Android Nexus 7 tablet to the BLE shield and test that it worked okay before connecting the sensing RoMeo #1 arduino.


I setup the BLE devices so that one was a Master and one was a Slave.  You do this by calling AT commands to the devices:

BLE Master Code:

#include <SoftwareSerial.h>  
#define RxD 3
#define TxD 2
SoftwareSerial BlueToothSerial(RxD,TxD);

void Test_BlueTooth()
{
   unsigned char t=0;
   String RXD = "";
   Serial.println("Test BlueTooth ...");
   BlueToothSerial.print("AT\r\n");  
   delay(100);
   while(BlueToothSerial.available()>0)
   {    
      RXD +=  char( BlueToothSerial.read() );
      delay(1);
   } 
   do{
     t++;
     delay(400);
     Serial.println("Test Failed ! Retrying ...");
   }while( ((RXD[0]!='O')&&(RXD[1]!='K'))&&(t<5));  
   if(t<5) Serial.println("Test Successful !\r\n");
   else { Serial.println("Retry Failed !"); while(1); }
}

void sendBlueToothCommand(char *Command)
{
  BlueToothSerial.print(Command);
  Serial.print(Command); 
  delay(100);
  while(BlueToothSerial.available())
  {    
     Serial.print(char(BlueToothSerial.read())); 
  }
}

void setupBlueTooth()
{
  Serial.println("Bluetooth Initialization ...");      
  sendBlueToothCommand("AT+NAME=Master\r\n");
  sendBlueToothCommand("AT+ROLE=1\r\n");// 1:Master   0:Slave
  sendBlueToothCommand("AT+PSWD=1234\r\n");
  sendBlueToothCommand("AT+UART=38400,0,0\r\n");
  sendBlueToothCommand("AT+CMODE=1\r\n");
  sendBlueToothCommand("AT+INIT\r\n");
  sendBlueToothCommand("AT+PAIR=2015,4,72450,10\r\n");//slave address 
  for(int i=0;i<5;i++) delay(1000);
  BlueToothSerial.flush();
  Serial.println("Bluetooth Initialized Successfully !\r\n");
}

void setup()
{
   Serial.begin(38400);     
   BlueToothSerial.begin(38400); 
   delay(500);
   Test_BlueTooth();  
   setupBlueTooth();
}

void loop()
{
  if(BlueToothSerial.available())
  {
     Serial.print(char(BlueToothSerial.read()));
  }
  if(Serial.available())
  {
     BlueToothSerial.print(char(Serial.read()));
  }      
}

The AT+PAIR command binds the BLE master to the BLE slave mac address.

BLE Slave Code:

#include <SoftwareSerial.h>  
#include <SpeechSynthesis.h>

#define RxD 7
#define TxD 6
SoftwareSerial BlueToothSerial(RxD,TxD);

char flag=1;
byte ssr[500];//define a character string

void Test_BlueTooth()
{
   unsigned char t=0;
   String RXD = "";
   Serial.println("Test BlueTooth ...");
   BlueToothSerial.print("AT\r\n");  
   delay(100);
   while(BlueToothSerial.available()>0)
   {    
      RXD +=  char( BlueToothSerial.read() );
      delay(1);
   } 
   do{
     t++;
     delay(400);
     Serial.println("Test Failed ! Retrying ...");
   }while( ((RXD[0]!='O')&&(RXD[1]!='K'))&&(t<5));  
   if(t<5) {
    Serial.println("Test Successful !\r\n");
   } else {
    Serial.println("Retry Failed !"); 
    while(1); 
   }
}

void sendBlueToothCommand(char *Command)
{
  BlueToothSerial.print(Command);
//  Serial.print(Command); 
  delay(100);
  while(BlueToothSerial.available())
  {    
//     Serial.print(char(BlueToothSerial.read())); 
  }
}

void setupBlueTooth()
{
//  Serial.println("Bluetooth Initialization ...");      
  sendBlueToothCommand("AT+NAME=Elechouse\r\n");
  sendBlueToothCommand("AT+ROLE=1\r\n");
  sendBlueToothCommand("AT+CMODE=0\r\n");
  sendBlueToothCommand("AT+PSWD=1234\r\n");
  sendBlueToothCommand("AT+UART=9600,0,0\r\n");
  delay(500);
  Serial.println("Bluetooth Initialized Successfully !\r\n");
  do{
    if(Serial.available())
    {
      if( Serial.read() == 'S')
      {
        sendBlueToothCommand("AT+RESET\r\n");
        flag = 0;
      }
    }
  }while(flag);
}

int recvTotal = 0;
int blTotal   = 0;
String textFromTablet;

void setup()
{
   Serial.begin(38400);     
   BlueToothSerial.begin(38400); 
//   Serial.begin(9600);     
//   BlueToothSerial.begin(9600); 
   delay(500);
   Test_BlueTooth();  
   setupBlueTooth();
}

void loop()
{
    //if type in BL Monitor on Android Terminal receive this data and show in Serial Monitor
    if(BlueToothSerial.available())
    {
      delay(10);
//      Serial.print(char(BlueToothSerial.read()));
      textFromTablet = BlueToothSerial.readString();
//      Serial.println("string=");Serial.println(textFromTablet);
/*      
      int str_len = textFromTablet.length()+1;
      char char_array[str_len];
      textFromTablet.toCharArray(char_array, str_len);
      saySomething(char_array);
*/      
      saySomething("hello");
    }

    //if type in Serial Monitor send this data to the Android Terminal
//    if(Serial.available())
//    {
////      blTotal = Serial.read();
      
//      BlueToothSerial.print(char(Serial.read()));
////      BlueToothSerial.print("BL received: ");
////      BlueToothSerial.println(blTotal, DEC);
//    }      
    
}

void saySomething(char* message) {
    Serial.println(message);
/*    
    SpeechSynthesis.buf_init(ssr);//Clear the buffer
    SpeechSynthesis.English(ssr,4,"7");
    SpeechSynthesis.English(ssr,6,message);
    SpeechSynthesis.Espeaking(0,6,4,ssr);//Executive commands above, "0" is synthesis command; "8" select speaker; "4" speech function  

    while(Serial.read()!=0x41)//waiting synthesis complete
    {}
    while(Serial.read()!=0x4F)//waiting play complete
    {}   
*/  
}

Once the two BLE devices have been configured, they will bind together on startup and that's all there is to it.  We can now use BlueToothSerial to send and receive between the two devices.




RoMeo #1 currently uses the following PINS:

Analog:
1 = SHARP IR Sensor
2 = RoMeo button to start the robot

Digital:
2,3 = BlueTooth communication
4,5,6,7 = motor controller servos
10 = I believe the PIXY uses this PIN(?)
11 = Ultrasonic PING sensor

Below, the code follows the following format:
Connect the ESP8266WiFi shield to the internet
Call out to the BLE speech shield to say "Press Start button"

Once the "Start button" has been pressed, we poll every 1250ms and read the Ultrasonci/PING sensor and SHARP IR sensor to see if any values have been detected and if those values are within a close range (5-20cm away).
If a value is detected then we either move left or move right, depending on which sensor detects a value.
We also check the PIXY to see if it has detected anything 'pink' and if it detects something 'pink' it speeds up the motor controllers.  Eventually, I'll re-code this so that it reads the X/Y/Width/Height values and gives_chase() to keep the 'pink' object within a specific range.
If a detected value is less than 5cm then we stop the motor controllers as we're about to hit something!

At the moment, we don't do anything with the internet connection, my plan is to perform a HTTP POST to send the detection data to a Web Server and store that data.  This will allow me to write a web app that will present the 'mapping' of the environment that the robot has wandered through.  It'll also mean that another robot could potentially connect to the Web Server and download the data and it can educate itself to know the environment rather than having to learn it from scratch.  Now, that opens up some interesting concepts to think about.  Awareness of the environment and only learning and sharing new information that can be shared to the collective brain..... all sounds a bit Borg-ish to me, but hey-ho, I'll fit a kill-switch that we can turn off :-)


Arduino Code

RoMeo #1

#include <NewPing.h>
#include <elapsedMillis.h>
#include <SPI.h>  
#include <Pixy.h>
#include <SoftwareSerial.h> 
#include <SparkFunESP8266WiFi.h>

//advance X1 speed
//:loop
//  detect PING/IR Sensor values
//  if PING <= 20cm stop, turnR A1
//  if IR   <= 20cm stop, turnL A2
//  advance X2 speed
//

const char mySSID[] = "virginmedia";
const char myPSK[] = "somepassword";
const char destServer[] = "example.com";
const String httpRequest = "GET / HTTP/1.1\nHost: example.com\nConnection: close\n\n";

boolean debugMode         = false;  //if true outputs to Serial Monitor
boolean pixyEnabled       = false;  //allows ability to not use PIXY
boolean keepMovingForward = false;

//Standard PWM DC control PINS  //For Romeo v1.1
int E1 = 5;    //M1 Speed Control
int E2 = 6;    //M2 Speed Control
int M1 = 4;    //M1 Direction Control
int M2 = 7;    //M1 Direction Control
int  adc_key_val[5] ={30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1; 

#define RxD 3
#define TxD 2
SoftwareSerial BlueToothSerial(RxD,TxD);

#define STARTpin A2                   //StartButton Pin
#define SHARPpin A1                   //IRPin Analog
#define PINGInterval 1250             //milliseconds to wait for checking PING and IR Sensors
const int triggerPingPin1 = 11;        //PingPin
const int maxDistance     = 200;      //cm
const int triggerDetectDistance = 20; //cm
const int triggerStopDistance   = 5;  //cm

elapsedMillis PINGTIMER;
NewPing sonar1(triggerPingPin1, triggerPingPin1, maxDistance);
Pixy pixy;                            //doesn't mention it anywhere but I think this takes PIN 10

// Convert ADC value to key number
int get_key(unsigned int input)
{   
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {  
      return k;  
    }
  }
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

void setup(void) 
  Serial.begin(9600);
  BlueToothSerial.begin(38400);
  delay(100);
  BlueToothSerial.print("Starting Robot");
  delay(1000);
  
  if(debugMode) { Serial.println("Starting Robot"); }
  //have to init the WiFi shield BEFORE anything else else it doesn't work
  initializeESP8266();  //init shield
  connectESP8266();     //connect to WiFi network

  if(debugMode) {
      displayConnectInfo(); //show the IP Address assigned
//      clientDemo();
  }
  //init the IR Analog PIN
  pinMode(SHARPpin, INPUT);
  //init the PINS for the wheels
  for(int i=4;i<=7;i++) {
    pinMode(i, OUTPUT);  
  }
  //init the PIXY camera
  if(pixyEnabled) { pixy.init(); }
  
  delay(1000);
  BlueToothSerial.print("Press START button");
  BlueToothSerial.print(" to activate robot");
  
  //we'll use the debug LED to output a heartbeat - just to know we're still alive
  pinMode(13, OUTPUT);


void loop(void) 
{  
  adc_key_in = analogRead(7);    // read the value from the sensor  

  digitalWrite(13, HIGH);

  /* get the key */
  key = get_key(adc_key_in);    // convert into key press
  if (key != oldkey) {   // if keypress is detected
    delay(50);      // wait for debounce time
    adc_key_in = analogRead(7);    // read the value from the sensor  
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey) {         
      oldkey = key;
      if (key >=0){
        Serial.println(adc_key_in, DEC);
        if(key == 1) { //up
          //start the robot moving
          keepMovingForward = true;
          advance(100,100);          
        }
        if(key == 2) { //down
          //manually stop the robot
          keepMovingForward = false;
          stop();
        }
        if(key == 0) { //right
          turn_R(100,100);
        }
        if(key == 3) { //left
          turn_L(100,100);
        }
        if(key == 4) { //stop
          stop();
        }
      }
    }
  }
  
  if(keepMovingForward) {
    //we're ineterested in the PING))) but only every 1250ms
    if (PINGTIMER > PINGInterval ) {
        PINGTIMER -= PINGInterval; //reset the timer
  //Serial.print("resetting timer="); Serial.println(PINGTIMER);
  
        digitalWrite(13, LOW);
  
        //Read PING Sensor value
        unsigned int uS = sonar1.ping(); //send ping, get ping time in microseconds uS
        unsigned int pingDistance = uS / US_ROUNDTRIP_CM; //convert time to distance
  
        //Read SHARP IR Sensor value
        uint16_t value  = analogRead (SHARPpin);
        double irDistance = get_IR (value); //Convert the analog voltage to the distance
        //Serial.println(value);  analog value reading
  
        if(debugMode) {
            Serial.print("PING Distance (cm): "); Serial.println(pingDistance);
            Serial.print("IR Distance   (cm): "); Serial.println(irDistance);
        }
  
        //sometimes get false readings of 0, so avoid this with the if
        if(pingDistance > triggerStopDistance && pingDistance <= triggerDetectDistance) {
            stop();
            turn_right("PING detected object, move right");
        } else if(pingDistance != 0 && pingDistance <= triggerStopDistance) {
            //we're about to hit the wall!
            BlueToothSerial.print("I am about to hit something, so I will now stop");
            keepMovingForward = false;
            stop();
        }
        if(irDistance > triggerStopDistance && irDistance <= triggerDetectDistance) {
            turn_left("IR detected object, move left");
        } else if(irDistance != 0 && irDistance <= triggerStopDistance) {
            //we're about to hit the wall!
            BlueToothSerial.print("I am about to hit something, so I will now stop");
            keepMovingForward = false;
            stop();
        }
        
    }  
  
    //allow us to not use the PIXY - could allocate to an ANALOG button trigger?
    if(pixyEnabled) {
      static int i = 0;
      int j;
      uint16_t blocks;
      char buf[32]; 
      blocks = pixy.getBlocks();
      if (blocks)
      {
        i++;    
        if (i%50==0)
        {
          if(debugMode) { sprintf(buf, "Detected %d:\n", blocks);
          Serial.print(buf); }
          for (j=0; j<blocks; j++)
          {
            if(pixy.blocks[j].signature == 3) { //only interested in the PINK objects
              if(debugMode) { sprintf(buf, "  block %d: ", j);
              Serial.print(buf); }
              //Print out ALL the info
              //pixy.blocks[j].print();
    //          pixy.blocks[j].x;      //0 to 319
    //          pixy.blocks[j].y       //0 to 199
              uint16_t width  = pixy.blocks[j].width;   //1 to 320
              uint16_t height = pixy.blocks[j].height;  //1 to 200
              if((width >= 150 && width <= 175) && (height >= 100 && height <= 135)) {
                //the PINK object is about 5/10cm away and quite close to PIXY
                give_chase("PINK Object is very close, let's chase it");
              }
            }
          }
        }
      }  
    }
  
    //keep moving forward but only if we are safe to do so
    if(keepMovingForward) {
      advance(100,100); //100 left, 100 right    
    }
  }
  
}

void turn_left(char* message) {
    BlueToothSerial.print(message);
    if(debugMode) { Serial.println(message); }
    turn_L(50,100);
    delay(500);
}

void turn_right(char* message) {
    BlueToothSerial.print(message);
    if(debugMode) { Serial.println(message); }
    turn_R(100,50);
    delay(500);
}

void run_away(char* message) {
    BlueToothSerial.print(message);
    if(debugMode) { Serial.println(message); }
    back_off(255,200);
    delay(500);
    stop();  
}

void give_chase(char* message) {
    BlueToothSerial.print(message);
    if(debugMode) { Serial.println(message); }
    advance(255,200);
    delay(500);
    stop();  
}

//return distance (cm)
double get_IR (uint16_t value) {
    if (value < 16)  value = 16;
    return 2076.0 / (value - 11.0);
}

void stop(void)                    //Stop
{
  digitalWrite(E1,LOW);   
  digitalWrite(E2,LOW);      
}   

void advance(char a,char b)        //Move Forward
{
  analogWrite (E1,a);              //PWM Speed Control
  digitalWrite(M1,HIGH);    
  analogWrite (E2,b);    
  digitalWrite(M2,HIGH);
}  

void back_off (char a,char b)      //Move Backward
{
  analogWrite (E1,a);
  digitalWrite(M1,LOW);   
  analogWrite (E2,b);    
  digitalWrite(M2,LOW);
}

void turn_L (char a,char b)        //Turn Left
{
  analogWrite (E1,a);
  digitalWrite(M1,LOW);    
  analogWrite (E2,b);    
  digitalWrite(M2,HIGH);
}

void turn_R (char a,char b)        //Turn Right
{
  analogWrite (E1,a);
  digitalWrite(M1,HIGH);    
  analogWrite (E2,b);    
  digitalWrite(M2,LOW);
}

void doRoutine1() {
  advance (255,200);
  delay(1000);
  back_off(255,200);
  delay(1000);
  stop();
}

void doRoutine2() {
  advance (255,200);
  delay(1000);
  turn_R(100,100);
  delay(1000);
  advance (255,200);
  delay(1000);
  turn_R(100,100);
  delay(1000);
  advance (255,200);
  delay(1000);
  turn_R(100,100);
  delay(1000);
  advance (255,200);
  stop();
}

void initializeESP8266()
{
  // esp8266.begin() verifies that the ESP8266 is operational
  // and sets it up for the rest of the sketch.
  // It returns either true or false -- indicating whether
  // communication was successul or not.
  // true
  int test = esp8266.begin();
  if (test != true)
  {
    Serial.println(F("Error talking to ESP8266."));
    return;
  }
  Serial.println(F("ESP8266 Shield Present"));
}

void connectESP8266()
{
  // The ESP8266 can be set to one of three modes:
  //  1 - ESP8266_MODE_STA - Station only
  //  2 - ESP8266_MODE_AP - Access point only
  //  3 - ESP8266_MODE_STAAP - Station/AP combo
  // Use esp8266.getMode() to check which mode it's in:
  int retVal = esp8266.getMode();
  if (retVal != ESP8266_MODE_STA)
  { // If it's not in station mode.
    // Use esp8266.setMode([mode]) to set it to a specified
    // mode.
    retVal = esp8266.setMode(ESP8266_MODE_STA);
    if (retVal < 0)
    {
      Serial.println(F("Error setting mode."));
      return;
    }
  }
  Serial.println(F("Mode set to station"));

  // esp8266.status() indicates the ESP8266's WiFi connect
  // status.
  // A return value of 1 indicates the device is already
  // connected. 0 indicates disconnected. (Negative values
  // equate to communication errors.)
  retVal = esp8266.status();
  if (retVal <= 0)
  {
    Serial.print(F("Connecting to "));
    Serial.println(mySSID);
    // esp8266.connect([ssid], [psk]) connects the ESP8266
    // to a network.
    // On success the connect function returns a value >0
    // On fail, the function will either return:
    //  -1: TIMEOUT - The library has a set 30s timeout
    //  -3: FAIL - Couldn't connect to network.
    retVal = esp8266.connect(mySSID, myPSK);
    if (retVal < 0)
    {
      Serial.println(F("Error connecting"));
    }
  }
}

void displayConnectInfo()
{
  char connectedSSID[24];
  memset(connectedSSID, 0, 24);
  // esp8266.getAP() can be used to check which AP the
  // ESP8266 is connected to. It returns an error code.
  // The connected AP is returned by reference as a parameter.
  int retVal = esp8266.getAP(connectedSSID);
  if (retVal > 0)
  {
    BlueToothSerial.print("Connected to Weye Feye");
    delay(500);
    Serial.print(F("Connected to: "));
    Serial.println(connectedSSID);
  }

  // esp8266.localIP returns an IPAddress variable with the
  // ESP8266's current local IP address.
  IPAddress myIP = esp8266.localIP();
  Serial.print(F("My IP: ")); Serial.println(myIP);
  BlueToothSerial.print("IP Address is");
  BlueToothSerial.print(myIP);
  
}

void clientDemo()
{
  // To use the ESP8266 as a TCP client, use the 
  // ESP8266Client class. First, create an object:
  ESP8266Client client;

  // ESP8266Client connect([server], [port]) is used to 
  // connect to a server (const char * or IPAddress) on
  // a specified port.
  // Returns: 1 on success, 2 on already connected,
  // negative on fail (-1=TIMEOUT, -3=FAIL).
  int retVal = client.connect(destServer, 80);
  if (retVal <= 0)
  {
    Serial.println(F("Failed to connect to server."));
    return;
  }

  // print and write can be used to send data to a connected
  // client connection.
  client.print(httpRequest);

  // available() will return the number of characters
  // currently in the receive buffer.
  while (client.available())
    Serial.write(client.read()); // read() gets the FIFO char
  
  // connected() is a boolean return value - 1 if the 
  // connection is active, 0 if it's closed.
  if (client.connected())
    client.stop(); // stop() closes a TCP connection.
}



RoMeo #2 currently uses the following PINS:

Digital:
6,7 = BlueTooth communication

Below, the code follows the following format:
The BLE shield listens for commands being sent to it.
Upon receiving data, it passes that data to the Speech shield that 'speaks' the message.

In the next version, it will then activate the motor controllers to move the robot.

RoMeo #2

#include <SoftwareSerial.h>  
#include <SpeechSynthesis.h>

#define RxD 7
#define TxD 6
SoftwareSerial BlueToothSerial(RxD,TxD);
byte ssr[500];//define a character string
String textFromTablet;

void setup()
{
   Serial.begin(57600);     
   BlueToothSerial.begin(57600); 
   delay(500);
   Serial.println("Setup completed");
}

void loop()
{
  //constantly polling to see if we have received anything from the BLE connection
    if(BlueToothSerial.available())
    {
      delay(10);
//      Serial.print(char(BlueToothSerial.read()));
      //instead of reading a char at a time, read the whole String
      //but to use SpeechSynthesis.English it needs a char array
      //so convert it like this
      textFromTablet = BlueToothSerial.readString();      
      int str_len = textFromTablet.length()+1;
      char char_array[str_len];
      textFromTablet.toCharArray(char_array, str_len);
      
      saySomething(char_array);
    }
    //only useful in debugging, no use when connected to Speech Shield
//    if(Serial.available())
//    {
//      BlueToothSerial.print(char(Serial.read()));
//    }      
}

void saySomething(char* message) {
  Serial.print("ECHO:");Serial.println(message);
  
    SpeechSynthesis.buf_init(ssr);//Clear the buffer
    SpeechSynthesis.English(ssr,4,"7");
    SpeechSynthesis.English(ssr,6,message);
    SpeechSynthesis.Espeaking(0,6,4,ssr);//Executive commands above, "0" is synthesis command; "8" select speaker; "4" speech function  

    while(Serial.read()!=0x41)//waiting synthesis complete
    {}
    while(Serial.read()!=0x4F)//waiting play complete
    {}   
}


That's RoMeo #2 on the left connected to the speaker.  RoMeo #1 is on the right connected to the sensors and the 'red' WiFi shield.

You'll note that there is a robot base on its side....that was the 'old' robot chassis.  I decided to combine the two chassis structures together.  I removed the servos and wheels from the new chassis and placed them onto the old chassis.  This involved some use of a dremel  :-)


Then it was time to rebuild the chassis, place RoMeo # 1 and #2 in different levels and stash the battery containers into the lower levels to balance out the weight distribution of the chassis:



Voila!  We now have a robot that can run from remote batteries and can navigate its way around its environment.

It's only version 1.0 for now, but it's a good start.


Good old eBay allowed me to order a couple of 'spares-or-repair' Doctor Who K9 models and hopefully I'll be able to use one of these as a container for the robot above!


There will be much more to come, I assure you.  I'm not leaving it 15 or 3 years again....





Here's my SONY AIBO ERS-111 charging up......



Comments