I’m not ashamed to say it: I’m a bit of an ATMEL guy. AVR microcontrollers are virtually exclusively what I utilize when creating hobby-level projects. Wile I’d like to claim to be an expert in the field since I live and breathe ATMEL datasheets and have used many intricate features of these microchips, the reality is that I have little experience with other platforms, and have likely been leaning on AVR out of habit and personal convention rather than a tangible reason. Although I was initially drawn to the AVR line of microcontrollers because of its open-source nature (The primary compiler is the free AVR-GCC) and longstanding ability to be programmed from non-Windows operating systems (like Linux), Microchip’s PIC has caught my eye over the years because it’s often a few cents cheaper, has considerably large professional documentation, and offers advanced integrated peripherals (such as native USB functionality in a DIP package) more so than the current line of ATTiny and ATMega microcontrollers. From a hobby standpoint, I know that ATMEL is popular (think Arduino), but from a professional standpoint I usually hear about commercial products utilizing PIC microcontrollers. One potential drawback to PIC (and the primary reason I stayed away from it) is that full-featured C compilers are often not free, and as a student in the medical field learning electrical engineering as a hobby, I’m simply not willing to pay for software at this stage in my life.

I decided to take the plunge and start gaining some experience with the PIC platform. I ordered some PIC chips (a couple bucks a piece), a PIC programmer (a Chinese knock-off clone of the Pic Kit 2 which is <$20 shipped on eBay), and shelved it for over a year before I got around to figuring it out today. My ultimate goal is to utilize its native USB functionality (something at ATMEL doesn’t currently offer in DIP packages). I’ve previously used bit-banging libraries like V-USB to hack together a USB interface on AVR microcontrollers, but it felt unnecessarily complex. PIC is commonly used and a bit of an industry standard, so I’m doing myself a disservice by not exploring it. My goal is USB functionality, but I have to start somewhere: blinking a LED.

Here’s my blinking LED. It’s a bit anticlimactic, but it represents a successful program design from circuit to writing the code to programming the microchip.

Based on my limited experience, it seems you need 4 things to program a PIC microcontroller with C:

The first thing I did was familiarize myself with the pin diagram of my PIC from its datasheet. I’m playing with an 18F2450 and the datasheet is quite complete. If you look at the pin diagram, you can find pins labeled MCLR (reset), VDD (+5V), VSS (GND), PGC (clock), and PGD (data). These pins should be connected to their respective counterparts on the programmer. To test connectivity, install and run the PICkit2 installer software and it will let you read/verify the firmware on the chip, letting you know connectivity is solid. Once you’re there, you’re ready to start coding!

I wish I were friends with someone who programmed PIC, such that in 5 minutes I could be shown what took a couple hours to figure out. There are quite a few tutorials out there – borderline too many, and they all seem to be a bit different. To quickly get acquainted with the PIC programming environment, I followed the “Hello World” Program in C tutorial on PIC18F.com. Unfortunately, it didn’t work as posted, likely because their example code was based on a PIC 18F4550 and mine is an 18F2450, but I still don’t understand why such a small difference caused such a big problem. The problem was in their use of LATDbits and TRISDbits (which I tried to replace with LATBbits and TRISBbits). I got around it by manually addressing TRISB and LATB. Anyway, this is what I came up with:

#include <p18f2450.h> // load pin names
#include <delays.h>   // load delay library

#pragma config WDT = OFF // disable watchdog timer
#pragma config FOSC = INTOSCIO_EC // use internal clock

void main() // this is the main program
{
	TRISB=0B00000000; // set all pins on port B as output
	while(1) // execute the following code block forever
	{
		LATB = 0b11111111; // turn all port B pins ON
		Delay10KTCYx(1);   // pause 1 second
		LATB = 0b00000000; // turn all port B pins OFF
		Delay10KTCYx(1);   // pause 1 second
	}
}


A couple notes about the code: the WDT=OFF disables the watchdog timer, which if left unchecked would continuously reboot the microcontroller. The FOSC=INTOSCIO_EC section tells the microcontroller to use its internal oscillator, allowing it to execute code without necessitating an external crystal or other clock source. As to what TRIS and LAT do, I’ll refer you to basic I/O operations with PIC.

Here is what the MPLAB IDE looked like after I successfully loaded the code onto the microcontroller. At this time, the LED began blinking about once per second. I guess that about wraps it up! This afternoon I pulled a PIC out of my junk box and, having never programmed a PIC before, successfully loaded the software, got my programmer up and running, and have a little functioning circuit. I know it isn’t that big of a deal, but it’s a step in the right direction, and I’m glad I’ve taken it.





