print python counter of GPIO pin output at set intervals - python

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()

Related

How to Display Time (not static) in python?

Alright,the problem is i'm trying to build a personal assistant with my amateur skills.
I want to display the time which should be running and not be static.
This is what you wanted ? create a endless loop (Since you didn't mention in what situation the loop will end, I assume it will run infinitely until you manually end it) and print() with end='\r' (replace prev print) and pause and refresh every second
import time
import datetime
while True:
now = datetime.datetime.now()
print(f"Current Date and Time: {now} ", end='\r')
time.sleep(1)

Python/Tkinter: trying to sample a signal and run a timer simultaneously: program freezes. Why?

As mentioned in the title, I am trying to run a timer, updating every second, while sampling a signal (for Raspberry Pi), currently simulating on PC.
The code for the timer works very well by itself, here it comes:
def update_timer(self, nap = 1):
while (self.sw_seconds > 0):
self.sw_seconds -= nap
m, s = divmod(self.sw_seconds, 60)
self.labels["Timer"]['text'] = '%02d:%02d' % (int(m), int(s))
self.labels["Timer"].after(1000, self.update_timer)
Now, the function I use to run simultaneously is:
def repeat_function(self,period,f,*args):
t = time.time()
while self.bool:
f(*args)
t += period
time.sleep(max(t - time.time(),0))
The overall program is lengthy and has been tested to work before calling the repeat_function, but I can fully copy it here if required. Just trying to be concise.
I have tested this configuration by launching the timer (which works by itself) and repeat_function(1.0,print,"Hi there\n"). My program freezes and I have to kill it every time.
Can anyone tell me what is wrong with the "repeat function"? In real life, it will have to capture a signal sample with a frequency of 10 Hz at least, so I cannot imagine this how this can work when it freezes already when asked to print a statement every second
Thank you, indeed, sleep (put the whole app to sleep) is the wrong tool for the job, with Threading it works well.

Question with python, music and events, is there a more elegant way of programming this?

Goal: To create a program that will be able to turn off and on lights to music based on events that are triggered from midi notes.
Hello all, I am hoping that this isn't too broad of a question to ask. I am working on a project where I get events from a midi file and turn those events into time. I take a note from the midi file and append it to a list as the time it was placed
Example:
https://imgur.com/swZsrk9
I take all of those and place them into a list. Don't worry about how I do that as that is not my main goal to discuss. I've just substituted the list with a hard-coded one on my example code.
I now have a list of times that I want lights to either turn on or off, now I just need to set an infinite loop with a timer that starts at 0 seconds (with the start of the song) and when the timer == (the next time in the list) it will print out a line. Here is my code:
import socket
import sys
import random
import time
from pygame import mixer
from mido import MidiFile
masterList = [12.37, 14.37, 15.12, 15.62,16.36, 17.61, 18.11, 19.11, 19.61, 20.35,]
mixer.init()
song = mixer.Sound('song.wav')
startTime = time.time()
endTime = startTime + song.get_length()
print(masterList)
print('Starting song.')
song.play()
print('Playing song, timer:',startTime)
while time.time() <= endTime:
#print(round(time.clock(),1),masterList[0])
if round(time.clock(),2) == masterList[0]:
print(round(time.clock(),2),"<-",masterList[0],"------------------")
del masterList[0]
#print('playing...')
time.sleep(.01)
mixer.quit()
Here is a video of it runing:
https://www.youtube.com/watch?v=VW-eNoJH2Wo&feature=youtu.be
Ignore the deprecation warnings
It works but sometimes, due to the nature of programming, the time.clock() does not always == the next item in the list. I knew that this would be a problem going in as you can't rely on how long the code takes to execute. Sometimes it takes a few more milliseconds than usual to complete a while loop so then when you call the time.clock() method it != the next time in the list. Then the list does not remove it's first item and then it will never equal that first item.
I tried going by 10 milliseconds (.1) but it doesn't give me the accuracy I need.
Also, it seems clunky, sometimes the events are delayed a few milliseconds and it makes the effect not as pleasing. As you can see from my video the times of the prints aren't lined up completely where they need to be, even though they are perfectly placed on where they need to be in the midi file.
Question: Is there a more elegant way of tackling this? I seem to keep finding ways of patching it to work better and then it always goes back to the nature of programming, where the cpu always is unreliable. I've been trying to think of different ways of doing this but I can't come up with any. Your help would be much appreciated!!
Since you're deleting the notes as you play them, have you tried using >= instead of ==?
E.g.,:
while time.time() <= endTime:
#print(round(time.clock(),1),masterList[0])
if round(time.clock(),2) >= masterList[0]:
print(round(time.clock(),2),"<-",masterList[0],"------------------")
del masterList[0]
That way the note will play as soon as possible after the specified time, and remove it from the queue. Only way to know actual performance is to test it, but at the very least it won't skip notes.

Python, how to check if a >= b for 5 seconds ? I used while loops and got delays in other functions

I'm an absolute noob in python and mostly in programming too. (so be critics I hope I can learn from that too)
I'm trying to create my "program" on a Raspberry Pi 3, with Raspbian OS
My problem is the following:
I'd like to test "if a >= b for 5 seconds" (where "a" is a value which I read out from the serial in an other function)
if yes do something if not do something else, to be seems really simple...
I all ready "party" solved it once in my code with a while loop in one of my functions, but when I copied the "time waiting while loop" to my other function it started to generate a huge delay (it's about the same amount of time which I was adding to my extra while loops)
I really hope someone could suggest me any other way to check "if a >= b for 5 seconds" other than a while loop
or if someone would have some free time to check on my code and tell me what mistakes I made (probably a lot of noob mistakes)
Here's my code which does not contains the critical 2 while loops (just one with 30 seconds delay)
`https://pastebin.com/RmEcLRJA`
And here's the other with the 2 extra while loops, which seems to be delaying the measurements (of my xwatts variable) with about 6-14 seconds in total (I gave 3 seconds delay in each while loop)
`https://pastebin.com/HB99vH9c`
P.S. sorry for the links my code is quiet long to paste here twice
My value "a" is a constantly changing value, it updates in less than 1 second, I need to know if a >= b for 5 seconds constantly, if it drops for 1 reading only (0.1 sec) it must restart the 5 seconds "timer"
You can use a while:
import time
end_time = time.time() + 5
while 'Wait 5 seconds':
if a >= b:
...
if time.time() > end_time:
break
Also removing all time.sleep() within the code will solve your delay issue.

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)

Categories

Resources