Monday, 1 October 2012

Raspberry Pi - LCD scroller tutorial

After having my Raspberry Pi for months now - I've finally started to have a little tinker with the GPIO. After a good few hours talking with Matt @ RaspberryPi Beginners and blaming my lack of electronics knowledge on things like...
- Broken resistors (also, claiming the resistors he gave me were magical resistor-diodes that only worked the right way around)
- Faulty multimeter (actually not faulty - was on the wrong setting for the resistors I was testing)
- Broken breadboard (not broken, I just can't read schematics)

...I finally got a 2x16 LCD working and displaying some bits and pieces through a cobbling of Python scripts.

The first thing I wrote was a simple message scroller for the LCD (file available here). The GPIO skeleton script is from RaspberryPi-Spy.co.uk. If you're going to try this you'll need to have your LCD setup first (I would recommend the videos by RaspberryPi Beginners for a step-by-step guide).The scrolling action is handled by the code from lines 74 - 83.
If you're new to Python - I'll walk you through how the scrolling works.

1:   str_pad = " " * 16  
2:   my_long_string = "this is a string that needs to scroll"  
3:   my_long_string = str_pad + my_long_string  
4:   for i in range (0, len(my_long_string)):  
5:    lcd_byte(LCD_LINE_1, LCD_CMD)  
6:    lcd_text = my_long_string[i:(i+15)]  
7:    lcd_string(lcd_text,1)  
8:    time.sleep(0.4)  
9:   lcd_byte(LCD_LINE_1, LCD_CMD)  
10:   lcd_string(str_pad,1)  

1. str_pad is the variable we are going to use to help us with the scrolling effect (I say 'effect', because the text isn't technically scrolling. What we're doing is providing a string that is too long to display on the LCD screen and then displaying the rightmost part of the string left one character at a time. If it helps, think of it as looking at a long line of text through a window only 16 characters wide and then moving that string left while keeping the window still). We've gone with 16 blank characters for our padding string - this will make the text look like it's scrolling in from the right onto a blank screen. A nice little trick to save typing in 16 actual spaces is to type a single " " character in quotes and then multiply it by 16. Python and other modern languages can perform (what looks like) arithmetic on strings. For example, "print 'badger' * 100" would give you badger badger badger badger...

2. my_long_string, this is our actual message. This can be whatever you like and is the actual message that will be displayed.

3. Now we join (in programming terms, Concatenate) the two strings together so we end up with the 16 padding spaces (for the blank screen) plus our message at the tail end.

4. Here we move right into loops. This one-liner is doing a few things at once. We are creating 'i' as our iterator (I might write another tutorial on this later on, in the mean time - there is some background here). Our iterator is based on the range of characters in our my_long_string variable. We get this figure through the range command, which in this case takes two parameters; the start value and an end value. It can also take a third 'step' value if you want to move through the iterator in particular jumps. The starting value is 0 and the end is the length of our my_long_string variable which is calculated with the last inline command len(my_long_string). This is pretty simple - len() will return the length of the object you are testing between the brackets. Also note that the following few lines are indented. This is how Python knows which code is part of the loop.

5. This is part of the GPIO > LCD functionality - I haven't had a good poke around this code yet to see what's going on under the hood, but it tells the GPIO which memory location to use for outputting to line 1 or 2 of the LCD.

6. Here we create a new string variable using a slice of the variable my_long_string. A slice is similar to a substring(substr) in other languages in that it allows you to take a section of an existing string based on a start and end position. In our code, we are using the value of our iterator to move through the string from left to right. This is because when using a for loop, the iterator increases / moves on to the next object in the iterator, allowing us to work through each character in our string.

7. This is where we display the current 'window' of our string. The lcd_string function is what sends your string to the GPIO and to the LCD. The first parameter passed to it is the slice of my_long_string which is stored in lcd_string. The second value passed to the function is the number 1 - which if you look at the rest of the script means the text is left justified.

8. time.sleep(0.4) uses the Time module to apply a brief delay at the end of the loop. Without this, the text will fly past and either be unreadable or you'll think the script is broken. At the end of the 0.4 seconds the script will loop back to line 5 until the end of my_long_string is reached.

9. Make note of the subtle indentation here again - moving back out two spaces to show we're not in the loop any more. We're setting up the LCD for writing to line 1 again.

10. A simple finish - we're writing the blank padding string to the screen to clear the LCD.

Hope this is useful, I'll be writing some more Python / Pi tutorials in the coming weeks. If there's a particular element of Python that needs explaining, I'll try and break it up into easier terms (disclaimer, I'm not a Python expert by any means but I know enough to get by).





4 comments:

  1. Nice Tutorial.
    Question about the code, how must i change your script to scroll from left to right?

    ReplyDelete
    Replies
    1. Hey - you'd need to look at putting the padding at the start of the string and then going through the loop backwards (so starting at the length of the string and then decreasing the loop counter to 0). So it will look like it's scrolling in the opposite direction.

      Delete
  2. Keep getting same error.

    lcd_string(lcd_text,1)
    TypeError: lcd_string() takes exactly 1 argument (2 given)

    ReplyDelete