I was brainstorming some RF circuits today and I had the desire to create a rapid transmitter/receiver pair that anyone would have around their house. I decided that AM or FM radio would be good since everyone can receive that, and pondered how best to generate the necessary radio signal and modulate it appropriately. After a few LC oscillator designs, I thought about the RC oscillators built into most micro-controllers. I grabbed an ATMEL AVR I had on hand (an ATTiny44A) and checked the datasheet. It had an 8MHz RC oscillator, which could be divided-down to 1MHz, and output on a CKOUT pin – all configurable with a few hardware fuses! Note that commercial AM radio stations are between 0.52 and 1.61 MHz, so a 1MHz signal would be smack-dab in the middle of our radio dial! I had to build a prototype to see how well it would work. Once concern was that the RC oscillator wouldn’t be stable enough to produce reliable audio – boy was I wrong!
schem

The circuitry is textbook simple. Appropriately configured, the AVR generates 5V square waves from its CKOUT pin. Although a pretty shape, they’re not powerful enough on their own to be heard across a room, so I needed an amplifier stage. A class C amplifier provided by a 2n7000 is commonly done in the low power amateur radio (QRP) community, so I went with it. A 2n7000 N-channel MOSFET with a 220-ohm resistor on the drain and the CKOUT directly into the gate did a fine job (I’ve used this design for 10MHz QRSS transmitters before), and I was able to modulate its amplitude by feeding the voltage from a MCU pin (turned on/off rapidly) through a decoupling capacitor into the drain of the MOSFET. I couldn’t have asked for a simpler result!

This code sends a message in Morse code. It seems too easy! Applications are endless, as this is one heck of an easy way to send audio from a micro-controller to a radio, and possibly to a computer. Morse code is easy, and since we have the ability to dynamically generate different audio frequencies and tones, data exchange is easy too! Nothing’s stopping you from adding the code to turn this into a RTTY (or Hellschreiber?) transmitter.
DSCN1670

Again, this transmitter can be heard on a standard AM radio tuned to about 1000 kHz. This is the setup I used with great success:
schem2

Here’s the code on the chip! Nothing complicated:

// designed for and tested with ATTiny44A
#include <avr/io.h>
#define F_CPU 1000000UL
#include <avr/delay.h>
#include <avr/interrupt.h>

void beep(){
	for(char i=50;i;i--){
		DDRA|=_BV(PA7);_delay_ms(1);
		DDRA&=~_BV(PA7);_delay_ms(1);
	}
}

void rest(){_delay_ms(100);}

void dot(){beep();rest();}
void dash(){beep();beep();beep();rest();}
void space(){rest();rest();}
void space2(){space();space();}

int main(){
	DDRA|=_BV(PA7);
	for(;;){
		dot();dot();dot();space(); 			// S
		dash();dot();dash();dot();space(); 	// C
		dash();dash();dash();space(); 		// O
		dash();space(); 					// T
		dash();space(); 					// T
		space2();
		dot();dash();dot();space();			// R
		dash();dash();dash();space(); 		// O
		dash();dot();dash();dot();space(); 	// C
		dash();dot();dash();space();		// K
		dot();dot();dot();space(); 			// S
		_delay_ms(1000); // silence
	}
	return 0;
}

THIS IS ILLEGAL to do if you exceed a certain amount of power because you’re stepping on legitimate commercial broadcasters and will have to deal with the FCC. Additionally, you are transmitting on more frequencies than the primary frequency because the signal is heavy in odd harmonics. This means a 1 MHz transmitter, producing square waves, will generate tones on 1, 3, 5, 7 MHz, etc. Don’t do this with much power! Heck, you probably shouldn’t do it at all 😉





This post describes a project I designed which transmits strings of data from a microcontroller to a PC’s screen using audio beeping in a special mode called Hellschreiber. Although these days it’s almost exclusively used by amateur radio operators, I thought it would make a cool microcontroller project! The result can be accomplished with a microcontroller and a speaker as a transmitter and a PC with a microphone as a receiver and decoder, or with actual radio equipment (even toy walkie talkies) by transmitting the tones over modulated radio frequencies for long distance communication! Ideas anyone?

SPECIAL THANKS: I’d like to think Mike Seese for his brainstorming help in making this project a reality. Mike and I are working on a high altitude balloon project together, and a creative inexpensive radio link is one of our goals. Thanks Mike!

