Learning things that normally the librarie does for me

Hello Arduino Community

i'm interested in learning how to do LOW LEVEL things.

For example in my Starter Kit is a LCD that can be connected with 4 or 8 Pins.

I realized that the libraries LiquidCristal.h print.h and so on does quite a lot of work for me and i would like to learn how to control an electronic component like the LCD without such a library and would like to ask if there are any tutorials or projects where i could learn these things.

(I tried to read these libraries on github but i realized that these libraries are already to big and to complex to start with)

With Kind Regards
Marc Landolt

To satisfy your curiosity for programming the LCD using low-level instruction (by-passing the high-level commands of LiquidCrystal.h Libary of Arduino), there are scopes for the Forum Members to prepare tutorials in this regard; but, the question is: how long this process could be continued!

The following write-up is intended just to satisfy your query on what is going on in the background when the instruction lcd.write(0x41) (for example) is executed.


Figure-1: Typical connection diagram between UNO and 16x2 PLCD (Parallel LCD)

1. The MCU places: LH at A0-pin to select LCDDR (LCD Data Register); 0100 (upper 4-bit of 0x41) on DPins-8, 9, 10, and 11; LL-LH-LL (Enable Pulse) at A1-pin.

2. Delay for a while

3. The MCU places: LH at A0-pin to select LCDDR (LCD Data Register); 00001 (lower 4-bit of 0x41) on DPins-8, 9, 10, and 11; LL-LH-LL (Enable Pulse) at A1-pin.

4. The character A automatically appears on the LCD; because, LCD is an ASCII display, and we have written the ASCII code (0x41 = 01000001) of A onto LCD.

All the low-level electrical/logical activities of Step-1 to 3 are carried out by the C/C++ instructions contained in the LiquidCrystal.h and Liquidcrystal.cpp files.

You can start small by asking one specific question that gets you going.

If you want to do things the hard way that's fine but you are going to need to work for it. Just start digging your way through the library source code. When you hit something you don't understand do some research until you understand it and then write some test code to verify that you do.

The Print class is pretty easy. You just have a print function overload for every data type you could possibly want to print. Those functions do the necessary conversions to turn the data into chars and then feed it into the write function. The write implementation is defined by the class that inherited from Print since at that point the code will be application specific. So the Print class allows libraries to share these generally useful conversion functions instead of having duplicate code in every library that needs them.

landev:
Hello Arduino Community

i'm interested in learning how to do LOW LEVEL things.

For example in my Starter Kit is a LCD that can be connected with 4 or 8 Pins.

I realized that the libraries LiquidCristal.h print.h and so on does quite a lot of work for me and i would like to learn how to control an electronic component like the LCD without such a library and would like to ask if there are any tutorials or projects where i could learn these things.

(I tried to read these libraries on github but i realized that these libraries are already to big and to complex to start with)

With Kind Regards
Marc Landolt

Bit level code is a bit beyond (no pun intended) ordinary C/C++ books.

As far as the LCD is concerned, I can explain how it works and that may help you a bit.

