how to run 2 if statements simultaneously - if-statement

i have this code and i'm having a problem with it, when the first if statement is working i can't run the second if statement until the last delay finishes and if the second if statement starts i can't run the first statement and vise versa
so what would be the be code to fix this problem i tried def and while but couldn't get to what i need
import RPi.GPIO as GPIO
import time
import lcddriver
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
display=lcddriver.lcd()
GPIO.cleanup()
# Configure Relay Output Pins
Relay1=31
Relay2=32
GPIO.setup(Relay1,GPIO.OUT)
GPIO.setup(Relay2,GPIO.OUT)
# Configure Relay Input Pins
IN1=29
IN2=15
GPIO.setup(IN1,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(IN2,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
while (1):
if GPIO.input(IN1)==1:
GPIO.output(Relay1,1)
display.lcd_clear()
display.lcd_display_string(" Input 1 ", 1)
display.lcd_display_string(" Opened ", 2)
time.sleep(0.5)
GPIO.output(Relay1,0)
display.lcd_clear()
time.sleep(1)
if GPIO.input(IN2)==1:
GPIO.output(Relay2,1)
display.lcd_clear()
display.lcd_display_string(" Input 2 ", 1)
display.lcd_display_string(" Opened ", 2)
time.sleep(0.5)
GPIO.output(Relay2,0)
time.sleep(1)
display.lcd_clear()
GPIO.cleanup()

That's because you're not in a multi-process program
Only one thread of your CPU is used
If you really need to run the two if statements at the same time you should change your code so that the parts you need to run is in the same if statement
If condition1:
Part1
If condition2:
Part2
Will become
If condition3:
Part1
Part2
It's an algorithmic error, you shouldn't seperate your block within two if(s)
I can suggest to use a function like this
def do_part_two():
Part2
def do_part_one():
Part1
If condition1:
Part1
do_part_two()
If condition2:
Part2
do_part_one()
But still I encourage you to change your if so that you're in my first solution case
N.B:
You can create a delay function and call it whenever you need
def delay(x):
time.sleep(x)

Related

Slow Python serial speed

I have connected an Arduino UNO to my raspberry pi and want to read from a connected Sensor with a Python Script.
When I try to read the sensor data from the Arduino IDE, it works perfectly fast, but with Python it is really slow.
This is my code:
import serial
from subprocess import call
from time import sleep
ser = serial.Serial('/dev/ttyACM0')
ser.baudrate = 9600
a = 0
stop = False
file = open("PulseData/MasterArrayData.txt","w")
if(ser.isOpen() == False):
ser.open()
print("Start scanning")
while stop == False:
test = ser.readline()
try:
testInt = int(test)
if testInt > 100 and testInt < 800:
print test
file.write(str(testInt))
file.write("\n")
a = a+1
except ValueError:
print "Not an integer"
if(a == 400):
stop = True
sleep(0.1)
file.close()
call(["./main", "PulseData/MasterArrayData.txt"])
I already tried to use a higher baud rate, or a shorter sleeping time, without success.
I've read that the speed can be improved with PyTTY, but unfortunately I didn't find any documentation about that.
I appreciate any help.
From comment by jasonharper:
Sleeping for a tenth of a second between readings is an absolute guarantee that you will get less than 10 readings per second. The occasional garbage value you're getting happens when the serial port buffer inevitably overflows and characters get lost.

Looping in Python Slowing Down with each Iteration

The following code produces the desired result, but the root of my issue stems from the process slowing down with each append. In the first 100 pages or so, it runs at less than one second per page, but by the 500s it gets up to 3 seconds and into the 1000s it runs at about 5 seconds per append. Are there suggestions for how to make this more efficient or explanations for why this is just the way things are?
import lxml
from lxml import html
import itertools
import datetime
l=[]
for pageno in itertools.count(start=1):
time = datetime.datetime.now()
url = 'http://example.com/'
parse = lxml.html.parse(url)
try:
for x in parse.xpath('//center'):
x.getparent().remove(x)
x.clear()
while x.getprevious() is not None:
del x.getparent()[0]
for n in parse.xpath('//tr[#class="rt"]'):
l.append([n.find('td/a').text.encode('utf8').decode('utf8').strip()\
,n.find('td/form/p/a').text.encode('utf8').decode('utf8').strip()\
,n.find('td/form/p/a').attrib['title'].encode('utf8').decode('utf8').strip()]\
+[c.text.encode('utf8').decode('utf8').strip() for c in n if c.text.strip() is not ''])
n.clear()
while n.getprevious() is not None:
del n.getparent()[0]
except:
print 'Page ' + str(pageno) + 'Does Not Exist'
print '{0} Pages Complete: {1}'.format(pageno,datetime.datetime.now()-time)
I have tried a number of solutions, such as disabling the garbage collector, writing one list as a row to file instead of appending to a large list, etc. I look forward to learning more from potential suggestions/answers.

How to change parameters without stopping the program

Suppose I write a program like this.
# run the program until the user gives a "stop" input
usrinpt=""`
n=1
while usrinpt!="stop":
n+=1
---- do-something -----
---- do-something -----
---- do-something -----
print n # print the number of loops it has gone through.
Now program will run until I manually change the parameter usrinpt to "stop". But using raw_input will stop the simulation at every step which is not what I want.
So, is there a way to change the usrinpt without stopting the simulation?
A more involved solution using a thread:
from __future__ import print_function # Python 2/3 compatibility
import sys
from time import sleep
from threading import Thread
if sys.version_info.major < 3:
input = raw_input
def do_something():
# doing the work
sleep(1)
usrinpt = ''
def main():
n = 1
while usrinpt != 'stop':
n += 1
do_something()
print('\nnumber of loops', n)
thread = Thread(target=main)
thread.start()
while True:
print('Enter "stop" to terminate program')
usrinpt = input().strip().lower()
if usrinpt == 'stop':
break
thread.join()
Sample program run:
python stop.py
Enter "stop" to terminate program
hello
Enter "stop" to terminate program
stop
number of loops 6
You can catch a KeyboardInterrupt exception:
from __future__ import print_function # Python 2/3 compatibility
n = 1
try:
while True:
n += 1
except KeyboardInterrupt:
print('\nnumber of loops', n)
When the user types <CTRL>-<C> the program prints the number of iterations and continues.

How can i make it so the program progresses while a 'while loop' is running a timer (python)

I need to know how i can enter user input while this while loop counting time is running. I know my program is not efficient nor organized as I am new to python. A simple but longer fix is better than a short fix that I would not understand.
import time
print 'Welcome To the Speedy Type Game!'
time.sleep(1)
print "You're objective is to win the game by typing the specific word before the time runs out"
print "Don't forget to press 'enter' after typing the word!!!!"
print "For round 1 you will have 5 seconds"
null = raw_input('Press enter when you are ready to start')
print '3'
time.sleep(1)
print '2'
time.sleep(1)
print '1'
time.sleep(1)
print 'GO'
C = 'poop'
x = 5
while C in ['poop']:
x = x - 1
time.sleep(1) #This is where my program comes to a halt.
C = raw_input("Print the word 'Calfornia': ") #I dont know how to make the program progress to here without stopping the timer above.
if x < 0:
print 'You have failed, game over!'
else:
print 'Good Job! let us move to the next round!'
There is no easy way to do this in Python - a single process is running at a time, so without e.g. threading (see https://stackoverflow.com/a/2933423/3001761) you can't overlap user input with counting. An easier approach might be:
def test(word, limit=5):
started = time.time()
while True:
result = raw_input("Type {0!r}: ".format(word))
finished = time.time()
if result == word and finished <= started + limit:
print 'Good Job! let us move to the next round!'
return True
elif finished > started + limit:
break
print 'Wrong, try again.'
print 'You have failed, game over!'
return False
Then call e.g.:
>>> test("California")
Type 'California': California # typed quickly
Good Job! let us move to the next round!
True
>>> test("California")
Type 'California': foo # typed wrongly but quickly
Wrong, try again.
Type 'California': California # typed quickly
Good Job! let us move to the next round!
True
>>> test("California")
Type 'California': foo # typed wrongly and slowly
You have failed, game over!
False
>>> test("California")
Type 'California': California # typed slowly
You have failed, game over!
False

plot goes to zero in between

import sys
import serial
import numpy as np
import matplotlib.pyplot as plt
from collections import deque
port = "COM11"
baud = 9600
timeout=1
ser = serial.Serial()
ser.port = port
ser.baudrate = baud
ser.timeout = timeout
a1 = deque([0.0]*100)
#ax = plt.axes(xlim=(0, 100), ylim=(0, 1000))
line, = plt.plot(a1)
plt.ion()
plt.ylim([0,1000])
try:
ser.open()
except:
sys.stderr.write("Error opening serial port %s\n" % (ser.portstr) )
sys.exit(1)
#ser.setRtsCts(0)
while 1:
# Read from serial port, blocking
data = ser.read(1)
# If there is more than 1 byte, read the rest
n = ser.inWaiting()
data = data + ser.read(n)
#sys.stdout.write(data)
print(a1)
a1.appendleft((data))
datatoplot = a1.pop()
line.set_ydata(a1)
plt.draw()
I am using msp430f5438a board.If I send the data with a new line between each data then I am not able to plot the data because in python the sometimes data gets printed as 78_9, 7_89,_789 where _ means space so python gives me a error cannot convert string to float. But If I say send the data from uart without any new line between them then I get a nice plot but in the plot after some irregular short intervals the plot goes to zero and then becomes fine again although I checked in hyperterminal I am not receiving any zero values
My question is:
Are the two cases I described are related to each other?What can be done to rectify this problem of plot going to zero in between?Because of this I am not getting a smooth wave.
Thanks
The problem might be in the way you handle the serial interface. As you are not parsing the serial input when it comes, it is possible that you receive two messages as follows:
1.23
4.56
7.
and
89
10.11
etc. This is because your code may split the input at any point. It may be so fast that you get one digit at a time, which is probably not what you wanted.
I suggest that if you pad your data with newlines and if the data is good in a terminal program, you use the readline method.
while 1:
# read a line from the input
line = ser.readline()
# try to make a float out of it
try:
a1.appendleft(float(line))
except ValueError:
# in case we got bad input, print it and go to the next line
print "Received an invalid line '{0}'".format(line)
continue
# do the plotting
This most probably fixes your problem.
Reading asynchronous serial line is surprisingly complicated, you usually need to parse the input in-the-fly with timeouts. Fortunately, this is done by pyserial when using readline.