Warning: Incomplete write-up.
Server Side:
Image –> Resize to 16px height –> Determine Pixel Red, Green and Blue components –> Compensate, arrange and bit-shift values to a byte string of 12 bit PWM (Pulse Width Modulation) values.
Micro-controller:
Use hall effect sensor for positioning –> Display RGB PWM image using internal microcontroller timers and serial communication.
Potential next steps:
- Add phase locked loop (PLL) clock multiplier to GSCLK line for faster display timing (4096 clock cycles)
- Modify library for multiplied GSCLK signal, allow “frames” to be imported on the fly via serial (or possibly parallel)
- Use an ESP8266 ESP-07 to get frames over TCP and relay those frames to the Arduino on the fly.
- Update PHP to have the fan automatically display new images
- Build transformer for power transmission from fan housing to fan blade.
Custom circuit boards, diodes on Red LEDs due to lower forward voltage.
PHP code adapted from Alex Leone’s original greyscale JAVA code:
[code language=”php”]
<?php
$source_file = "latest.png";
//$im = ImageCreateFromPng($source_file); //For later use
//$im = ImageCreateFromJpeg($source_file); //For later use
function imageCreateFromAny($filepath) {
$type = exif_imagetype($filepath); // [] if you don’t have exif you could use getImageSize()
$allowedTypes = array(
1, // [] gif
2, // [] jpg
3, // [] png
6 // [] bmp
);
if (!in_array($type, $allowedTypes)) {
return false;
}
switch ($type) {
case 1 :
$im = imageCreateFromGif($filepath);
break;
case 2 :
$im = imageCreateFromJpeg($filepath);
break;
case 3 :
$im = imageCreateFromPng($filepath);
break;
case 6 :
$im = imageCreateFromBmp($filepath);
break;
}
return $im;
}
$im = ImageCreateFromAny($source_file);
$imgw = imagesx($im);
$imgh = imagesy($im);
$line = "#define ANIRGB_FRAMES ".($imgw).PHP_EOL;// "\r\n"; // PHP_EOL;
//echo $line;
$data = $line;
$line = "uint8_t aniRGB[NUM_TLCS * 24 * ANIRGB_FRAMES] PROGMEM = {".PHP_EOL;
//echo $line;
$data .= $line;
for ($i=$imgw; $i>0; $i–)
{
for ($j=0; $j <= ($imgh – 1); $j+=2)
{
// get the rgb value for current pixel
$rgb = ImageColorAt($im, $i, $j);
$rgb2 = ImageColorAt($im, $i, ($j + 1));
// extract each value for r, g, b
/*
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
*/
$a = (int)round(0.4 * (($rgb >> 16) & 0xFF));
$b = (int)round(0.8 * (($rgb >> 8) & 0xFF));
$c = (int)($rgb & 0xFF);
$d = (int)round(0.4 * (($rgb2 >> 16) & 0xFF));
$e = (int)round(0.8 * (($rgb2 >> 8) & 0xFF));
$f = (int)($rgb2 & 0xFF);
// echo $a.",".$b.",".$c.",".$d.",".$e.",".$f.",,"; //DEBUG
$line = ((((int)$a >> 4) & 0xFF).",".((((int)$a << 4) | ((int)$b >> 8)) & 0xFF).",".((int)$b & 0xFF).",".(((int)$c >> 4) & 0xFF).",".(((int)($c << 4) | ((int)$d >> 8)) & 0xFF).",".((int)$d & 0xFF).",".(((int)$e >> 4) & 0xFF).",".((((int)$e << 4) | ((int)$f >> 8)) & 0xFF).",".((int)$f & 0xFF).",");//.PHP_EOL;
//echo $line;
$data .= $line;
}
$line = PHP_EOL;
//echo $line;
$data .= $line;
}
$line = "};".PHP_EOL;
//echo $line;
$data .= $line;
//echo $data;
$myFile = "aniRGB.h";
$fh = fopen($myFile, ‘w’) or die("can’t open file");
fwrite($fh, $data);
fclose($fh);
?>
[/code]
Arduino Code based on TLC5940 Library animation sketch and customised accordingly
[code]
/*
Writes "Ardunio" with Persistance of Vision (POV) with 16 LEDs (output 0
is on bottom, output 15 is top). The animation below doesn’t work with
more than 1 TLC.
I generated the animation with the included java code:
<arduino folder>/hardware/libraries/Tlc5940/examples/BasicAnimations
To use the code, run
java AnimationCreator
in the folder above and it will parse all images in the folder to
.h files. For best results use images that are 16 pixels high.
See the BasicUse example for hardware setup.
Alex Leone <acleone ~AT~ gmail.com>, 2009-02-03 */
#include "Tlc5940.h"
#include "tlc_animations.h"
#include "aniRGB.h"
const int hallPin = 7;
void setup()
{
Tlc.init();
delay(5000);
}
void loop()
{
if (digitalRead(hallPin) == HIGH) {
}
else if (!tlc_onUpdateFinished) { // checks to see if the animation is finished playing
/*
void tlc_playAnimation(prog_uint8_t *animation, uint16_t frames,
uint16_t periodsPerFrame);
periods per frame is PWM periods, 1.024ms per frame (0 is valid – this
will play the animation as fast as possible).
Plays an animation in the "background".
Don’t call Tlc.update() while this is running.
You can check if this is done with !tlc_onUpdateFinished */
tlc_playAnimation(aniRGB, ANIRGB_FRAMES, 0);
// If you don’t want to do anything until it’s finished, use:
// while (!tlc_onUpdateFinished);
}
else {
//wait
}
}
[/code]