今天实验树莓派通过 I2C 驱动操作 LCD1602 液晶屏,屏幕带I2C 方式的驱动模块,可以极大的简化接线和驱动程序。本文利用C语言和python来实验操作LCD1602液晶屏,python程序方面分别显示字符串,IP地址,树莓派状态信息,功能更加丰富。特别是lcd_status.py程序设置为开机启动,那么树莓派的IP地址、状态都可以一目了然。作为可视化界面,当然也可以显示任何你需要的信息。
今晚搞了一晚,主要有三个地方花了时间。
一是模块上有一颗可调电阻,用于调节显示的对比度,如果你的屏幕无论怎么调试都不见显示,记得调节一下这里,这个问题纠结了我好久才发现!!!
二是运行python程序时,没有把float浮点数转换成字符串str,LCD不能写入浮点数。
三是树莓派要开启I2C功能。
1、接线图
GND --- GND VCC --- 接树莓派 3.3V
SDA --- I2C 数据 SCL --- I2C 时钟
2、启用树莓派的I2C功能
可以通过sudo raspi-config命令来开启,也可以VNC到树莓派来可视化开启。
运行命令看一下是否识别到屏幕, 地址为0x27,这说明已经成功连接了 LCD1602 屏幕。
sudo i2cdetect -y 1
3、C语言操作LCD lcd.c
#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>
#include <wiringPiI2C.h>
#include <string.h>
int LCDAddr = 0x27;
int BLEN = 1;
int ad;
void write_word(int data){
inttemp = data;
if(BLEN== 1)
temp |= 0x08;
else
temp &= 0xF7;
wiringPiI2CWrite(ad,temp);
}
void send_command(int comm){
intbuf;
buf= comm & 0xF0;
buf|= 0x04;
write_word(buf);
delay(2);
buf&= 0xFB;
write_word(buf);
buf= (comm & 0x0F) << 4;
buf|= 0x04;
write_word(buf);
delay(2);
buf&= 0xFB;
write_word(buf);
}
void send_data(int data){
intbuf;
buf= data & 0xF0;
buf|= 0x05;
write_word(buf);
delay(2);
buf&= 0xFB;
write_word(buf);
buf= (data & 0x0F) << 4;
buf|= 0x05;
write_word(buf);
delay(2);
buf&= 0xFB;
write_word(buf);
}
void init(){
send_command(0x33);
delay(5);
send_command(0x32);
delay(5);
send_command(0x28);
delay(5);
send_command(0x0C);
delay(5);
send_command(0x01);
wiringPiI2CWrite(ad,0x08);
}
void clear(){
send_command(0x01);
}
void write(int x,int y, char data[]){
intaddr,i;
inttmp;
if(x<0) x=0;
if(x>15)x=15;
if(y<0) y=0;
if(y>1) y=1;
addr= 0x80 + 0x40 * y +x;
send_command(addr);
tmp= strlen(data);
for(i= 0; i < tmp; i++){
send_data(data[i]);
}
}
int main(void){
ad= wiringPiI2CSetup(LCDAddr);
init();
write(0,0,"Hello");
write(1,1,"pi");
delay(2000);
}
write函数的第一二个参数的含义是列号和行号。
编译C语言:gcc lcd.c -o lcd -lwiringPi
运行程序:./lcd
4、python操作LCD
4.1 LCD显示字符 lcd1602.py
import time
import smbus
BUS = smbus.SMBus(1)
LCD_ADDR = 0x27
BLEN = 1 #turn on/off background light
def turn_light(key):
global BLEN
BLEN = key
if key ==1 :
BUS.write_byte(LCD_ADDR ,0x08)
else:
BUS.write_byte(LCD_ADDR ,0x00)
def write_word(addr, data):
global BLEN
temp = data
if BLEN == 1:
temp |= 0x08
else:
temp &= 0xF7
BUS.write_byte(addr ,temp)
def send_command(comm):
# Send bit7-4 firstly
buf = comm & 0xF0
buf |= 0x04 # RS = 0, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)
# Send bit3-0 secondly
buf = (comm & 0x0F) << 4
buf |= 0x04 # RS = 0, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)
def send_data(data):
# Send bit7-4 firstly
buf = data & 0xF0
buf |= 0x05 # RS = 1, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)
# Send bit3-0 secondly
buf = (data & 0x0F) << 4
buf |= 0x05 # RS = 1, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)
def init_lcd():
try:
send_command(0x33) # Must initialize to 8-line mode at first
time.sleep(0.005)
send_command(0x32) # Then initialize to 4-line mode
time.sleep(0.005)
send_command(0x28) # 2 Lines & 5*7 dots
time.sleep(0.005)
send_command(0x0C) # Enable display without cursor
time.sleep(0.005)
send_command(0x01) # Clear Screen
BUS.write_byte(LCD_ADDR ,0x08)
except:
return False
else:
return True
def clear_lcd():
send_command(0x01) # Clear Screen
def print_lcd(x, y, str):
if x < 0:
x = 0
if x > 15:
x = 15
if y <0:
y = 0
if y > 1:
y = 1
# Move cursor
addr = 0x80 + 0x40 * y + x
send_command(addr)
for chr in str:
send_data(ord(chr))
if __name__ == '__main__':
init_lcd()
print_lcd(0, 0, 'Hello, world!')
print_lcd(0, 1, 'Hello, world!')
运行程序:python lcd1602.py,print_lcd函数的前两个参数分别是列号和行号。
4.2 LCD显示时间 lcd_time.py
显示时间的python:lcd_time.py,需要使用到lcd1602.py的 print_lcd函数,所以调用lcd1602.py文件。
#!/user/bin/env python
import smbus
import time
import sys
import lcd1602 as LCD
if __name__ == '__main__':
LCD.init_lcd()
time.sleep(1)
LCD.print_lcd(2, 0, 'Raspberry Pi')
for x in xrange(1, 4):
LCD.turn_light(0)
LCD.print_lcd(4, 1, 'LIGHT OFF')
time.sleep(0.5)
LCD.turn_light(1)
LCD.print_lcd(4, 1, 'LIGHT ON ')
time.sleep(0.5)
LCD.turn_light(1)
while True:
now = time.strftime('%m/%d %H:%M:%S', time.localtime(time.time()))
LCD.print_lcd(1, 1, now)
time.sleep(0.2)
4.3 LCD显示IP地址 lcd_ip.py
和显示时间类似,显示树莓派的ip地址,这个程序可以设置为开机启动,这样就可以直观知道树莓派的IP地址了。
#!/user/bin/env python
import os
import smbus
import time
import sys
import socket
import subprocess
import lcd1602 as LCD
def getLocalIP():
ip = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('114.114.114.114', 0))
ip = s.getsockname()[0]
except:
name = socket.gethostname()
ip = socket.gethostbyname(name)
if ip.startswith("127."):
cmd = '''/sbin/ifconfig | grep "inet " | cut -d: -f2 | awk '{print $1}' | grep -v "^127."'''
a = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
a.wait()
out = a.communicate()
ip = out[0].strip().split("\n")
if len(ip) == 1 and ip[0] == "" or len(ip) == 0:
return False
ip = "over".join(ip)
return ip
if __name__ == '__main__':
LCD.init_lcd()
time.sleep(1)
LCD.print_lcd(2, 0, 'Raspberry Pi')
for x in xrange(1, 4):
LCD.turn_light(0)
LCD.print_lcd(4, 1, 'LIGHT OFF')
time.sleep(0.5)
LCD.turn_light(1)
LCD.print_lcd(4, 1, 'LIGHT ON ')
time.sleep(0.5)
LCD.turn_light(1)
while True:
now = time.strftime('%m/%d %H:%M:%S', time.localtime(time.time()))
ip=getLocalIP()
LCD.print_lcd(1, 1, ip)
time.sleep(0.2)
4.4 LCD显示树莓派状态 lcd_status.py
和显示IP地址类似,滚动显示树莓派温度,cpu使用率,内存信息和硬盘信息。
#!/user/bin/env python
import os
import smbus
import time
import sys
import socket
import subprocess
import lcd1602 as LCD
def getLocalIP():
ip = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('114.114.114.114', 0))
ip = s.getsockname()[0]
except:
name = socket.gethostname()
ip = socket.gethostbyname(name)
if ip.startswith("127."):
cmd = '''/sbin/ifconfig | grep "inet " | cut -d: -f2 | awk '{print $1}' | grep -v "^127."'''
a = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
a.wait()
out = a.communicate()
ip = out[0].strip().split("\n")
if len(ip) == 1 and ip[0] == "" or len(ip) == 0:
return False
ip = "over".join(ip)
return ip
# Return CPU temperature as a character string
def getCPUtemperature():
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=","").replace("'C\n",""))
# Return RAM information (unit=kb) in a list
# Index 0: total RAM
# Index 1: used RAM
# Index 2: free RAM
def getRAMinfo():
p = os.popen('free')
i = 0
while 1:
i = i + 1
line = p.readline()
if i==2:
return(line.split()[1:4])
# Return % of CPU used by user as a character string
def getCPUuse():
return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))
# Return information about disk space as a list (unit included)
# Index 0: total disk space
# Index 1: used disk space
# Index 2: remaining disk space
# Index 3: percentage of disk used
def getDiskSpace():
p = os.popen("df -h /")
i = 0
while 1:
i = i +1
line = p.readline()
if i==2:
return(line.split()[1:5])
if __name__ == '__main__':
LCD.init_lcd()
time.sleep(1)
LCD.print_lcd(2, 0, 'Raspberry Pi')
for x in xrange(1, 4):
LCD.turn_light(0)
LCD.print_lcd(4, 1, 'LIGHT OFF')
time.sleep(0.5)
LCD.turn_light(1)
LCD.print_lcd(4, 1, 'LIGHT ON ')
time.sleep(0.5)
LCD.turn_light(1)
while True:
now = time.strftime('%m/%d %H:%M:%S', time.localtime(time.time()))
ip=getLocalIP()
# CPU informatiom
CPU_temp = getCPUtemperature()
CPU_usage = getCPUuse()
# RAM information
# Output is in kb, here I convert it in Mb for readability
RAM_stats = getRAMinfo()
RAM_total = round(int(RAM_stats[0]) / 1000,1)
RAM_used = round(int(RAM_stats[1]) / 1000,1)
RAM_free = round(int(RAM_stats[2]) / 1000,1)
# Disk information
DISK_stats = getDiskSpace()
DISK_total = DISK_stats[0]
DISK_used = DISK_stats[1]
DISK_perc = DISK_stats[3]
LCD.clear_lcd()
LCD.print_lcd(0, 0, now)
LCD.print_lcd(0, 1, ip)
time.sleep(2)
LCD.clear_lcd()
LCD.print_lcd(0, 0, 'CPU Temperature='+CPU_temp)
LCD.print_lcd(0, 1, 'CPU Use='+CPU_usage)
time.sleep(2)
LCD.clear_lcd()
LCD.print_lcd(0, 0, 'RAM Total='+str(RAM_total)+'MB')
LCD.print_lcd(0, 1, 'RAM Used='+str(RAM_used)+'MB')
time.sleep(2)
LCD.clear_lcd()
LCD.print_lcd(0, 0, 'RAM Free='+str(RAM_free)+'MB')
LCD.print_lcd(0, 1, 'DISK Total Space='+str(DISK_total)+'B')
time.sleep(2)
LCD.clear_lcd()
LCD.print_lcd(0, 0, 'DISK Used Space='+str(DISK_used)+'B')
LCD.print_lcd(0, 1, 'DISK Used Percentage='+str(DISK_perc))
time.sleep(2)
5、实际效果图
6、设置开机启动
修改 /etc/rc.local 文件,在 exit 0 前面增加一行后台运行lcd_status.py的代码:
sudo python /home/pi/sensor/lcd_status.py &
网友评论