9600 bps

We were able to get to 19200 baud with PC Audio->FT232->PC and 9600 baud Android->FT232->PC. The circuit is very simple using a single opto isolator. Android at 9600 is a bit unstable, 4800 is very very stable. We are looking at possible reasons why.  Next, reading data and dynamically sending data.

image

image

Jack Update

Got a fire lit under our butts and we have been wiring like crazy!  First, we are now over 100 twitter posts and 300 twitter followers.. Buzz and Facebook, you guys are way behind!

Second, we have finally gotten a stable 300 baud transmission test working with a simple opamp comparator to shift 1.2v logic to 4.5v logic!!!!!!!!!!

 

IMG_1254

 

 

So lets start off with the sketch.  This code just decodes serial ‘r’ and turns on the red portion of our tri color LED etc.

void setup() {
  Serial.begin(300);
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  digitalWrite(2,HIGH);
  digitalWrite(3,HIGH);
  digitalWrite(4,HIGH);
}
void loop() {
  byte val;
  if(Serial.available())
  {
    val=Serial.read();
    digitalWrite(2,HIGH);
    digitalWrite(3,HIGH);
    digitalWrite(4,HIGH);
    if(val==’r'){digitalWrite(2,LOW);}
    if(val==’g'){digitalWrite(3,LOW);}
    if(val==’b'){digitalWrite(4,LOW);}
   
  }
}

 

Our circuit uses an LM324 opamp configured as a comparator (diagram coming soon). 

I’m using C# to generate WAV files at 44100 Khz.  44100 is standard PCM/WAV sampling frequency.  The only baud that divides evenly is 300bps.  We will going for 9600, but we may have to actually write an android program to do that as any interval of 9600 seems to cause the music player to crash.

IMG_1242[5]

 

Below is the main WAV generation program.  We are using an open source library to generate the actual WAV file.  As you can see I generate a WAV file for just about anything. Some of this code was actually ported from the software serial library on the arduino!

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using WaveLibrary;

namespace WavGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            int rate = 44100;
            int baudrate = 300;
            int samples = rate / baudrate;

            WaveFile f = new WaveFile(1, 8, rate);
            List<byte> data = new List<byte>();
            for (int i = 0; i < 10; i++)
            {
                data.AddRange(BuildString("*****************\r\n", samples));
                data.AddRange(BuildString("*****************\r\n", samples));
                data.AddRange(BuildString("www.flakelabs.com\r\n", samples));
                data.AddRange(BuildString("*****************\r\n", samples));
                data.AddRange(BuildString("*****************\r\n", samples));

                data.AddRange(BuildString("www.sparkfun.com\r\n", samples));
                data.AddRange(BuildString("www.hackaday.com\r\n", samples));
                data.AddRange(BuildString("www.makezine.com\r\n", samples));
                data.AddRange(BuildString("www.xkcd.com\r\n", samples));
            }
            f.SetData(data.ToArray());
            f.WriteFile("FLAKELABS.wav");

            f = new WaveFile(1, 8, rate);
             data = new List<byte>();
            data.AddRange(BuildBit(true, samples*100));
            for (byte i = 0; i < 255; i++)
            {
                data.AddRange(BuildByte(i, samples));
            }
            data.AddRange(BuildBit(true, samples*100));
            f.SetData(data.ToArray());

            f.WriteFile("count.wav");

            List<byte> cdata = new List<byte>();

            f = new WaveFile(1, 8, rate);
            cdata.AddRange(BuildBit(true, samples * 100));
            for (int i = 0; i < 100; i++)
            {
                cdata.AddRange(BuildChar('r', samples));
                cdata.AddRange(BuildBit(true, samples * 5));
            }

            cdata.AddRange(BuildBit(true, samples * 100));
            f.SetData(cdata.ToArray());
            f.WriteFile("red.wav");
            cdata.Clear();

            f = new WaveFile(1, 8, rate);
            cdata.AddRange(BuildBit(true, samples * 100));
            for(int i=0;i<100;i++)
            {
                cdata.AddRange(BuildChar('g',samples));
                cdata.AddRange(BuildBit(true, samples * 5));
            }

            cdata.AddRange(BuildBit(true, samples * 100));
            f.SetData(cdata.ToArray());
            f.WriteFile("green.wav");
            cdata.Clear();

            f = new WaveFile(1, 8, rate);
            cdata.AddRange(BuildBit(true, samples * 100));

            for(int i=0;i<100;i++)
            {
                cdata.AddRange(BuildChar('b',samples));
                cdata.AddRange(BuildBit(true, samples * 5));
            }

            f.SetData(cdata.ToArray());
            cdata.AddRange(BuildBit(true, samples * 100));

            f.WriteFile("blue.wav");
            cdata.Clear();

        }

        static byte[] BuildString(string s,int samples)
        {
            List<byte> data = new List<byte>();

            data.AddRange(BuildBit(true,samples));
            data.AddRange(BuildBit(true, samples));
            data.AddRange(BuildBit(true, samples));
            foreach (char c in s)
            {
                data.AddRange(BuildChar(c,samples));
            }
            data.AddRange(BuildBit(true, samples));
            data.AddRange(BuildBit(true, samples));
            data.AddRange(BuildBit(true, samples));

            return data.ToArray();
        }

        static byte[] BuildChar(char c, int samples)
        {
            return BuildByte((byte)c, samples);
        }

        static byte[] BuildByte(byte b, int samples)
        {
            Console.Write("Printing {0} {1}  ", b, (int)b);
            List<byte> data = new List<byte>();
            data.AddRange(BuildBit(false, samples));//start bit

            byte mask = 0;
            for (byte i = 0; i < 8; i++)
            {
                mask = (byte)Math.Pow(2, i);
                if ((b & mask) == mask)
                {
                    Console.Write("1");
                    data.AddRange(BuildBit(true, samples));
                }
                else
                {
                    Console.Write("0");
                    data.AddRange(BuildBit(false, samples));
                }

            }
            data.AddRange(BuildBit(true, samples));//stop bit

            Console.WriteLine();
            return data.ToArray();
        }

        static byte[] BuildBit(bool bit, int samples)
        {
            byte[] bitdata = new byte[samples];
            for (int i = 0; i < samples; i++)
            {
                if (bit)
                {
                    bitdata[i] = 0;//since the opamp inverts our signal!!!
                }
                else
                {
                    bitdata[i] = 255;
                }
            }
            return bitdata;
        }

    }
}
 

