My little LCD menu. Several options and features.

Just fiddling around trying to make a decent menu.

But now I'm on the look for a bigger serial lcd, any recommendations?

20x4 or larger.

Nice Stigern.

Did you use the menu library from the playground?
Also some nice things on your blog.
Sorry i don't have any recommendations on lcd's.

Jeroen

I would personally recommend the serial LCD (20x4) from sparkfun. As long as you don't mind black on green then it is a good product. If you want a different colour then you can buy the serial modules seperately to add on to an LCD of your chosing.

If you want to go bigger than 20x4 with a serial LCD then you should probably look at serial graphic LCDs.

Mowcius

Interesting speed . Will you post the code?

Yot: No, it's my own recipe :stuck_out_tongue: Only libaries used are NewSoftSerial and MegaServo.

Oh, thanks. I put most projects on my blog too :slight_smile: Nice to see
people read it.

mowcius: Yes, but I really love the black-blue, or just any other
color than the default green stuff. But where can I get 20x4 lcds,
and that serial module?

I was also looking on these nice lcds:
http://www.phanderson.com/lcd106/lcd107.html

Or some from futurlec, 40 x 4 Character LCD Display with Backlight Technical Data
But they aren't serial.

But I'm confused, since it seems like they use another PIC for
serial com, will it be different? or ?

tytower: Sure!

Warning: Very ugly code, and not commented enough :stuck_out_tongue:
But you asked! hehe ;D

You can always buy some Atmega8's and turn them into standalone LCD-receivers, turning any LCD you can buy from Ebay(generally like $5) into a serial enabled LCD!:slight_smile:

You if you use the Matrix Orbital commands on the Atmega8, you still have about 2.5k of code room, so you can throw in some analogRead routines and post those to the LCD or the Master arduino.

Hm, but anyone know if those phanderson lcds are any good?

Or look like they could work fine with the arduino?
If they work the same way those sparkfun lcds do, I'm buying one.

Hm, but anyone know if those phanderson lcds are any good?

The LCD #117-2400 operates at 2400 and is primarily intended for the PICAXE

Looking at the page, it does not look like they would be very good with arduino. They have just not been designed for it.

If they work the same way those sparkfun lcds do, I'm buying one.

Nope, they are completely different to the the sparkfun LCDs.

Yes, but I really love the black-blue, or just any other
color than the default green stuff. But where can I get 20x4 lcds,
and that serial module?

The serial backpack for attaching to any 'normal' LCD can be bought from here: SparkFun Serial Enabled LCD Backpack - LCD-00258 - SparkFun Electronics
The LCDs can be bought from almost anywhere. Ebay, sparkfun, robotics stores. Watch out for different connector displays though. The 40x4 LCD that was linked will not be compatible with the serial backpack. Compatible LCDs typically have a row of 15 connectors in the top left for connecting to.

Mowcius

I'm telling you, if you don't mind soldering a few components... a serial enabled backpack is fairly easy to make. I used some old atmega8's, uploaded a sketch that implements alot of the commands from Matrix Orbital type LCDs (serial enabled) I'm able to run LCD-Smartie, run multiple LCD's from one arduino, etc.

Only "bad" thing is, you'd need a hardware programmer for the atmega8's unless you have some with the bootloader already.

I even added some "EEPROM write, EEPROM read, and analogRead commands" just because it's an arduino!

It's fairly simple, to use it:
Serial.print(254, BYTE); // command byte
Serial.print(70, BYTE);// turns backLight off
Serial.print(254, BYTE);// gotta send another command byte
Serial.print(69, BYTE); // turns ON the backLight

Here's examples for reading and writing to eeprom:
Reading:
Serial.print(254, BYTE); // command byte
Serial.print(65, BYTE); // "EEPROM Read"
if(Serial.available() > 0){
EEPROMVALUE = Serial.read();
}

