LCD – James Batchelor https://james-batchelor.com Useful I.T & VoIP Ramblings Sun, 30 Oct 2016 17:33:47 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.5 https://james-batchelor.com/wp-content/uploads/2025/05/cropped-cropped-logo-jb-202505-32x32.png LCD – James Batchelor https://james-batchelor.com 32 32 Update: Raspberry Pi Temperature Display https://james-batchelor.com/index.php/2016/10/30/update-raspberry-pi-temperature-display/ Sun, 30 Oct 2016 17:33:47 +0000 http://james-batchelor.com/?p=501 Continue reading "Update: Raspberry Pi Temperature Display"]]> With the cooler outdoor temperatures, a bug in my original code for the temperature display has cropped up:

IMG_6295

The DS18B20 returns temperatures with up to three decimal places, with the decimal point omitted, therefore a temperature of 10oC would be shown as 10000 by the sensor. To deal with this and for the display to show the temp to one decimal, I used this code:

        temperature1a = str (tempdata1[2:-3])

temperature1b = str (tempdata1[4:-2])

temperature1 = str ((temperature1a) + ‘.’ + temperature1b))

Here the value is essentially split in two, the number before the decimal and the number after, then the third line of code joins them back together with the decimal point in place. This is achieved by reading the value, then chopping off a number of characters using the [2:-3], this would chop off 2 characters at the start of the string, and 3 from the end.

The bug arises when the ambient temperature falls below 10oC as the sensor will output a 4 integer value as opposed to 5. This in turn will cause the cropping function to read incorrect values as its operation depends on a constant integer length.

As a result, the code will still function, but lower temperature values would be displayed without any decimalisation. Not happy with this I worked on another solution:

First Attempt

Referencing back to the original post on REUK, the code floated the text value into and integer, then a division of the value by 1000 gave the value a decimal point. Expanding on this I thought to keep the value as an integer to add the decimal, then convert to a string to allow the chopping off of the extra decimal places.

On testing however, I was getting inconsistent values, some values displayed with a decimal, others without.

I discovered that the DS18B20 would output a constant 5 or 6 figure value, however when floating to an integer, any trailing zeros after the first decimal place is removed. Therefore the snipping could again corrupt the output.

Result

Until I can find a better solution, it is better to keep it as simple as possible and display the temperature values intact, except the division by 1000 to add the decimal. Luckily the 20×4 LCD display is large enough to accommodate this, with only minor layout tweaks.

IMG_6303

For those interested, here is the amended code to read the sensor and output the value:

        tempfile1 = open(“/sys/bus/w1/devices/28-000007f34893/w1_slave”)

temptext1 = tempfile1.read()

tempfile1.close()

tempdata1 = temptext1.split(“\n”)[1].split(” “)[9]

temperature1 = float(tempdata1[2:])

temperature1 = temperature1 / 1000

]]>
Raspberry Pi Temperature Display https://james-batchelor.com/index.php/2016/09/30/raspberry-pi-temperature-display/ Fri, 30 Sep 2016 19:30:10 +0000 http://james-batchelor.com/?p=486 Continue reading "Raspberry Pi Temperature Display"]]> Nothing grand to start with, but as a first project I thought to combine a 20×4 LCD display with two DS18B20 temperature sensors to monitor indoor and outdoor temperatures. This would replace a cheap display I had been using but was sceptical on its accuracy.

Getting the basics right involved making the device blend in to the current setup without the usual mass of wires protrude. From the last round of the seam ably endless cable management war I used a shoebox base as a stand for the webserver and network switch, with the box hiding the various power bricks and extra cable, with most coming from the Xbox 360. Still having the shoebox lid I thought it would be good to use as a modular part to house the Pi and display.

Current Setup
Current Setup

Case chosen, I used some box packaging as a spacer to allow the lid to fit on the box base, with the lid overhanging bit a few millimetres to allow the lid to fit over the base. Then a chance to layout the machine within the voids.

As the Pi and drive would have ended upside down, I decided to use wire and hot glue to suspend them from the lid as a crude cage, hanging them between the base and top allowed to maximise cooling.

Wire and hot glue keeps components on place
Wire and hot glue keeps components on place

Now for the screen, after successful breadboard testing, I converted it onto a piece of stripboard. As it was one-sided stripboard all connectors had to be on the same side, but luckily there was enough room to allow all connections and still have the screen flush to the box. The board design was modified to integrate a switch to provide power to the LCD backlight LED.

Display connection board
Display connection board

Measuring from the outside, a hole was cut for the screen and another for the switch that supplied power to the LCD backlight. Inserting and checking fit for the screen and switch the header cables were connected to the GPIO pins of the Pi.

pitemp04
Layout complete