All that’s left if the video and the future.  We will be playing with using optoisolators to level shift and are hoping to get greater than 9600 baud out of this thing.  Then we will look at what it takes to receive data from arduino.  Can anyone tell where we are going?  Worlds greatest arduino shield!

Idea on how to teach computer classes

Like every other American I had an idea on how to teach computer classes after reading this article on why kids are turned off of computer classes I started thinking.

In the article the claim is that classes teach the baseline boring stuff and fail to engage students.  Taking many a programming class I can definitely understand that.

First, teach HARDWARE. Nothing is more fun and tangible then making a servo move or a light blink.  The baseline electronics are pretty simple and not even necessary.  Hardware makes things less abstract and more fun.

Second, start with a cool program and slowly modify and extend it to do their bidding.  Rather than jump from “Hello World” to an if statement and lose everyone in between, start with something fun.  Give the students a program, let them modify it. First step, change blink rate of an LED on a robot. Instant gratification. 

The article explains that what we do is like teaching spelling to learn English. I completely agree.  Parents read to their children and are exposed to the fun elements of language from the very beginning. Why not tie that to how we teach programming.

 

As a father to be, I will be teaching my kids how to program this very same way.

FLAKElabs Update

We now have a facebook page! We will be using that to upload photos too.  I think it’s a bit easier than flickr.

On Monday we met with Pete at sparkfun to talk about the future of our android audio communication system.  If we can get something soon we may have our first product ship via sparkfun. Got a tour of their facility, still wiping the drool off my face.

Lastly. IT’S A BOY!!! Getting excited about adding another hacker to the family!

Control FT232 with C#

