Control Sparki over Serial

Hello!

I have spent some time to write a serial wrapper for the Sparki. The aim was to give control over the Sparki to an external device as my Mac in my case via serial commands. I would like to give a python program control, maybe I will work on a wrapper on this side too…

It is not complete but it supports controlling the following parts of the Sparki:

[code]1.) SERVO
1/30/ to position at 30 degrees
1/-45/ to position at -45 degrees
Response: “svdg:value”

2.) DRIVE
2/1/2/ do drive forward 2cm outputs "mvf:2"
2/2/-1/ to drive backwards infinite outputs "mvb:-1"
2/3/-1/ to stop wheels (the third parameter is not used) outputs "mvstop:1"
Response: “mv[b|f|stop]:value”

3.) TURN
3/1/100/ turn left 100 degrees ouputs "turn:-100"
3/2/45/ turn right 45 degrees outputs "turn:45"
Response: “turn:value”

4.) GRIPPER
4/1/1000/ open the gripper for one second outputs "grop:1000"
4/2/500/ close the gripper for a half second outputs "grcl:500"
Response:“gr[op|cl]:value”

----------------------------------------SENSORS
5.) ULTRASONIC RANGE FINDER
5/ to get the pinged dist printed out
Response: “dist:value”

6.) INFRARED REFLECTANCE
6/ example output "ir1:167,ir2:958,ir3:970,ir4:909,ir5:884"
Response: “ir1:value,ir2:value,ir3:value,ir4:value,ir5:value”

7.) LIGHT SENSORS
7/ example output “light1:337,light2:308,light3:292”

8.) COMPASS
8/ example output “magx:967.84,magy:706.56,magz:249.32”

9.) ACCELEROMETER
9/ example output “acclx:-0.09,accly:-0.46,acclz:-9.87”[/code]

Those commands can be chained. So you could enter

to turn the servo and scan multiple times.

Enough talking. Here is the code:

#include <Sparki.h>

signed long serialdata; //holds the currently read serial data
int inbyte;
int loopcounter; //loopcounter
/*
This getserial() function is highly influenced by ROBOTMAN's forum post "Controlling An Arduino Via Serial"
 http://forums.trossenrobotics.com/tutorials/how-to-diy-128/complete-control-of-an-arduino-via-serial-3300/
 */
long getSerial()
{  
  inbyte = 0;
  serialdata = 0;
  if (Serial.available() > 0) {
    while (inbyte != '/')  
    { 

      inbyte = Serial.read();    
      //this probably could be done better, in this version signs are parsed into a boolean var
      boolean negative = false;
      if (inbyte == '-'){
        negative = true;
        inbyte = Serial.read();
      }
      if ( inbyte > 0 && inbyte != '/')    
      {  
        if (negative == false)
        {     
          serialdata = serialdata * 10 + inbyte - '0';   
        }
        else {
          serialdata = (serialdata * 10 + inbyte - '0') * -1;   
        }   
        //Serial.println(serialdata);    
      }  
    }    
    return serialdata;  

  }
}  


void setup()
{
  loopcounter=1;
  sparki.clearLCD();
  delay(250);
  sparki.println("Serial connect...");
  sparki.updateLCD();
  Serial.begin(9600);
  while (!Serial) ; //Wait for the serial to connect
  Serial.println("#Starting program");
  sparki.clearLCD();
  delay(250);

}