As a professional dental student by day and amateur electrical/RF engineer by night, I’m having a very strange summer. I’m developing rapidly in my experience and skills in both arenas. I finally feel like I have a working knowledge of most fundamental electrical and radio frequency concepts, and I’m starting to see patients and do procedures on humans (no more mannequins) in the student dental clinic. For legal and ethical reasons I do not write specifics about what I do with my patients, but I certainly make up for it by documenting the electronic projects I work on! My goals of doing this are to (a) inspire potential electronics tinkerers to come up with new ideas and attack new projects, and (b) receive feedback and insight from those more experienced than me to help me grow in my knowledge. My eye caught a comment a few posts ago that made me smile: You have been blessed with talent and the drive to attempt things not been tried before, keep it up, great job. –David S While I can’t claim that everything I do is truly novel or never tried before, I appreciate the encouraging words. Thank you David S!

Today’s project is a fun one involving vintage wartime radio equipment, amateur radio computer software, and a healthy dose of microcontrollers! My goal is to design a single chip Hellschreiber (technically Feldhellschreiber) transmitter. “Hellschreiber” translates into English as “Light Writer” and is a pun on the name of its inventor, Rudolf Hell, who built the first device in 1920. It was intended to allow messages to be transferred over poor radio links too noisy for intelligible voice or radioteletype (RTTY) communication. Its cool factor is upped by the fact that it was sometimes used by the German military in conjunction with the Enigma encryption system during World War 2! [As an aside, RTTY is still pretty sweet and dates back to the mid 1800s! Check out hardware receivers in video 1 and video 2]

Seeing a battlefield-ready Hellschreiber receiver gives you a good idea of how it works. (The video isn’t mine, I found it on youtube.) The concept is relatively simple (shown above), and the receiver has only 2 moving parts. A spinning corkscrew presses a ticker tape into ink when it receives a radio signal. As the radio signal beeps on and off, the corkscrew contacts at different positions at different times, and letters are written on the ticker tape! anaglyph-hell-GL-11The designers of these things were extraordinarily creative! The picture on the right shows a Hellschreiber transmitter – basically a typewriter with mechanical wizardry that turns key presses into a series of radio tones corresponding to the pixelated shape of a character.

Almost a century later, people are still sending messages around the world using Hellschreiber! With an amateur radio license and an amateur radio transceiver you can tune around special Hellschreiber calling frequencies and engage in conversations with other people who enjoy using this unique mode. Computers have modernized the process, allowing you to send Hellschreiber text by typing on your keyboard and receive it by just looking at your screen. My favorite program (free) to do this is Digital Master 780, part of Ham Radio Deluxe.

This is the project I just completed. It takes strings of text stored (or dynamically generated) in an array on a microcontroller (I’m using an ATMega48, but the code is almost identical for any ATMEL AVR microcontroller, and easy adapted for other architectures) and turns it into an audio tone using PWM. This audio tone could be fed into a speaker and a microphone across the room could receive it and use the software to show the received data, or the audio could be fed into a radio transmitter and a PC hooked to the receiver could decode the audio. Either way, the text in the microcontroller is converted to Hellschreiber audio tones ready to be used however you see fit! Although I designed it as a resilient way to transmit GPS/altitude data from a high altitude balloon using a small, cheap, low-power radio transmitter, this project is just the foundation of a plethora of potential projects!
DSCN1663

Here’s the circuit I’m using. It’s actually less complicated than shown – all those yellow wires are going to my AVR programmer! The chip just receives +5V and GND, and the audio is generated automatically and output on the OC0A pin, which happens to be pin 12 on my ATMega48. The output (audio level square waves) is fed to a crystal oscillator like this one, which generates square waves with an amplitude equal that to the input. Thus, by audio-frequency AC from the microchip, decoupled through a series capacitor, added to the power supply of the oscillator (provided by the 5V rail through a 1.8k resistor), we effectively produce an amplitude modulated (AM) radio signal!
DSCN1667

This is the receiver I’m using. I’m lucky enough to have an all-mode, general-coverage, 100W amateur radio transceiver! It’s a Yaesu 857-D and I’m completely in love with it. It’s quite pricey though! You can find wide coverage receive-only radios called radio scanners (or police scanners), often for $20 or so on eBay which would do just as good a job of receiving all sorts of radio signals! Whatever you use, after tuning into the audio with the ham radio delux software, you’ll be able to decode Hellschreiber like this:
hell

