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.