Final Project [solo]- Arduino Farsi Display

The concept:

The premise of my project is very simple: construct and display Persian/Arabic letters on Arduino LCD, with the main purpose of displaying the Persian calendar date (Hijri Shamsi) – as a gift to my dad (an older generation electrical engineer). But you can input anything through p5.js to be displayed on the LCD.

Note: Hijri Shamsi is an ancient solar calendar and one of the oldest in the world. It begins on the March equinox as determined by astronomical calculation to mark the beginning of spring, where we celebrate new beginnings (Nowruz). The months’ names are the same as ancient Zoroastrian names (represented with Farsi letters, read right to left). The days are represented using Hindu-Arabic numerals.

Sample digital representation of Hijri Shamsi date
Sample box to hold the LCD

Like all sophisticated projects, however, the devil is in the details.

Displaying special characters on LCD:

lcd.print() function only supports ASCII characters. A series of calculations and mappings are involved in order to display special characters.

LCD 16x2 can display 32 characters (2 rows, 16 columns). And each character is composed of 40 pixels (8 rows and 5 columns). You will have to write your own bit-level custom character code. Take a look at the example below:
// %%%%%%%%%%%%%%%%
byte customChar[8] = {
    0b00000,
    0b01010,
    0b11111,
    0b11111,
    0b01110,
    0b00100,
    0b00000,
    0b00000
};
// %%%%%%%%%%%%%%%%

The good news is that you can make your own letters or special characters (and fonts) on a matrix on this website and get the HEX representation for your letters.

hex representation of letter م

This is the Persian alphabet matrix (credits to gurgleapps) that I will use in this project:

// %%%%%%%%%%%%%%%%
const unsigned char pers_char [71][8] = {
    0x00, 0x1C, 0x20, 0x08, 0x08, 0x08, 0x08, 0x00, 	//0	alef1
    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 	//1	alef2 
    0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 	//2	alef3
    0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x02, 	//3	be1
    0x00, 0x00, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x10, 	//4	be2
    0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x07,    	//5	pe1
    0x00, 0x00, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x38, 	//6	pe2
    0x00, 0x03, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00, 	//7	te1
    0x00, 0x14, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x00, 	//8	te2
    0x02, 0x05, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00, 	//9	the1
    0x08, 0x14, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x00, 	//10 	the2
    0x00, 0x00, 0x0C, 0x12, 0x01, 0x3E, 0x00, 0x04, 	//11	jim1
    .
    .
    .

    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 	//69	slash
    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 	//70	backslash
};
// %%%%%%%%%%%%%%%%

And the final step is presenting the character on the LCD. If you look at the heart example above, you see a bit-level representation of the character, but gurgleapps gives us a set of hex values. So some conversion needs to happen here. Each hexadecimal digit represents four bits (binary digits). We could write a simple but useful function that converts each hex value to bitmap characters and [depending on cursor position] display the custom bitmap.

p5.js:

p5.js is where the user input is stored and communicated to Arduino over serial operations. P5.js would take the input in English, convert it into Farsi, and send it to Arduino to display on LCD. The user has to let the program know, after inputting the text, whether they want the program to translate or transliterate the text to Farsi.

Note:

This is ambitious; if the translation part does not fit into the timeframe, p5.js will only convert computer date to Shamsi date, transliterate it, and display on the LCD.

Challenges:

The biggest challenge is perhaps constructing words (my name consists of letters م ر ی م. But almost all letters have a compact form that you have to use when writing words, so my name reads مریم ). This explains why I have several variations of one letter in the hex matrix. The way I would approach this is through many rounds of trial and error and experimenting with spacing and character sizes.

The next challenge would be displaying each character in a reverse manner (the letters read from right to left). The cursor has to be reversed every time there is a character input.

The 16×2 screen is limited and there will be character overflow and boundary issues, but the main goal here is to display the date and the LCD offers more than enough space for that purpose.

Timeline:

The week of November 28th: Experiment with displaying standalone letters. Get a good idea of the 16×2 space and the position of the cursor.

The week of December 5th: Get input from p5.js. Ensure the characters form words in a correct and consistent manner.

The week of December 12th: Experiment with adding colors. Build a frame for the LCD (a small structure with a stand so it could be put on disk). Prepare for the showcase.

Leave a Reply