Well. Get to do any cool stuff? Anyone have any sketches they’d like to share? Anyone using the bluetooth yet?
Not me, not yet. Working my way slowly through the examples that are there, while preparing my Mindstorms class for tomorrow (yeah, a Sunday class. sigh…)
So far, I’m only doing minimal changes to the remote software, like having the code for Melody instead of a single beep. Since I don’t use SparkiDuino, that turned out to be more troublesome than expected, as the file “pitches.h” was nowhere to be found. I had to re-install SparkiDuino, grab the file, de-install SparkiDuino, copy the file to my regular Arduino IDE. But hey, it works.
Hi,
I have started playing around with the bluetooth serial. Like all bluetooth serials (at least on Windows 7) they can be a bit tricky to setup and might require some restarts of the bluetooth chip and scanning services in the bluetooth device manager before it connects. The sketch acts on some basic keyboard commands via the bluetooth serial to start and stop a wall mapping program that outputs HTML code on the bluetooth serial output. The HTML code on the bluetooth serial output can be pasted in to an editor (starting from the -tag to the -tag) and saved as HTML to display the positions of the Sparki in a modern web browser. It’s far from accurate and somewhat messy but it’s something. 
[code]
#include <Sparki.h>
uint8_t loop_iter = 0;
int servo_pos[] = {-45,-30,-15,0,0,15,30,45};
int remote_code = 0;
char bt_input = 0;
int is_moving = 0;
/* Keep track of movement */
struct sparki_pos_type
{
float angle;
float distance;
float total_distance;
float x;
float y;
};
struct sparki_pos_type curr_pos;
struct sparki_color_type
{
int r;
int g;
int b;
};
struct sparki_color_type line_color = {0,0,0};
void setup()
{
// Need to re-initilize Bluetooth serial port for some reason…
Serial1.end();
Serial1.begin(9600);
Serial1.println(“Enter command:”);
Serial1.println(“w: Move Forward\r\ns: Stop\r\na: Rotate Right\r\nd: Rotate Left\r\nr: Reset position”);
pos_reset();
}
void loop() {
float heading;
int distance, light_left, light_center, light_right;
loop_iter++;
// Get bluetooth char and act
if(Serial1.available() > 0)
bt_input = bt_action();
// Get sensor readings
heading = get_heading();
distance = sparki.ping();
sparki.readAccelData();
light_left = sparki.lightLeft();
light_center = sparki.lightCenter();
light_right = sparki.lightRight();
// Display sensor readings
sparki.clearLCD();
sparki.print(“Heading(deg)= “);
sparki.println(heading);
sparki.print(“Distance(cm)= “);
sparki.println(distance);
sparki.println(“Accel(X,Y,Z)= “);
sparki.print(sparki.xAxisAccel);sparki.print(”,”);
sparki.print(sparki.yAxisAccel);sparki.print(”,”);
sparki.println(sparki.zAxisAccel);
sparki.println(“Light(L,C,R)= “);
sparki.print(light_left);sparki.print(”,”);
sparki.print(light_center);sparki.print(”,”);
sparki.println(light_right);
sparki.print("BT input char= ");
sparki.println(bt_input);
sparki.print(“Pos(x,y)= “);
sparki.print((int)curr_pos.x);sparki.print(”,”);sparki.print((int)curr_pos.y);
sparki.updateLCD();
// Wall mapper
if(is_moving) {
// Update position
curr_pos.distance += 0.5;
// Scan surroundings
sparki.servo(servo_pos[(loop_iter % (sizeof(servo_pos)/sizeof(int)))]);
// Check for obstruction
if((distance != -1) && (distance < 10)) {
sparki.beep();
sparki.moveBackward(10); // Function not accurate (it's using delay, I guess proper way would be to count steps instead?)
curr_pos.distance -= 5;
if(curr_pos.distance < 0)
curr_pos.distance = 0;
// Calculate new x, y and output SVG line
update_pos_draw_line();
sparki.moveRight(30*1.96); // Function not accurate (it's using delay, I guess proper way would be to count steps instead?)
curr_pos.angle -= 30;
if(curr_pos.angle < 0)
curr_pos.angle += 360;
curr_pos.total_distance += curr_pos.distance;
// Update color
line_color.r = loop_iter % 100;
line_color.g = (loop_iter * 2) % 100;
line_color.b = (loop_iter * 4) % 100;
sparki.RGB(line_color.r, line_color.g, line_color.b);
sparki_go();
}
}
delay(111);
}
void sparki_go()
{
is_moving = 1;
curr_pos.distance = 0;
sparki.moveForward();
}
void sparki_stop()
{
is_moving = 0;
sparki.moveStop();
}
void update_pos_draw_line()
{
float old_x = curr_pos.x;
float old_y = curr_pos.y;
curr_pos.x += cos ( curr_pos.angle * PI / 180.0 ) * curr_pos.distance;
curr_pos.y += sin ( curr_pos.angle * PI / 180.0 ) * curr_pos.distance;
bt_svg_line(old_x, old_y, curr_pos.x, curr_pos.y, line_color);
}
/*
- Filter min/max Magnometer samples and calculate average heading over sample period
*/
int curr_heading_index = 0;
float heading[] = {0,0,0,0,0};
int heading_len = (sizeof(heading)/sizeof(float));
float get_heading() {
float avg_heading = 0, min_heading = 360, max_heading = 0;
// Get heading and sample it
heading[curr_heading_index] = sparki.compass();
// Increment index
if(++curr_heading_index > heading_len)
curr_heading_index = 0;
// Accumulate all sample values
for(int i = 0; i < heading_len; i++) {
avg_heading += heading[i];
if(heading[i] < min_heading)
min_heading = heading[i];
if(heading[i] > max_heading)
max_heading = heading[i];
// Serial.print(heading[i]); Serial.print(" ");
}
// Serial.print("min = “); Serial.print(min_heading); Serial.print(”, max = "); Serial.print(max_heading);
// Deduct max and min values
avg_heading -= min_heading;
avg_heading -= max_heading;
// Calculate average
avg_heading = avg_heading / (heading_len - 2);
return avg_heading;
}
void pos_reset()
{
curr_pos.total_distance = curr_pos.x = curr_pos.y = 0;
curr_pos.angle = 90;
}
uint16_t svg_width = 1280;
uint16_t svg_height = 1024;
void bt_svg_begin()
{
Serial1.print("\r\n\r\n\r\n<svg width="");Serial1.print(svg_width);
Serial1.print("" height="");Serial1.print(svg_height);Serial1.println("">");
}
void bt_svg_end()
{
Serial1.println("\r\n\r\n");
}
void bt_svg_line(float start_x, float start_y, float end_x, float end_y, struct sparki_color_type color)
{
float origo_x = (svg_width/2);
float origo_y = (svg_height/2);
Serial1.print("<line x1=""); Serial1.print(origo_x+start_x);Serial1.print("" “);
Serial1.print(“y1=””); Serial1.print(origo_y-start_y);Serial1.print("" “);
Serial1.print(“x2=””); Serial1.print(origo_x+end_x);Serial1.print("" “);
Serial1.print(“y2=””); Serial1.print(origo_y-end_y);Serial1.print("" “);
Serial1.print(“style=“stroke:rgb(”);
Serial1.print(color.r2);Serial1.print(",");Serial1.print(color.g2);Serial1.print(”,”);Serial1.print(color.b*2);
Serial1.println(");stroke-width:2"/>");
#if 0 // Disable text
Serial1.print("<text x=""); Serial1.print(origo_x+end_x);
Serial1.print("" y=""); Serial1.print(origo_y-end_y);
Serial1.print("" fill=“black”>(");
Serial1.print(end_x); Serial1.print(", “); Serial1.print(end_y); Serial1.println(”)");
#endif
}
char bt_action() {
char bt_input = Serial1.read();
switch(bt_input){
case ‘w’:
case ‘W’: bt_svg_begin();
pos_reset();
sparki_go();
break;
case ‘s’:
case ‘S’: update_pos_draw_line();
bt_svg_end();
sparki_stop();
break;
case ‘a’:
case ‘A’: sparki.moveLeft();
break;
case ‘d’:
case ‘D’: sparki.moveRight();
break;
case ‘z’:
case ‘Z’: sparki.moveBackward();
break;
case ‘r’:
case ‘R’: pos_reset();
break;
default:
break;
}
return bt_input;
}[/code]
Just uploaded your code & had a play. It’s pretty slick
. Thanks for sharing.
Actually…I was only using the keys to drive it around. I was pretty damn happy with that. Now I’m after reading your post again & I can what now? I can map my room & display in web browser? Have to investigate. 
I’ve pasted the following from the serial monitor & made a html file with it as instructed…
But, I must be doing something wrong, because Safari on displays a web page with only the html code on it.
@Trevor
Looks ok to me. You must open it in a HTML5 compatible brower that allow inline SVG. I have tried it with Chome and Opera, but not Safari. It should work with latest Safari according to caniuse.com/svg-html5 .
Btw, I updated the code in my original post so that when you stop Sparki by striking the s key it outputs the last movement made.
Got it. Thanks Ingemar.
I had to make some changes to the way TextEdit was handling the file as per computerhope.com/forum/index … ic=72485.0
@CleoQc: I was at something similar yesterday. Noticed the pitches.h missing too (I’m in Arduino IDE). Found some stuff from a search online though:
Here’s some code I patched together. Apologies…my notes are all over the place!!! If somebody musically inclined on here wants to right some music…
[code]/*******************************************
Melody
This example shows how to make a short melody
with Sparki’s buzzer.
Code is based on example code for Sparki by www.arcbotics.com.
This example is based on the Arduino example
by Tom Igoe.
Modified by Trevor Moody with code from example at http://www.arduino.cc/en/Tutorial/PlayMelody#.Uv_iUXmnmuc
********************************************/
#include <Sparki.h> // include the sparki library
//#include “pitches.h” // include a list of pitches
#define c 3830 // 261 Hz
#define d 3400 // 294 Hz
#define e 3038 // 329 Hz
#define f 2864 // 349 Hz
#define g 2550 // 392 Hz
#define a 2272 // 440 Hz
#define b 2028 // 493 Hz
#define C 1912 // 523 Hz
// Define a special note, ‘R’, to represent a rest
#define R 0
// notes in the melody:
// MELODY and TIMING =======================================
// melody[] is an array of notes, accompanied by beats[],
// which sets each note’s relative length (higher #, longer note)
int melody[] = { d, R, d, e, d, g, f, R, R, d, R, d, e, d, a, g };
int noteDurations[] = { 8, 8, 2, 4, 8, 4, 16, 16, 16, 16, 8, 8 };
int MAX_COUNT = sizeof(melody) / 2; // Melody length, for looping.
//D / D * * E D G * F# / / D / D * * E D A * G / / D / D * * + D - B G F# * E / / + C / C * * - B G A * G",
// note durations: 4 = quarter note, 8 = eighth note, etc.:
void setup() {
//move all code from HERE to loop to play over & over again until it wrecks your head!!! 
// play each note in the arrays
for (int thisNote = 0; thisNote < 8; thisNote++) {
// calculate the note duration as 1 second divided by note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
sparki.beep(melody[thisNote],noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
sparki.noBeep();
}
//TO HERE
}
void loop() {
}[/code]
@Trevor:
Looks good, have to try it out. One cool thing would be I you could write the notes on the keyboard to play it in real time. Alternatively write a set of notes and once you press enter it plays the melody.
Check out to see how to read multiple keystrokes:
arduino.cc/en/Serial/ReadBytesUntil