Components and supplies
Arduino Nano R3
SainSmart MAX7219 Dot Matrix Module 4 in one for Arduino
NulSom Inc. Ultra Compact RS232 to TTL Converter with Male DB9 (3.3V to 5V)
Project description
Code
My Scrolling Marquee
arduino
My first public posting of code. Please feel free to comment back with suggestions. I used 2 samples and pieced them together based on the status of D2 for controlling of scrolling the message.
1// kayaking_t 2// my office marquee - currently connected via Contact Closure and RS232 to a Crestron MP3E for message control. 3// 4// Use the MD_MAX72XX library to scroll text on the display 5// 6// Demonstrates the use of the callback function to control what 7// is scrolled on the display text. 8// 9// User can enter text on the serial monitor and this will display as a 10// scrolling message on the display. 11// Speed for the display is controlled by a pot on SPEED_IN analog in. 12 13#include <MD_MAX72xx.h> 14#include <SPI.h> 15 16#define PRINT_CALLBACK 0 17 18#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); } 19 20// Define the number of devices we have in the chain and the hardware interface 21// NOTE: These pin numbers will probably not work with your hardware and may 22// need to be adapted 23#define HARDWARE_TYPE MD_MAX72XX::FC16_HW 24#define MAX_DEVICES 8 25 26#define CLK_PIN 13 // Digital or SCK - // originally pin 13 27#define DATA_PIN 11 // PWM or MOSI - // originally pin 11 28#define CS_PIN 10 // PWM or SS - // originally pin 10 29 30// SPI hardware interface 31MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); 32 33// Scrolling parameters 34#define SCROLL_DELAY 75 // in milliseconds 35 36#define CHAR_SPACING 1 // pixels between characters 37 38// Global message buffers shared by Serial and Scrolling functions 39#define BUF_SIZE 75 40char curMessage[BUF_SIZE]; 41char newMessage[BUF_SIZE]; 42bool newMessageAvailable = false; 43 44uint16_t scrollDelay; // in milliseconds 45 46// scrolling/static switch status 47const int scrollSwitch = 2; 48int scrollYes = 0; 49 50void readSerial(void) 51{ 52 static uint8_t putIndex = 0; 53 54 while (Serial.available()) 55 { 56 newMessage[putIndex] = (char)Serial.read(); 57 //Serial.println(newMessage); 58 if ((newMessage[putIndex] == '\ 59') || (putIndex >= BUF_SIZE-3)) // end of message character or full buffer 60 { 61 // put in a message separator and end the string 62 newMessage[putIndex++] = ' '; 63 newMessage[putIndex] = '\\0'; 64 // restart the index for next filling spree and flag we have a message waiting 65 putIndex = 0; 66 newMessageAvailable = true; 67 } 68 else if (newMessage[putIndex] != '\ ') 69 // Just save the next char in next location 70 putIndex++; 71 } 72} 73 74void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col) 75// Callback function for data that is being scrolled off the display 76{ 77#if PRINT_CALLBACK 78 Serial.print("\ 79 cb "); 80 Serial.print(dev); 81 Serial.print(' '); 82 Serial.print(t); 83 Serial.print(' '); 84 Serial.println(col); 85#endif 86} 87 88uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t) 89// Callback function for data that is required for scrolling into the display 90{ 91 static char *p = curMessage; 92 static uint8_t state = 0; 93 static uint8_t curLen, showLen; 94 static uint8_t cBuf[8]; 95 uint8_t colData; 96 97 // finite state machine to control what we do on the callback 98 switch(state) 99 { 100 case 0: // Load the next character from the font table 101 showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf); 102 curLen = 0; 103 state++; 104 105 // if we reached end of message, reset the message pointer 106 if (*p == '\\0') 107 { 108 p = curMessage; // reset the pointer to start of message 109 if (newMessageAvailable) // there is a new message waiting 110 { 111 strcpy(curMessage, newMessage); // copy it in 112 newMessageAvailable = false; 113 } 114 } 115 // !! deliberately fall through to next state to start displaying 116 117 case 1: // display the next part of the character 118 colData = cBuf[curLen++]; 119 if (curLen == showLen) 120 { 121 showLen = CHAR_SPACING; 122 curLen = 0; 123 state = 2; 124 } 125 break; 126 127 case 2: // display inter-character spacing (blank column) 128 colData = 0; 129 curLen++; 130 if (curLen == showLen) 131 state = 0; 132 break; 133 134 default: 135 state = 0; 136 } 137 138 return(colData); 139} 140 141 void scrollText(void) 142{ 143 static uint32_t prevTime = 0; 144 145 // Is it time to scroll the text? 146 if (millis()-prevTime >= scrollDelay) 147 { 148 mx.transform(MD_MAX72XX::TSL); // scroll along - the callback will load all the data 149 prevTime = millis(); // starting point for next time 150 } 151} 152 153void printText(uint8_t modStart, uint8_t modEnd, char *pMsg) 154// Print the text string to the LED matrix modules specified. 155// Message area is padded with blank columns after printing. 156{ 157 uint8_t state = 0; 158 uint8_t curLen; 159 uint16_t showLen; 160 uint8_t cBuf[8]; 161 int16_t col = ((modEnd + 1) * COL_SIZE) - 1; 162 163 mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF); 164 165 do // finite state machine to print the characters in the space available 166 { 167 switch(state) 168 { 169 case 0: // Load the next character from the font table 170 // if we reached end of message, reset the message pointer 171 if (*pMsg == '\\0') 172 { 173 showLen = col - (modEnd * COL_SIZE); // padding characters 174 state = 2; 175 break; 176 } 177 178 // retrieve the next character form the font file 179 showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf); 180 curLen = 0; 181 state++; 182 // !! deliberately fall through to next state to start displaying 183 184 case 1: // display the next part of the character 185 mx.setColumn(col--, cBuf[curLen++]); 186 187 // done with font character, now display the space between chars 188 if (curLen == showLen) 189 { 190 showLen = CHAR_SPACING; 191 state = 2; 192 } 193 break; 194 195 case 2: // initialize state for displaying empty columns 196 curLen = 0; 197 state++; 198 // fall through 199 200 case 3: // display inter-character spacing or end of message padding (blank columns) 201 mx.setColumn(col--, 0); 202 curLen++; 203 if (curLen == showLen) 204 state = 0; 205 break; 206 207 default: 208 col = -1; // this definitely ends the do loop 209 } 210 } while (col >= (modStart * COL_SIZE)); 211 212 mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON); 213} 214 215 216 217 218void setup() 219{ 220 mx.begin(); 221 mx.setShiftDataInCallback(scrollDataSource); 222 mx.setShiftDataOutCallback(scrollDataSink); 223 224 scrollDelay = SCROLL_DELAY; 225 226 strcpy(curMessage, "AV Rocks! "); 227 newMessage[0] = '\\0'; 228 229 Serial.begin(57600); 230 Serial.print("\ 231[MD_MAX72XX Message Display]\ 232Type a message for the scrolling display\ 233End message line with a newline"); 234} 235 236void loop() 237{ 238 scrollYes = digitalRead(scrollSwitch); 239 readSerial(); 240 if (scrollYes == 0){ 241 printText(0, MAX_DEVICES-1, newMessage); 242 } else { 243 scrollText(); 244 } 245} 246
My Scrolling Marquee
arduino
My first public posting of code. Please feel free to comment back with suggestions. I used 2 samples and pieced them together based on the status of D2 for controlling of scrolling the message.
1// kayaking_t 2// my office marquee - currently connected via Contact Closure and RS232 to a Crestron MP3E for message control. 3// 4// Use the MD_MAX72XX library to scroll text on the display 5// 6// Demonstrates the use of the callback function to control what 7// is scrolled on the display text. 8// 9// User can enter text on the serial monitor and this will display as a 10// scrolling message on the display. 11// Speed for the display is controlled by a pot on SPEED_IN analog in. 12 13#include <MD_MAX72xx.h> 14#include <SPI.h> 15 16#define PRINT_CALLBACK 0 17 18#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); } 19 20// Define the number of devices we have in the chain and the hardware interface 21// NOTE: These pin numbers will probably not work with your hardware and may 22// need to be adapted 23#define HARDWARE_TYPE MD_MAX72XX::FC16_HW 24#define MAX_DEVICES 8 25 26#define CLK_PIN 13 // Digital or SCK - // originally pin 13 27#define DATA_PIN 11 // PWM or MOSI - // originally pin 11 28#define CS_PIN 10 // PWM or SS - // originally pin 10 29 30// SPI hardware interface 31MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); 32 33// Scrolling parameters 34#define SCROLL_DELAY 75 // in milliseconds 35 36#define CHAR_SPACING 1 // pixels between characters 37 38// Global message buffers shared by Serial and Scrolling functions 39#define BUF_SIZE 75 40char curMessage[BUF_SIZE]; 41char newMessage[BUF_SIZE]; 42bool newMessageAvailable = false; 43 44uint16_t scrollDelay; // in milliseconds 45 46// scrolling/static switch status 47const int scrollSwitch = 2; 48int scrollYes = 0; 49 50void readSerial(void) 51{ 52 static uint8_t putIndex = 0; 53 54 while (Serial.available()) 55 { 56 newMessage[putIndex] = (char)Serial.read(); 57 //Serial.println(newMessage); 58 if ((newMessage[putIndex] == '\n') || (putIndex >= BUF_SIZE-3)) // end of message character or full buffer 59 { 60 // put in a message separator and end the string 61 newMessage[putIndex++] = ' '; 62 newMessage[putIndex] = '\\0'; 63 // restart the index for next filling spree and flag we have a message waiting 64 putIndex = 0; 65 newMessageAvailable = true; 66 } 67 else if (newMessage[putIndex] != '\r') 68 // Just save the next char in next location 69 putIndex++; 70 } 71} 72 73void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col) 74// Callback function for data that is being scrolled off the display 75{ 76#if PRINT_CALLBACK 77 Serial.print("\ 78 cb "); 79 Serial.print(dev); 80 Serial.print(' '); 81 Serial.print(t); 82 Serial.print(' '); 83 Serial.println(col); 84#endif 85} 86 87uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t) 88// Callback function for data that is required for scrolling into the display 89{ 90 static char *p = curMessage; 91 static uint8_t state = 0; 92 static uint8_t curLen, showLen; 93 static uint8_t cBuf[8]; 94 uint8_t colData; 95 96 // finite state machine to control what we do on the callback 97 switch(state) 98 { 99 case 0: // Load the next character from the font table 100 showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf); 101 curLen = 0; 102 state++; 103 104 // if we reached end of message, reset the message pointer 105 if (*p == '\\0') 106 { 107 p = curMessage; // reset the pointer to start of message 108 if (newMessageAvailable) // there is a new message waiting 109 { 110 strcpy(curMessage, newMessage); // copy it in 111 newMessageAvailable = false; 112 } 113 } 114 // !! deliberately fall through to next state to start displaying 115 116 case 1: // display the next part of the character 117 colData = cBuf[curLen++]; 118 if (curLen == showLen) 119 { 120 showLen = CHAR_SPACING; 121 curLen = 0; 122 state = 2; 123 } 124 break; 125 126 case 2: // display inter-character spacing (blank column) 127 colData = 0; 128 curLen++; 129 if (curLen == showLen) 130 state = 0; 131 break; 132 133 default: 134 state = 0; 135 } 136 137 return(colData); 138} 139 140 void scrollText(void) 141{ 142 static uint32_t prevTime = 0; 143 144 // Is it time to scroll the text? 145 if (millis()-prevTime >= scrollDelay) 146 { 147 mx.transform(MD_MAX72XX::TSL); // scroll along - the callback will load all the data 148 prevTime = millis(); // starting point for next time 149 } 150} 151 152void printText(uint8_t modStart, uint8_t modEnd, char *pMsg) 153// Print the text string to the LED matrix modules specified. 154// Message area is padded with blank columns after printing. 155{ 156 uint8_t state = 0; 157 uint8_t curLen; 158 uint16_t showLen; 159 uint8_t cBuf[8]; 160 int16_t col = ((modEnd + 1) * COL_SIZE) - 1; 161 162 mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF); 163 164 do // finite state machine to print the characters in the space available 165 { 166 switch(state) 167 { 168 case 0: // Load the next character from the font table 169 // if we reached end of message, reset the message pointer 170 if (*pMsg == '\\0') 171 { 172 showLen = col - (modEnd * COL_SIZE); // padding characters 173 state = 2; 174 break; 175 } 176 177 // retrieve the next character form the font file 178 showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf); 179 curLen = 0; 180 state++; 181 // !! deliberately fall through to next state to start displaying 182 183 case 1: // display the next part of the character 184 mx.setColumn(col--, cBuf[curLen++]); 185 186 // done with font character, now display the space between chars 187 if (curLen == showLen) 188 { 189 showLen = CHAR_SPACING; 190 state = 2; 191 } 192 break; 193 194 case 2: // initialize state for displaying empty columns 195 curLen = 0; 196 state++; 197 // fall through 198 199 case 3: // display inter-character spacing or end of message padding (blank columns) 200 mx.setColumn(col--, 0); 201 curLen++; 202 if (curLen == showLen) 203 state = 0; 204 break; 205 206 default: 207 col = -1; // this definitely ends the do loop 208 } 209 } while (col >= (modStart * COL_SIZE)); 210 211 mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON); 212} 213 214 215 216 217void setup() 218{ 219 mx.begin(); 220 mx.setShiftDataInCallback(scrollDataSource); 221 mx.setShiftDataOutCallback(scrollDataSink); 222 223 scrollDelay = SCROLL_DELAY; 224 225 strcpy(curMessage, "AV Rocks! "); 226 newMessage[0] = '\\0'; 227 228 Serial.begin(57600); 229 Serial.print("\ 230[MD_MAX72XX Message Display]\ 231Type a message for the scrolling display\ 232End message line with a newline"); 233} 234 235void loop() 236{ 237 scrollYes = digitalRead(scrollSwitch); 238 readSerial(); 239 if (scrollYes == 0){ 240 printText(0, MAX_DEVICES-1, newMessage); 241 } else { 242 scrollText(); 243 } 244} 245
Downloadable files
Office Marquee
Here's the fritzing file - my first attempt...
Office Marquee
Office Marquee
Here's the fritzing file - my first attempt...
Office Marquee
Documentation
Oak Enclosure
Not 100% accurate as I did have to make some modifications during installation.
Oak Enclosure
Comments
Only logged in users can leave comments