How to generate sound signal through a GPIO pin on BeagleBone - python

I am looking for pointers/tips on how to generate a synthesized sound signal on the BeagleBone akin to watch the tone() function would return on a Arduinos. Ultimately, I'd like to connect a piezo or a speaker on a GPIO pin and hear a sound wave out of it. Any pointers?

This is how I managed to solve this question on the Beaglebone using Python and PyBBIO:
#!/usr/bin/python
# Circuit:
# * A Piezo is connected to pin 12 on header P8. - GPIO1_12
# * A LED is connected to pin 14 on header P8. - GPIO0_26
# * A button is connected to pin 45 on header P8. - GPIO2_6
# Use a pull-down resistor (around 10K ohms) between pin 45 and ground.
# 3.3v for the other side of the button can be taken from pins 3 or 4
# on header P9. Warning: Do not allow 5V to go into the GPIO pins.
# * GND - pin 1 or 2, header P9.
def setup(): # this function will run once, on startup
pinMode(PIEZO, OUTPUT) # set up pin 12 on header P8 as an output - Piezo
pinMode(LED, OUTPUT) # set up pin 14 on header P8 as an output - LED
pinMode(BUTTON, INPUT) # set up pin 45 on header P8 as an input - Button
def loop(): # this function will run repeatedly, until user hits CTRL+C
if (digitalRead(BUTTON) == HIGH):
# was the button pressed? (is 3.3v making it HIGH?) then do:
buzz()
delay(10) # don't "peg" the processor checking pin
def delay(j): #need to overwrite delay() otherwise, it's too slow
for k in range(1,j):
pass
def buzz(): #this is what makes the piezo buzz - a series of pulses
# the shorter the delay between HIGH and LOW, the higher the pitch
limit = 500 # change this value as needed;
# consider using a potentiometer to set the value
for j in range(1, limit):
digitalWrite(PIEZO, HIGH)
delay(j)
digitalWrite(PIEZO, LOW)
delay(j)
if j==limit/2:
digitalWrite(LED, HIGH)
digitalWrite(LED, LOW) # turn it off
run(setup, loop)

Check out this page. From userland (e.g. python) you can use set a pin to high or low by writing to the correct sysfs file in /sys/class/gpio.

The GPIO pins of the AM3359 are low-voltage and with insufficient driver strength to directly drive any kind of transducer. You would need to build a small circuit with a op-amp, transistor or FET to do this.
Once you've done this, you'd simply set up a timer loop to change the state of the GPIO line at the required frequency.
By far the quickest and easiest way of getting audio from this board is with a USB Audio interface.

Related

Detects sound and sets GPIO

I am looking for a solution that detects sound and sets GPIO21 to low and GPIO21 to high, after 5 minutes when there is no sound.
I need it for a streamer (Raspberry Pi) that will run shairport-sync, tidal-connect and spotify. When sound is detected, GPIO should trigger my amplifier.
Unfortunately I can not code python, so I hope someone can help
#SolveltPlanet
It is disabled via #dtparam=audio=on and I have Python 2.7.16 installed. Here is aplay -l
**** List of PLAYBACK Hardware Devices ****
card 1: AUDIO [SMSL USB AUDIO], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
I think you might find this link helpful: Detecting audio. You shouldn't need all of the code in that answer, just the part on detecting silence.
I believe you can use the python gpiozero library for using the GPIO ports. You should be able to treat it as an LED.
import gpiozero #For GPIO
import time #To sleep
###REPLACE THIS WITH YOUR OWN FUNCTION (Like the one I posted in the above link)###
def is_silent():
return True
pin = gpiozero.LED(21) #Set up the GPIO pin
pin.on() #Turn it on
seconds_since_sound = 300 #Set seconds since last sound to high
while(True):
if(is_silent): #Check if there is no sounds
if(seconds_since_sound >= 300): #If there is no sounds and it has been more than 5 mins since the last sound
pin.on() #Turn on
else:
seconds_since_sound += 1 #Otherwise increment by a second
time.sleep(1) #Sleep for a second
else:
seconds_since_sound = 0 #If there is a sound then set timer to 0
pin.off() #Turn off
Unfortunately I am unable to test if the code works as I do not have access to a raspberry pi.
It looks like the silence detection does not work in python 3.
EDIT:
It looks like you can record the soundcard on some devices using this line of code:
import pyaudio #import pyaudio
p = pyaudio.PyAudio() #setup pyaudio
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, output=True, frames_per_buffer=CHUNK_SIZE, input_device_index=2) #open pyaudio stream
snd_data = array('h', stream.read(CHUNK_SIZE)) #Capture data (should be done in while loop)
return (max(snd_data) > threshold) #Check if data is louder than threshold
(Change the input device index to point to the output of your sound card)
Once again, I am unable to test if this works as it only runs of python 2. It uses pyaudio.

