Generating barcodes on LCD display

This demonstrates generation of Code-39 barcodes on an LCD display.
LCD display is this http://www.sparkfun.com/products/9351
With SerialGLCD download | SourceForge.net and serialGLCD library for Arduino download | SourceForge.net
Text 7 characters or less can be generated on screen. The barcode is perfectly readable with Zbar.
The code is somewhat rough:

#include <serialGLCD.h>
#include <ctype.h>
  serialGLCD lcd;
  char ctl[]="NwNnWnWnN";
  char zero[]="NnNwWnWnN";
  char one[]="WnNwNnNnW";
  char two[]="NnWwNnNnW";
  char three[]="WnWwNnNnN";
  char four[]="NnNwWnNnW";
  char five[]="WnNwWnNnN";
  char six[]="NnWwWnNnN";
  char seven[]="NnNwNnWnW";
  char eight[]="WnNwNnWnN";
  char nine[]="NnWwNnWnN";
  char A[]="WnNnNwNnW";
  char B[]="NnWnNwNnW";
  char C[]="WnWnNwNnN";
  char D[]="NnNnWwNnW";
  char E[]="WnNnWwNnN";
  char F[]="NnWnWwNnN";
  char G[]="NnNnNwWnW";
  char H[]="WnNnNwWnN";
  char I[]="WnNnNwWnN";
  char J[]="WnNnNwWnN";
  char K[]="WnNnNnNwW";
  char L[]="NnWnNnNwW";
  char M[]="WnWnNnNwN";
  char N[]="NnNnWnNwW";
  char O[]="WnNnWnNwN";
  char P[]="NnWnWnNwN";
  char Q[]="NnNnNnWwW";
  char R[]="WnNnNnWwN";
  char S[]="NnWnNnWwN";
  char T[]="NnNnWnWwN";
  char U[]="WwNnNnNnW";
  char V[]="NwWnNnNnW";
  char W[]="WwWnNnNnN";
  char X[]="NwNnWnNnW";
  char Y[]="WwNnWnNnN";
  char Z[]="NwWnWnNnN";
  char sp[]="NwWnNnWnN";
  int xc = 1;
   void intr(char *c){
    int n;
    for(n = 0;n < 9;n++){
      switch(c[n]){
        case 'W': lcd.drawLine(xc, 0, xc, 64, 0); delay(7); lcd.drawLine(xc+1, 0, xc+1, 64, 0); delay(6); xc+=2; break;
        case 'N': lcd.drawLine(xc, 0, xc, 64, 0); delay(7); xc++; break;
        case 'w': xc+=2; break;
        case 'n': xc++; break;
      }
     if(xc > 128){Serial.println("OVRFLW");}
    }
    xc++;
  }
  void str(char *s){
    char a;
    char *x;
    for(a = 0;a < strlen(s);a++){
       switch(tolower(s[a])){
         case '*': x=ctl; break;
         case 'a': x=A; break;
         case 'b': x=B; break;
         case 'c': x=C; break;
         case 'd': x=D; break;
         case 'e': x=E; break;
         case 'f': x=F; break;
         case 'g': x=G; break;
         case 'h': x=H; break;
         case 'i': x=I; break;
         case 'j': x=J; break;
         case 'k': x=K; break;
         case 'l': x=L; break;
         case 'm': x=M; break;
         case 'n': x=N; break;
         case 'o': x=O; break;
         case 'p': x=P; break;
         case 'q': x=Q; break;
         case 'r': x=R; break;
         case 's': x=S; break;
         case 't': x=T; break;
         case 'u': x=U; break;
         case 'v': x=V; break;
         case 'w': x=W; break;
         case 'x': x=X; break;
         case 'y': x=Y; break;
         case 'z': x=Z; break;
         case ' ': x=sp; break;
         case '0': x=zero; break;
         case '1': x=one; break;
         case '2': x=two; break;
         case '3': x=three; break;
         case '4': x=four; break;
         case '5': x=five; break;
         case '6': x=six; break;
         case '7': x=seven; break;
         case '8': x=eight; break;
         case '9': x=nine; break;
         default : x=sp;
       }
       intr(x);
    }
  }
void setup(){ 
  Serial.begin(115200);
  delay(1500);
  lcd.resetLCD();
  delay(250);
  unsigned char x,y;
  for(x = 0;x < 128;x++){
    for(y = 0;y < 64;y++){
      lcd.togglePixel(x, y, 1);
    }
  }
  str("*TEST*");
}
void loop(){

}

Cam0Pic12-05-04_23.21.59.jpg

Pretty cool. :slight_smile:

