Date: 2/19/2016
Scrolling text looks great on even the lowest resolution displays. The persistence of vision effect is so strong that the words move by and I never notice the pixels. I remembered some really tiny pixelated typefaces including Silkscreen and thought I could easily get that working in Processing. I got the typeface loaded in Processing just fine, but when I scaled it down to just 5 pixels tall the text was very blurry.
I wasn't sure how to fix that problem so I decided to just make some high-res images with text, scale them down, and display the images. It's not ideal, doesn't allow for any adjustment or customization, but worked just fine for the moment.
Below is a video of text scrolling across the flip-dot display:
Here's a video of the reflection off the display onto the ceiling:
And, after an image of the text I used, the code for scrolling text:
// Scroll Text 2
//
// For LinkSprite V3 and AlfaZeta flip-dot display
// by Michael Shaub 2016
import processing.serial.*;
// The serial port:
Serial myPort;
int frameDelay = 50;
//variables for flipDot
int rowCounter = 0;
int row1 = 0; //hold variable for row1
int row2 = 0; //hold variable for row2
int row3 = 0; //hold variable for row3
int row4 = 0; //hold variable for row4
int row5 = 0; //hold variable for row5
int row6 = 0; //hold variable for row6
int row7 = 0; //hold variable for row7
int rowArray[ ] = {0,0,0,0,0,0,0};
boolean mirrorX = true; //flip Left & Right?
boolean mirrorY = false; //flip Top & Bottom?
int dotSize = 50; //diameter of the dots - for preview
PImage pix = createImage(28,7, RGB); //PImage to hold the actual size image
int pixLength = pix.width*pix.height; //total amount of pixels
boolean drawRow = false; //use to alternate drawing a row of dots or skipping
float a = 0.0;
float inc = TWO_PI/25.0;
PGraphics pixOrig; //PGraphics to hold the actual size image
PImage text1;
PImage text2;
PImage text3;
int scrollCounter = 0;
int textSelector = 1;
void setup(){
size(1400,350);
// List all the available serial ports:
printArray(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[0], 57600);
ellipseMode(CORNER);
noStroke();
//frameRate(3);
text1 = loadImage("artatthemca.png"); //PImage for text image
text2 = loadImage("2.png"); //PImage for text image
text3 = loadImage("3.png"); //PImage for text image
pixOrig = createGraphics(28,7); //PGraphics to hold the actual size image
//preset the PImage
pix.loadPixels();
for(int i=0; i<pixLength; i++){
pix.pixels[i] = color(0); //set each pixel to black
}
pix.updatePixels();
}
void draw(){
background(35);
switch(textSelector){
case(1):
if(scrollCounter > text1.width+pixOrig.width){
scrollCounter = 0;
textSelector++;
}
break;
case(2):
if(scrollCounter > text2.width+pixOrig.width){
scrollCounter = 0;
textSelector++;
}
break;
case(3):
if(scrollCounter > text3.width+pixOrig.width){
scrollCounter = 0;
textSelector++;
}
break;
}
if(textSelector > 3) textSelector = 1;
//Draw Text
pixOrig.beginDraw();
pixOrig.background(0);
switch(textSelector){
case(1):
pixOrig.image(text1, pixOrig.width-scrollCounter, 0); //draw text starting offscreen to the right
break;
case(2):
pixOrig.image(text2, pixOrig.width-scrollCounter, 0); //draw text starting offscreen to the right
break;
case(3):
pixOrig.image(text3, pixOrig.width-scrollCounter, 0); //draw text starting offscreen to the right
break;
}
pixOrig.endDraw();
//do dithering biz here
pix.loadPixels();
pixOrig.loadPixels();
for(int y=0; y<7; y++){
for(int x=0; x<28; x++){
color oldpixel = pixOrig.get(x, y);
color newpixel = findClosestColor( color(brightness(oldpixel) + random(-100,100)) ); //the wider the range of randomness the "softer" the result. Lower is harder edge
pix.pixels[x+y*pix.width] = newpixel; //copy colors from one image to the other
}
}
pix.updatePixels();
//draw on screen
pix.loadPixels();
for(int j=0; j<7; j++){
for(int i=0; i<28; i++){
if(i < 7) {
if(mirrorX){
rowArray[6-i] = int( red(pix.pixels[i+j*pix.width])/255); //for now, only do for the 1st 7 columns
}else{
rowArray[i] = int( red(pix.pixels[i+j*pix.width])/255); //for now, only do for the 1st 7 columns
}
println( rowArray[i] );
}
fill( pix.pixels[i+j*pix.width] ); //read pixel values, set fill color to that
ellipse(i*dotSize,j*dotSize,dotSize,dotSize);
}
rowCounter = j;
prepDotRow(j); //set the row through bitwise operations
}
printToFlipDots(); //call the flipDot conversion
scrollCounter++;
delay (frameDelay);
}
void prepDotRow(int rowNum){
int tempRowCounter = rowNum+1;
if(mirrorY) tempRowCounter = 7-rowNum;
//bitshift values from array
for(int i=0; i<rowArray.length; i++){
int a = rowArray[i];
int b = a << i; //bitshift the value the number of positions equal to the digit
switch(tempRowCounter){
case 1:
row1 = row1 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 2:
row2 = row2 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 3:
row3 = row3 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 4:
row4 = row4 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 5:
row5 = row5 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 6:
row6 = row6 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 7:
row7 = row7 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
}
}
}
void printToFlipDots(){
int test_2[]= {0x80, 0x87, 0xFF, row1, row2, row3, row4, row5, row6, row7, 0x8F};
//int test_2[]= {0x80, 0x87, 0xFF, 0, rowCounter, scrollCounter, 0, 0, 0, 0, 0x8F};
for(int i=0; i<test_2.length; i++){
myPort.write(test_2[i]);
}
//reset row values for next frame
row1 = 0;
row2 = 0;
row3 = 0;
row4 = 0;
row5 = 0;
row6 = 0;
row7 = 0;
}
void keyPressed(){
if(key == 'x') mirrorX = ! mirrorX;
if(key == 'y') mirrorY = ! mirrorY;
}
color findClosestColor(color c) {
color r;
// Treshold function
if (brightness(c) < 128) {
r = color(0);
}
else {
r = color(255);
}
return r;
}
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.