Next the temperature sensors, connecting via the GPIO pins of the Pi, these connected to a small piece of stripboard that acted as a connector to the DS18B20 chips to allow easy, modular access to them, and positioned to the rear of the case. I used pin headers to connect the indoor sensor, connected with wire salvaged from an old PC, and a 2.54mm PCB terminal block connecter to wire the external sensor.

Temperature sensor connection board
Temperature sensor connection board

The indoor sensor was simple enough, but not having a waterproof variant of the DS18B20 sensor resulted in me creating one by soldering wires direct to the sensor, using heat shrink insulation on the pins and covering in hot glue to create a crude weatherproof version. This turned out well as the single strand wire allowed precise angling of the sensor to ensure it remained out of sunlight but not touching surfaces that were susceptible to sunlight heat.

Indoor DS18B20 chip converted to outdoor use
Indoor DS18B20 chip converted to outdoor use

A bit of cable management and it was put in place. Next up was to power it up and apply the code to provide the display.
This code is contained in a single .py file within the home folder of Debain, by entering sudonano display.py and entering the following:

from Adafruit_CharLCD import Adafruit_CharLCD
from subprocess import *
from time import sleep, strftime
from datetime import datetime

import os
import time
import Adafruit_CharLCD as LCD

# Raspberry Pi pin configuration:
lcd_rs = 27 # Note this might need to be changed to 21 for older revisi$
lcd_en = 22
lcd_d4 = 25
lcd_d5 = 24
lcd_d6 = 23
lcd_d7 = 18
lcd_backlight = 4

# Define LCD column and row size for 16×2 LCD.
lcd_columns = 20
lcd_rows = 4

# Initialize the LCD using the pins above.
lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7,
lcd_columns, lcd_rows, lcd_backlight)

# Print a welcome message to show script has started
lcd.message(‘James-Batchelor.com\n \n Starting up…’)

# Wait 5 seconds
time.sleep(5.0)

#—-Begin Loop—–

lcd.clear()

while 1:

#Read outdoor temperature
tempfile1 = open(“/sys/bus/w1/devices/28-000007f34893/w1_slave”)
thetext1 = tempfile1.read()
tempfile1.close()
tempdata1 = thetext1.split(“\n”)[1].split(” “)[9]
temperature1a = str (tempdata1[2:-3])
temperature1b = str (tempdata1[4:-2])
temperature1 = str ((temperature1a) + ‘.’ + (temperature1b))

#Read indoor temperature
tempfile2 = open(“/sys/bus/w1/devices/28-000007f268b0/w1_slave”)
thetext2 = tempfile2.read()
tempfile2.close()
tempdata2 = thetext2.split(“\n”)[1].split(” “)[9]
temperature2a = str (tempdata2[2:-3])
temperature2b = str (tempdata2[4:-2])
temperature2 = str ((temperature2a) + ‘.’ + (temperature2b))

#Read system temperature
cputempfile = os.popen(“/opt/vc/bin/vcgencmd measure_temp”)
cputemptext = cputempfile.read()
cputempfile.close()
cputemp = str (cputemptext[5:-3])

#Read system CPU load
cpuloadfile = os.popen(“uptime | tail -c 17”)
cpuloadtext = cpuloadfile.read()
cpuloadfile.close()
cpuload = str (cpuloadtext[:-13])

#Write to screen
lcd.clear()
lcd.message(datetime.now().strftime(‘%a %d%b%Y %H:%M\n’))
lcd.message(‘ Outdoor Temp: %s’ % ( temperature1 ) + ‘\n\n’ )
lcd.message(‘ Indoor Temp: %s’ % ( temperature2 ) + ‘\n\n\n’ )
lcd.message(‘RPi: T=%s’ % ( cputemp ) + ‘ L=%s’ % (cpuload) )
#Update screen every 20 seconds
sleep(20)

Ctrl O and Ctrl X to save, then the file was converted to executable by entering on the commnd line:
Sudo chmod +x display.py

The script will continuously run when started, but to make it start in the first instance, enter:
Sudo nano /etc/rc.local

In the file, enter the following at the end of the file, before the exit(0) line:
(sleep 1;sudo python /home/james/display.py)&

A quick reboot via sudo reboot and the script will update the display.

pitemp06
Finished product

Modifications

A check via various phone weather apps shows that the outside temperature was working great. However, the high indoor temperatures left me again sceptical. Luckily I had another Raspberry Pi and spare temperature sensors and found out I needed to move the indoor sensor further away from the case to provide more accurate readings.

Indoor sensor move away from heat sources
Indoor sensor move away from heat sources

So far its working great, but forever wanting more I’m currently researching how to send these temperature readings to a database in order to create graphs on daily temperatures. The Raspberry Pi community already has a host of different ways of achieving this, it’s just about picking the right one for me and implementing it to my needs.

Resources

LCD display code: Adafruit
Original temperature display code: REUK

]]>