Introduction: Raspberry Pi + Arduino Serial With LCD Screen


This is my Raspberry Pi info LCD, I wanted to try and get the Arduino and Raspberry Pi talking to each other through USB serial and I made this little project.

The Raspberry Pi uses a python script to get the data and then sends it as a string to the arduino which then displays the information on an LCD.

Step 1: Materials Needed

  1. 1x Raspberry PI (I'm using the Raspberry Pi B+ with rasbian wheezy found here )
  2. 1x Arduino (I'm using the Arduino UNO)
  3. 1x LCD 16x2 (Something like this)

Step 2: Connecting the LCD to the Arduino

Now you can connect the arduino to the LCD anyway you prefer but to connect the arduino and the LCD I used a project I found here on instructables which I found to be really helpful it allows you to use a shift register to connect the arduino and the LCD using only 3 wires, but you can always connect the LCD directly to the arduino if you don't need any extra pins on the arduino. The main parts used are the arduino, the LCD, a shift register and an NPN transistor for the LED backlight of the LCD

This is the link to that instructable: click here You can follow the steps and find the full list of parts needed there.

If you connect the arduino in any other way you might need to change a couple of things in the code like the library import, the way the LCD gets initialised, and some commands to print to the LCDmight be different.

Step 3: Connecting the Arduino to the Raspberry PI

This is simple just connect the usb which you use to program the arduino into a free port on the Raspberry PI

Step 4: The Code & How It Works

As you can see in the images and the code I added two more wires from the arduino to the LCD these basically control the LCD contrast instead of using a potentiometer and the screen brightness with PWM.

The arduino code listens for any strings coming in through the serial port, removes the first two characters which I chose to be the position where to write the string on the LCD and the rest would be the string to output.

String Format: ##String (since this is a 16x2 LCD the first number can range from 0-15 X position and the second number from 0 to 1 Y position)

The python script is written so that it always adds the coordinates before the string I wrote a function which takes two arguments the first argument is the string that will be displayed at 00 (first line of lcd) and at 01 (second line of lcd)

The commands to get the Raspberry Pi system info in the python script I found them online at click here

This is the python function which sends the strings to the arduino:

def serialClear():

def serialWrite(Line1, Line2):
serialClear(); //clear LCD time.sleep(betWait) //wait a bit for stringRead timeout ser.write("00"+Line1) //send first line time.sleep(betWait) //wait a bit for stringRead timeout ser.write("01"+Line2) //send second line

The Arduino Code (File also attached)

#include <LiquidCrystal595.h> // include the library
LiquidCrystal595 lcd(7,8,9); // datapin, latchpin, clockpin int contrastPin = 6; int brightnessPin = 10; int contrast = 135; int brightness = 255; String input = ""; String stringRec = ""; String pos = ""; int posX = 0; int posY = 0;

void setup() { pinMode(contrastPin,OUTPUT); pinMode(brightnessPin,OUTPUT); lcd.begin(16,2); // 16 characters, 2 rows lcd.clear(); analogWrite(contrastPin, contrast); analogWrite(brightnessPin, brightness); Serial.begin(9600); Serial.setTimeout(500); }

void loop() { if(Serial.available() > 0){ input = Serial.readString(); pos = input.substring(0,2); posX = pos.substring(0,1).toInt(); posY = pos.substring(1,2).toInt(); stringRec = input.substring(2); /*Serial.println("String: "); Serial.println(stringRec); Serial.println(); Serial.println("Pos: "); Serial.print(posX); Serial.print(" "); Serial.print(posY); Serial.println();*/ } if(stringRec.equals("clr")){ lcd.clear(); stringRec = ""; } lcd.setCursor(posX,posY); lcd.print(stringRec); }

The Full Python Code (File also attached)

import os, urllib, json, serial, time

#start serial conection with arduino ser = serial.Serial('/dev/ttyACM0', 9600)

betWait = 1 #wait before sending second string cant go lower than 1 because of arduino StringRead timeout sleepTime = 3 #wait before sending next batch of info

# 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]) #Get external IP def getIP(): data = urllib.urlopen("").read() return data def serialClear(): ser.write("00clr") def serialWrite(Line1, Line2): serialClear(); time.sleep(betWait) ser.write("00"+Line1) time.sleep(betWait) ser.write("01"+Line2)

def getPID(): pid = os.getpid() return pid time.sleep(3) #wait for arduino to reset

while True: # 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_free = DISK_stats[1] DISK_perc = DISK_stats[3] #external IP IP = getIP() #Python script pid PID = getPID() #OUTPUT TO ARDUINO serialWrite("Process ID", str(PID)) time.sleep(sleepTime) serialWrite("Temperature:", CPU_temp + " C") time.sleep(sleepTime) serialWrite("CPU Usage:", CPU_usage + "%") time.sleep(sleepTime) serialWrite("Total RAM:", str(RAM_total) + " MB") time.sleep(sleepTime) serialWrite("Used RAM:", str(RAM_used) + " MB") time.sleep(sleepTime) serialWrite("Free RAM:", str(RAM_free) + " MB") time.sleep(sleepTime) serialWrite("Total Disk Space:", str(DISK_total)+"B") time.sleep(sleepTime) serialWrite("Free Disk Space:", str(DISK_free) + "B") time.sleep(sleepTime) serialWrite("Disk Used:", str(DISK_perc)) time.sleep(sleepTime) serialWrite("Public IP:", str(IP)) time.sleep(sleepTime) #DEBUG OUTPUTS # print(CPU_temp) # print(CPU_usage) # print(RAM_total) # print(RAM_used) # print(RAM_free) # print(DISK_total) # print(DISK_free) # print(DISK_perc) # print(IP) # print("\n") # time.sleep(3)

Step 5: Before Running the Python Script

Before running the python code on the raspbery pi you mightneed to change this line :

#start serial conection with arduino
ser = serial.Serial('/dev/ttyACM0', 9600)

'/dev/ttyACM0' is the name usb port where the arduino is connected

To find out yours simply connect to the pi through ssh and type the following command (with the arduino disconnected):

ls /dev/tty* 

Then connect the arduino and type it again and check which item was just added

You can edit the code on the raspberry pi using:

sudo nano 

After editing the file use ctrl+x to save and type 'y' to confirm overwrite

To run the script type (make sure arduino is connected first!):

python ""

in this case:


and if you want to run the script in the background without leaving the ssh session open type

python "" &

in this case:

python &

Step 6: Final Result!

Remember I did this just as a little project to get the Arduino and Raspberry Pi talking through serial feel free to change the code and modify it to work with your project :)

Serial without Raspberry Pi

To send strings to the arduino without the raspberry pi and and python script you can use the serial monitor included with the arduino IDE remember to add the coordinates before the strings eg. "00String" or "01String" or I'll also include a java program which uses the RXTX library to send Strings similar to the python script:

To set up the RXTX library you can follow the tutorial here

The java code:

import*; import java.util.*;

public class Runner { final static String PORT = "COM3"; static SerialPort serialPort;

public static void main(String[] args) throws Exception{ Enumeration portList = CommPortIdentifier.getPortIdentifiers(); OutputStream outputStream = getPort(portList); for(int i = 0; i < 10; i++) { strOut(outputStream, "Test " + i + " Line 1", "Test " + i +" Line 2"); } strOut(outputStream, "Test Completed", "Succesfully");

outputStream.close(); serialPort.close(); } public static OutputStream getPort(Enumeration portList) { CommPortIdentifier portId; OutputStream outputStream = null;

while(portList.hasMoreElements()){ portId = (CommPortIdentifier) portList.nextElement(); if(portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { if(portId.getName().equals(PORT)) { try { serialPort = (SerialPort)"SimpleWriteApp", 2000); } catch (PortInUseException e) { System.out.println("Error: Port In Use"); } try { outputStream = serialPort.getOutputStream(); }catch(IOException e) { System.out.println("Error: IO Error"); } try{ serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch(UnsupportedCommOperationException e) { System.out.println("Error: Unsuported Operation"); } } } } return outputStream; } public static void strOut(OutputStream oS, String line1, String line2) throws Exception { Thread.sleep(3000); oS.write("00clr".getBytes()); Thread.sleep(1000); oS.write(("00"+line1).getBytes()); Thread.sleep(1000); oS.write(("01"+line2).getBytes()); } }

Pi/e Day Contest

Participated in the
Pi/e Day Contest