You are viewing an older revision! See the latest version
Shiftbrite LED Rotation Display
Introduction¶
- As the bike wheel rotates, a string of Shiftbrite LEDs display an image on a polar coordinate system
- Hall Effect sensor is used to find the time for 1 full rotation of the bicycle wheel
- Timing determined by dividing the total time of 1 full rotation into the number of segments that we want to display.
Materials Used¶
- 10 LED Bar of Shiftbrites
- 9V Battery
- Hall Effect Sensor, ATS177 Manufactures by Diodes Inc.
- 2 Magnets, Neodymium Iron Boron, 10800g
- Mbed
- Lots of Electrical Tape and Zip Ties
http:
http:i.imgur.com/bkM3v.png}}
How it Works¶
Part 1: Converting a Bitmap Image to the Rotational Display Array¶
- Uses a C# console application to transform a 21x21 pixel bitmap image to rotational display arrays for the Mbed
Part 2: Understanding the Hall Effect Sensor¶
- The Hall Effect Sensor is a "latch type" sensor that outputs "high" when subjected to a "N" Magnetic Field and outputs a "low" when subjected to a "S" magnetic field. Thus, we used two magnets to "set" and "reset" the device. The distance was within a half an inch from from the magnets.
- Within the Mbed, an interrupt function was created to activate whenever the Hall Effect Sensor was set to low. Within this function, the Mbed recorded the time for the full rotation and then reset the timer as well as image indices.
Part 3: Shiftbrite SPI Chain¶
- The Shiftbrites are connected together serially; thus, we send 10 SPI commands one after another to light up a current segment.
- The segment time is calculated by dividing the total rotation time (found from the hall effect sensor) by the number of segments needed to light up. We played with the number of segments we wanted to use for lighting up the full wheel and found that if we used too few segments, the resolution of our image would be very low, while using too many would delay the SPI commands sent to the Shiftbrites.
Video Demos¶
INSERT VIDEOs HERE!
Code¶
MBED Software¶
/* ----- 4180 Final Design Project -----
Bicycle Wheel LED Image Display
*/
#include "mbed.h"
InterruptIn hall(p28); // This interupt is used to poll the Hall Effect IC
DigitalOut latch(p8);
DigitalOut enable(p9);
Timer timer; // This timer is used to time the wheel's rotation
int LEDRowNumber = 10; // This is equal to the number of divisions the user has setup for his or her image
int cycle_time = 0; // Global Variable for the full rotation
int rowIndex = 0; // Index for shifting through the Image array
bool top_wheel = false; // Variable Debug LED Circuit
int color = 0; // Variable for shifting through colors
int j; // For Loop index for LED debug circuit
float adj_cycle_time = 0; // Variable used to hold "cycle_time / LEDRowNumber"
//Cycles through different colors on RGB LED
SPI spi(p5, p6, p7);
//Use SPI hardware to write color values to LED driver chip
void RGB_LED(int red, int green, int blue) {
unsigned int low_color=0;
unsigned int high_color=0;
high_color=(blue<<4)|((red&0x3C0)>>6);
low_color=(((red&0x3F)<<10)|(green));
spi.write(high_color);
spi.write(low_color);
latch=1;
latch=0;
}
//Interupt Routine used to detect when the magnet passes the Hall Effect Sensor
void intRoutine() {
cycle_time = timer.read_ms(); //This is only called then the Hall Effect IC returns a "0"
adj_cycle_time = cycle_time / LEDRowNumber; //Calculates the time between sending each LED Row within the color Arrays
timer.reset(); //Resets the Timer
rowIndex = 0; //Resets the Row to be sent so the image always stays in the relatively same place
color=0; //Resets the color Index for the LED sample wheel so the image always stays in the same place
}
int main() {
hall.mode(PullUp); //Initializes the PullUp Resistor for the Hall Effect Sensor
hall.fall(&intRoutine); //Initializes the Interrupt Routine for the Hall Effect Sensor (on falling edge)
spi.format(16,0); //Initializes the Shiftbright LED Chain
spi.frequency(500000);
enable=0;
latch=0;
wait(2);
timer.start(); //Starts the Timer
/*//----- Color Initialization for Debug Program -----
int red=0;
int green=0;
int blue=0;
*/
/* //----- Spiral Pattern -----
int red[10][10]={50,0,0,0,0,0,0,0,0,0
,0,50,0,0,0,0,0,0,0,0
,0,0,50,0,0,0,0,0,0,0
,0,0,0,50,0,0,0,0,0,0
,0,0,0,0,50,0,0,0,0,0
,0,0,0,0,0,50,0,0,0,0
,0,0,0,0,0,0,50,0,0,0
,0,0,0,0,0,0,0,50,0,0
,0,0,0,0,0,0,0,0,50,0
,0,0,0,0,0,0,0,0,0,50};
int green[10][10]={50,0,0,0,0,0,0,0,0,0
,0,50,0,0,0,0,0,0,0,0
,0,0,50,0,0,0,0,0,0,0
,0,0,0,50,0,0,0,0,0,0
,0,0,0,0,50,0,0,0,0,0
,0,0,0,0,0,50,0,0,0,0
,0,0,0,0,0,0,50,0,0,0
,0,0,0,0,0,0,0,50,0,0
,0,0,0,0,0,0,0,0,50,0
,0,0,0,0,0,0,0,0,0,50};
int blue[10][10]={50,0,0,0,0,0,0,0,0,0
,0,50,0,0,0,0,0,0,0,0
,0,0,50,0,0,0,0,0,0,0
,0,0,0,50,0,0,0,0,0,0
,0,0,0,0,50,0,0,0,0,0
,0,0,0,0,0,50,0,0,0,0
,0,0,0,0,0,0,50,0,0,0
,0,0,0,0,0,0,0,50,0,0
,0,0,0,0,0,0,0,0,50,0
,0,0,0,0,0,0,0,0,0,50};
*/
//----- Pac Man -----
int red[10][10]={50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,0,0,50,50
,50,50,50,50,50,50,50,50,50,50
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50};
int green[10][10]={50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,0,0,50,50
,50,50,50,50,50,50,50,50,50,50
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,50,50,50,50,50,50,50,50,50,50
,50,50,50,50,50,50,50,50,50,50};
int blue[10][10]={0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0};
/*// -----Blue Triangle: From Bitmap Image Program -----
int red[36][10]={0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,0,0,0,42,42,42,
0,0,0,0,0,0,0,0,0,42,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,42,
0,0,0,0,0,0,0,0,0,42,
0,0,0,0,0,0,0,0,42,42,
0,0,0,0,0,0,0,0,42,42,
0,0,0,0,0,0,0,0,42,42,
0,0,0,0,0,0,0,0,0,42,
0,0,0,0,0,0,0,0,0,42,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,42,
0,0,0,0,0,0,0,42,42,42,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0};
int green[36][10]={0,0,0,0,42,42,42,42,42,42,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,0,0,0,42,42,42,
0,0,0,0,0,0,0,0,42,42,
0,0,0,0,0,0,0,42,42,42,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,0,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42,
0,0,0,0,42,42,42,42,42,42};
int blue[36][10]={42,42,42,42,0,0,0,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,42,42,42,0,0,0,
42,42,42,42,42,42,42,42,42,0,
42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,0,
42,42,42,42,42,42,42,42,42,0,
42,42,42,42,42,42,42,42,0,0,
42,42,42,42,42,42,42,42,0,0,
42,42,42,42,42,42,42,42,0,0,
42,42,42,42,42,42,42,42,42,0,
42,42,42,42,42,42,42,42,42,0,
42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,0,
42,42,42,42,42,42,42,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,42,42,42,0,0,0,
42,42,42,42,42,42,42,42,0,0,
42,42,42,42,42,42,42,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,42,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0,
42,42,42,42,0,0,0,0,0,0};
*/
while(1) {
//led1 = hall; // Used for Debugging the Hall Effect IC
//led2 = !hall; // Used for Debugging the Hall Effect IC
//----- Code for Cycling through a 2D Picture Array -----
wait_ms(adj_cycle_time);
for(int i=9;i>=0;i--){ //If we update without any waiting, the LEDs change colors super fast, and you won't notice the shifting LEDs
RGB_LED( red[rowIndex][i], green[rowIndex][i], blue[rowIndex][i]);
}
rowIndex++;
if(rowIndex>=LEDRowNumber){
rowIndex = 0;
}
/* //----- Debug Code: Rainbow Pattern ------ (Pre 2D Color Array)
wait_ms(adj_cycle_time);
top_wheel = true;
if (top_wheel && (color == 0)) {
// Red, Color 0
//printf("RED RED RED\r\n");
red = 50;
blue = 0;
green = 0;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color++;
}
if (top_wheel && (color == 1)) {
//printf("ORANGE ORANGE ORANGE\r\n");
// Orange, Color 1
red = 50;
blue = 0;
green = 25;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color++;
}
if (top_wheel && (color == 2)) {
//printf("YELLOW YELLOW YELLOW\r\n");
// Yellow, Color 2
red = 50;
blue = 0;
green = 50;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color++;
}
if (top_wheel && (color == 3)) {
//printf("GREEN GREEN GREEN\r\n");
// Green, Color 3
red = 0;
blue = 0;
green = 50;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color++;
}
if (top_wheel && (color == 4)) {
//printf("CYAN CYAN CYAN\r\n");
// Cyan, Color 4
red = 0;
blue = 50;
green = 50;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color++;
}
if (top_wheel && (color == 5)) {
//printf("BLUE BLUE BLUE\r\n");
// Blue, Color 5
red = 0;
blue = 50;
green = 0;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color++;
}
if (top_wheel && (color == 6)) {
//printf("PURPLE PURPLE PURPLE\r\n");
//Purple, Color 6
red = 50;
blue = 50;
green = 0;
for(j = 0; j < 10; j++)
RGB_LED(red, green, blue);
top_wheel = false;
color = 0;
}
*/
}
}
C# Bitmap to LED Array Program¶
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace BitmapToLEDRotationImage
{
class Program
{
static void Main(string[] args)
{
//File location for the Bitmap Image you want to convert
System.Drawing.Bitmap image = (Bitmap)Bitmap.FromFile("C:\\Users\\Kris\\Dropbox\\Projects\\EasyBMPProject\\TestProject1\\TestProgram1_Csharp\\testImage2.bmp");
//File Location for the Output Arrays for the New Arrays
System.IO.StreamWriter file = new System.IO.StreamWriter("C:\\Users\\Kris\\Dropbox\\Projects\\EasyBMPProject\\TestProject1\\TestProgram1_Csharp\\test.txt");
//Initializing Arrays for Color Components of the Bitmap Images
int[,] redOld = new int[21,21];
int[,] grnOld = new int[21,21];
int[,] bluOld = new int[21,21];
//Initializing Arrays for Color Components of the Converted Bitmap Images
int[,] redNew = new int[36, 10];
int[,] grnNew = new int[36, 10];
int[,] bluNew = new int[36, 10];
//Embedded For Loop for Creating Color Arrays for the Original Bitmap Image
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 21; j++)
{
Color pixelColor = image.GetPixel(i, j);
int g = pixelColor.G / 6;
grnOld[i, j] = g;
int b = pixelColor.B / 6;
bluOld[i, j] = b;
int r = pixelColor.R / 6;
redOld[i, j] = r;
int a = pixelColor.A / 6;
string text = String.Format("Index ({4},{5}) has these ARGB values: Alpha:{0}, " +
"red:{1}, green: {2}, blue {3}\r\n", new object[] { a, r, g, b, i, j });
System.Console.Write(text);
}
}
//Embedded For Loop for Finding the New Color Arrays for the LED Bicycle Wheel
int theta; // Variable for Angle in Degrees
double newTheta; // Variable for the Converted Angle in Radians
float oldX = 0; // Starting "X" Coordinate
double newX; // Variable for Converting Old "X" Point to new point after degree rotation
double newY; // Variable for Converting Old "Y" Point to new point after degree rotation
int rowIndex = 0; // Variable for keeping the Rows Managable
for (theta = 0; theta > -360; theta -= 10) // Cycles through the degrees from 0 to 360
{
newTheta = (double)(theta * 3.14) / 180; // Converts Values from degrees to Radians
for (int oldY = 1; oldY < 11; oldY++) // Cycles through points 1 through 10 on the Y axis
{
newX = 10.5 + oldX * Math.Cos(newTheta) - oldY * Math.Sin(newTheta); // Value for Finding the "X" index for the color "theta" degrees away from the other point
newY = 10.5 + oldX * Math.Sin(newTheta) + oldY * Math.Cos(newTheta); // Value for Finding the "Y" index for the color "theta" degrees away from the other point
redNew[rowIndex, oldY - 1] = redOld[(int)newY, (int)newX]; // Uses "newX" and "newY" to find the color for the new index for the red array
grnNew[rowIndex, oldY - 1] = grnOld[(int)newY, (int)newX]; // Uses "newX" and "newY" to find the color for the new index for the red array
bluNew[rowIndex, oldY - 1] = bluOld[(int)newY, (int)newX]; // Uses "newX" and "newY" to find the color for the new index for the red array
}
rowIndex++;
}
//Embedded For Loops for Writing the Color Arrays to a Text File
string redMessage = "RED,";
file.Write(redMessage);
file.Write("\r\n");
for (int i = 0; i < 36; i++)
{
for (int j = 0; j < 10; j++)
{
string text = String.Format("{0},", new object[] { redNew[i, j] });
file.Write(text);
}
file.Write("\r\n");
}
string bluMessage = "BLUE,";
file.Write(bluMessage);
file.Write("\r\n");
for (int i = 0; i < 36; i++)
{
for (int j = 0; j < 10; j++)
{
string text = String.Format("{0},", new object[] { bluNew[i, j] });
file.Write(text);
}
file.Write("\r\n");
}
string grnMessage = "Green,";
file.Write(grnMessage);
file.Write("\r\n");
for (int i = 0; i < 36; i++)
{
for (int j = 0; j < 10; j++)
{
string text = String.Format("{0},", new object[] { grnNew[i, j] });
file.Write(text);
}
file.Write("\r\n");
}
file.Close();
while (true) { };
}
}
}