The LCD acts sort of like a bare memory chip. You put data on the bus (i.e. a total of 8 ones or zeros), an address on the address bus, then "turn on" ("assert" is the proper word) the "WR(ite)" pin, then blip (assert, then de-assert the EN(able pin). This causes the bit pattern on the data bus to be "pushed" into the storage location you selected.

The Arduino AVR chips (as well as most others) are able to set each pin to one of 3 states... LOW/OFF/0 , HIGH/ON/1 and finally OPEN/FLOATING/? (this last one is for READING something outside).

Now, concerning the LCD, it needs to be powered up and initialized (i.e. told how many characters and rows it has, which port to use if it's a serial/parallel type and whether it's in 4 bit or 8 bit mode, etc...).

Let's assume it's setup for 8 bits and parallel data mode (makes the following easier to understand).

Right now, the LCD cursor (i.e. the electronic position of display memory inside the LCD is set to row 0, column 0). Now, let;s say we want to display a letter "A" at that location.

First we put
** **01000001** **
on the 8 bit data port (hex 0x41, decimal 65, ASCII A), then using another pin, set the WR (write) pin to LOW (0 volts, logic 0) then finally using another pin, bring the EN (enable) pin high for a few microseconds (the datasheet for the LCD will tell us what the proper value is) and this causes the bit pattern 01000001 to be placed in LCD display memory.

In turn, the LCD looks up the internal bit pattern to generate a picture of an "A" on the LCD and turns on those segments (you don't need to worry about that - the LCD controller chip does that itself). Also, the internal LCD controller automatically moves it's internal "cursor" to the next location. Repeating the sequence above would result in "AA" being displayed.

Now, say you didn't want "A" but instead "B". You than have to send a command to the LCD to move it's cursor back one place, then "print" a space there (to erase the A), then move the cursor back AGAIN (remember the LCD automatically moves the cursor up one each time you print), then finally put your replacement character "B" in place.

All of these detailed, low level commands are fairly complicated and there are quite a few of them:


[b]Display Clear
Cursor Home
Entry Mode Set
Display Control
Cursor or display shift
Function control
Brightness Control (VFD only)
CG Ram address setting
DD Ram address setting
Busy flag / Address read
Write data to CG or DD ram
Read data from CG or DD ram[/b]

And, each one of these takes parameters that define exactly what the command DOES, as well as certain delays required to alloy a certain command to complete. If you make a SINGLE MISTAKE in a command or parameter, the LCD can go crazy or just go blank (or print gibberish).

So, rather than writing in this low level, the programmer tediously uses the data sheet for all the nitty-gritty and writes functions with understandable, real world names like "SetCursor" or "ClearScreen" or "SetBrightness" (vfd only), etc...

Finally all of these functions or subroutines are collected together into a "class" which is given a name (in Arduino land, the class name is "LiquidCrystal").

After including the "LiquidCrystal" library into your sketch, all you need to do is make a local copy of the class, then use it... for example:

// example - not working code
#include <LiquidCrystal> // pull in the LCD driver code library
static LiquidCrystal LCD (pins, rw, en, etc); // make a copy called "LCD" and define pins

void setup (void)
{
    LCD.begin(16,2); // call function "init" and tell it 16 chars, 2 rows
    LCD.print("Hello therx"); // oops typo!
    LCD.print("\be."); // backspace then change x to e and add a period
}

See? All the library does is insulate you from the tedious, error prone attempts at controlling the LCD bit by bit, byte by byte. You COULD simply have all the LCD functions in your own sketch and not even use LiquidCrystal, but why? And, what if you wanted to use TWO LCD displays at once? Using the library, all you need to do is define another copy of the class (with the appropriately different pin numbers) and, say, call it "LCD1".

Then, everything done to LCD.xxx goes to the first one and LCD1.xxx goes to the second. No need to re-write any code!

Lastly, mostly FYI, the Arduino boards have 8 bit PORTS where one 8 bit value can be written in one operation and all 8 pins will assume the appropriate 1 or 0 value. This would be ideal for the LCD to simply use one whole port for it's data.

BUT, each BIT of the LCD data port can be on any pin, which means the LCD most probably will not be connected to a whole port. So, the library, in addition to all it has to do, ALSO has to keep track of EACH pin used by a particular port bit, then build up the data a bit at a time, then finally "push" it all into the LCD (the EN pin).

If it was required that the LCD data port be all connected to one PORT, and if the driver didn't have to juggle bits, it would probably be 8 to 10 times faster (but so what? How fast can YOU read?) :slight_smile:

Hope this makes some sense, and feel free to ask anything else.

pert:
The Print class is pretty easy. You just have a print function overload for every data type you could possibly want to print.

The overloaded Print library / function made me tear out more hair than anything else. It took me a long time to figure out what "virtual" functions were and how, for eaxmple, exactly WHICH "print()" was called depending on the context.

I understand it now, but getting there was a really bumpy road.

landev:
(I tried to read these libraries on github but i realized that these libraries are already to big and to complex to start with)

I reckon the answer is to start exploring a simpler library and as your knowledge increases you can explore the more complex ones.

It is also important to have a a clear understanding of how to interface with simple pieces of hardware - for example get a simple 7-segment display and learn how to connect it and how to make shapes appear. If you focus on a simple piece of hardware you can get a great deal of info from the product datasheet.

When you have a good understanding about how different pieces of hardware work you will have in your mind a concept of what is probably going on inside the library before you ever open the library code. For example if you know that servos need a pulse of a certain width at regular intervals you can explore the Servo library to see where it generates those pulses.

By the way I do not mean that you need to have a good understanding of every specific piece of hardware - just the general concepts on which they are built.

...R

Thank you for your answers and your hints :slight_smile:

Speaking of LCD... you might find this 8-bit Guy video(s) interesting: How a Character LCD works Part 1 - YouTube