I'm running into memory issues with an Arduino Nano driving some old HDSP-2000/HDSP-2011 chips.
I cannot seem to get the ASCII 5x7 array into PROGMEM
and have it read properly. It's so low on memory that I set up a second Arduino to send char[]
strings through I2C to keep the Nano from locking up. This sort of worked to my advantage that I can multi-task and I'll probably keep it that way but it still keeps locking up or spitting gibberish.
The display Arduino is constantly bit-banging the displays - multiplexed with two 14-bit (acts as one 28-bit) Serial in / parallel out shift registers and and 5 column drivers. All displays use 5 common anode + columns, which have to be pulse timed with the registers.
#include <Wire.h>
//*** HDSP2011 Display Demo
//*** ASCII-DEMO
//*** [email protected]
//*** Paul Huinink has a webpage on displays www.huinink.info and specifically HDSP200X series displays www.spagmon.com
//*** Modified December-2013 by Patrick Hickey: added HP HDSP single digit display and RGB LED
//*** Patrick Hickey [email protected]
//modified 3/2018 by Brandon McRee - removed support for LED and single digit HDSP DISPLAY
//figure out latch pin
// an array of 5 bytes per ASCII
// 5 bytes cause 5 columns
// 7 bits per column (no LSB)
const byte ascii_5x7[] = { //when I put this in PROGMEM i get gibberish, without it the SRAM is 87% full...
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF2, 0x00, 0x00,// !
0x00, 0xE0, 0x00, 0xE0, 0x00,// "
0x28, 0xFE, 0x28, 0xFE, 0x28,// #
0x24, 0x54, 0xFE, 0x54, 0x48,// $
0xC4, 0xC8, 0x10, 0x26, 0x46,// %
0x6C, 0x92, 0xAA, 0x44, 0x0A,// &
0x00, 0xA0, 0xC0, 0x00, 0x00,// 39
0x00, 0x38, 0x44, 0x82, 0x00,// 40
0x00, 0x82, 0x44, 0x38, 0x00,// 41
0x28, 0x10, 0x7C, 0x10, 0x28,// *
0x10, 0x10, 0x7C, 0x10, 0x10,
0x00, 0x0A, 0x0C, 0x00, 0x00,
0x10, 0x10, 0x10, 0x10, 0x10,
0x00, 0x06, 0x06, 0x00, 0x00,
0x04, 0x08, 0x10, 0x20, 0x40,
0x7C, 0x8A, 0x92, 0xA2, 0x7C,//48 0
0x00, 0x42, 0xFE, 0x02, 0x00,//49 1
0x42, 0x86, 0x8A, 0x92, 0x62,//50 2
0x84, 0x82, 0xA2, 0xD2, 0x8C,
0x18, 0x28, 0x48, 0xFE, 0x08,
0xE4, 0xA2, 0xA2, 0xA2, 0x9C,
0x3C, 0x52, 0x92, 0x92, 0x0C,
0x80, 0x8E, 0x90, 0xA0, 0xC0,
0x6C, 0x92, 0x92, 0x92, 0x6C,
0x60, 0x92, 0x92, 0x94, 0x78,
0x00, 0x6C, 0x6C, 0x00, 0x00,
0x00, 0x6A, 0x6C, 0x00, 0x00,
0x10, 0x28, 0x44, 0x82, 0x00,
0x28, 0x28, 0x28, 0x28, 0x28,
0x00, 0x82, 0x44, 0x28, 0x10,
0x40, 0x80, 0x8A, 0x90, 0x60,
0x4C, 0x92, 0x9E, 0x82, 0x7C,
0x7E, 0x88, 0x88, 0x88, 0x7E,//65 A
0xFE, 0x92, 0x92, 0x92, 0x6C,
0x7C, 0x82, 0x82, 0x82, 0x44,
0xFE, 0x82, 0x82, 0x44, 0x38,
0xFE, 0x92, 0x92, 0x92, 0x82,
0xFE, 0x90, 0x90, 0x90, 0x80,// 70
0x7C, 0x82, 0x92, 0x92, 0x5E,
0xFE, 0x10, 0x10, 0x10, 0xFE,
0x00, 0x82, 0xFE, 0x82, 0x00,
0x04, 0x02, 0x82, 0xFC, 0x80,
0xFE, 0x10, 0x28, 0x44, 0x82,
0xFE, 0x02, 0x02, 0x02, 0x02,
0xFE, 0x40, 0x30, 0x40, 0xFE,
0xFE, 0x20, 0x10, 0x08, 0xFE,
0x7C, 0x82, 0x82, 0x82, 0x7C,
0xFE, 0x90, 0x90, 0x90, 0x60,// P
0x7C, 0x82, 0x8A, 0x84, 0x7A,
0xFE, 0x90, 0x98, 0x94, 0x62,
0x62, 0x92, 0x92, 0x92, 0x8C,
0x80, 0x80, 0xFE, 0x80, 0x80,
0xFC, 0x02, 0x02, 0x02, 0xFC,
0xF8, 0x04, 0x02, 0x04, 0xF8,
0xFC, 0x02, 0x0C, 0x02, 0xFC,
0xC6, 0x28, 0x10, 0x28, 0xC6,
0xE0, 0x10, 0x0E, 0x10, 0xE0,
0x86, 0x8A, 0x92, 0xA2, 0xC2,
0x00, 0xFE, 0x82, 0x82, 0x00,
0x40, 0x20, 0x10, 0x08, 0x04,
0x00, 0x82, 0x82, 0xFE, 0x00,
0x20, 0x40, 0x80, 0x40, 0x20,
0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x80, 0x40, 0x20, 0x00,
0x04, 0x2A, 0x2A, 0x2A, 0x1E,
0xFE, 0x12, 0x12, 0x12, 0x0C,
0x1C, 0x22, 0x22, 0x22, 0x22,
0x0C, 0x12, 0x12, 0x12, 0xFE,// 100 d
0x1C, 0x2A, 0x2A, 0x2A, 0x1A,// 101 e
0x00, 0x10, 0x7E, 0x90, 0x40,
0x12, 0x2A, 0x2A, 0x2A, 0x3C,
0xFE, 0x10, 0x10, 0x10, 0x0E,
0x00, 0x00, 0x5E, 0x00, 0x00,
0x04, 0x02, 0x02, 0xBC, 0x00,
0x00, 0xFE, 0x08, 0x14, 0x22,
0x00, 0x82, 0xFE, 0x02, 0x00,
0x3E, 0x20, 0x1C, 0x20, 0x3E,
0x3E, 0x10, 0x20, 0x20, 0x1E,
0x1C, 0x22, 0x22, 0x22, 0x1C,
0x3E, 0x28, 0x28, 0x28, 0x10,
0x10, 0x28, 0x28, 0x28, 0x3E,
0x3E, 0x10, 0x20, 0x20, 0x10,
0x12, 0x2A, 0x2A, 0x2A, 0x24,
0x20, 0x20, 0xFC, 0x22, 0x24,
0x3C, 0x02, 0x02, 0x02, 0x3C,
0x38, 0x04, 0x02, 0x04, 0x38,
0x3C, 0x02, 0x0C, 0x02, 0x3C,// x
0x22, 0x14, 0x08, 0x14, 0x22,// y
0x20, 0x12, 0x0C, 0x10, 0x20,// z
0x22, 0x26, 0x2A, 0x32, 0x22,//123 {
0x00, 0x10, 0x6C, 0x82, 0x82,//124 |
0x00, 0x00, 0xEE, 0x00, 0x00,//125 }
0x82, 0x82, 0x6C, 0x10, 0x00,
0x20, 0x40, 0x40, 0x40, 0x80,
0xA8, 0x68, 0x3E, 0x68, 0xA8,
0xBE, 0x2A, 0x2A, 0x2A, 0xA2,
0x00, 0x20, 0x50, 0xA0, 0x00,
0x04, 0x22, 0x7C, 0xA0, 0x40,
0x84, 0xFC, 0x04, 0x00, 0x20,
0xFE, 0x02, 0x02, 0x12, 0x02,
0x1C, 0x22, 0x14, 0x08, 0x36,
0x4E, 0x3E, 0x60, 0x40, 0x40,
0x0C, 0x12, 0x52, 0xB2, 0x1C,//136 ê
0x08, 0x1C, 0x2A, 0x2A, 0x2A,
0xF8, 0x40, 0x40, 0x3C, 0x02,
0x7C, 0x92, 0x92, 0x7C, 0x00,
0x42, 0x44, 0x38, 0x04, 0x02,
0x20, 0x3E, 0x20, 0x3E, 0x22,
0x10, 0x20, 0x3C, 0x22, 0x20,
0x18, 0x24, 0x7E, 0x24, 0x18,
0x1C, 0x22, 0x0C, 0x22, 0x1C,
0x82, 0xC6, 0xAA, 0x92, 0x82,
0x3A, 0x46, 0x40, 0x46, 0x3A,
0x54, 0x54, 0x54, 0x54, 0x54,
0x44, 0x28, 0x10, 0x28, 0x44,
0x10, 0x10, 0x54, 0x10, 0x10,
0x00, 0x70, 0x88, 0x88, 0x70,
0x60, 0x90, 0x8A, 0x80, 0x40,
0xFE, 0xFE, 0x92, 0x92, 0x92,
0x0A, 0x1A, 0x2A, 0x4A, 0x8A,
0x8A, 0x4A, 0x2A, 0x1A, 0x0A,
0x28, 0x2C, 0x38, 0x68, 0x28,
0x04, 0xFE, 0x80, 0x80, 0x80,
0x4C, 0x92, 0x92, 0x7C, 0x00,//157 Ø
0x04, 0x02, 0x7C, 0x80, 0x40,
0x38, 0x44, 0x38, 0x44, 0x38,
0xAA, 0x54, 0xAA, 0x54, 0xAA,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xBE, 0x00, 0x00,
0x38, 0x44, 0xFE, 0x44, 0x00,
0x12, 0x7E, 0x92, 0x92, 0x42,
0xBA, 0x44, 0x44, 0x44, 0xBA,
0xA8, 0x68, 0x3E, 0x68, 0xA8,
0x00, 0x00, 0xEE, 0x00, 0x00,
0x50, 0xAA, 0xAA, 0xAA, 0x14,
0x00, 0x80, 0x00, 0x80, 0x00,
0x7C, 0xBA, 0xAA, 0xAA, 0x7C,
0x12, 0xAA, 0xAA, 0xAA, 0x7A,
0x10, 0x28, 0x54, 0xAA, 0x44,
0x80, 0x80, 0x80, 0x80, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00,
0x7C, 0xAA, 0xBA, 0x82, 0x7C,
0x80, 0x80, 0x80, 0x80, 0x80,
0x00, 0xE0, 0xA0, 0xE0, 0x00,
0x22, 0x22, 0xFA, 0x22, 0x22,
0x00, 0x48, 0x98, 0xA8, 0x48,
0x00, 0x00, 0xA8, 0xA8, 0x70,
0x00, 0x00, 0x40, 0x80, 0x00,
0x04, 0xF8, 0x10, 0x10, 0xE0,
0x60, 0xFE, 0x80, 0xFE, 0x80,
0x00, 0x00, 0x10, 0x10, 0x00,
0x08, 0x00, 0x02, 0x04, 0x00,
0x00, 0x48, 0xF8, 0x08, 0x00,
0x00, 0xE8, 0xA8, 0xE8, 0x00,
0x44, 0xAA, 0x54, 0x28, 0x10,
0xF0, 0x04, 0x0C, 0x14, 0x2E,
0xF0, 0x00, 0x12, 0x26, 0x1A,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0x0C, 0x12, 0xA2, 0x02, 0x04,
0x1E, 0xA8, 0x68, 0x28, 0x1E,
0x1E, 0x28, 0x68, 0xA8, 0x1E,
0x1E, 0xA8, 0xA8, 0xA8, 0x1E,
0x9E, 0xA8, 0xA8, 0xA8, 0x9E,
0x9E, 0x28, 0x28, 0x28, 0x9E,
0x1E, 0x68, 0xA8, 0x68, 0x1E,
0x7E, 0x90, 0xFE, 0x92, 0x92,
0x70, 0x8A, 0x8C, 0x88, 0x88,
0x3E, 0xAA, 0x6A, 0x2A, 0x22,
0x3E, 0x2A, 0x6A, 0xAA, 0x22,
0x3E, 0xAA, 0xAA, 0xAA, 0x22,
0xBE, 0x2A, 0x2A, 0x2A, 0xA2,
0x00, 0xA2, 0x7E, 0x22, 0x00,
0x00, 0x22, 0x7E, 0xA2, 0x00,
0x00, 0xA2, 0xBE, 0xA2, 0x00,
0x00, 0xA2, 0x3E, 0xA2, 0x00,
0x10, 0xFE, 0x92, 0x82, 0x7C,
0xBE, 0x90, 0x88, 0x84, 0xBE,
0x1C, 0xA2, 0x62, 0x22, 0x1C,
0x1C, 0x22, 0x62, 0xA2, 0x1C,
0x1C, 0xA2, 0xA2, 0xA2, 0x1C,
0x9C, 0xA2, 0xA2, 0xA2, 0x9C,
0x9C, 0x22, 0x22, 0x22, 0x9C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x3A, 0x4C, 0x54, 0x64, 0xB8,
0x3C, 0x82, 0x42, 0x02, 0x3C,
0x3C, 0x02, 0x42, 0x82, 0x3C,
0x3C, 0x82, 0x82, 0x82, 0x3C,
0xBC, 0x02, 0x02, 0x02, 0xBC,
0x60, 0x10, 0x4E, 0x90, 0x60,
0xFE, 0x44, 0x44, 0x44, 0x38,
0x7E, 0xA4, 0xA4, 0x58, 0x00,
0x04, 0xAA, 0x6A, 0x2A, 0x1E,
0x04, 0x2A, 0x6A, 0xAA, 0x1E,
0x04, 0xAA, 0xAA, 0xAA, 0x1E,
0x84, 0xAA, 0xAA, 0xAA, 0x9E,
0x04, 0xAA, 0x2A, 0xAA, 0x1E,
0x04, 0x6A, 0xAA, 0x6A, 0x1E,
0x2E, 0x2A, 0x1C, 0x2A, 0x3A,
0x30, 0x4A, 0x4C, 0x48, 0x00,
0x1C, 0xAA, 0x6A, 0x2A, 0x1A,
0x1C, 0x2A, 0x6A, 0xAA, 0x1A,
0x1C, 0xAA, 0xAA, 0xAA, 0x1A,
0x1C, 0xAA, 0x2A, 0xAA, 0x1A,
0x00, 0x80, 0x5E, 0x00, 0x00,
0x00, 0x00, 0x5E, 0x80, 0x00,
0x00, 0x40, 0x5E, 0x40, 0x00,
0x00, 0x40, 0x1E, 0x40, 0x00,
0x0C, 0x12, 0x52, 0xB2, 0x1C,
0xBE, 0x90, 0xA0, 0xA0, 0x9E,
0x0C, 0x92, 0x52, 0x12, 0x0C,
0x0C, 0x12, 0x52, 0x92, 0x0C,
0x0C, 0x52, 0x52, 0x52, 0x0C,
0x4C, 0x52, 0x52, 0x52, 0x4C,
0x0C, 0x52, 0x12, 0x52, 0x0C,
0x10, 0x10, 0x10, 0x54, 0x10,
0x18, 0x26, 0x3C, 0x64, 0x18,
0x1C, 0x82, 0x42, 0x02, 0x1C,
0x1C, 0x02, 0x42, 0x82, 0x1C,
0x1C, 0x42, 0x42, 0x42, 0x1C,
0x1C, 0x42, 0x02, 0x42, 0x1C,
0x20, 0x12, 0x4C, 0x90, 0x20,
0xFE, 0x48, 0x48, 0x30, 0x00,
0x20, 0x92, 0x0C, 0x90, 0x20,
};
int column[] = {
8,7,6,5,4}; // change this to other general input/output arduino-pins as you like d8=pin 1
int data = 2; // change this to other general input/output arduino-pins as you like
int clock = 3; // change this to other general input/output arduino-pins as you like
int brightness = 2000; // keep high for max visibility. To high will cause flikkering
const int numberOflDisplays = 4; // change this if total number of HDSP200x's is different.
int tekstDat[numberOflDisplays * 4 * 5]; // this is the array that store's what on the displays. 4 digits per display and 5 columns per digit.
unsigned long tijd; // used to trigger events in one of the examples below
char buf[40];
boolean flagRx = false; //allowed to receive if false
//*****************************************************************setup*************************************************************
void setup(){
//Serial.begin(9600);
for (int i = 0; i < 5; i++){
pinMode(column[i], OUTPUT);
}
for (int i = 0; i < 5; i++){
digitalWrite(column[i], LOW);
}
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
digitalWrite(data, LOW);
digitalWrite(clock, HIGH);
tijd = millis();
Wire.begin(8); // join i2c bus with address #8 >>important<<
Wire.onReceive(receiveEvent); // register event
}
//***********************************************************************************end setup******************************************************
void loop(){
char PROGMEM clr[] = " ";
char PROGMEM scroll[] = "1979 TECH CONTROL PANEL by Brandon McRee";
char PROGMEM scroll2[] = "Remember Stupid... you have to drive this home :)";
if(flagRx == false){
delay(10); //needs this delay to be stable
scrollText(scroll, 8); //scrolling text, speed : second number is var howslow how slow this is a test of fastdraw text (short strings)
delay(1000);
//scrollText(scroll2, 10);
delay(10);
flagRx = true; // can now recieve
}
else{
writeText(buf);
for (int i = 0; i< 50; i++) draw(); //does this continuously - display HDSP2011
}
/*
scrollText(scroll3, 10);
delay(10);
//short quick text write
scrollText(hello, 8);
scrollText(world, 8);
delay(500);
delay(5);
writeText("TEST") ; //letters only? special charachters
for (int i = 0; i< 100; i++) draw();
delay(5);
writeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ;
for (int i = 0; i< 70; i++) draw();
delay(5);
writeText("1234567890") ;
for (int i = 0; i< 100; i++) draw();
delay(5);
writeText("!@#$%^&*()") ;
for (int i = 0; i< 50; i++) draw(); //delay??
delay(5);
delay(1000);
*/
writeText(buf);
for (int i = 0; i< 50; i++) draw(); //does this continuously
}
//****************end of main loop *********************************
void receiveEvent(int howMany) {
int i;
for (i=0; i<howMany; i++){
buf[i] = Wire.read(); //read I2C data (address 8)
}
flagRx = true; // set flag, we received something. will figure out how to clear when
// while (1 < Wire.available()) { // loop through all but the last
}
//int x = Wire.read(); // receive byte as an integer not used
//Serial.println(x); // print the integer
void writeDigit(int positie, int ascii){
for (int i =0; i< 5;i++){
tekstDat[(numberOflDisplays * 4 - positie) * 5 + i] = ascii_5x7[ascii*5+i];
}
}
void scrollText(String tekkst, long howSlow){
int leng = tekkst.length();
for (int u=-numberOflDisplays*4;u<leng;u++){ // first N digits will be spaces. N = all digits of display. So one screen blank before first character apears.
for (int v=0; v< numberOflDisplays*4;v++){
if (( (u+v) >= 0 ) && ((u+v) < leng)){ // separete leading and tailing spaces from actual string
char oneChar= tekkst.charAt(u+v);
writeDigit(v+1, oneChar); // write the character of the string
}
else{
writeDigit(v+1, 32); // write ascii-value 32 = a space.
}
}
for (long teller = 0; teller < howSlow; teller++){
draw();
}
}
}
void writeText(String tekst){
int tl = tekst.length();
int spacesNeeded = 4 * numberOflDisplays - tl;
if (spacesNeeded <0){
tl = 4 * numberOflDisplays;
}
else{
for (int u = 0; u < spacesNeeded; u++){
tekst.concat(" ");
}
tl = 4 * numberOflDisplays;
}
char tekst_[tl];
for (int vv = 0; vv < tl; vv++){
char tt = tekst.charAt(tl-vv-1);
for (int i =0; i< 5;i++){
//tekstDat[vv*5+i] = ascii_5x7[tt*5+i]; //old using SRAM
//tekstDat[vv*5+i] = (pgm_read_byte(ascii_5x7))[tt*5+i]; //new try and read from PROGMEM does not compile :/
}
}
}
void dot(byte x, byte y, boolean oo){
if ((x < (numberOflDisplays *4 * 5)) && (y < 7)){
byte oldByte = tekstDat[x] & (0xFF - (2<<y));
tekstDat[x] = oldByte | (2<<y);
}
}
void draw(){
for (int Kolom = 0; Kolom < 5; Kolom++){ // 5 columns to be strobed
// pumping in 3 x 4 x 7 bits per one stobe of the column
for (int displayNo = 0; displayNo < numberOflDisplays; displayNo++){ // number of displays
for (int digitNo = 0; digitNo < 4; digitNo++){ // 4 characters per display
for (int diodeNo = 0; diodeNo < 7; diodeNo++){ // 7 row-elements
digitalWrite(clock, HIGH);
digitalWrite(data, tekstDat[Kolom + 5*(displayNo*4 + digitNo) ] &(2<<diodeNo)); // magic
digitalWrite(clock, LOW);
}
}
}
digitalWrite(column[Kolom], HIGH);
delayMicroseconds(brightness);
digitalWrite(column[Kolom], LOW);
}
}
PROGMEM
and have it read properly.” You should solve this problem, rather than try to work around it. A font definitely belongs toPROGMEM
.