I am using the sainsmart 4x20 lcd. I have successfully created (createChar) and displayed a custom character. However, I'd like to modify my custom character in my main loop (so I can control each element (pixel?) of each character.
When I move the createChar function into the main loop, the program seems to stop working.
Has anyone used successfully createChar to update/modify a custom character in the main loop, or can it only be done in setup()?
You can do it anywhere. However, you need to be careful not to do it EVERY time through the loop (many thousands of times a second) as the LCD display will not respond quickly and is can end up with corrupted character definitions (I have seen this behaviour). The solution is to only change the character when it needs to be changed, and if this is very frequently then find a different solution for displaying your information.
What do you mean by 'it stops working'? You need to be more specific.
The problem you may be experiencing is that pretty much all the LiquidCrystal libraries have a bug in their createChar() function in that they do not point the lcd back to display memory after the data is written to CGRAM.
To fix this make sure you do setCursor() call after your createChar() call before you send any further characters to the display using print() or write() etc...
Otherwise, the characters will not show on the display and you will corrupt the CGRAM since the character data will be written to CGRAM instead of display ram.
There should be no issue with how fast or how often you re-program the custom characters.
If there is, it is s/w bug in the library.
I don't think it is really a bug since, unless the the R/W line is implemented, the author of the library has no way of knowing where you you want the cursor to be set when you are finished.
When the device is initialized the cursor is set to (0,0) and after that it is up to the programmer to deal with the positioning unless he or she is satisfied with the automatic incrementing (or decrementing). The LCD controller does keep track of the position and it is possible to read that information if the R/W line implemented.
When you create a character you change that information and when you finish creating characters the cursor is left pointing to the next (or previous) memory location just as it always is.
If the R/W line were implemented then the library could be written to read that information before actually creating the character and then the position could be reset when done. Otherwise an obvious compromise would be to always set the position to (0,0) but that could possibly cause other problems for some programmers.
just for my information: could I use the R/W line even when I am talking to the LCD via I2C?
If so, how?
Only if the particular I2C adapter implements the R/W line. Many do but some don't.
You would use the same techniques that one would use to read the busy flag. The flag is returned in the most significant bit and this is what a 'busy flag' routine checks. The other seven bits contain the address to which the cursor is pointing.
You can find some examples showing how to read the busy flag, not using I2C and not dealing with the address information either, by following the LCD Programming Examples link at http://web.alfredstate.edu/weimandn .