Raspberry Pi 4 output python if else results to LCD: Random characters

I am attempting to make a simple python script that uses a moisture sensor on GOIP 21 and will output text on a display.
What I have:
Raspberry Pi 4 4GB
Arducam 1602 16x2 LCD Display Module Based on HD44780
KeeYees 5 Pcs High Sensitivity Soil Moisture Sensor Module with Female to Female Jump Wires, Sensor Module Watering System Manager for Arduino TE215
Breadboard 830
It's only a learning attempt, after I figure this out I plan on buying better sensors and actually having them display accurate percentages. For not a simple moisture detected vs no-detected is okay with me.
My code seems to work for outputting to the console, however when I try to output to the LCD, it gives some weird characters and stops. Not sure what to do as i'm not a python wiz (you'd think id be more like php, but nah lol).
Here is my code
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import sys
sys.path.append('/home/pi/lcd')
import lcd
#GPIO SETUP
moist1 = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(moist1, GPIO.OUT)
def callback(moist1):
if GPIO.input(moist1):
lcd.GPIO.cleanup()
lcd.lcd_init()
lcd.lcd_byte(lcd.LCD_LINE_1, lcd.LCD_CMD)
lcd.lcd_string("Water Is Good", 2)
lcd.lcd_byte(lcd.LCD_LINE_2, lcd.LCD_CMD)
lcd.lcd_string("Don't Add", 2)
lcd.GPIO.cleanup()
else:
lcd.GPIO.cleanup()
lcd.lcd_init()
lcd.lcd_byte(lcd.LCD_LINE_1, lcd.LCD_CMD)
lcd.lcd_string("Add Water Now!", 2)
lcd.lcd_byte(lcd.LCD_LINE_2, lcd.LCD_CMD)
lcd.lcd_string("!!!!!!!!!!!!!!", 2)
lcd.GPIO.cleanup()
GPIO.add_event_detect(moist1, GPIO.BOTH, bouncetime=300) # let us know when the pin goes HIGH or LOW
GPIO.add_event_callback(moist1, callback) # assign function to GPIO PIN, Run function on change
# infinite loop
while True:
time.sleep(1)
I can't figure out what I am doing wrong. Please let me know if you see it. Thanks

rotary encoder script for raspberry pi using python

I have a setup in which I have a motor turning a 5cm diameter shaft at about 1 revolution a second. I need to stop the motor after a predetermined number of revolutions - lets say 10 for now.
The sensor mechanism I am using is simply a magnet and reed switch. The following script works well to record each time the switch is triggered.
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
button1=22
GPIO.setup(button1,GPIO.IN,pull_up_down=GPIO.PUD_UP)
while(1):
if GPIO.input(button1)==0:
print "Button 1 Pressed"
sleep(0.5)
Whilst this script runs the motor -
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BOARD)
Motor1A = 19
Motor1B = 21
Motor1E = 23
GPIO.setup(Motor1A,GPIO.OUT)
GPIO.setup(Motor1B,GPIO.OUT)
GPIO.setup(Motor1E,GPIO.OUT)
print "Going forwards"
GPIO.output(Motor1A,GPIO.LOW)
GPIO.output(Motor1B,GPIO.HIGH)
GPIO.output(Motor1E,GPIO.HIGH)
GPIO.cleanup()
In a nutshell then what I am seeking is a combined script which counts the number of event inputs on pin 22 and then turns pin 23 (the motor enable pin) to LOW on the count of 10.
Many thanks
Nick

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.

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