A few notes about the code: Each letter is sent twice vertically and I don’t think I should have done that. It’s easy enough to correct by eliminating the second FOR loop in the sendChar() function, and doubling the height of the pixels transmitted by changing on(1) and off(1) to on(2) and off(2). Then again, I could be mistaken – I don’t use this mode much. Also, horizontal width of characters (increase this and horizontally compress the received image to reduce the effects of noise) is controlled by a single variable, dynamically adjustable in software. Characters are created from a 3×5 grid (15 bits) and stored as an integer (16 bits, 2 bytes in AVR-GCC). Custom characters are certainly possible! This program takes 16.1% of program space (658 bytes) and 25.4% of data space (130 bytes) and certainly leaves room for optimization.

// designed for and tested with ATMega48
#include <avr/io.h>
#define F_CPU 8000000UL
#include <avr/delay.h>
#include <avr/interrupt.h>

/*
character format (3x5):
	KFA
	LGB
	MHC
	NID
	OJE

variable format:
	2-byte, 16-bit int 0b0ABCDEFGHIJKLMNO
	(note that the most significant bit is not used)
*/
#define A 	0b0111111010011111
#define B 	0b0010101010111111
#define C	0b0100011000101110
#define D	0b0011101000111111
#define E	0b0100011010111111
#define F	0b0100001010011111
#define G 	0b0100111000101110
#define H	0b0111110010011111
#define I	0b0100011111110001
#define J	0b0111110000100011
#define K	0b0110110010011111
#define L	0b0000010000111111
#define M	0b0111110110011111
#define N	0b0011111000001111
#define O	0b0011101000101110
#define P	0b0010001010011111
#define Q	0b0111011001011110
#define R	0b0010111010011111
#define S	0b0100101010101001
#define T	0b0100001111110000
#define U	0b0111110000111111
#define V	0b0111100000111110
#define W	0b0111110001111111
#define X	0b0110110010011011
#define Y	0b0110000011111000
#define Z	0b0110011010110011
#define n0	0b0111111000111111
#define n1	0b0000011111101001
#define n2	0b0111011010110111
#define n3	0b0111111010110001
#define n4	0b0111110010011100
#define n5	0b0101111010111101
#define n6	0b0101111010111111
#define n7	0b0110001011110000
#define n8	0b0111111010111111
#define n9	0b0111111010111101
#define SP	0b0000000000000000
#define BK	0b0111111111111111
#define SQ	0b0001000111000100
#define PR	0b0000110001100011
#define AR	0b0001000111011111

volatile char width=1; // width of characters, widen to slow speed

#define spd 8300 // synchronization, incr to make it slant upward

void rest(char times){while (times){times--;_delay_us(spd);}}

void on(char restfor){OCR0A=110;rest(restfor);}
void off(char restfor){OCR0A=0;rest(restfor);}

void sendChar(int tosend){
	char w;
	char bit;
	for(w=0;w<width*2;w++){ // left column
		off(1);
		for (bit=0;bit<5;bit++){
				if ((tosend>>bit)&1) {on(1);}
				else {off(1);}
			}
		off(1);
		}
	for(w=0;w<width*2;w++){ // middle column
		off(1);
		for (bit=5;bit<10;bit++){
				if ((tosend>>bit)&1) {on(1);}
				else {off(1);}
			}
		off(1);
		}
	for(w=0;w<width*2;w++){ // right column
		off(1);
		for (bit=10;bit<15;bit++){
				if ((tosend>>bit)&1) {on(1);}
				else {off(1);}
			}
		off(1);
		}
	off(14); // letter space (1 column)
}

// CUSTOMIZE THE MESSAGE, OR GENERATE IT DYNAMICALLY!
int message[]={AR,AR,AR,S,W,H,A,R,D,E,N,PR,C,O,M,SP,R,O,C,K,S,
	SP,AR,AR,AR,SP,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,
	V,W,X,Y,Z,n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,BK,SP};

void sendMessage(){
	char i;
	for(i=0;i<sizeof(message)/2;i++){
		sendChar(message[i]);
	}
}

int main(){ // ### PROGRAM STARTS HERE ###

	// this sets up CPWM in CTC mode,
	// it may be slightly different for other chips
	DDRD|=255; // OC0A is now an output
	TCCR0A=0b01000010; // toggle on match, CTC mode
	TCCR0B=0B00000011; // set prescalar

	for(;;){
		width=1; // fast mode
		sendMessage();
		width=3; // slow mode
		sendMessage();
	}

	return 0;
}




[warning]This is one part of a multi-post project

view PART 1 for circuity and theory[/warning]