Writing:
Serial.print(254, BYTE); // command byte
Serial.print(64, BYTE); // "Write EEPROM"
Serial.print(241, BYTE);// ADDRESS for EEPROM
Serial.print(15, BYTE); // value to store into EEPROM

I made a small library for using the LCD.. it's VERY basic, just uses the above commands into the commands like lcd.print lcd.read etc, just borrowed the Print class. I've tried it with a 4x20 and 2x16 LCD's and works great!

But all this for a $3 atmega8, few components and some extra work! :slight_smile: I did see the Serial enabled Chips, they're the "#117 lcd chip", they're a PIC pre-programmed to handle inverted serial (I think).

#include "LCD4Bit_mod.h"
#include <EEPROM.h>
//#include <Streaming.h>
const byte backLight = 13;

//create object to control an LCD.  
//number of lines in display=1
LCD4Bit_mod lcd = LCD4Bit_mod(2); 


void setup() { 
  pinMode(backLight, OUTPUT);  //we'll use the debug LED to output a heartbeat
  digitalWrite(backLight,HIGH);
  Serial.begin(19200);

  lcd.init();
  lcd.clear();
  lcd.printIn("   LCD Ready: ");
}


byte serial_getch(){

  int incoming;  
  while (Serial.available()==0){
  }
  // read the incoming byte:
  incoming = Serial.read();

  return (byte) (incoming &0xff);
}