Yes! And easier to implement then I thought.
But the code needs alot of work, including more efficient lookup table packing and putting the huge tables in PROGMEM.

My android device with the Barcode Scanner was able to scan the photo. It's the text TEST, right? :wink:

including more efficient lookup table packing

The codes can be optimized quite easily

You have 4 codes
W = Wide line
N = narrow line
w= wide space
n = narrow space

char zero[]="NnNwWnWnN";

Because line and space are alternating you can replace this scheme with 2 codes if you keep track of the mode (Line | Space) in the code.

W = Wide
N = narrow

char zero[]="NNNWWNWNN";

2 codes ?? thats binary so we can replace W=1 and N=0

char zero[]="000110100";

9 bits can be encoded in an int.

int zero = 0x0034;

Now make an array of ints of all the chars you want to support

int BCint[40] = {....TBD ...}
char BCchar[40] = "#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ";

lookup the index in the BCchar and use the index to find the corresponding int in thBCint array

This brings back the whole logic to something like this...

char text[] = "HELLO";

for (int i=0; i< strlen(text); i++)
{
  c = text[i];  // optionally do a toupper();
  int index = -1;
  for (int j=0; j<40; j++)   
  {
    if (BCchar[j] == c)
    {
      index = j;
      break;
    }
  }
  if (index > -1) printCode(BCint[index]);
}

int indexof(char c, char* ar)
{
  int rv = -1;
  for

searching the character in the BCchar array can be made faster by

  • using binary search or
  • order the chars based upon - Letter frequency - Wikipedia - (the ints should be ordered accordingly)
  • use the ascii value of the char to display to calculate the index ==> isdigit() etc...

Succes

sth77:
My android device with the Barcode Scanner was able to scan the photo. It's the text TEST, right?

That is correct. It seems quite easy to decode.

robtillaart:

including more efficient lookup table packing

The codes can be optimized quite easily

I was able to implement your method although its easier said then done :grin:

searching the character in the BCchar array can be made faster by

  • using binary search or
  • order the chars based upon - Letter frequency - Wikipedia - (the ints should be ordered accordingly)
  • use the ascii value of the char to display to calculate the index ==> isdigit() etc...

Succes

Speed is fairly uncritical because the LCD is slow.

Here is the new code:

#include <serialGLCD.h>
#include <ctype.h>
serialGLCD lcd;
char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
int code[]={52,289,97,352,49,304,112,37,292,100,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,168,162,138,42,148,0};
  int xc = 1;
   void intr(int c){
    int n;
    int mask = 256;
    char state = 1;
    for(n = 0;n < 9;n++){
        if(c & mask){
          if(state){
            lcd.drawLine(xc, 0, xc, 64, 0); delay(7); lcd.drawLine(xc+1, 0, xc+1, 64, 0); delay(6);
          }          
          xc+=2; 
        } else {
          if(state){
            lcd.drawLine(xc, 0, xc, 64, 0); delay(7); 
          }
          xc++;
        }
      mask /= 2;
      state = !state;
     if(xc > 128){Serial.println("OVRFLW");}
    }
    xc++;
  }
void str(char *s){
  char a;
  int r;
  for(a = 0;a < strlen(s);a++){
    for(r = 0;r < strlen(index);r++){
      if(toupper(s[a]) == index[r]){
       intr(code[r]);
       break;
      }
    }
  }
}
void setup(){ 
  Serial.begin(115200);
  delay(1500);
  lcd.resetLCD();
  delay(250);
  unsigned char x,y;
  for(x = 0;x < 128;x++){
    for(y = 0;y < 64;y++){
      lcd.togglePixel(x, y, 1);
    }
  }
  str("*TEST*");
}
void loop(){

}

I wonder if 2-D barcodes would readable from an LCD?

I have to ask: other than the coolness-factor why did you do this?

Yes.

I have to ask: other than the coolness-factor why did you do this?

Who wouldn't want to generate a barcode with an Arduino and display it on an LCD?
Its mostly about the "coolness-factor".

Note the QR code was displayed but not generated. Generating QR codes is difficult.

Cam0Pic12-05-05_16.38.29.jpg

Who wouldn't want to generate a barcode with an Arduino and display it on an LCD?

And with similar code it might be printed on a thermal printer (ok other drawline routine)

Note the QR code was displayed but not generated. Generating QR codes is difficult.

For those who want to try (no arduio code) check - libqrencode -

Hi, i tried the above code, but i'm getting a black screen with a few white dots.
Is the code working?

I don't have a Serial GLCD like yours , I just have a KS0108 display. Can you help me to adapt the code with another library?