27 September 2013

Raspberry Pi: Temperature and Time on a 16x2 LCD Display

I've continued to tinker with my Raspberry Pi Internet Radio and have recently been focusing on a menu system using the 16x2 display. With a bit of creative coding you can emulate an on-screen menu system quite well with some simple code.

One part I wanted to share this week was my main screen that shows the temperature and the time on a home screen. Both of these elements are updated every few seconds and the delay doesn't affect button pushes at any time. Consider it like a live desktop monitor as such. Magic!


The Nerdbox
All hail the mighty NERDBOX!


Here's a quick video I uploaded today sharing the update, which also includes some of the other features I have been playing with such as custom Radio station names, artist/track scrolling and Tweeting the Pi's temperature with a button push (more on that in my other blog here).




So, if you've read this far, you probably want to know how to get your Pi temperature/time on your LCD screen. Let's begin...


Step 1: What you need


Pretty obvious this time round:
  • Raspberry Pi setup
  • 16x2 LCD screen (other sizes should work - aim for the HD44780 type)
You need to have the LCD set up and working already, again, lots of information on the web on this. This post is more about looking at the code once you have one set up already.

That's all really. I wont go into keyboards, text editors etc - comment if you need help here.


Step 2: Context and Familiarisation


Let's just get our heads around some of the code/functions we will be using first.

A bit of context here on the command we will use to get the Pi's temperature. Go to terminal and type in the following:
 /opt/vc/bin/vcgencmd measure_temp  

You should get the current temperature displayed in this format:
 temp=34.7'C  

That's how we get the temperature for our display (we will use some code later to turn that into a string to use on our LCD).

Now similarly we find out the time, again in Terminal type:
 date  

Which should give you something like this:
 Thu Sep 26 21:25:40 BST 2013  

Now when I mention these later, you'll kind of understand what they are, what they do, and where the information will be coming from.

**Optional**
I personally think if you're approaching anything with a 16x2 LCD, the best place to start is to try and create an Internet Radio with one first. 

Now that kind of sounds hard, but due to the number of examples, forum conversations and YouTube videos on this subject - it really is as simple as following instructions. Try Meistervisions tutorial as a starting point, and Google yourself mad from there.



Step 2: The Python Code


Let's jump straight in and take a overall look at my code to kick us off - it may look a bit daunting but if I can work this out, so can you. Grab a coffee, take your time and stick with this. Oh and...my coding is very poor - but it works!
 def menu():  
  timelastchecked = 0  
  time.sleep(0.5)  
  while(1):  
   if time.time() >= timelastchecked:  
    timelastchecked = time.time()+3  
    mystring = ""  
    mytime = ""  
    mytemp = ""  
    pretemp = "NBX ["  
    posttemp = "] "  
    f=os.popen("date")  
    for i in f.readlines():  
     mytime += i  
     mytime = mytime[11:-13]  
     f=os.popen("/opt/vc/bin/vcgencmd measure_temp")  
     for i in f.readlines():  
      mytemp += i  
      mytemp = mytemp[5:-3]  
      mystring = pretemp + mytemp + posttemp + mytime  
      lcd_byte(LCD_LINE_1, LCD_CMD)  
      lcd_string(mystring,1)  
      lcd_byte(LCD_LINE_2, LCD_CMD)  
      lcd_string("< Off   Menu >",2)  
   else:  
    if ( GPIO.input(NEXT) == False):  
     menu1()  
    if ( GPIO.input(PREV) == False):  
     off()  


Confused? Great. Let's break it down...

Lines 1-3: (some initial stuff)

 def menu():  
  timelastchecked = 0  
  time.sleep(0.5)  

def menu(): - this is just defining this entire section of code as a module

timelastchecked = 0 - we will use this later on, it helps to not run the code too quick

time.sleep(0.5) - I just use this in case I hold the button down too long, keeps things controlled.

Lines 4-12: (getting us ready to create a string with the temperature and time)
  while(1):  
   if time.time() >= timelastchecked:  
    timelastchecked = time.time()+3  
    mystring = ""  
    mytime = ""  
    mytemp = ""  
    pretemp = "NBX ["  
    posttemp = "] "  
    f=os.popen("date")  

while(1): - I ended up using a 'while' because without it, my buttons didn't seem to work

