Python: For Loop to change 1 property on multiple objects - python

The Python code below works perfectly to light 3 LEDs sequentially on a Rasberry Pico; however, I want to use a for loop with part of the object name plus the value of the for loop iterator. If LEDs were added to the board, all that would be needed is a change of the for range(1,x).
Something like the followning does not seem work (Python feels it is getting a value with no properites):
for loop_value in range(1,4):
#turn LED on, wait, turn LED off
LED_external_[loop_value].value(1)
utime.sleep(1)
LED_external_[loop_value].value(0)
Thanks so much for any input. I feel the function is a convoluted workaround. The for loop would be so much better !!!
########## start (works perfectly, Python coded in Thonny IDE) #######
from machine import Pin
import utime
# assign pin to green LED and initialize to off state
LED_external_1 = machine.Pin(14, machine.Pin.OUT)
LED_external_1.value(0)
# assign pin to yellow LED and initialize to off state
LED_external_2 = machine.Pin(15, machine.Pin.OUT)
LED_external_2.value(0)
# assign pin to red LED and initialize to off state
LED_external_3 = machine.Pin(11, machine.Pin.OUT)
LED_external_3.value(0)
def on_off(LED_Obj_Name):
#turn LED on, wait, turn LED off
LED_Obj_Name.value(1)
utime.sleep(1)
LED_Obj_Name.value(0)
while True:
on_off(LED_external_1)
on_off(LED_external_2)
on_off(LED_external_3)
############################# end ####################################

LED_external_[loop_value].value(1) here you're treating LED_external_ as a list. What you can do is add all LEDs to a list and iterate that list.
LED_list = [LED_external_1, LED_external_2, LED_external_3]
for item in LED_list:
#turn LED on, wait, turn LED off
item.value(1)
utime.sleep(1)
item.value(0)

Related

Pulse when dimming lights by setting duty cycle of PCA9685

I have a AC current dimmer (MPDMv4.1) that takes a PWM signal to dim a halogen bulb. The PWM signal is coming from a PCA9685 servo HAT.
This works just perfectly with the following code:
from board import SCL, SDA
import busio
from adafruit_pca9685 import PCA9685
ic2_bus = busio.I2C(SCL, SDA)
pca = PCA9685(i2c_bus)
pca.frequency = 1000
while True:
value = input(„Enter a value from 0 to 100“)
duty_cycle = int(round((100 - int(val))/100 * 57000))
pca.channels[15].duty_cycle = duty_cycle
My problem occurs if I put the PCA9685 object initialization inside the endless loop, as such:
from board import SCL, SDA
import busio
from adafruit_pca9685 import PCA9685
ic2_bus = busio.I2C(SCL, SDA)
while True:
pca = PCA9685(i2c_bus)
pca.frequency = 1000
value = input(„Enter a value from 0 to 100“)
duty_cycle = int(round((100 - int(val))/100 * 57000))
pca.channels[15].duty_cycle = duty_cycle
It does of course not make sense to put the initialization inside the loop in this example. But my program is looping through different temperature sensors and based on the derived temperatures dims lights. The dimming is done in a separate process, because there is supposed to be a gradual change of the actual value to the target value to make the change smoother. I cannot wait for this to end with the main process, so I started a subprocess that takes care of this. But every time this process is started, the PCA9685 object has to be newly generated, and I get this pulse of bright light, which is not acceptable for my application. This pulse happens also when I‘m not actually changing the duty cycle, just by generating the object. It‘s only visible when the light is far from maximum power.
I tried to pickle the PCA9685 object and give it to the dimming process as an argument, but _io.FileIO objects cannot be pickled.
I also tried several different libraries, it’s always the same. Hence my question: Does anybody know how this is caused? Is this inevitable when establishing the connection? Can it potentially be circumvented?
Best and many thanks,
Gero

How can I make the Raspberry Pico not automount as USB storage while using Circuit Python

