NIW2
Posts: 3
Joined: Tue Jul 02, 2019 3:54 am

I2C lcd isnt working with multiprocessing(solved mp was not the issue))

Tue Jul 02, 2019 3:57 am

(i am quite new to coding and the rpi so bare with me pls)


I am using multiprocessing to run 2 loops simultaneously, and when I try to use the lcd from one of these loops it gets a remote I/o error and I can no longer find the lcd when using the command:

> sudo i2cdetect -y 1

(Also, the lcd works fine within the same program as long as it's not in one of these loops)

After rebooting the pi the lcd is visible again. What is going on?

Edit: I was making the sda pin a gpio output smh.
Last edited by NIW2 on Wed Jul 03, 2019 4:50 pm, edited 1 time in total.

Andyroo
Posts: 3776
Joined: Sat Jun 16, 2018 12:49 am
Location: Lincs U.K.

Re: I2C lcd isnt working with multiprocessing

Tue Jul 02, 2019 8:54 am

Welcome to the forum,

Without seeing the code it’s a bit hard to tell but a few possible ideas:
1) The power to the screen is wrong or fluctuates
2) A command to the screen is wrong and is corrupting the screen controls
3) You have a clash in the threads
4) Something else on the bus is affecting the LCD

Have you tried your code outside of a thread?
Need Pi spray - these things are breeding in my house...

NIW2
Posts: 3
Joined: Tue Jul 02, 2019 3:54 am

Re: I2C lcd isnt working with multiprocessing

Tue Jul 02, 2019 6:44 pm

I have tried the lcd out of a thread in the same program, and in other programs and it works just fine.

I can copy some of the code, but it will be a few minutes.

User avatar
mikronauts
Posts: 2709
Joined: Sat Jan 05, 2013 7:28 pm
Contact: Website

Re: I2C lcd isnt working with multiprocessing

Tue Jul 02, 2019 6:56 pm

Two threads (or programs) cannot access the same i2c pheripheral at the same time.

Google "semaphores" (locks) and/or write one i2c server process and send messages to it from other threads.

Google "server daemon" or "server thread"
NIW2 wrote:
Tue Jul 02, 2019 6:44 pm
I have tried the lcd out of a thread in the same program, and in other programs and it works just fine.

I can copy some of the code, but it will be a few minutes.
http://Mikronauts.com - home of EZasPi, RoboPi, Pi Rtc Dio and Pi Jumper @Mikronauts on Twitter
Advanced Robotics, I/O expansion and prototyping boards for the Raspberry Pi

NIW2
Posts: 3
Joined: Tue Jul 02, 2019 3:54 am

Re: I2C lcd isnt working with multiprocessing

Tue Jul 02, 2019 7:46 pm

something odd just happened. this code here works fine:

Code: Select all

import lcddriver
import time
from multiprocessing import Process

lcd = lcddriver.lcd()

lcd.lcd_clear()
time.sleep(1)
lcd.lcd_display_string("test line 1", 1)
time.sleep(1)
def outLoop():
	while True:
		lcd.lcd_clear()
		lcd.lcd_display_string("Test line 2",2)
		time.sleep(1)
		lcd.lcd_display_string("Test line 2**",2)
		time.sleep(1)
def printLoop():
	while True:
		print("TEST")
		time.sleep(1)

if __name__ == "__main__":
	Process(target=outLoop).start()
	Process(target=printLoop).start()

But this code doesnt: (note there is a lot here, it is for an underwater robot. if u need I can cut out the unimportant parts)

Code: Select all

#***INCOMPLETE***#

import serial #use ttyS0
from evdev import InputDevice, categorize, ecodes, KeyEvent
import os
import RPi.GPIO as gpio
import lcddriver
import time
from multiprocessing import Process

comm = serial.Serial("/dev/ttyS0", 9600)

lcd = lcddriver.lcd()
lcd.lcd_clear()

lcd.lcd_display_string("####LEAK DETECTED###", 1)


gpio.setmode(gpio.BCM)
gpio.setup(4, gpio.OUT, initial = 0)
gpio.setup(3, gpio.OUT, initial = 0)
def sizer(msg,value):
	valstr = str(value)
	length = len(valstr)
	if length  == 1:
		valstr = "000"+ valstr
 	elif length == 2:
		valstr = "00"+ valstr
	elif length ==3:
		valstr = "0" + valstr
	msg = msg + valstr
	return msg
#these functions are copied from the rov controll. i am puting the conversion from input to output in the topside instead of ROV side rpi.