I love embedded programming and Arduino but it can be overkill if all you are doing is flipping some pins on and off. Now people have posted how to do this in C but I prefer C#.  With a FT232RL and a SSOP to DIP adapter I can control an RGB LED for $7.90!

First you will need to install the FT232 with the drivers from this page http://www.ftdichip.com/Drivers/D2XX.htm . These drivers allow for more complex communication (same as what Arduino requires).

Second you will need a dll from FDI http://www.ftdichip.com/Projects/CodeExamples/CSharp/FTD2XX_NET_106.zip

 

Now simply add a reference and you can talk in C#! Below is my example of a simple RGB LED blinking.

IMG_0992

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FTD2XX_NET;
using System.Threading;

namespace FT232
{
    class Program
    {

        //red= pin 1
        //blue = pin 5
        //green = pin 3

        static byte RED = 254;
        static byte BLUE = 253;
        static byte GREEN = 251;

        static void Main(string[] args)
        {
            FTDI f = new FTDI();
            uint ndevices = 0;
            f.GetNumberOfDevices(ref ndevices);
            Console.WriteLine( "Detected {0} devices.",ndevices);
            if(ndevices==0){return;}
            uint device=0;
            FTD2XX_NET.FTDI.FT_STATUS s;
            for (uint i = 0; i < ndevices; i++)
            {
                Console.WriteLine("Device {0}", i);
                s= f.OpenByIndex(device);
                FTD2XX_NET.FTDI.FT_DEVICE type = FTD2XX_NET.FTDI.FT_DEVICE.FT_DEVICE_UNKNOWN;
                f.GetDeviceType(ref type);
                Console.WriteLine(type);
                f.Close();
            }

            if (ndevices>1)
            {
                Console.Write("Choose which device:");
                device=uint.Parse(Console.ReadLine());
            }

            s = f.OpenByIndex(device);
            Console.WriteLine(s);
            //set all pins to async bitban
            s = f.SetBitMode(255, FTDI.FT_BIT_MODES.FT_BIT_MODE_ASYNC_BITBANG);
            uint byteswritten=0;
            while (1 == 1)
            {
                f.Write(new byte[] { RED }, 1, ref byteswritten);
                Thread.Sleep(300);
                f.Write(new byte[] { 255 }, 1, ref byteswritten);

                f.Write(new byte[] { BLUE }, 1, ref byteswritten);
                Thread.Sleep(300);
                f.Write(new byte[] { 255 }, 1, ref byteswritten);

                f.Write(new byte[] { GREEN }, 1, ref byteswritten);
                Thread.Sleep(300);
                f.Write(new byte[] { 255 }, 1, ref byteswritten);

            }

        }
    }
}

FLAKElabs endorses OSHW

FLAKElabs while still on the backburner endorsed Open Source Hardware. We are committed to releasing everything we do as OSHW and have added our name to the list of amazing makers, engineers and scientists!

http://freedomdefined.org/OSHW

FLAKElabs Update!

Hi all, I’m sure you are all wondering where the heck we have been.  Well, first we are pregnant! That was a big surprise to us and has caused us to take a step back from flakelabs to finish up some other projects (Massive renovation underway). 

Second, we have joined the cellbots group and have offered them our information on where we got and it looks like they have a demo going already!

http://www.cellbots.com/uncategorized/new-type-of-cellbot-now-with-no-microcontroller/

 

Does this mean we are out of the running? Heck no, I just emailed Pete @ Sparkfun about working with them on getting this project going again.  I think a simple version like cellbots did where the servo is doing direct drive is a great plan, and a direction we have been going. I also would like to explore full Arduino bridging for the Android phone as well.  Definitely a more complex project, but with bigger implications!

We are also going to be moving this site to be just a hardware hack blog.  I have done a few other hardware hacks that I am going to post and have a lot more underway.  We figured for a few years we will work on getting some blog cred and then when the money and time is right, we are going to launch again!

 

Thanks for your readership,

Michael and Julie

Sprinkle

XKCD’s new interface

First, I love the the new interface. Second, pure joy when i found this hidden Easter egg.

image

Paradigm shift

