Python Forum
Weird refresh rate with i2c lcd
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Weird refresh rate with i2c lcd
#1
Hey everyone,

I am working on a program that gives me the values from different sensors.
On its own, the i2c screen seems to work fine, but when I use it with my program it seems to ‘slow down’. Like updating information seems to slow it down to the point where you can see the screen clear just to update one value.


Here is the module I’m using

Thanks!
Reply
#2
The lcd class calls time.sleep() several times in it's constructor, but that'd only be an issue if you're making tons of new instances.

So... share some code so we can give more helpful advice :)
Reply
#3
It’s in a while loop, so it might be the problem.

However, when I test it as a clock, that’s what i do, and it works fine.

The code is in my Pi. So I will have to get it tomorrow after work.
Reply
#4
Here is the code I use to control the lcd
from os import path
import ast
import time
import json
from lib.customLibs import lcdScreen
import lib. i2cLCD as lcddriver
from datetime import datetime
from auth import *

class displayScreen:
    def __passedData():
        values = {}
        with open("systemHWDriverFiles/display_passValues.txt", 'rt') as inf:
            r = str(inf.read()[1:-1]).split(', ')
        for i in r:
            for key, value in ast.literal_eval(i).items():
                if key not in values:
                    values[key] = []
                values[key].append(value)
        return values

    def __processData(data):
        resp = {}
        if 'apiCall' in data:
            Session = loginInfo()
            for i in data['apiCall']:
                resp[i] = Session.makeCall(i).text
        return resp
    def run():
        return displayScreen.__processData(displayScreen.__passedData())
        

    
test = displayScreen.run()

datetime.datetime.now()
now = datetime.datetime.now()

display = lcddriver.lcd()
display.lcd_display_string("Time: %s" %now.strftime("%H:%M:%S"), 1)
display.lcd_display_string(str(test['/api/phprobes/8/read']+'ppm   '+test['/api/phprobes/9/read']+'F'), 2)
My main script, loads in sensors based on api call, and ones that are manually entered and puts them into a while loop.

#Set up display /path from passed values
import json
from multiprocessing import Process
import ast
from os import path
import time

#Hardware Classes
from sensorClass import *
from lib.systemHW import *


#importing custom libs
from lib.customLibs import *

#import cred config files and system info
from auth import *

#API Sessions
Session = loginInfo()

#Create Sensors list
resp = Session.makeCall('/api/equipment')

hwObjects = {}
for k in json.loads(resp.text):
	senIndex = len(hwObjects)
	if chkFile(['Sensors/'+k['name']+'.py', 'driverFiles/'+k['name']+'_Sensor.txt', 'powerStatus/'+k['name']+'_Power.txt']):
		hwObjects[senIndex] = Sensor(k['id'], k['name'], k['outlet'], k['on'], senIndex)

#adding SystemHW
senIndex = len(hwObjects)
hwObjects[senIndex] = (systemHW('display', senIndex))
hwObjects[senIndex].addArg({'apiCall': '/api/phprobes/8/read'})
hwObjects[senIndex].addArg({'apiCall': '/api/phprobes/9/read'})
hwObjects[senIndex].addArg({'path': 'driverFiles/TestEquipment_Sensor.txt'})
hwObjects[senIndex].addArg({'path': 'driverFiles/TestEquipment2_Sensor.txt'})
#Looping hwObjects

def processLoop():
		func = []
		
		for processes in hwObjects:
			f = Process( target = hwObjects[processes].run, args=[])
			f.start()
			func.append(f)

		for f in func:
			f.join()

		return True

while processLoop():
	pass
Here is the class that the lcd uses:

from os import path
import json

#define class
class systemHW:
    def __init__(self, hwName, hwIndex):
        self.hwName = hwName
        self.hwFileLocation = "systemHWDriverFiles/"+hwName+"_passValues.txt"
        self.hwIndex = hwIndex
        self.arg = []
    
    def addArg(self, *argv):
        for i in argv:
            self.arg.append(i)
    
    
    def show(self, ):
        return [str(self.hwName), str(self.hwFileLocation), str(self.hwIndex)]
    
        
    def online(self):
        return True
            
    def run(self, *argv):
            if self.online():
                arg = self.arg
                updateValue = open(self.hwFileLocation, "w")
                updateValue.write(str(arg))
                updateValue.close()
                __import__('systemHW.'+self.hwName)