Last week I had the crazy idea of sending data from a PC to a microchip through the monitor, using javascript and a web interface as a ridiculously simple data transfer platform that would work on virtually any computer! While I quickly hacked together the hardware, I struggled with the web interface (I’m a little slow with javascript) and I got a lot of help from people around the internet, especially after my project (and need for assistance) was mentioned on Hack-A-Day!
DSCN1657

This is part two of a multi-page project. To fully understand what I’m trying to accomplish and why I want to accomplish it, read the first part of the project.

Finally, I have a working javascript! I’d like to thank Tom, Riskable, Ben, and Mike for their input on this script. We got it to a point where we think it’s friendly to the majority of browsers and platforms. The idea is simple – enter two bytes to send the chip, it generates it’s own checksum (an XOR of the two bytes), and it flashes it out. Here’s a photo of the interface, click it for a live demo:

flasher_interfaceHere’s the code that goes on the microchip:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#define F_CPU 12000000UL
#include <util/delay.h>
#include "lcd.h"
#include "lcd.c"

volatile int times=1000;

char readADC(char pin){
  ADMUX = 0b1100000+pin; // AVCC ref on ADC5
  ADCSRA = 0b10000111; //ADC Enable, Manual Trigger, Prescaler 128
  ADCSRA |= (1<<ADSC); // reset value
  while (ADCSRA & ( 1<<ADSC)) {}; // wait for measurement
  return ADCH;
}

int main(void)
{
  lcd_init(LCD_DISP_ON);
  char lastClock=0;
  char thisClock=0;
  char thisClock2=0;
  char thisData=0;
  char buffer[8];

  char lastNum=0;
  char bitsGotten=0;

  int msInactive=0;

  /*for(;;){
    itoa(readADC(5), buffer, 10);
    lcd_gotoxy(0,15);
    lcd_puts(buffer);

    itoa(readADC(4), buffer, 10);
    lcd_gotoxy(8,0);
    lcd_puts(buffer);
  }*/

  for(;;){
    thisClock = readADC(5);
    if (thisClock<250){
      _delay_ms(1);
      if (readADC(5)>250) {break;}

      _delay_ms(1);
      if (readADC(4)<250) {thisData=1;}
      else {thisData=0;}
      lastNum=lastNum*2+thisData; // left shift, add data
      itoa(thisData, buffer, 10);
      lcd_puts(buffer);
      msInactive=0;

      bitsGotten++;
      if (bitsGotten==8){
        lcd_gotoxy(1,1);
        lcd_puts("=   ");
        lcd_gotoxy(2,1);
        itoa(lastNum, buffer, 10);
        lcd_puts(buffer);
        bitsGotten=0;
        lastNum=0;
        lcd_gotoxy(0,0);
      }

      while (1) {
        if (readADC(5)>250){
          _delay_ms(10);
          if (readADC(5)>250){break;}
        }
      }
    }
    else{
      msInactive++;
      if (msInactive==400){
        bitsGotten=0;
        lastNum=0;
        lcd_clrscr();
        lcd_puts(" TIMEOUT");
        _delay_ms(1000);
        lcd_clrscr();
        lcd_gotoxy(0,0);
        lcd_puts("________ =");
        lcd_gotoxy(0,0);
      }
    }
    _delay_ms(1);
  }
}

Here’s the javascript in a web page:

<html>
<head>
<style>
.flasher {
  font-weight: bold;
  text-align: center;
  color: #888888;
  width: 200px;
  height: 200px;
  background-color: black;
  float: left;
  -webkit-transform: translateZ(0);
  border-right-style:dotted;
  border-color:#888888;
  border-width:1px;
}
</style>
<script type="text/javascript">

/* Copyright 2011, Tom Hayward <tom@tomh.us>, MIT License */

var ms = 50,
  bytes = 0,
  leftblock = null,
  rightblock = null,
  statustext = null;

function sendBit(bit) {
  if (bit) {rightblock.style.backgroundColor = 'white';}
  else {rightblock.style.backgroundColor = 'black';}
  leftblock.style.backgroundColor = 'white';
  setTimeout(function() {
  leftblock.style.backgroundColor = 'black';
  rightblock.style.backgroundColor = 'black';
  }, ms);
}

function sendByte(byte) {
  var bits = 8;
  setTimeout(function() {
  var timer = setInterval(function() {
    bits--;
    sendBit(byte >> bits & 1);
    if (bits == 0) {clearInterval(timer);return;}
  }, ms * 2);
  }, ms * 2 * bits * bytes++);
}