Our goal from the beginning has been to get people excited about programming on phones. To be honest.. I find it difficult for me to get excited about programming on phones. The field is so disjointed and volatile. It seems like every week something new comes along.

Eventually this will fizzle out and we will see some winners emerge. This has really made me backtrack and re-think, what are we actually gaining by programming on the phone. Initially it was because the phone is LOADED with useful stuff. GPS, Accelerometers, Compasses, Screens etc.  It also contains a very amazing processor, but what if that wasn’t such a big deal?

Where I am going with this, is what if we instead did programming on the uP/Arduino. Lots of people know how to program them and are very good with them. So what we are proposing to do is to turn the phone into a stable intelligent slave. (The worlds most amazing shield!)

We would make the phone bridge services found on the phone to the Arduino! By enabling a well defined command syntax we can give the Arduino a color LCD, camera, accelerometers etc. So what we are considering at this stage is building a very, very good Android App that provides the ability for sensor data to be shipped to the Arduino.  In the beginning the Android App would serve as the master app. Just configure your sensor update intervals for each sensor and the Arduino will poll for them.

The eventual goal will be to allow the Arduino to manipulate the screen of the Android as well. But this will require the use of the microphone on the android. For now, we will just get the data to the Arduino.

 

 

image

Feedback requested

I’ve been examining many, many different ways for phones to communicate with robots.  I have many options and would appreciate some feedback.

Goals:

  • Works cross platform / cross manufacturer
  • Ideally electrically isolated to prevent phone damage.
  • Works without soldering anything on the phone
  • Works without jail breaking / rooting the phone

UART via headphones

image

The idea is to simply build WAV files that have a 9600 sample rate and have the data encoded in them. Simply play the 64.wav to send the byte 64 out the speaker jack. Then use a transistor to step-up the 1.2 volt signal to 5 volts to be received by an Arduino/uP motor controller.

Since phones seem to be increasingly non standard we would implement this device with a 3.5mm male head phone jack. Most people have their own adapters to use standard head phones. We could see a limited supply of adapters as well.

UART over IR via headphones (passive)

image

Using ideas like the Griffin Pocket beamer http://www.codeproject.com/KB/mobile/PocketBeamer.aspx we could build a fairly simple IR Transmitter. The problem is that the Griffin technology is patented.  They do some really impressive stuff like modulate 22Khz on the Left and Right channels to increase the frequency response to 44Khz since most devices only emit 22Khz signals. Again this would be implemented with 3.5mm jacks.

 

UART over IR via headphones (active)

image

This would stay away from Griffin IP entirely. This device would use a 555 timer or(Attiny) to generate the 38Khz signal required by IR.  Any signal over .7 volts would enable the 555 timer anything less would disable it. This device would require its own batteries. On the receiving side a simple IR transistor with builtin gain control would be used.

This would require its own batteries that would be separate from the robot. It is electrically isolated from the robot.  Another fun aspect of this idea.. is that you could turn your phone into a remote (although a clunky one).

DTMF via headphones

image

DTMF seems to be very standard on phones and is well understood. DTMF tones could be sent to an MT8870 chip or possibly directly to an ATTINY to be decoded. This however is as good as UART over serial and is very slow.

DTMF via speaker phone

image

Similar to the above except the speaker phone is used to send the DTMF tones to a microphone on the robot. This could be very loud and annoying but is nice because it offers electric isolation. This would require additional preamps on the robot and would require only a single robot to operate at a given time.

Bluetooth

image

A great deal of phones seem to use Blue tooth. The problem is that getting cheap Bluetooth chips is difficult. It also seems difficult to program against Bluetooth on most phones.

Photo diode + LCD

image

A rather evil and low tech idea. Simply light up a portion of the screen to create a logic level high from a photo diode.  To control an H-bridge you would need 4 distinct portions of the screen to point photo diodes at. While guaranteed to work on any phone this provides very crude control of a robot.

UART direct

image

Some phones (HTC, Iphone) expose proprietary connectors with UART on them already. This is not cross manufacturer and requires you to jail break the Iphone.

 

 

Well anyway…Internet, weigh in your opinions.