void loop(){

  byte rxbyte;
  byte temp;
  byte addr;
  int val;

  rxbyte = serial_getch();

  if (rxbyte == 254) //Matrix Orbital uses 254 prefix for commands
  {
    switch (serial_getch())
    {

    case 64: // EEPROM Write (address, value) 
      addr = serial_getch();
      delay(10);
      val = serial_getch();
      EEPROM.write(addr, val);
      break;

    case 65: // EEPROM Read  (address)
      addr = serial_getch(); // EEPROM address
      val = EEPROM.read(addr); //
      Serial.print(val, BYTE);
      break;

    case 69: //backlight on (at previously set brightness)
      // not implemented      
      digitalWrite(backLight, HIGH);                  
      break;

    case 70: //backlight off
      // not implemented      
      digitalWrite(backLight, LOW);                  
      break;

    case 71:  //set cursor position
      temp = (serial_getch() - 1);  //get column byte
      switch (serial_getch())  //get row byte
      {
        //line 1 is already set up
      case 2:
        temp += 0x40;
        break;
      case 3:
        temp += 0x14;
        break;
      case 4:
        temp += 0x54;
        break;
      default:
        break;
      }
      lcd.commandWrite(0b10000000 + temp);
      break;

    case 72:  //cursor home (reset display position)
      lcd.commandWrite(2);
      break;

    case 74:  //show underline cursor
      lcd.commandWrite(0b00001110);
      break;

    case 75:  //underline cursor off

    case 84:  //block cursor off
      lcd.commandWrite(0b00001100);
      break;

    case 76:  //move cursor left
      lcd.commandWrite(16);
      break;

    case 77:  //move cursor right
      lcd.commandWrite(20);
      break;

    case 78:  //define custom char
      lcd.commandWrite(64 + (serial_getch() * 8));  //get+set char address
      for (temp = 7; temp != 0; temp--)
      {
        lcd.print(serial_getch()); //get each pattern byte
      }
      break;

    case 83:  //show blinking block cursor
      lcd.commandWrite(0b00001111);
      break;
    case 86:  //GPO OFF
      //implement later
      break;

    case 87:  //GPO ON
      /*temp = serial_getch();
                               if (temp == 1)
                               {
                                     GPO1 = GPO_ON;
                               }*/
      break;

    case 88:  //clear display, cursor home
      lcd.commandWrite(1);
      break;

      /*###############################################################      
       case 152: //set and remember (doesn't save value, though)
       case 153: //set backlight brightness
       //not implemented
       break;
       //these commands ignored (no parameters)
       //case 35: //read serial number //USING FOR EEPROM//
       //case 36: //read version number
       case 55: //read module type
       case 59: //exit flow-control mode
       //case 65: //auto transmit keypresses
       case 96: //auto-repeat mode off (keypad)
       case 67: //auto line-wrap on
       case 68: //auto line-wrap off
       case 81: //auto scroll on
       case 82: //auto scroll off
       case 104: //init horiz bar graph
       case 109: //init med size digits
       case 115: //init narrow vert bar graph
       case 118: //init wide vert bar graph
       break;
       ###############################################################*/

    default:
      //all other commands ignored and parameter byte discarded
      temp = serial_getch();  //dump the command code
      break;
    }
    return;
  } //END OF COMMAND HANDLER

  //change accented char to plain, detect and change descenders
  //NB descenders only work on 5x10 displays. This lookup table works
  //  with my DEM-20845 (Display Elektronik GmbH) LCD using KS0066 chip.
  switch (rxbyte)
  {
    //chars that have direct equivalent in LCD charmap
    /*            case 0x67: //g
                       rxbyte = 0xE7;
                       break;
                 case 0x6A: //j
                       rxbyte = 0xEA;
                       break;
                 case 0x70: //p
                       rxbyte = 0xF0;
                       break;
                 case 0x71: //q
                       rxbyte = 0xF1;
                       break;
                 case 0x79: //y
                       rxbyte = 0xF9;
                       break;
     */  case 0xE4: //ASCII "a" umlaut
    rxbyte = 0xE1;
    break;
  case 0xF1: //ASCII "n" tilde
    rxbyte = 0xEE;
    break;
  case 0xF6: //ASCII "o" umlaut
    rxbyte = 0xEF; //was wrong in v0.86
    break;
  case 0xFC: //ASCII "u" umlaut
    rxbyte = 0xF5;
    break;

    //accented -> plain equivalent
    //and misc symbol translation
  case 0xA3: //sterling (pounds)
    rxbyte = 0xED;
    break;
    /*            case 0xB0: //degrees symbol
                       rxbyte = 0xDF;
                       break;
     */  case 0xB5: //mu
    rxbyte = 0xE4;
    break;
  case 0xC0: //"A" variants
  case 0xC1:
  case 0xC2:
  case 0xC3:
  case 0xC4:
  case 0xC5:
    rxbyte = 0x41;
    break;
  case 0xC8: //"E" variants
  case 0xC9:
  case 0xCA:
  case 0xCB:
    rxbyte = 0x45;
    break;
  case 0xCC: //"I" variants
  case 0xCD:
  case 0xCE:
  case 0xCF:
    rxbyte = 0x49;
    break;
  case 0xD1: //"N" tilde -> plain "N"
    rxbyte = 0x43;
    break;
  case 0xD2: //"O" variants
  case 0xD3:
  case 0xD4:
  case 0xD5:
  case 0xD6:
  case 0xD8:
    rxbyte = 0x4F;
    break;
  case 0xD9: //"U" variants
  case 0xDA:
  case 0xDB:
  case 0xDC:
    rxbyte = 0x55;
    break;
  case 0xDD: //"Y" acute -> "Y"
    rxbyte = 0x59;
    break;
    /*            case 0xDF: //beta  //mucks up LCDSmartie's degree symbol??
                       rxbyte = 0xE2;
                       break;
     */  case 0xE0: //"a" variants except umlaut
  case 0xE1:
  case 0xE2:
  case 0xE3:
  case 0xE5:
    rxbyte = 0x61;
    break;
  case 0xE7: //"c" cedilla -> "c"
    rxbyte = 0x63;
    break;
  case 0xE8: //"e" variants
  case 0xE9:
  case 0xEA:
  case 0xEB:
    rxbyte = 0x65;
    break;
  case 0xEC: //"i" variants
  case 0xED:
  case 0xEE:
  case 0xEF:
    rxbyte = 0x69;
    break;
  case 0xF2: //"o" variants except umlaut
  case 0xF3:
  case 0xF4:
  case 0xF5:
  case 0xF8:
    rxbyte = 0x6F;
    break;
  case 0xF7: //division symbol
    rxbyte = 0xFD;
    break;
  case 0xF9: //"u" variants except umlaut
  case 0xFA:
  case 0xFB:
    rxbyte = 0x75;
    break;
  default:
    break;
  }

  lcd.print(rxbyte);  //otherwise a plain char so we print it to lcd
  return;


}