I am using Circuit Python on a Raspberry Pi Pico to give me hardware buttons for keyboard shortcuts. I am using Circuit Python as opposed to MicroPython because it has the USB_HID library.
I don't want the Pico to automatically mount as USB storage when being plugged in. I just want it to act as a HID device. I am aware that I can write a boot.py script in addition to a code.py but I can't find anywhere online what to put in this which would prevent it from mounting as a USB device. I also still want it to mount as USB sometimes (when a button is pressed/GPIO pin is connected) so there is a still a way for me to change the code on the device.
Is this possible? And, if so, what should the boot.py look like to only mount when a certain GPIO pin is connected?
I recently came across a need to do the same that you are looking for, and after a decent rabbit hole, have determined that it can't be done at this time.
https://github.com/adafruit/circuitpython/issues/1015
Looks like the request was opened a few years ago and is still listed as open.
I am not sure if running a pi zero in "gadget" mode can accomplish this or not, but may be worth a look
The code below is what I use. Roughly, it checks to see if a button connected to one of the Pico's IO pins. If the button is pressed when the cable is plugged in, then it mounts as a USB drive. If the button is not pressed, it's not mounted:
import storage
import board, digitalio
# If not pressed, the key will be at +V (due to the pull-up).
# https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/circuitpy-midi-serial#circuitpy-mass-storage-device-3096583-4
button = digitalio.DigitalInOut(board.GP2)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP
# Disable devices only if button is not pressed.
if button.value:
print(f"boot: button not pressed, disabling drive")
storage.disable_usb_drive()
This was adapted from examples on Adafruit's site
Here's a good HID guide:
https://learn.adafruit.com/circuitpython-essentials/circuitpython-hid-keyboard-and-mouse
Here's the HID example:
import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
# A simple neat keyboard demo in CircuitPython
# The pins we'll use, each will have an internal pullup
keypress_pins = [board.A1, board.A2]
# Our array of key objects
key_pin_array = []
# The Keycode sent for each button, will be paired with a control key
keys_pressed = [Keycode.A, "Hello World!\n"]
control_key = Keycode.SHIFT
# The keyboard object!
time.sleep(1) # Sleep for a bit to avoid a race condition on some systems
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :)
# Make all pin objects inputs with pullups
for pin in keypress_pins:
key_pin = digitalio.DigitalInOut(pin)
key_pin.direction = digitalio.Direction.INPUT
key_pin.pull = digitalio.Pull.UP
key_pin_array.append(key_pin)
# For most CircuitPython boards:
led = digitalio.DigitalInOut(board.D13)
# For QT Py M0:
# led = digitalio.DigitalInOut(board.SCK)
led.direction = digitalio.Direction.OUTPUT
print("Waiting for key pin...")
while True:
# Check each pin
for key_pin in key_pin_array:
if not key_pin.value: # Is it grounded?
i = key_pin_array.index(key_pin)
print("Pin #%d is grounded." % i)
# Turn on the red LED
led.value = True
while not key_pin.value:
pass # Wait for it to be ungrounded!
# "Type" the Keycode or string
key = keys_pressed[i] # Get the corresponding Keycode or string
if isinstance(key, str): # If it's a string...
keyboard_layout.write(key) # ...Print the string
else: # If it's not a string...
keyboard.press(control_key, key) # "Press"...
keyboard.release_all() # ..."Release"!
# Turn off the red LED
led.value = False
time.sleep(0.01) ```
The example only prints Hello World, so it's not very useful, but it's a good base to mod.
i try this and it work
https://learn.adafruit.com/circuitpython-essentials/circuitpython-storage
it not write to code.pi but in boot.py you have to create the file first.

Raspberry pi servo doesn't stop

So I'm trying to use a servo (Doman s0306d) with the pi camera, tried running this script I found to test the motor, it starts running but doesn't stop unless I manually unplug it from the breadboard.
import RPi.GPIO as IO # calling for header file for GPIO’s of PI
import time # calling for time to provide delays in program
IO.setwarnings(False) # do not show any warnings
IO.setmode (IO.BCM) # programming the GPIO by BCM pin numbers. (like PIN29 as‘GPIO5’)
IO.setup(19,IO.OUT) # initialize GPIO19 as an output
p = IO.PWM(19,50) # GPIO19 as PWM output, with 50Hz frequency
p.start(7.5) # generate PWM signal with 7.5% duty cycle
time.sleep(4)
for x in range(0,5): # execute loop forever
p.ChangeDutyCycle(7.5) # change duty cycle for getting the servo position to 90º
time.sleep(1) # sleep for 1 second
p.ChangeDutyCycle(12.5) # change duty cycle for getting the servo position to 180º
time.sleep(1) # sleep for 1 second
p.ChangeDutyCycle(2.5) # change duty cycle for getting the servo position to 0º
time.sleep(1) # sleep for 1 second
p.ChangeDutyCycle(0)
p.stop()
IO.cleanup()
Any ideas ? Thank you.
[EDIT] The servo you are using is a "continuous" servo - so you need to give it the zero speed or "STOP" setting pulse width of 1500us (according to the website http://www.domanrchobby.com/content/?150.html). I haven't used PWM on the pi but if the percentages are of the 50Hz pulse rate (20ms interval) then that should be your 7.5% centre value. You need to make sure the servo gets that pulse before your code exits.
[Original] You are setting the duty cycle to 0 when you exit, which will probably mean the servo doesn't get any pulses. Some servos will stop sometime after they don't get pulses, but some servos (particularly digital servos, but not all) will continue to try achieve the setting from the last pulse they received. Suggest you leave the setting at the mid range 7.5 which you know the servo can achieve and delay for a little while before cleaning up.

Turn led on in function with different args. Python

I can’t seem to wrap my head around how to do this. I tried searching but it just returns how to turn on a led with a raspberry pi. So here I am. I am trying to make a function so that I can check multiple values and if they match turn a led on. I guess my major issue is when it is true the led turns on, but if the next function shares the same led it will turn it off. If that makes sense.
#
def turnon(led,x)
if x == updating_x:
turn led # from led, on
else:
turn led # from led, off
while True:
#led 1
turnon(1,20)
#led 1
turnon(1,50)
#led 2
turnon(2,10)
So say updating_x=20 so the led #1 would turn on but then the next function that has the same LED would turn it off. I thought about changing it to this
if x == updating_x:
turn led # from led, on
time.sleep()
turn led off
else:
pass
But it is somewhat time critical and I will want the multiple leds to turn on together and not just one after the other. I don’t want to get caught just sleeping if the value change true for another led.
FYI, the plan is 60ish leds with around 70 different check values
Any ideas on the right way to do this? and Thanks!
Edit:
Sorry I will try and explain it better. So with the example I gave, I want led 1 to turn on if the update_x == 20 or 50. (if update_x = 20 now) In the loop, it runs the first function which is true so the led turns on. But the second function will be false so it turns the led off, although it is still true for the first function. The problem is that I want to keep the led on until the first function returns false.
Ignore the second bit with the time.sleep in it, just an idea but won't work for what I want.
writing this I had an idea of having the x variables I want to work in a list and using that list in the function parameters, if that works. In the end there will be around 60 leds with about 5 values to turn each one on, 60 lists sounds like a pain.

How can keep a timed count of user input (from a button)?

I'm using a Raspberry Pi 2 and a breadboard to make a morse code interpreter. The circuit is a simple button that lights up an LED when pressed. How could I use functions to count how long the button is held down?
You haven't given sufficient details of your circuit to pin this down to your particular use case, so I'll suggest the following (on which I'll base my code):
Connect the LED (with series resistor) to GPIO 12
Connect a 10k resistor between GPIO 11 and the 3.3V rail (acts as a pull-up)
Connect the push-button between GPIO 11 and Ground (0V).
I'd then write the code to monitor the pin and log the time for each press into a list. You can read out the values in the same order which allows you to process the times and interpret the code from them.
import RPi.GPIO as GPIO
import time
# set up an empty list for the key presses
presses = []
# set up the GPIO pins to register the presses and control the LED
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(11, GPIO.IN)
# turn LED off initially
GPIO.output(12, False)
while True:
# wait for input to go 'low'
input_value = GPIO.input(11)
if not input_value:
# log start time and light the LED
start_time = time.time()
GPIO.output(12, True)
# wait for input to go high again
while not input_value:
input_value = GPIO.input(11)
else:
# log the time the button is un-pressed, and extinguish LED
end_time = time.time()
GPIO.output(12, False)
# store the press times in the list, as a dictionary object
presses.append({'start':start_time, 'end':end_time})
You'll finish up with a list that looks something like this:
[{start:123234234.34534, end:123234240.23482}, {start:123234289.96841, end:123234333.12345}]
The numbers you see here are in units of seconds (this is your system time, which is measured in seconds since the epoch).
You can then use a for loop to run through each item in the list, subtract each end time from the start time, and of course subtract the start of the next press from the end of the previous one, so that you can assemble characters and words based on the gaps between presses. Have fun :-)

Categories

Resources