Python Test sensors, then run them all again until keypress - python

I`m making a python program for my small greenhouse to test different condition.
What I need it to do is: when the program ends, wait 5 min then run all the tests again.
This is my first ever full python program, so if you can keep the answer in the low learing curve area it would be greatly appriciated.
example:
temp=probe1
humidity=probe2
CO2=probe3
if temp==25:
print ("25)"
if humidity==90:
print ("90")
if CO2==1000
print ("1000")
import time
time.sleep (300)
start again from top until keypress

You can put what you have now in a while True loop to achieve the desired result. This will run forever, making measurements every 5 minutes, until you interrupt the program by pressing Ctrl-C.
import time
while True:
temp=probe1
humidity=probe2
CO2=probe3
if temp==25:
print ("25")
if humidity==90:
print ("90")
if CO2==1000
print ("1000")
time.sleep (300)
However, I'm left wondering how likely it is that your sensors give precisely the values you check for. You might go without any output for hours or even longer, depending on the precision of the sensor values. You might want to check the rounded sensor values, e.g. if round(temp) == 25.
Or maybe you want to know when temp is 25 or higher, which you can check with if temp >= 25.
Another possibility would be to always print the sensor data, and print an extra warning in case the values are higher than some threshold, e.g.:
import time
while True:
temp=probe1
humidity=probe2
CO2=probe3
print("Temp:", temp, "degrees")
if temp>=25:
print (" Too hot!")
print("Humidity:", humidity, "%")
if humidity>=90:
print (" Too humid!")
print("CO2:", CO2, "units")
if CO2>=1000
print (" Too much CO2!")
time.sleep (300)

Related

Update text in the pycharm console

I'm trying to make a script to calculate pi, but by increasing the steps in the main for loop, it drastically increases in the time it takes to calculate. Sometimes its hard to tell if its doing anything at all. So to fix this I put the following in the main for loop:
# prints the progress percentage (or pp)
pp = (i/rolls)*100
print(pp.__round__(pp_decimals))
rolls in the total number of times the loop will execute.
But this presents a new problem, this ends up printing ALOT of text, and all the print calls end up lagging my pc as well as clogging up the terminal. So my question is, how can I edit the text or delete previous text in order to clear up the output?
It is best to approach your problem in a different way. I assume that i is loop counter so you can print progress percentage in every t times instead clearing the output:
# prints the progress percentage (or pp)
if i % 10 == 0: # t is 10 in this example
pp = (i/rolls)*100
print(pp.__round__(pp_decimals))

Does using print() too much cause it to fail?

TL;DR:
The print() result is not updating in a Windows Console. Executes fine in IDLE. Program is executing even though Windows Console is not updating.
Background
I have a file, test.py that contains:
Edit: Included the conditions that I used to see if the Console was updating. Eventually the series of X values never prints again in Console and the Console never scrolls back up (as it normally does when output is being generated at the bottom).
count = 0
while True:
print ("True")
count += 1
if count == 10:
print ("XXXXXXXXX")
count = 0
When I run this in cmd.exe it obviously prints a very large number of True.
However, after about 25 seconds of running, it stops printing any more, though the program is still running and can be seen in the Task Manager.
I have a program with some progress indicators that end up stay at say 50% even though they are moving well beyond 50% simply because print() is not showing in the Console output.
Edit: The true use case problem.
The above code was just a test file to see if printing in Console stopped in all programs, not the one I was running. In practice, my program prints to Console and looks like:
line [10] >> Progress 05%
Where line [10] isn't real but I merely typed here to show you that print() sends to that line in the Console window. As my program continues it increments:
line [10] >> Progress 06%
line [10] >> Progress 11%
.
.
.
line [10] >> Progress 50%
Each time line [10] is overwritten. I use ANSI escape characters and colorama to move the Console cursor accordingly:
print('\x1b[1000D\x1b[1A')
This moves the cursor 1000 columns left and 1 row up (so the start of the previous line).
Something is happening where the print("Progress " + prog + "%") is not showing up anymore in Console because eventually the next bit of Python gets executed:
line [11] >> Program Complete...
I verified the resultants which get put into a folder. So the program continued to run while the Console did not update.
Edit: Here is the script running the updates to the stdout.
def check_queue(q, dates, dct):
out = 0
height = 0
# print the initial columns and rows of output
# each cell has a unique id
# so they are stored in a dictionary
# then I convert to list to print by subscripting
for x in range(0, len(list(dct.values())), 3):
print("\t\t".join(list(dct.values())[x:x+3]))
height +=1 # to determine where the top is for cursor
while True:
if out != (len(dates) * 2):
try:
status = q.get_nowait()
dct[status[1]] = status[2]
print('\x1b[1000D\x1b[' + str(height + 1) + 'A')
# since there was a message that means a value was updated
for x in range(0, len(list(dct.values())), 3):
print("\t\t".join(list(dct.values())[x:x+3]))
if status[0] == 'S' or 'C' or 'F':
out += 1
except queue.Empty:
pass
else:
break
In short, I pass a message to the queue from a thread. I then update a dictionary that holds unique cell IDs. I update the value, move the cursor in Console to the upper left position of the printed list, and print over it.
Question:
When using stdout, is there a limit to how many times you can print to it in a period of time?
That may well be an illusion (maybe because there's a maximum limit of lines in the console and new ones just replace the first ones then).
There's definetly no limit how much you can print. You could verify this with something that changes each iteration, for example a loop that counts the number of iterations:
import itertools
for i in itertools.count():
print(i, "True")
I cannot reproduce the problem in Windows 10 using 64-bit Python 3.6.2 and colorama 0.3.9. Here's the simple example that I tested:
import colorama
colorama.init()
def test(M=10, N=1000):
for x in range(M):
print('spam')
for n in range(N):
print('\x1b[1000D\x1b[' + str(M + 1) + 'A')
for m in range(M):
print('spam', m, n)
Each pass successfully overwrites the previous lines. Here's the final output from looping N (1000) times:
>>> test()
spam 0 999
spam 1 999
spam 2 999
spam 3 999
spam 4 999
spam 5 999
spam 6 999
spam 7 999
spam 8 999
spam 9 999
If this example fails for you, please update your question and include the versions of Windows, Python, and colorama that you're testing.
Sounds like it might be a system limitation, not a Python process issue? I've never run across a 'hang' related to print statements (or any built-in function), however you may want to look at mapping performance and memory usage:
High Memory Usage Using Python Multiprocessing
As far as how many times you can print in a period of time, that is almost exclusively based on the speed the system executes the code. You could run some benchmark tests (execution time / number of executions) across several platforms to test performance with specific system specs, but I'd say the likely cause of your issue is system / environment related.

Displaying Raspberry Pi clock on LCD display

I have a Raspberry Pi running an LCD display. I found the Python script below which displays the time on the display, but I notice there's a delay of almost a second between the Pi's time and the LCD.
I tried removing the last line of the code (sleep(1)) and that removed the delay but the LCD flickers a lot.
Can anyone please explain the function of that last line, and whether there's a way to display the time on the LCD without a delay?
Thanks.
#!/usr/bin/python
import RPi.GPIO as GPIO
from Adafruit_CharLCD import Adafruit_CharLCD
from subprocess import *
from time import sleep, strftime
from datetime import datetime
lcd = Adafruit_CharLCD()
lcd.begin(16,1)
GPIO.setup(18, 0)
GPIO.output(18, 1)
while 1:
lcd.clear()
lcd.message(datetime.now().strftime('%b %d %H:%M:%S\n'))
sleep(1)
The sleep(1) instructs the program to "sleep" for 1 second. This is actually very significant because that means that the while loop (which is always true) will then only run once every second. When you take away the sleep(1) line, that means the while loop never takes a break and continues running as fast as the computer can go infinitely. One thing you might try is just reducing the sleep(1) to some smaller value. For example, you can specify sleep(0.1)
By reducing the amount of time it sleeps, that means the clock will update more frequently. Right now with sleep(1) the clock updates once every second, which makes perfect sense. However, you might increase accuracy by having the clock update 10 times every second with sleep(0.1). Let me know if this all makes sense.
The flickering is likely caused by the fact that the program is clearing and repopulating the display so many times a second.
Edit: Documentation suggests that sending decimal values to the sleep() function is valid
Edit 2: An extra bit about how to only refresh the display if right at the turn of a second
from datetime import datetime
from time import sleep, mktime
dti = mktime(datetime.now().timetuple())
while 1:
ndti = mktime(datetime.now().timetuple())
if dti < ndti:
dti = ndti
lcd.clear()
lcd.message(datetime.now().strftime('%b %d %H:%M:%S\n'))
sleep(0.95)
else:
sleep(0.01)
In essence, here's how it works:
When starting the program, create a datetime in integer form (our var dti). By "integer form" I mean add up all the seconds from some arbitrary start date (e.g. 1970-01-01 00:00:00) and use that as a reference for time. For example, today (2016-08-18 00:00:00) might be something like 1471478400 seconds since 1970. Once we have that value, we start our loop.
At the beginning of the loop, we always create a new datetime integer (ndti) to track where we are since the last time we ran the loop. With this information handy, we hop into the if conditional. if our new datetime integer (ndti) has changed fully by one second compared to our old datetime integer (dti) then that means, obviously, one second has passed. Since that is the case, we will now set our reference datetime integer to the datetime now (dti = ndti). Then we display our message (lcd.clear() and lcd.message()). After that we will sleep the program for just under 1 whole second (sleep(0.95)). Since some computers can possibly sleep more than the exact allotted time, this gives us .05 seconds of cushion to be inaccurate. In the event that we are running through the if conditional and a second has not passed yet, we would sleep the program for a short time and continue repeating until a second has actually passed (sleep(0.01)).
If everything goes exactly as planned, then for each second our program should be refreshing the lcd screen only once, and it should also be sleeping for roughly 95% of that second, so that we aren't spinning our wheels for no reason the whole time. Another part to note is that since our else clause tells the program to sleep for 0.01 seconds, that means that, in most cases, our clock can only ever be inaccurate by a margin of 0.01 seconds, which is quite good. This is low enough to be mostly undetectable by humans. Let me know if all this makes sense.
I tested this out via command line (replacing the lcd stuff with simple print statements) and it seemed to line up exactly with another time tracking resource (http://time.is/)
Try it out and see if it works for you.
IT is best way to print date and time on lcd
firstly download or git clone rplcd library for lcd add in upper side of code
import RPLCD
textDate = strftime("%d %A %Y", gmtime())
textTime = strftime("%H:%M:%S", gmtime())
lcd_string(textDate,LCD_LINE_1)
lcd_string(textTime,LCD_LINE_2)

Function works well alone, but not assigned to a button in Tkinter

I´m a begginer with python, and I hope that somebody can help me with this, I´m in a stack. I´m writing a simple code that conects with an odometer by ITCIP, recive data, process it and store in a dictionary, when some defined distance is reached the while loop breaks and return a dictionary with the data. These function works perfect alone.
The problem comes when I want to execute the function from a GUI with Tkinter, I assign the function to a button, when the button is pressed the function starts, but is blocked in the last loop, if I close the GUI the function show the data in the console, but doesn´t return the dictinary, any error appears. I try with "lambda:", without it, executing an external script with "execfile()", calling the function in a external file, and the functions never ends. Only when ist breaked with Crt+c. Here is a reduced code of "odom.py":
from Tkinter import *
import socket
from datetime import datetime, timedelta
v0=Tk()
v0.config(bg="gray")
v0.geometry("400x300")
v0.title("GUI")
def func():
ITCIPadress='172.17.18.21'
port=6000
i=0 #initialize the dictionary
rueda = {i:{
'position':i,
'distance':i}}
distancetomeasure=float(raw_input("distance to measure(in m): "))
dist=float(0)
distincr=float(0)
rev=0.5 ##odometer wheel circunference in meter
stepsrev=8192.0#Number of steps/revolution in the odometer
s = socket.socket()
s.connect((ITCIPadress, port))
while dist<=distancetomeasure: #It works in positive and negative direction
recibido = s.recv(45)#number of bytes recived
print "Recibido:", recibido
Postime_tmp=map(int, re.findall('\d+', recibido))#split the data
position_tmp=int(Postime_tmp[0])
rueda.update({i:{'position':Postime_tmp[0],
'distance':dist}})
if i>0: #because when i=0 there is no increment
incr_tmp=(rueda[i]['position']-rueda[i-1]['position'])
distincr=(incr_tmp/stepsrev)*rev
print distincr
dist=dist+distincr
print 'the distance till yet is:', dist
rueda.update({i:{'position':Postime_tmp[0],
'distance':dist}})
i=i+1
print "the distance from start point is:", dist
s.close()
return rueda
b1=Button(v0,text='Start the odometer',command= lambda: func())
b1.pack(fill=BOTH, expand=1) #command= execfile(C:\odometer.py)[calling another file with the function]
v0.mainloop() #command= lambda: odometer.measuredistance()[calling another file with the function]
#if __name__ == '__main__':
# rueda = func()
If I comment the part of the GUI, and unblock the last two lines, it works perfectly, but within a GUI doesn´t. I cannot understand why this behavior happens.
This is with the GUI, measuring 1 meter, it stacks on the last:
0.037109375
the distance till yet is: 0.896179199219
Recibido: POSITION=25403046 TIMESTAMP=104308321
0.0422973632812
the distance till yet is: 0.9384765625
Recibido: POSITION=25403756 TIMESTAMP=104502033
0.0433349609375
the distance till yet is: 0.981811523438
Recibido:
and this is executing only the function, measuring 1 meter too:
0.037109375
the distance till yet is: 0.896179199219
Recibido: POSITION=25403046 TIMESTAMP=104308321
0.0422973632812
the distance till yet is: 0.9384765625
Recibido: POSITION=25403756 TIMESTAMP=104502033
0.0433349609375
the distance till yet is: 0.981811523438
Recibido: POSITION=25404477 TIMESTAMP=104705956
0.0440063476562
the distance till yet is: 1.02581787109
the distance from start point is: 1.02581787109
this last one returns also the dictionary with all the interest values. Any help will be grateful! Thanks
the reason you are not seeing anything returned is that it effectively gets returned to the button you are using to call the function, as #Yann says, you should try and build up your GUI to do the entire of your program, otherwise there is little point to having both a GUI and command line visible to the user
First of all, you should not use a raw_input inside a function called by a GUI. Instead, try to build your GUI, with an input field for your 'distancetomeasure' variable.
After that, instead of returning the results, why not building another widget GUI to display these ?
It's been a long time since I last used Tkinter, but it's a nice GUI, and you should, if you have the time, how to build a nice app by visiting http://effbot.org/tkinterbook/tkinter-index.htm for example.
But if you're in a hurry, I'm sure other fellows here will gladly help you :)

print python counter of GPIO pin output at set intervals

I'm having a problem with a task i'm doing with an anemometer that works using a switch every revolution. The task is using a raspberry pi therefore the language is in python.
What I am trying to do is print a counter value every 10 seconds. However I don't want it to be a delay where nothing happens during the 10 second wait. Basically I want the number of times a switch is pressed in 10 seconds printed to me every 10 seconds.
Sorry if that was vague any extra info needed just ask.
While True:
stuff = dio.readU8(portB)
dio.write8(portA, stuff)
if stuff == 192:
print ('on')
else:
print ('off')
This is what it currently does simply constantly print its state either on or off I havn't yet implemented a counter as I am unsure the way it works in python and am wondering if it is similar to other languages i'm new to python I only usually use Java. The above code works even though values may look weird.
You could use the time module to watch the time, put it in at the end of the event catching code to see if 10+ seconds has passed.
something like...
import time
last_time = time.time()
#start of event catching loop
if time.time() - last_time >= 10
print buttonCountVariable
last_time = time.time()

Categories

Resources