Vol. 01: Glowstick a Go-Go

Bunnie Huang prototypes two kinetic glowsticks: instead of creating a single arc of light, glowsticking dancers can now create their own two-dimensional fantasias.



+ Downloads & Extras:

Bill of Materials

When I'm building these kind of prototypes, I almost never choose any part that I cannot find in stock at Digi-Key. There may be other better or cheaper inductors, but they were too hard to acquire for a project like this one.

Qty Digikey P/N Description
10399-1100-1-ND0.1uF 0603 Capacitor
2311-1.0KGCT-ND1k 0603 resistor
1X928CT-ND4 MHz ceramic resonator
1308-11771-1-ND22uH inductor, SMT
3311-47KGCT-ND47k 0603 resistor
2399-1556-1-ND47uF, 6.3V "C" tantalum capacitor
1311-80.6KHCT-ND82k 0603 resistor
1311-100KGCT-ND100k 0603 resistor
1311-200GCT-ND200 ohm 0603 resistor
1311-221KHCT-ND221k 0603 resistor
2311-240KHCT-ND240k 0603 resistor
25230TRK-NDBoard-mount battery connector ends
1H2131-ND6-pin programming header
4743C083181JCT-ND180 ohm resistor array (optional)
16160-1436-1-NDRed LED, 0603 case
867-1820-1-NDRGB combo LED (optional)
3MA3J70000LCT-NDSchottky diode, SOT-23 package
1MAX1676EUB-NDVoltage regulator / MAX1676EUB
4MM74HC595M-ND8-bit shift-register
1PIC16LF876A-I/SS-NDPIC microcontroller
3P8045SCT-NDPush-button switch

Code Listings

Listing 1: code used to implement the FPGA on the first prototype

module top(hdc, led);

    output    hdc;
	 output [15:0] led;

	 reg [23:0] 	 count;
    wire 				 clk, to_bufg;
	 wire [4:0] 	 spriteCnt;
	 wire [3:0] 	 frameCnt;
	 reg [15:0] 	 ledinv;

	 OSC4 oscut (.F8M(), .F500K(), .F16K(to_bufg), .F490(), .F15() ); 
  BUFG bufut (.I(to_bufg), .O(clk)); 

	 assign 			 led[15] = !ledinv[15];
	 assign 			 led[14] = !ledinv[14];
	 assign 			 led[13] = !ledinv[13];
	 assign 			 led[12] = !ledinv[12];
	 assign 			 led[11] = !ledinv[11];
	 assign 			 led[10] = !ledinv[10];
	 assign 			 led[ 9] = !ledinv[ 9];
	 assign 			 led[ 8] = !ledinv[ 8];
	 assign 			 led[ 7] = !ledinv[ 7];
	 assign 			 led[ 6] = !ledinv[ 6];
	 assign 			 led[ 5] = !ledinv[ 5];
	 assign 			 led[ 4] = !ledinv[ 4];
	 assign 			 led[ 3] = !ledinv[ 3];
	 assign 			 led[ 2] = !ledinv[ 2];
	 assign 			 led[ 1] = !ledinv[ 1];
	 assign 			 led[ 0] = !ledinv[ 0];
	 
  always @(posedge clk) begin
			count <= count + 1;
	 end

	 assign spriteCnt[4:0] = count[9:5];
	 assign frameCnt[3:0] = count[19:16];
	 // 130 bpm = 2.167 bps = 0.4615 seconds per beat
	 // four bars = 34.67 seconds
	 // 19 64  about one minute
	 // 18 32 // 16 bars
	 // 17 16 // 8 bars
	 // 16 8  // about four bars  <== set point at four bar points
	 // 15 4  // 2 bars
	 // 14 2  // about one bar
	 // 13 1 second
	 // 12 500 milliseconds
	 // 11 250
	 // 10 125
	 // 9 62.5
	 // 8 31.25 milliseconds
	 // 7 15
	 // 6 7.5  ms

	 always @(spriteCnt or frameCnt) begin
			case( frameCnt )
				4'b000: begin
					casex( spriteCnt ) // smiley face
						5'bx0000:
							ledinv <= 16'b0000001111000000;
						5'bx0001:
							ledinv <= 16'b0000110000110000;
						5'bx0010:
							ledinv <= 16'b0001000000001000;
						5'bx0011:
							ledinv <= 16'b0011000000001100;
						5'bx0100:
							ledinv <= 16'b0110011001100110;
						5'bx0101:
							ledinv <= 16'b0100011001100010;
						5'bx0110:
							ledinv <= 16'b1100000000000011;
						5'bx0111:
							ledinv <= 16'b1000000000000001;
						5'bx1000:
							ledinv <= 16'b1000000000000001;
						5'bx1001:
							ledinv <= 16'b1100100000010011;
						5'bx1010:
							ledinv <= 16'b0100010000100010;
						5'bx1011:
							ledinv <= 16'b0110001111000110;
						5'bx1100:
							ledinv <= 16'b0011000000001100;
						5'bx1101:
							ledinv <= 16'b0001000000001000;
						5'bx1110:
							ledinv <= 16'b0000110000110000;
						5'bx1111:
							ledinv <= 16'b0000001111000000;
					endcase // case( spriteCnt )
				end // case: 4'b000
				4'b001: begin
					 case( spriteCnt ) // rabbit
						 5'b00000:
						 5'b11111:			         
							 ledinv <= 16'b1100110000000011;
					 endcase // case( spriteCnt )
				end
			endcase // case( frameCnt )
			
	 end // always @ (spriteCnt or frameCnt)
	 
	 assign hdc = 1'b1; // always high, so configuration status LED is off

endmodule

Listing 2: Snippet of C code of a PIC function call for displaying data using the second prototype's scheme.

#include <16F876A.h>
#device ICD=TRUE
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT

#define SD_CLR_MSK 0x10
#define SD_CLK_MSK 0x08
#define SD_RCK_MSK 0x20

void display_green(unsigned long data) {
 char i;
 char db = 0;

 port_c = SD_CLR_MSK;

 // shift the bits in
 for( i = 0; i < 16; i++ ) {
  db = SD_CLR_MSK;
  ((data & 0x8000) == 0x8000) ? (db |= 1) : (db |= 0);
  data <<= 1;

  port_c = db;
  db |= SD_CLK_MSK;
  port_c = db;
  db &= ~SD_CLK_MSK;
  port_c = db;
 }

 // now make it show up
 port_c = SD_RCK_MSK | SD_CLR_MSK;
 port_c = SD_CLR_MSK;

}

Join the conversation -- every MAKE article has an online page that includes a place for discussion. We've made these RSS and Atom feeds to help you watch the discussions: subscribe.