function Pause() {
timer = setTimeout("endpause()",5000); // 3 secs
return false;
}

function endpause() {
sendData();
return false;
}

function sendData() {

  var button = document.getElementById('sendnow'),
    byte1 = parseInt(document.getElementById('b1').value),
    byte2 = parseInt(document.getElementById('b2').value),
    checksum = byte1 ^ byte2;
  leftblock = document.getElementById('leftblock');
  rightblock = document.getElementById('rightblock');
  statustext = document.getElementById('status');
  bytes = 0; // reset byte counter

  document.getElementById('b3').value = checksum;
  button.disabled = true;
  statustext.innerHTML = "Writing data...";

  sendByte(byte1);
  sendByte(byte2);
  sendByte(checksum);

  setTimeout(function() {
  statustext.innerHTML = "done";
  button.disabled = false;
  }, ms * 2 * 8 * bytes);

}

</script>
</head>
<body bgcolor="#666">

<h1>PC/MCU Flasher Interface</h1>
<code>
Byte 1: <input id="b1" type="text" name="b1" size="3" value="255" /> <br>
Byte 2: <input id="b2" type="text" name="b2" size="3" value="0" />  <br>
CHKsum: <input id="b3" type="text" name="b3" size="3" value="" disabled="disabled" />  <br>
<br>
<input id="sendnow" type="button" value="SEND NOW" onClick="javascript:Pause();" />
<br><br><br>
<p>Status: <span id="status"></span></p>
</code>
<div id="leftblock" class="flasher"> CLOCK</div>
<div id="rightblock" class="flasher"> DATA</div>

</body>
</html>




UPDATE! >>> [FINISHED PROJECT HERE]

Several days ago I had a crazy idea. I was driving to Orlando to pick my wife up from the airport and it was dark and stormy on the highway and I was thinking about the backlash I got from my Sound Card Microcontroller/PC Communication project, where I used an embarrassingly simple hardware to accomplish the simple task of exchanging a few bytes of data between a PC and microcontroller (in the face of many people who adamantly prefer more complicated “traditional standard” methods). The car in front of me drove with his emergency flashers on, and at times all I could see were his lights. At that moment the crazy idea popped in my head – I wonder if I could use a PC monitor and phototransistors to send data to a microchip? I can’t think of any immediate uses for this capability, but perhaps if I make a working prototype I’ll stumble upon some. Either way, it sounds like a fun project!
DSCN1652

The circuit is as simple as it gets. PHOTOTRANSISTOR MICROCONTROLLER CIRCUITA phototransistor is exactly what it says, a photo (light-triggered) transistor (uses small current to trigger a large current). It’s a photodiode with a small transistor circuit built in. Make sure you give it right polarity when you plug it in! For some reason (likely known to electrical engineers, not dental students) the larger metal piece in the plastic part, which I normally associate as negative for LEDs, should be plugged in the +5V for my photodiode. Again, make sure you hook yours up right. I purchased mine from eBay quite cheaply, but I’ll bet you can find some in RadioShack. Note that the value of the 22k resistor is important, and that your needed value may differ from mine. The resistor relates to sensitivity, the larger the value the more sensitive the device is to light. If it’s too sensitive, it will sense light even when aimed at a black portion of the screen.
hardcode

Initial tests were done using the pins as digital inputs. This was difficult to achieve because, even as transistorized photo-diodes, it took a large difference in light to go from 5V to 0V (even past the 2.5V threshold). After a few minutes of frustration, I decided to use ADC to measure the light intensity. I use only the most significant 8 bits (ADCH). I found that in ambient light the readings are 255, and that white monitor light is around 200. Therefore my threshold is 250 (4.88V?) and I use this for logic decisions. Here’s my setup showing the ADC value of each phototransistor translated into a 1 and 0 for clock (C) and data (D). Both are aimed toward the lamp, so both show a logical 1:
DSCN1651

My first test involved reading the data from the image above. The clock is on the bottom line, data is on the top. Every time the clock transitions from black to white, the value of the data at that point is read (white=1, black=0) and the number is placed on a screen. Here’s what it looks like in action:

Hopefully soon we can get a JavaScript interface going! Rather than swiping I’d like to just point this at the screen and let JS flash some squares for my device to read. This will allow virtually unlimited amounts of data to be transferred, albeit slowly, to the micro-controller. Here’s a preliminary sketch of how to send strings.
string

Remember now we’re using a time domain, not a 2d barcode. I really stink at writing JavaScript, I’m going to have to pull in some help on this one!