Scrolling Text Display
A scrolling text display, using 294 LEDs to simulate a stock exchange ticker.
Components and supplies
1
Arduino UNO
1
WS2812 Addressable LED Strip
1
5V 4000mA Switching Power Supply
Apps and platforms
1
Arduino IDE
Project description
Code
Scrolling Text Display - Code
arduino
Scrolling text display - code Hard coded string & output colours due to issues that I didn't have time to fully debug. I appreciate it's not the prettiest code, and there are certainly going to be more efficient ways to do it, but I ran out of time to make a perfect solution, and this worked for how I needed it.
1#include <Adafruit_NeoPixel.h> 2#include <Stdint.h> 3 4#ifdef __AVR__ 5#include <avr/power.h> 6#endif 7 8#define stripPin 6 9#define stripPinB 9 10 11#define ledTotal 150 // zero indexed, so one less than you need. I.e. 50 leds = 49 here 12#define ledTotalB 144 // zero indexed... 13#define rowSize 6 // zero indexed... 14#define columnSize 41 // zero indexed... 15#define charWidth 5 // ** one indexed ** 16 17byte displayOutput[columnSize + 1] = {0}; 18byte displayColors[columnSize + 1] = {0}; 19byte currentStatus = 0; // 0 = off, 1 = on 20unsigned int maxLoad = 0; 21 22// was 68 with lower case chars, 42 without -- 40 without l/r arrow -- 42 WITH PLUS AND DOT 23byte displayLetters[42][charWidth] = { // [A] = chars/digits contained in array, [B] = charWidth (no need to add 1, as was 'one indexed' at #define) 24 {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0 // , 0x00 25 {0x00, 0x42, 0x7f, 0x40, 0x00}, // 1 26 {0x42, 0x61, 0x51, 0x49, 0x46}, // 2 27 {0x21, 0x41, 0x45, 0x4b, 0x31}, // 3 28 {0x18, 0x14, 0x12, 0x7f, 0x10}, // 4 29 {0x27, 0x45, 0x45, 0x45, 0x39}, // 5 30 {0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6 31 {0x01, 0x71, 0x09, 0x05, 0x03}, // 7 32 {0x36, 0x49, 0x49, 0x49, 0x36}, // 8 33 {0x06, 0x49, 0x49, 0x29, 0x1e}, // 9 34 35 {0x7e, 0x11, 0x11, 0x11, 0x7e}, // A 36 {0x7f, 0x49, 0x49, 0x49, 0x36}, // B 37 {0x3e, 0x41, 0x41, 0x41, 0x22}, // C 38 {0x7f, 0x41, 0x41, 0x22, 0x1c}, // D 39 {0x7f, 0x49, 0x49, 0x49, 0x41}, // E 40 {0x7f, 0x09, 0x09, 0x09, 0x01}, // F 41 {0x3e, 0x41, 0x49, 0x49, 0x7a}, // G 42 {0x7f, 0x08, 0x08, 0x08, 0x7f}, // H 43 {0x00, 0x41, 0x7f, 0x41, 0x00}, // I 44 {0x20, 0x40, 0x41, 0x3f, 0x01}, // J 45 {0x7f, 0x08, 0x14, 0x22, 0x41}, // K 46 {0x7f, 0x40, 0x40, 0x40, 0x40}, // L 47 {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M 48 {0x7f, 0x04, 0x08, 0x10, 0x7f}, // N 49 {0x3e, 0x41, 0x41, 0x41, 0x3e}, // O 50 {0x7f, 0x09, 0x09, 0x09, 0x06}, // P 51 {0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q 52 {0x7f, 0x09, 0x19, 0x29, 0x46}, // R 53 {0x46, 0x49, 0x49, 0x49, 0x31}, // S 54 {0x01, 0x01, 0x7f, 0x01, 0x01}, // T 55 {0x3f, 0x40, 0x40, 0x40, 0x3f}, // U 56 {0x1f, 0x20, 0x40, 0x20, 0x1f}, // V 57 {0x3f, 0x40, 0x38, 0x40, 0x3f}, // W 58 {0x63, 0x14, 0x08, 0x14, 0x63}, // X 59 {0x07, 0x08, 0x70, 0x08, 0x07}, // Y 60 {0x61, 0x51, 0x49, 0x45, 0x43}, // Z 61 62 {0x00, 0x00, 0x00, 0x00, 0x00}, // space 63 {0x10, 0x18, 0x1c, 0x18, 0x10}, // new up arrow 64 {0x04, 0x0c, 0x1c, 0x0c, 0x04}, // new down arrow 65 {0x08, 0x08, 0x08, 0x08, 0x08}, // dash / maintain 66 {0x08, 0x08, 0x3E, 0x08, 0x08}, // plus 67 {0x00, 0x60, 0x60, 0x00, 0x00} // full stop 68}; 69 70const int stockQty = 17; // this is the amount of different stock values to be contained, *!* ONE indexed *!* 71const int stockStepQty = 5; // *!* ONE indexed *!* 72int stockStep = 0; 73/*String stockNames[stockQty] = { 74 "MH", "EJ", "SG", "MC", "AS", "JWL", "RP", "HCJ", "JT", "KC", "HCN", "MK", "JWK", "RB", "KS", "EC", "AW" 75};*/ 76/*int stockValues[stockStepQty][stockQty] = { // dies 3 from end, color wise 77 {5, 12, 41, 52, 157, 74, 63, 96, 17, 86, 104, 49, 76, 46, 91, 61, 121}, 78 {6, 13, 40, 52, 155, 73, 60, 98, 18, 85, 105, 48, 77, 47, 90, 59, 125}, 79 {6, 12, 39, 53, 155, 75, 58, 99, 18, 84, 104, 46, 78, 46, 88, 60, 123}, 80 {7, 11, 42, 55, 156, 74, 59, 98, 17, 85, 106, 47, 77, 45, 92, 58, 124}, 81 {6, 13, 40, 54, 157, 75, 60, 97, 18, 85, 105, 48, 77, 46, 95, 60, 122} 82};*/ 83 84Adafruit_NeoPixel strip = Adafruit_NeoPixel(ledTotal + 1, stripPin, NEO_RGB + NEO_KHZ800); 85Adafruit_NeoPixel stripB = Adafruit_NeoPixel(ledTotalB + 1, stripPinB, NEO_RGB + NEO_KHZ800); 86 87void setup() { 88 strip.begin(); 89 strip.show(); 90 stripB.begin(); 91 stripB.show(); 92 93 pinMode(13, OUTPUT); 94} 95String inputString = "MJC|-5 CDL|-1 HJC^+10 MAK^+2 GJK|-8 EBJ^+5 HJC^+10 JCW^+0.02 ADS|-3 SEG^+5 RFB^+7 KGO^+2 MJH|-0.043 KHS^+0.054 SIC^0.008 EJC^+0.001 AMW^+5 LDK|-7 JCT^+9 JKM^+4 RJP|-4 SKC^+9 JLW|-5 HKC^+5 LMP^+7 ANS^+5 "; 96String colString = "0001110000111000022220000222000011100002220000222200002222220000111000022200002220000222000011111110000222222200002222220000222222200002220000111000022200002220000111000022200001110000222000022200002220"; 97 98void loop() { 99 for (int i = 0; i < inputString.length(); i++) { 100 char currentChar = inputString[i]; 101 int currentCol, colorMode;// = int(colString[i]) - 48; // minus 48 because int("0") will return the ascii value of char '0' (48) 102 103 if ((currentChar >= 'A') && (currentChar <= 'Z')) { 104 currentCol = 0; 105 } else if (((currentChar >= '0') && (currentChar <= '9')) || (currentChar == '+') || (currentChar == '-')) { 106 currentCol = colorMode; 107 } else if (currentChar == '^') { 108 colorMode = 2; 109 currentCol = colorMode; 110 } else if (currentChar == '|') { 111 colorMode = 1; 112 currentCol = colorMode; 113 } 114 115 int indexValue; 116 if ((currentChar >= '0') && (currentChar <= '9')) indexValue = currentChar - 48; // 0-9 117 else if ((currentChar >= 'A') && (currentChar <= 'Z')) indexValue = currentChar - 55; // upper case 118 //else if ((currentChar >= 'a') && (currentChar <= 'z')) indexValue = currentChar - 61; // lower case , check that these are in the right place / the offset is correct, as i may have put the array chunk back in the wrong place!! 119 else if ((currentChar == ' ')) indexValue = 36; // space, was 62 when lower case chars 120 else if ((currentChar == '^')) indexValue = 37; // up arrow, was 63 when lower case chars 121 else if ((currentChar == '|')) indexValue = 38; // down arrow, was 64 when lower case chars 122// else if ((currentChar == '<')) indexValue = 39; // left arrow, was 65 when lower case chars 123// else if ((currentChar == '>')) indexValue = 40; // right arrow, was 66 when lower case chars 124 else if ((currentChar == '-')) indexValue = 39; // dash / maintain, was 67 when lower case chars, 41 with l/r arrows 125 else if ((currentChar == '+')) indexValue = 40; // plus 126 else if ((currentChar == '.')) indexValue = 41; // full stop 127 128 for (int x = 0; x < charWidth; x++) { 129 if (currentStatus == 0) currentStatus = 1; 130 else if (currentStatus == 1) currentStatus = 0; 131 setStatusIndicator(currentStatus); 132 133 nudgeColumns(displayLetters[indexValue][x], currentCol); // inputCols[i]); // strip.Color(0,0,255)); 134 displayUpdate(0); 135 136 delay(100); 137 } 138 nudgeColumns(0, 0); // - 1 might break things here? or make things go white due to the lookup default being white 139 if (currentStatus == 0) currentStatus = 1; 140 else if (currentStatus == 1) currentStatus = 0; 141 setStatusIndicator(currentStatus); 142 displayUpdate(0); 143 delay(100); // this will be 200 as per the rest once confirmed that the double jump issue is done! 144 } 145 146 if (stockStep == (stockStepQty - 1)) stockStep = 0; // is this used anymore?! 147 else stockStep++; // as above 148} 149 150int getIntLength(int value){ 151 // Function created by "zed_0xff" at: https://stackoverflow.com/a/3068412/7905386 152 int l=!value; 153 while(value){ l++; value/=10; } 154 return l; 155} 156 157int getMappedPixel(int columnID, int rowID){ 158 int z; 159 160 z = columnSize - columnID; 161 if (columnID % 2) z++; 162 163 z = z* (rowSize + 1); 164 if (columnID % 2) z = z - rowID - 1; 165 else z = z + rowID; 166 167 if (z>= 120) z++; 168 return z; 169} 170 171void setMappedColor(int columnID, int rowID, long pixelColor) { 172 int mappedPixel = getMappedPixel(columnID, rowID); 173 174 if (mappedPixel < ledTotal) { 175 strip.setPixelColor(mappedPixel, pixelColor); 176 } 177 else { 178 mappedPixel = mappedPixel - ledTotal; 179 stripB.setPixelColor(mappedPixel, pixelColor); 180 } 181} 182 183void colorAll(long color) { 184 for (int i = 0; i <= rowSize; i++) { 185 for (int j = 0; j <= columnSize; j++) { 186 setMappedColor(j, i, color); 187 } 188 } 189} 190 191void convertToBits(byte inputValue, int outputArray[]) { 192 //if (inputValue & 0x80) outputArray[0] = 1; // not used? 193 if (inputValue & 0x40) outputArray[0] = 1; 194 if (inputValue & 0x20) outputArray[1] = 1; 195 if (inputValue & 0x10) outputArray[2] = 1; 196 if (inputValue & 0x08) outputArray[3] = 1; 197 if (inputValue & 0x04) outputArray[4] = 1; 198 if (inputValue & 0x02) outputArray[5] = 1; 199 if (inputValue & 0x01) outputArray[6] = 1; 200} 201 202void displayUpdate(long backColor) { 203 colorAll(backColor); 204 205 for (int i = 0; i <= columnSize; i++) { 206 int columnData[rowSize + 1] = {0}; 207 convertToBits(displayOutput[i], columnData); 208 209 for (int j = 0; j <= rowSize; j++) { 210 if (columnData[rowSize-j] == 1) setMappedColor(i, j, colorLookup(displayColors[i])); // was displayColors[i][j] before memory save 211 } 212 } 213 214 strip.show(); 215 stripB.show(); 216} 217 218void nudgeColumns(byte newData, byte newColor) { 219 for (int i = 0; i < columnSize; i++) { 220 displayOutput[i] = displayOutput[i + 1]; 221 for (int j = 0; j <= rowSize; j++) { 222 displayColors[i] = displayColors[i + 1]; 223 } 224 } 225 displayOutput[columnSize] = newData; 226 227 if (newColor >= 0) { // created for memory save 228 for (int k = 0; k <= rowSize; k++) { 229 displayColors[columnSize] = newColor; 230 } 231 } 232} 233 234long colorLookup(int inputColor) { 235 long outputColor = 0; 236 switch (inputColor) { 237 case 0: 238 outputColor = strip.Color(255,255,255); // white 239 break; 240 case 1: 241 outputColor = strip.Color(255,0,0); // red 242 break; 243 case 2: 244 outputColor = strip.Color(0,255,0); // green 245 break; 246 case 3: 247 outputColor = strip.Color(0,0,255); // blue 248 break; 249 case 4: 250 outputColor = strip.Color(255,255,0); // yellow/amber 251 break; 252 case 5: 253 outputColor = strip.Color(0,255,255); // cyan 254 break; 255 case 6: 256 outputColor = strip.Color(255,0,255); // magenta 257 break; 258 default: 259 outputColor = strip.Color(255,255,255); // white 260 break; 261 } 262 263 return outputColor; 264} 265 266void setStatusIndicator(byte inputStatus) { 267 if (inputStatus == 0) { 268 digitalWrite(13, LOW); 269 } else { 270 digitalWrite(13, HIGH); 271 } 272}
Downloadable files
Schematic for scrolling text display
Schematic for scrolling text display

Schematic for scrolling text display
Schematic for scrolling text display

Comments
Only logged in users can leave comments