if time.time() >= timelastchecked - and - timelastchecked = time.time()+3  - this is our first 'if' statement. It's saying "if it hasn't been 3 seconds since the last time I updated the LCD with temperature/time, skip this, because otherwise our temperature will be updating too quick and will look messy/twitchy"


mystring = "" / mytime = "" / mytemp = ""  - this is just starting a few strings that we will use later.

pretemp = "NBX [" / posttemp = "] " - again, we're starting strings, but this time we're specifying what we want in them. You can see that 'pretemp' is the first part that shows on my LCD, and 'posttemp' is the closing part for the temperature. In a bit we will add the middle section which is the temperature, then stitch them all together in one final combined string.

f=os.popen("date") - now this function/command is deprecated (I keep getting told on StackExchange!!) but it works so that's OK by my standards. Anyway, this is turning a terminal command (date) into a line, ready for us to manipulate.

Lines 13-16: Turn the 'date' line into simple XX:XX time string:
   for i in f.readlines():  
    mytime += i  
    mytime = mytime[11:-13]  
    f=os.popen("/opt/vc/bin/vcgencmd measure_temp")  

for i in f.readlines(): - read the line of text that came back from our previous 
f=os.popen("date") command.

mytime += i - makes our previously made empty string 'mytime' into the full line of text from 'date'

mytime = mytime[11:-13] - takes our new long string 'mytime' and chops 11 characters from the front, and 13 from the back, leaving us with just the time part (we started with "Thu Sep 26 21:25:40 BST 2013"

f=os.popen("/opt/vc/bin/vcgencmd measure_temp") - Similar function as above, turning the terminal command (/opt/vc/bin/vcgencmd measure_temp) into a line of text for us to play with.

Lines 17-20: Turn the 'measure_temp' line into a simple temperature string
    for i in f.readlines():  
     mytemp += i  
     mytemp = mytemp[5:-3]  
     mystring = pretemp + mytemp + posttemp + mytime   

for i in f.readlines(): - read the line of text that came back from our previous f=os.popen("/opt/vc/bin/vcgencmd measure_temp") command.

mytemp += imakes our previously made empty string 'mytemp' into the full line of text from 'f=os.popen("/opt/vc/bin/vcgencmd measure_temp")'

mytemp = mytemp[5:-3] - takes our new long string 'mytemp' and chops 5 characters from the front, and 3 from the back, leaving us with just the numerical temperature reading  (we started with "temp=34.7'C  ")


mystring = pretemp + mytemp + posttemp + mytime - this puts together strings pretemp, mytemp, posttemp and mytime into a single string called "mystring"


I.e. 'NBX [34.7] 17:55' (16 characters to fill the line...clever!)


Lines 21-25: Put our new strings on the LCD

    lcd_byte(LCD_LINE_1, LCD_CMD)  
    lcd_string(mystring,1)  
    lcd_byte(LCD_LINE_2, LCD_CMD)  
    lcd_string("< Off   Menu >",2)  

lcd_byte(LCD_LINE_1, LCD_CMD) - ready to send text to line 1


lcd_string(mystring,1) - send the string 'mystring' to line 1

lcd_byte(LCD_LINE_2, LCD_CMD) 
- ready to send text to line 2

lcd_string("< Off     Menu >",2) - send the text inside the "" to line 2


Lines 26-30: Define what to do if it hasn't been 3 seconds since the last temp update
   else:  
    if ( GPIO.input(NEXT) == False):  
     menu1()  
    if ( GPIO.input(PREV) == False):  
     off()  

Standard stuff - it's just saying "check the buttons for input". As this cycles over and over within a 'while' statement, buttons should remain responsive throughout.

Step 3: Run the code/script

No real guidance or rules here - I have this set to run when my LCD is set on particular menus. You could just show the temperature when a button is clicked, or just on boot etc. Configure to you heart's desire!


That's all folks

Drop a comment for any help, subscribe, +1, Tweet, share, write me a letter, send me a fiver...whatever...just show me the love :)




*****UPDATE*****

After a few requests, here is a link to a PasteBin of my full radio code for those that want to salvage parts for your own project. There isn't much guidance in the code, but I will do a FULL tutorial once I finish my plywood case.

http://pastebin.com/sNrKJUg9


If this helped you, +1 me, subscribe and say "Hi" on Twitter. ENJOY!



Average Man