Reply
#5
I just skimmed your code, did not follow control, etc. But these stand out to me.

Is there anything that is preventing this from occurring?
def processLoop():
        func = []
         
        for processes in hwObjects:
            f = Process( target = hwObjects[processes].run, args=[])
            f.start()
            func.append(f)
 
        for f in func:
            f.join()
 
        return True
 
while processLoop():
    pass
From my perspective it appears to constantly loop and create new processes which would drag a program to halt. Also concatenation is a sure way to bottleneck a program and IO (file write/read) is one of the slowest processes, so restricting them would be ideal.
Recommended Tutorials:
Reply
#6
(Sep-10-2020, 10:39 AM)metulburr Wrote: I just skimmed your code, did not follow control, etc. But these stand out to me.

Is there anything that is preventing this from occurring?

No, but that loop is kind of the point of the program.

It reads sensors and displays their values on the screen.

Is there a better way to do this?

I used join(), to make sure that the loop doesn’t start again until each process has finished.
Reply
#7
I removed all the IO in the scripts,

It is defiantly faster, but the screen screen is still kinda wonky

When I run the demo clock script, it looks like the just the seconds are changing. however when I put it in the program i wrote, the whole screen clears before anything updates.

I've read online that i could speed it up by using the screens cursor to just change what's needed. Is there a script that anyone knows that does that?
Reply
#8
What's the demo clock script? If it's doing most of what you want, and doing it well, it would be helpful to take a look at it.

My #1 concern with things like this is always that the code makes total sense, but I have no way of actually testing it, which makes it super hard to help figure out what's going on.
Reply
#9
I've changed the script a bit to remove the file io

Here is the Main script

#import cred config files and system info
from auth import *

#API Sessions
Session = loginInfo()

#Create Sensors list
resp = Session.makeCall('/api/equipment')

hwObjects = {}
for k in json.loads(resp.text):
	senIndex = len(hwObjects)
	if chkFile(['Sensors/'+k['name']+'.py', 'driverFiles/'+k['name']+'_Sensor.txt', 'powerStatus/'+k['name']+'_Power.txt']):
		hwObjects[senIndex] = Sensor(k['id'], k['name'], k['outlet'], k['on'], senIndex, Session)

#adding SystemHW
senIndex = len(hwObjects)
hwObjects[senIndex] = (systemHW('display', senIndex))
hwObjects[senIndex].addArg({'apiCall': '/api/phprobes/8/read'})
hwObjects[senIndex].addArg({'apiCall': '/api/phprobes/9/read'})
#hwObjects[senIndex].addArg({'path': 'driverFiles/TestEquipment_Sensor.txt'})
#Looping hwObjects

def processLoop():
		func = []
		for processes in hwObjects:
			f = Process( target = hwObjects[processes].run, args=[])
			f.start()
			func.append(f)

		for f in func:
			f.join()


		return True

while processLoop():
	pass
Here is the Class that imports the lcd script
from os import path, getcwd
import json
from subprocess import Popen, PIPE


#define class
class systemHW:
    def __init__(self, hwName, hwIndex):
        self.hwName = hwName
        self.hwFileLocation = "systemHWDriverFiles/"+hwName+"_passValues.txt"
        self.hwIndex = hwIndex
        self.arg = []
    
    def addArg(self, *argv):
        for i in argv:
            self.arg.append(i)
    
    
    def show(self, ):
        return [str(self.hwName), str(self.hwFileLocation), str(self.hwIndex)]
    
        
    def online(self):
        return True
            
    def run(self, *argv):
            if self.online():
                arg = self.arg
                __import__('systemHW.'+self.hwName)
        
Reply
#10
I figured it out.

it was actually all due to this annoying little code
display = lcddriver.lcd()
whenever an instance of the lcd() class is made, the __init__() function runs, and resets the screen. so anyone else having this problem, simply removing the line from the while loop will fix the problem

in mycoses, i couldn't do that, so i changed the __init__ method to a new one called start(), and wrote code that only runs it once.
nilamo likes this post
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020