#GET DEAD ZONES FROM TESTING
#basic equation ((input/maxinput)*(maxout - minout)) + minout = output
def convert(val):
	out = ((val/1023.0)*316) + 232
	out = int(out)

	if out == 619:
		out = 618 #these are the max and min values. the if statements prevent it from going over.
	elif out == 161:
		out = 162
	return out
def convert255(val):
	out = ((val/255.0)*316) + 232
	out = int(out)
	#if out == 619:
	#	out = 618
	#elif out == 161:
	#	out = 162
	return out


def serialLoop(): #needs gpio items to activate, needs depth input
	lcd.lcd_clear()

	leak = False
	temp = 0.0
	depth = 0.0
	
	while True:
		#msgin = comm.read(8)
		msgin = "leakleak"
		if msgin == "leakleak":
			print("**LEAK DETECTED** FLIP EMERGENCY SHUTDOWN SWITCH")
			gpio.output(4, gpio.HIGH) #buzzer
			lcd.lcd_display_string("####LEAK DETECTED###", 1)

		elif msgin == "calibrat":
			print("ROV calibrated.")
			gpio.output(3, gpio.HIGH) #green LED (add blink later)

		elif msgin[0:3] == "dep": #substring length 3 char, offset 0
			depth = float(msgin[2:5])
			print(depth)

		elif msgin[0:3] == "tem":
			temp = float(msgin[2:5])
			print(temp)

		if depth >= 100:
			print("*******WARNING*******")
			print("**EXCEDING RATED DEPTH**")
		time.sleep(1)
		
def inputLoop(): #no lcd stuff here

	input = InputDevice('/dev/input/event0')

	lights = False

	mtr1 = 390
	mtr2 = 390
	mtr4 = 390
	srv1 = 0 #get 0 value
	for event in input.read_loop():
		if event.type == ecodes.EV_KEY: #reads buttons pressed
			print(event.code)
			if event.value == 1:

				if event.code == 289 : #Manipulator Release Begin
					print("Releasing Manip")
					comm.write("manpOpen")

				elif event.code == 288: #Manipulator Grab Begin
					print("Manip Grabbing")
					comm.write("manClose")

				elif event.code == 290: #Lights Toggle
					if lights == False:
						lights = True
						print("Lights On")
						comm.write("lightsOn")
					elif lights == True:
						lights = False
						print("Lights Off")
						comm.write("lightOff")
				elif event.code == 298:
					print("Shuting Down ROV and Surface Controller.")
					print("Wait for the indicator lights on the ROV and RPi to go off before killing power.")
					comm.write("exitexit")
					os.system("sudo shutdown -h now")

				elif event.code == 299:
					print("Emergency Power Cut Initiated")
					comm.write("powerCut")
			elif event.value == 0: #buttons Depressed

				if event.code == 289: #Manipulator Release Stop
					print("Releasing Manip Stopped")
					comm.write("manpStop")
				elif event.code == 288: #Manipulator Grab Stop
					print("Manip Grabbing Stopped")
					comm.write("manpStop")

		elif event.type == ecodes.EV_ABS:
			absevent = categorize(event)
			val = absevent.event.value
			msg = ""
			#print(absevent.event.code) #prints the event code

			if absevent.event.code != 16 and absevent.event.code != 5: #not sideways top hat and rotate
				if absevent.event.code == 17: #top hat
					msg = "absh"
					if val == -1:
						comm.write("srv10525")
						print("lookup")
					elif val == 0:
						comm.write("srv10390")
						print("lookzero")
					elif val == 1:
						comm.write("srv10255")
						print("lookdown")
	                            #look up = -1, look down = 1, look stop = 0

				else:
					#absz = vertical, absy = forward/back, absx = horizontal, absr = rotate.



					if absevent.event.code == 1: #joystick y, vertical
						msg = "mtr4"
						val = convert(val)
						msg = sizer(msg,val)
						comm.write(msg)

					elif absevent.event.code == 6: #throttle x, rotate.
						#needs work
						val = convert(val)
					elif absevent.event.code == 2: #throttle
						msg = "mtr1"
						val = convert255(val)
						msg = sizer(msg,val)
						comm.write(msg)

						msg = "mtr2"
						msg = sizer(msg,val)
						comm.write(msg)

					elif absevent.event.code == 0: #joy x side to side
						msg = "mtr3"
						val = convert255(val)
						msg = sizer(msg,val)
						comm.write(msg)

			print(msg)
if __name__ == '__main__':
	Process(target=inputLoop).start()
	Process(target=serialLoop).start()

Any Ideas what is causing only the second program not to work?

Edit: when testing multiprocessing and having two threads using the lcd on the working program, it just stopped displaying text while that program was active, not have an I/O error so it is possible that multiprocessing may not be the problem.

Return to “Python”