void loop()
{
  getSerial();
  switch(serialdata)
  {
  case 1: //servo positioniong "1/degrees/"
    {
      //fetch degrees
      getSerial();
      //sparki.print(serialdata);
      int servo_degree=serialdata;
      sparki.servo(servo_degree);
      delay(250);
      Serial.print("svdg:");
      Serial.println(servo_degree);
      sparki.print("svdg:");
      sparki.println(servo_degree);
      delay(250);
      break; 
    }
  case 2://DRIVE
    {
      //fetch direction
      getSerial();
      int direction = serialdata;
      //fetch distance to move
      getSerial();
      int distance =serialdata;
      if (direction == 1){
        distance > 0 ? sparki.moveForward(distance) : sparki.moveForward();
        delay(100);
        Serial.print("mvf:");
        Serial.println(distance);
        sparki.print("mvf:");
        sparki.println(distance);
        delay(250);
      }
      else if (direction == 2){
        distance > 0 ?  sparki.moveBackward(distance):sparki.moveBackward();
        delay(100);
        Serial.print("mvb:");
        Serial.println(distance);
        sparki.print("mvb:");
        sparki.println(distance);
        delay(250);
      }
      else if (direction = 3){
        sparki.moveStop();
        delay(100);
        Serial.println("mvstop:1");
        sparki.println("mvstop:1");
        delay(250);

      }
      break;
    }
  case 3: //TURN
    {
      //fetch direction
      getSerial();
      int direction = serialdata;

      //fetch degrees
      getSerial();
      int turn_degrees = serialdata;
      if (direction == 1  && turn_degrees > 0 ){
        sparki.moveLeft(turn_degrees);
        delay(500);
        Serial.print("turn:-");  
        Serial.println(turn_degrees);
        sparki.print("turn:-");  
        sparki.println(turn_degrees);
        delay(250);
      }
      else if(direction == 2 && turn_degrees > 0){
        sparki.moveRight(turn_degrees);

        delay(500);
        Serial.print("turn:");  
        Serial.println(turn_degrees);
        sparki.print("turn:");  
        sparki.println(turn_degrees);
        delay(250);
      }

      break;
    }
  case 4: //GRIPPER
    {
      getSerial();
      int direction = serialdata;

      getSerial();
      int duration = serialdata;
      if (direction == 1 && duration > 0){
        sparki.gripperOpen();
        delay(duration);
        sparki.gripperStop();
        Serial.print("grop:");  
        Serial.println(duration);
        sparki.print("grop:");  
        sparki.println(duration);
        delay(250);
      }
      else if (direction == 2 && duration > 0){
        sparki.gripperClose();
        delay(duration);
        sparki.gripperStop();
        Serial.print("grcl:");  
        Serial.println(duration);
        sparki.print("grcl:");  
        sparki.println(duration);
        delay(250);
      }

      break;
    }
  case 5: //ULTRASONIC RANGE FINDER
    {
      int distance = sparki.ping(); 
      Serial.print("dist:");
      Serial.println(distance);
      sparki.print("dist:");
      sparki.println(distance);
      break; 

    }
  case 6: //INFRARED REFLECTANCE
    {
      int edgeLeft   = sparki.edgeLeft();   // measure the left edge IR sensor
      int lineLeft   = sparki.lineLeft();   // measure the left IR sensor
      int lineCenter = sparki.lineCenter(); // measure the center IR sensor
      int lineRight  = sparki.lineRight();  // measure the right IR sensor
      int edgeRight  = sparki.edgeRight();  // measure the right edge IR sensor
      Serial.print("ir1:");
      Serial.print(edgeLeft);
      Serial.print(",ir2:");
      Serial.print(lineLeft);
      Serial.print(",ir3:");
      Serial.print(lineCenter);
      Serial.print(",ir4:");
      Serial.print(lineRight);
      Serial.print(",ir5:");
      Serial.println(edgeRight);

      sparki.print("ir1:");
      sparki.println(edgeLeft);
      sparki.print("ir2:");
      sparki.println(lineLeft);
      sparki.print("ir3:");
      sparki.println(lineCenter);
      sparki.print("ir4:");
      sparki.println(lineRight);
      sparki.print("ir5:");
      sparki.println(edgeRight);
      break;
    }

  case 7: //LIGHT SENSORS
    {
      int left   = sparki.lightLeft();   // measure the left light sensor
      int center = sparki.lightCenter(); // measure the center light sensor
      int right  = sparki.lightRight();  // measure the right light sensor
      Serial.print("light1:");
      Serial.print(left);
      Serial.print(",light2:");
      Serial.print(center);
      Serial.print(",light3:");
      Serial.println(right);

      sparki.print("light1:");
      sparki.println(left);
      sparki.print("light2:");
      sparki.println(center);
      sparki.print("light3:");
      sparki.println(right);
      break;
    }
  case 8: //COMPASS
    {
      float x  = sparki.magX();   // measure the magnetometer x-axis
      float y  = sparki.magY();   // measure the magnetometer y-axis
      float z  = sparki.magZ();   // measure the magnetometer z-axis
      Serial.print("magx:");
      Serial.print(x);
      Serial.print(",magy:");
      Serial.print(y);
      Serial.print(",magz:");
      Serial.println(z);
      sparki.print("magx:");
      sparki.println(x);
      sparki.print("magy:");
      sparki.println(y);
      sparki.print("magz:");
      sparki.println(z);
      break;
    }
  case 9: //ACCELEROMETER
    {
      float x  = sparki.accelX();   // measure the accelerometer x-axis
      float y  = sparki.accelY();   // measure the accelerometer y-axis
      float z  = sparki.accelZ();   // measure the accelerometer z-axis
      Serial.print("acclx:");
      Serial.print(x);
      Serial.print(",accly:");
      Serial.print(y);
      Serial.print(",acclz:");
      Serial.println(z);
      sparki.print("acclx:");
      sparki.println(x);
      sparki.print("accly:");
      sparki.println(y);
      sparki.print("acclz:");
      sparki.println(z);
      break;
    }
  }
  sparki.updateLCD();
  delay(100);
  loopcounter++;
}

My personal bluetooth setup is not working very well so i preferred Serial ouput via USB. If your setup is working better than mine and you bluetooth connects properly you could globally search replace “Serial.” with “Serial1.” to communicate this way.

The above is unoptimized “proof of concept”- code. If you think it’s ugly and/or wrong please post your comment.

Greetings,
Silmor.