Stigern, link to your original code at pastebin isn't for me. Can you post a fresh link?

Thanks

Stigern sent me a link a while back; try this: #include <NewSoftSerial.h>#include <MegaServo.h>#define BANDGAPREF 14 //// - Pastebin.com

Steve

Late to the conversation. I have used the LCD117 ($14) from http://www.moderndevice.com/products/lcd117-kit with my own LCD's. no problems. It reads at 9600, not 2400.
LCD117 Comands: http://cdn.shopify.com/s/files/1/0038/9582/files/LCD117_Board_Command_Summary.pdf?1260768875
Sparkfun's Commans: http://www.sparkfun.com/datasheets/LCD/SerLCD_V2_5.PDF

I use this in the setup section of my sketch:

Serial1.begin(9600); //configure display for 4x20
Serial1.print("?G420"); //configure display for 4x20
delay(100);
Serial1.print("?Bff"); //ensure Backlight is on
delay(100);
Serial1.print("?s7"); //Set tab to 7
delay(100);
Serial1.print("?fHello, JC!");

They are pretty flexible. I have never used the sparkfun LCD backpack. CaptainObvious has good information about building your own. It would be something that is extensible and easily modified for different needs. In fats, I think I'm going to do that this week and post back.

Below is an arduino demo sketch for the LCD117:

#include <SoftwareSerial.h>

/* port of Peter Anderson's LCD117_1.BS2 (Parallax Basic Stamp 2) to Arduino
Paul Badger 2007
Comments and bug fixes Ian Patterson 9/08
original Peter H. Anderson, Baltimore, MD, Oct, '06

Configured for 2 x 16 display
Printing demonstration will probably look ugly with shorter displays
Delays in bargraph section are probably longer than necessary as a new version of the firmware
has been implemented since this demo was written.

Delays may be tweaked by reducing the delay time until the LCD117 chip crashes
(As shown by appearance of startup screen. Don't worry you won't hurt anything.)
Then increase the delay a tad.

I took some liberties with code

  • changed printing demonstration slightly
  • eliminated speaker demonstration
  • extended bar graph section
    */

char N;
int I;
int ByteVar;

int NN;
int Remainder;
int Num_5;

#define rxPin 4 // rxPin is immaterial - not used - just make this an unused Arduino pin number
#define txPin 14 // pin 14 is analog pin 0, on a BBB just use a servo cable :), see Reference pinMode
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

// mySerial is connected to the TX pin so mySerial.print commands are used
// one could just as well use the software mySerial library to communicate on another pin

void setup(){

pinMode(txPin, OUTPUT);
mySerial.begin(9600); // 9600 baud is chip comm speed

mySerial.print("?G216"); // set display geometry, 2 x 16 characters in this case
delay(500); // pause to allow LCD EEPROM to program

mySerial.print("?Bff"); // set backlight to ff hex, maximum brightness
delay(1000); // pause to allow LCD EEPROM to program

mySerial.print("?s6"); // set tabs to six spaces
delay(1000); // pause to allow LCD EEPROM to program

mySerial.print("?D00000000000000000"); // define special characters
delay(300); // delay to allow write to EEPROM
// see moderndevice.com for a handy custom char generator (software app)
mySerial.print("?f"); // clear the LCD
delay(10);
mySerial.print("...");

//crashes LCD without delay
mySerial.print("?D11010101010101010");
delay(300);

mySerial.print("?D21818181818181818");
delay(300);

mySerial.print("?D31c1c1c1c1c1c1c1c");
delay(300);

mySerial.print("?D41e1e1e1e1e1e1e1e");
delay(300);

mySerial.print("?D51f1f1f1f1f1f1f1f");
delay(300);

mySerial.print("?D60000000000040E1F");
delay(300);

mySerial.print("?D70000000103070F1F");
delay(300);

mySerial.print("?c0"); // turn cursor off
delay(300);

}

