Unwanted output in simple python script - python

Hello i'm starting with python on a RPI B+, i made a simple while loop but i'm getting weird output.
#!/usr/bin/python
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(3,GPIO.OUT)
while 1:
print "LED OFF"
GPIO.output(3,GPIO.LOW)
time.sleep(1)
print "LED ON"
GPIO.output(3,GPIO.HIGH)
time.sleep(1)
When GPIO3 is LOW it repeatedly outputs ^[[B until it's HIGH again.
The letter B changes depending on the pin i'm using.
Why is this happening? It looks like it is registering a button press, but i'm certainly not pressing any buttons nor do i have any input on the GPIO.
I tried another keyboard but it didn't make a difference.
This is the output i'm getting from this :
LED OFF
^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[BLED ON
^[[BLED OFF
^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[BLED ON
^[[BLED OFF
^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[B^[[BLED ON
^[[BLED OFF
I should note that the LED's do blink correctly.
EDIT :
When i switch focus to the text editor while the program runs, the output is normal but the down button gets pressed which causes the cursor inside the text editor to go down.
I'm starting to think this is a OS problem, i'm using the Porta Pi image, i use that img for my arcade cabinet so i thought i might aswell use it for this.

I'm starting with Python on a RPI B++ too. Lots of fun!! But anyway: this won't solve your problem I guess, but I was asking myself while looking at your script: shouldn't you put tabs before all lines after the while?

Me again, looking over a few of my scripts for RPi, I think your output syntax is off. As in:
GPIO.output(3,GPIO.LOW)
Should be:
GPIO.output(3,LOW)
I think that's why my suggestion of 1,0,True,False wasn't working. These shouldn't have "GPIO." In front of them.
Let me know if that works
-Cheers

Related

How do I break out of the loop at anytime with a keypress while in another window?

Hey I'm a beginner programmer, trying to write some code to press the letter 'k' on the keyboard every 4 seconds, while also being able to shut down the program with a keystroke WHILE IN A DIFFERENT WINDOW.
I've tried using this,
import time
import pyautogui
def kicker():
while True:
time.sleep(4)
pyautogui.press('k')
try:
while True:
kicker()
except KeyboardInterrupt:
pass
but I can only KeyboardInterrupt while the window I am coding in (jupyter notebook) is open, when I go into another window (with jupyter still open in the background) I can no longer interrupt the loop.
How can I make it so I can interrupt the loop on a keypress (not necessarily KeyboardInterrupt) while not on the jupyter notebook window?
You may want to use pyxhook to listen for all keystrokes on your machine. Do note that this is roughly the same as a keylogger and might involve admin access on your machine so there may be some safety concerns to think about.
Here is an example script from the repo that showcases it printing the event, but the line of interest is the function on line 15:
def kbevent(event):
global running
if event.Ascii == <...Put ascii code for k here...>:
running = False

clearing the terminal for my python text adventure

working with the current version of python after a quick google search and a perusal of stack overflow I'm not seeing what I'm looking for. I'm trying to find a way to clear the screen with every new print to the screen. So you would get the intro text for a room and there is a monster in the room so when you press a to attack it would delete the intro text and the new text saying what weapon you used and how much damage you did would be printed. then when the monster dies you the damage prompts would go away and you would get the dead enemy empty room text with the press these keys to go a direction text. the current version of my game is here https://github.com/GusRobins60/AdventureGame.git hopefully that will give you an idea of the text i'd be displaying. thanks for any help.
For windows you can use a lambda function to easily create an anonymous function which you can use to clear the terminal again and again:
clear = lambda: os.system('cls')
clear()
Or if you're on Linux then swap 'cls' with 'clear'.
Are you using windows? If so, you can try:
import os
os.system('cls')
Or something similar after each page is complete and needs to be cleared.
To clear the terminal using ANSI escape codes:
import sys
sys.stdout.write("\33[H\33[2J") #"\33" is the ESC character
sys.stdout.flush()
\33[H moves the cursor to the top left of the terminal, and \33[2J clears the screen. Using sys.stdout.write here instead of print avoids writing a newline, so the cursor stays on the first line of the screen, instead of being on the second line when using print().

Issues launching headless soundboard script on boot

I'm building a headless soundboard using Raspberry Pi, and as such need a way to launch the script I'm using on boot. The program was edited and tested using the default editor Pi shot up, Thonny, and everything seems to run as intended. The buttons I'm using all play the sounds I expect them to, no issues.
I went ahead and edited rc.local to run the script as soon as the Pi boots (specifically, I added sudo python /filepath/soundboard.py & above exit 0), which it does. It seems to run identically to the way it did using Thonny, but sound cuts off after about 5 seconds, even if no buttons are pressed. When I run it directly through the command line, the same issue occurs.
The code here has been compressed, as there is more than one button, but they all use the same line.
import pygame
import random
import glob
from gpiozero import Button
import time
pygame.init()
while True:
n = glob.glob('/filepath/*.wav')
btn_0 = Button(8)
btn_0.when_pressed = pygame.mixer.stop
btn_0.when.held = lambda: pygame.mixer.Sound(random.choice(n)).play()
As far as I can tell, the while loop continues to run the program, but pressing buttons does nothing. Also, since adding the loop, the code dumps a Traceback, showing the error
gpiozero.exc.GPIOPinInUse: pin 8 is already in use by <gpiozero.Button objext on pin GPIO8, pull_up=True, is_active=False>
which might have something to do with my issue? btn_0 isn't the only button to have two functions assigned to it, but the only one to throw up this error, no matter what pin I use. The error doesn't appear if I remove the loop from the code.
You create btn_0 in an infinit while loop again and again. In the second iteration btn_0 is probably the first button that is created again. But pin 8 (which should be used for the button) has been assigned to the old instance of btn_0 in the last iteration.
You should move the glob.glob statement and the button initialization outside of the While loop. If the while loop is necessary to keep you program running place it below the initialization code and iterate over nop ore pause statements (whatever works).
If pygame.init starts it own looped thread you do not need a while loop at the end at all.
I don't know anything about pygame, so the last statement is just a guess.
Example:
import pygame
import random
import glob
from gpiozero import Button
import time
pygame.init()
n = glob.glob('/filepath/*.wav')
btn_0 = Button(8)
btn_0.when_pressed = pygame.mixer.stop
btn_0.when.held = lambda: pygame.mixer.Sound(random.choice(n)).play()
while True:
nop

Python Loop Capability

I am attempting to write a program for my school project, on a raspberry pi. The program concept is fairly simple. The pi is looking at 4 GPIO pin inputs, and will output a different basic animation to the LED matrix depending on the input.
The main loop is a simple while(1) loop that always runs. Within this loop, the program is constantly checking to see what the input is from the 4 GPIO input pins on the pi. When the input is matched to one of the if statements, then it runs a short 'animation' in which is displays an image on the LED matrix, waits, clears the matrix, displays another image, waits, and clears again. For example, this could be a 'blinking smiley face' animation where the first image displayed is a smiley face with its eyes open, and the second image is a smiley face with its eyes closed. With the pausing in between the pictures getting displayed, it appears the image on the screen is actually blinking.
This setup is shown below for clarity (not actual code, gets the idea across though):
while(1) {
currentState = [GPIO.input(pin1), GPIO.input(pin2), GPIO.input(pin3), GPIO.input(pin4)]
if((currentState[0] == 1) and (currentState[1] == 0) and (currentState[2] == 1) and (currentState[3] == 0)) {
matrix.SetImage(open_eyes)
time.sleep(.3)
matrix.Clear()
matrix.SetImage(closed_eyes)
time.sleep(.3)
matrix.Clear()
}
if((currentState[0] == 0) and (currentState[1] == 1) and (currentState[2] == 0) and (currentState[3] == 1)) {
matrix.SetImage(closed_mouth)
time.sleep(.3)
matrix.Clear()
matrix.SetImage(open_mouth)
time.sleep(.3)
matrix.Clear()
}
}
The issue I am having with this setup is if the input changes during an animation, then it will not cut off the animation it is currently on to start the next. This is obvious the way the code is structured since the currentState variable is only being set at the beginning of the while loop.
To accomplish this immediate switch, I attempted to make each animation a function, and just run the function within the if statements. However, then the program never would break out of those functions to check to see what the input is. I am now stuck, and if anyone has any ideas on how to accomplish this, I would love to hear them.
The issue here is time.sleep. During the sleep, the program won't detect changes to the currentState - as you correctly recognise. One way to handle this (I'm not going to write the code for you, but explain the general idea), is to keep your animation state in an object which gets updated on every while loop cycle. Things become a bit more complex than what you have because you will need to track the .3 seconds using some kind of time monitoring. So you'd set your object state to something like:
animation.state = 'blinking'
animation.started = datetime.now()
Then once you detect .3 seconds have passed, you can change your animation state. If the currentState changes, you can reset the animation state.
Alternatively you could spawn a thread for the animation. That would be natural in some ways (and easy in Go for example) but a bit trickier if you're not used to Python threading.

how do I print a title for the top of my running program to continuously be visible for a code that prints and runs an endless amount of data?

Example: (to stay visible on the running program, able to view it at anytime if needed to scroll to the top)
print("this is my title")
print("here is my sub title")
count = 0
while count < 5000:
print("hello")
count = count + 1 # or count += 1
My code runs for as long as I set it too, that's not the problem. But when the program runs, it never shows the top printed title, or if I were to stop the program for a moment and physically scroll to the top, that printed title and other various text isn't visible.
How do I fix this to where, even if I wanted to print a million items, I could still see the printed title and printed information at the top?
First a useful non python way:
If you run a script (say my_long_print_script.py) from the terminal you can use less (in linux and osx for sure):
python my_long_print_script.py | less
then use enter to scroll down and q to quit.
Writing to stdout in python
In python you can directly write to stdout and 'overwrite' your previous output. This can lead to some sort of progress bar behaviour, I'm not sure this is what you want, here is an example:
# content of my_long_print_script.py:
import sys
from time import sleep
sys.stdout.write('This title should stay\n')
sys.stdout.write('this subtitle too\n')
for count in xrange(100):
sleep(0.1)
sys.stdout.write('{0}\r'.format(count))
sys.stdout.flush()
When you run this as a script (so you type python my_very_long_print_script.py in the terminal) the two title lines will persist and below a single line will continuously be updated.
FYI: I added the sleep because the count changes too quickly otherwise.
Hope this was somehow useful.
You'll probably want to use python's curses library. This is how you create "windows" that can be redrawn in-place.
I wrote a CLI version of 2048 that would scroll the terminal every time I output the game's board after a move. Using curses, I can now just overwrite the previous board without any scrolling.
Basically you'll want to initialize a new curses window object, set your output string to "My Title Here" and issue a window.redraw() command at (0,0) every time your program iterates.

Categories