continued on in next post

void loop(){

mySerial.print("?f"); // clear the LCD

delay(1000);

mySerial.print("?f"); // clear the LCD
delay(100);
delay(3000);

mySerial.print("?x00?y0"); // cursor to first character of line 0

mySerial.print("LCD117 serial ?6?7");
mySerial.print("?0?1?2?3?4?5"); // display special characters

delay(3000);

mySerial.print("?x00?y1"); // move cursor to beginning of line 1
mySerial.print("moderndevice.com"); // crass commercial message

delay(6000); // pause six secs to admire

mySerial.print("?f"); // clear the LCD

mySerial.print("?x00?y0"); // move cursor to beginning of line 0

mySerial.print(" LCD 117 chip by"); // displys LCD #117 on the screen

mySerial.print("?x00?y1"); // cursor to first character of line 1
mySerial.print(" phanderson.com");

delay(3000); // pause three secs to admire

mySerial.print("?f"); // clear the screen

mySerial.print("?x00?y0"); // locate cursor to beginning of line 0
mySerial.print("DEC HEX ASCI"); // print labels
delay(100);
// simple printing demonstation
for (N = 42; N<= 122; N++){ // pick an arbitrary part of ASCII chart - change as you wish
mySerial.print("?x00?y1"); // locate cursor to beginning of line 1

mySerial.print(N, DEC); // display N in decimal format
mySerial.print("?t"); // tab in

mySerial.print(N, HEX); // display N in hexidecimal format
mySerial.print("?t"); // tab in

// glitches on ASCII 63 "?"
if (N=='?'){
mySerial.print("??"); // the "??" displays a single '?' - see Phanderson 117 docs
}
else{
mySerial.print(N, BYTE); // display N as an ASCII character
}

mySerial.print(" "); // display 3 spaces (blanks) as ASCII characters

delay(500);
}

delay (1000);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
delay(10);
mySerial.print("?l"); // clear line; custom char. 1
delay(10);
mySerial.print(" Bar Graph Demo");
delay(10);
mySerial.print("?n"); // cursor to beginning of line 1 + clear line 1
delay(500);

// bar graph demo - increasing bar
for ( N = 0; N <= 80; N++){ // 16 chars * 5 bits each = 80
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

Num_5 = N / 5; // calculate solid black tiles
for (I = 1; I <= Num_5; I++){
mySerial.print("?5"); // print custom character 5 - solid block tiles
delay(4);
}

Remainder = N % 5; // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command; see end note
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(5);
}

delay(50);

for ( N = 80; N >= 0; N--){ // decreasing bar - 16 chars * 5 bits each
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

Num_5 = N / 5; // calculate solid black tiles
for (I = 1; I <= Num_5; I++){
mySerial.print("?5"); // print custom character 5 - solid block tiles
delay(5);
}

Remainder = N % 5; // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(5);
}

delay(500);
mySerial.print("?f"); // clears screen
delay(50);
mySerial.print(".");
delay(60);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
delay(250);
mySerial.print(" .");
delay(10);

mySerial.print("?D0000000000000001F"); // define special characters
delay(300); // delay to allow write to EEPROM
//crashes LCD without delay
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(" ."); // dots for user feedback
delay(10);

mySerial.print("?D10000000000001F1F");
delay(300);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(" . ");
delay(10);

mySerial.print("?D200000000001F1F1F");
delay(300);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(". ");
delay(10);

mySerial.print("?D3000000001F1F1F1F");
delay(300);

mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(" .");
delay(10);

mySerial.print("?D40000001F1F1F1F1F");
delay(300);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(" .");
delay(10);

mySerial.print("?D500001F1F1F1F1F1F");
delay(300);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(" . ");
delay(10);

mySerial.print("?D6001F1F1F1F1F1F1F");
delay(300);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(". ");
delay(10);

mySerial.print("?D71F1F1F1F1F1F1F1F");
delay(300);
mySerial.print("?y0?x00"); // cursor to beginning of line 0
mySerial.print(" . ");
delay(10);

mySerial.print("?c0"); // turn cursor off
delay(300
);

mySerial.print("?f"); // clear the LCD

delay(1000);

mySerial.print("?y0?x00"); // cursor to beginning of line 0
delay(10);
mySerial.print("?l"); // clear line
delay(10);
mySerial.print(" Vertical Bar ");
delay(10);
mySerial.print("?n"); // cursor to beginning of line 1 + clear line 1
mySerial.print(" Demo ");
delay(500);

// vertical bar graph demo - increasing bar
for ( N = 0; N <= 15; N++){
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

if (N < 8){
mySerial.print("?y0?x00 "); // cursor to beginning of line 1 and writes blank space
mySerial.print("?y1?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}
else{
mySerial.print("?y1?x00?7"); // cursor to beginning of line 1 and writes black character
mySerial.print("?y0?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}

}
delay(100);

for ( N = 15; N >= 0; N--){
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

if (N < 8){
mySerial.print("?y0?x00 "); // cursor to beginning of line 1 and writes blank space
mySerial.print("?y1?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}
else{
mySerial.print("?y1?x00?7"); // cursor to beginning of line 1 and writes black character
mySerial.print("?y0?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}

}
delay(50);
for ( N = 0; N <= 15; N++){ // decreasing bar
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

if (N < 8){
mySerial.print("?y0?x00 "); // cursor to beginning of line 1 and writes blank space
mySerial.print("?y1?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}
else{
mySerial.print("?y1?x00?7"); // cursor to beginning of line 1 and writes black character
mySerial.print("?y0?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}

}
delay(100);

for ( N = 15; N >= 0; N--){
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

if (N < 8){
mySerial.print("?y0?x00 "); // cursor to beginning of line 1 and writes blank space
mySerial.print("?y1?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}
else{
mySerial.print("?y1?x00?7"); // cursor to beginning of line 1 and writes black character
mySerial.print("?y0?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}

}
delay(50);
for ( N = 0; N <= 15; N++){
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

if (N < 8){
mySerial.print("?y0?x00 "); // cursor to beginning of line 1 and writes blank space
mySerial.print("?y1?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}
else{
mySerial.print("?y1?x00?7"); // cursor to beginning of line 1 and writes black character
mySerial.print("?y0?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}

}
delay(100);

for ( N = 15; N >= 0; N--){ // 16 chars * 8 bits each = 80
mySerial.print("?y1?x00"); // cursor to beginning of line 1
delay(10);

if (N < 8){
mySerial.print("?y0?x00 "); // cursor to beginning of line 1 and writes blank space
mySerial.print("?y1?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}
else{
mySerial.print("?y1?x00?7"); // cursor to beginning of line 1 and writes black character
mySerial.print("?y0?x00");
Remainder = (N % 8); // % sign is modulo operator - calculates remainder
// now print the remainder
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder
delay(10);

}

}
delay(1000);
}

/*
Note the line pair first seen as:
mySerial.print("?"); // first half of the custom character command
mySerial.print(Remainder, DEC); // prints the custom character equal to remainder

This is a clever technique to use the variable "Remainder" to print a custom character
that depends on the (integer) value of "Remainder" using the ?# command where # is expected to be
an integer constant in the range #=0 to #=7.
*/

Sorry for all the posts, the forum wouldn't let me put it one post.

Next time, may I suggest you use the # code button?

Mowcius