Hello and thank you for reading. As a hobby project I thought it would be fun to try and create my own communication protocol. I am trying to use the GPIO-pins on my Raspberry Pi 4 to send a digital signal. The reason for using a Raspberry Pi is because I want to connect it to a webpage that I want to run on the Pi. I am using Python with the RPi.GPIO library to control the pins. I am very much at the start of this project but I already ran into a problem.
When sending pulses for my signal I get a strange offset when going for higher speeds. See the code below:
import RPi.GPIO as GPIO
import time
pin = 18 # select pin
pulse_time = 1/100 # set lenght of pulse
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, GPIO.HIGH) # set pin high
time.sleep(pulse_time) # wait
GPIO.output(pin, GPIO.LOW) # set pin low
time.sleep(pulse_time)
GPIO.output(pin, GPIO.HIGH)
time.sleep(pulse_time)
GPIO.cleanup()
In the variable "pulse_time" I set the wait time for the pulses. In this case I am trying to send bits with a speed of 100 bits per second. Which would be 1 bit per 10 milliseconds. See the image below for the data signal (sorry for bad quality, my oscilloscope doesn't have a USB-port for screenshots).
In the image above you can see the 2 pulses I send with my Python code. The first pulse is exactly 10ms long, just as I wanted, but the second pulse already gets a slight offset. When changing the bps to 1000 instead of 100, the offset gets a lot worse. For my project I intend to use a bitrate of 2400 bps.
I also tried doing the same things using C++ instead of Python, since C++ is generally faster/better at controlling hardware. Sadly the GPIO library 'wiringPi' for C++ got deleted and I can't find another way to control the GPIO-pins using C++.
Now that I explained the situation I have the following questions:
Can I set a clock speed in Python for controlling the pins at a set speed? If so, what is the max bps I could reach?
Is there a new way to control the GPIO-pins using C++ instead of Python?
Am I an idiot for trying to do this on a Raspberry Pi and should I use something else?
Any advice would be appreciated. Thank you in advance for taking the time to answer any of my questions.
I think this offset could come from the time it takes to run GPIO.output(pin, GPIO.HIGH).
You could improve this by measuring this execution time and condier it in the time.sleep(...). (e.g. time.sleep(pulse_time - some_gpio_time)
Have a look at timeit to measure the time experimentally or you could try to measure it on the fly and consider it in the consecutive sleep.
But keep in mind, that an applicaiton like that is not intented to fulfill hard realtime requirements and you will always get some error. To achieve better timing you would need to implement this as a linux kernel module, but this might go a bit too far for a hobby project.
Related
I'm trying to use Python to 'mic-monitor', i.e., to playback the mic signal through the headphones in real-time, in addition to any other output signal from the PC.
I can accomplish this by amending my PC's playback settings, but I want to do it with Python, so that I can program a Raspberry Pi to mic-monitor my cheap headset for the PS4.
I can almost accomplish this with PyAudio or sounddevice, but there is a small but significant delay. So:
Is there a way to eradicate that latency with Python, for example by somehow accessing my PC's inputs more directly?
Otherwise, why is it not possible with Python?
Can I somehow configure the Raspberry Pi to mic monitor in the same way as my PC?
Sounddevice code is shown below for reference:
import sounddevice as sd
duration = 5.5 # seconds
def callback(indata, outdata, frames, time, status):
if status:
print(status)
outdata[:] = indata
with sd.Stream(channels=2, callback=callback):
sd.sleep(int(duration * 1000))
There will always be latency with a computer in-between. Professional audio gear is usually custom built for minimal latency (or it's just analog). To reduce latency you need to record smaller chunks at a time before sending them to the output which does introduce more processing overhead. Using smaller chunks can also at some point introduce more jitter in the signal because the inter-frame latency might not keep up with the sample rate. PortAudio is probably likely able to be configured to have a bit less latency, but you're probably getting a lot of the delay from the OS and audio drivers as well. Here's a page discussing how you can optimize the OS and audio drivers for minimal latency on a Raspberry Pi. PortAudio (the driver behind most python audio libraries), also has a discussion on audio driver latency based on your operating system.
looking at the documentation for sd.Stream, it looks like even if you specify a smaller blocksize, due to the implementation, it may make latency even worse.
There is however an option to specify an exact latency (if a particular delay is desirable) or to achieve a best effort "as fast as possible" by specifying latency = "low" This attempts to take into account the specific hardware you're using, and go as fast as possible.
I have a very strange relay problem. I wrote a code to change LED state in RaspberryPi. before I purchased the 4-channel 5v relay board I used LED to indicate HIGH and LOW. That works perfectly fine, but once I connect the relay board it switch vigorously for about half a second, and then work inversely to the outputs, the outputs are generally low but the relays then stay at the normally open positions and switch over to normally closed once they get a high.
To make this more confusing, I connected the relays together with the LED's just to be sure, now the LED's still light up correctly and the relays still switch incorrectly
What bugs me though?
from gpiozero import LED
from time import sleep
red = LED(17)
while True:
red.on()
sleep(1)
red.off()
sleep(1)
(1) Ah, your relay module has a JD-Vcc jumper, so you need to cap/uncap the jumper and wire the Rpi 3V3 signal line and 3V3 or 5V power lines accordingly.
The JD-Vcc jumper setting is a a bit complicated.
You might like to read the following EE SE Q&A for more details on wiring the signal and power lines for JD-Vcc relay module:
How to properly use a relay module with a JD-VCC jumper for Raspberry Pi?
(2) Your "Status LED shows on but relay not switched on/off accordingly" might be related the common problem of "Relay always on but never off" or "Rpi's logical High signal is not High enough to switch off relay".
The reason is that Rpi High is only about 3V but not high enough as Arduino High which is specified as 4V. So the status LED misleadingly shows On status but relay not switched Off/On accordingly. (This confusing problem arises because the relay is originally designed for Arduino whose logical High is higher than Rpi High.)
Again this is complicated to explain by a couple of sentences.You might like to read the above EE SE Q&A (Especially Appendix B) for more details.
I have my circuit hooked up correctly. It's a simple python script running on my RPi 2.
I've done this countless times and I decided to mess around with it today since it's been a while but I know I have the circuit correct and if I hook it up with my 5V, it will stay lit. But if I connect it to a GPIO and use my python script, the LED blinks for a random amount of times (usually for about 3-5 seconds) and then it just stops.
I've tested it with a multimeter and the jumper wires are all working. I tested continuity on the GPIO pin w/ GND and it would beep for as many times as it would make the LED blink and then continuity would stop.
My script continues to run and if I print something during the loop, it will continue to loop.
Everything is pointing to my RPi being broken but I've done nothing to it to break it and it's been sitting quietly since I've last used it.
Does anyone have any insight into this? This is really frustrating because this is just a simple script that should not have any issues.
Occasionally, when I messed with the wires, the LED would momentarily flash but it would be a very weak flash and then nothing. I've also tried to connect it directly to the RPi and skipping the extra wires and it still doesn't work. It seems like the GPIO pin is messed up but I've tried it with multiple GPIO pins.
When I try with other pins (currently using GPIO-07), it will tell me that the pin is already in use, even though it is most definitely not.
I'm also using the same script that I have saved on my Pi from a long time ago. 0 changes made to it but it's no longer looping infinitely, it stops after 4 seconds.
this is my first post on stack overflow yet I use it all the time to solve my many programming issues. So first off, thank you for any help that is given.
I have been given a task by my advisor to get HC-05 sending and receiving serial comms with python and I am at my wits end on the final part of getting it up and running. I have searched everything I possibly can and have not yet found the answer, or even a similar issue. I have the comms working somewhat well. My baud rate is set at 115200 and have that matched in python serial. I am using an Arduino to gather values from sensors on a robot, send the values to python over serial to run calculations then have the result send back. I am sending two values and only receiving one. I first got it up and running by using serial comms over usb cable and it works perfect. I then made a few alterations to get it sending over bluetooth. The data that is being sent from the Arduino through bluetooth is perfect. When I do calculations and send the result back, however, the values are off. I have a timer Interrupt Service Routine (ISR) running on the Arduino that sends the values at 100Hz. If I slow that down to 10Hz, the response from computer to Arduino gets better and if I slow it down to 1HZ it is perfect. Unfortunately, I really need it to be working well at 100Hz for accurate control of my robot. I have included a link below of a plot of the response at 10Hz. Alpha and Theta are values sent from Arduino, V is a calculation done by python and V_echo is V being sent to Arduino, multiplied by 2 and sent back to python. As you can see, V_echo is broken and jagged when it should be a smooth line like the others. All of this tells me that while the send rate of the HC-05 is fine, the receive rate is too slow. I have changed baud rate possibilities, played with making the HC-05 a master vs. slave and slave-loop... slave works the best. The last thing I can think of is using stop bits. I have pyserial sending two stop bits and have the HC=05 stop bit set to two by using AT+UART=115200,1,0. If stop bits are my solution, I clearly have it set up wrong. I don't know exactly what python does when I include stop bits and furthermore I don't know if I need to do any program that reads the bit or if the HC-05 just understands it... If stop bits are not my answer, I look forward to finding out what is. Thanks again.
Is there any way to get a working 433MHz-Sender or -Receiver in a Python Thread?
I have tried those from Ninjablocks and those from Adafruit. But the Problem is that these are all c or c++ scripts, that are outputting to stdout and have no end of the output. I also tried piping them through a Unix-FIFO but there no data is transmitted until I close the Program (Ctrl + C) the second problem is, that the finished programs doesn't recognize my ninjablocks 433MHz Temperature Sensor, that is one of the most important parts of the system.
The 433 MHz Sender/Receiver are connected with the GPIOs of my Raspberry PI (Version B, Rev 2.0)
My Goal is to get the several 433 MHz Sensors (And some sonsors connected via i2c or spi these are already working) working with a python script, that does calculate some Rules (e.g. When Motion detected in Living Room, and between Sunset and Sunrise, turn Light on; Turn on Heating when Temperature Drops below 20°C etc.)
I have written a small program:
import RPi.GPIO as io
data = [] * 10000
while not interrupted:
data.append(io.input(rxPin))
io.wait_for_edge(rxPin, io.BOTH
I expected that code to output something like 1010101010101 because every Edge is recognized. My next step would have been to measure time between the edges and - based on that time - decide if it was a short 1/0 or a long 1/0 (433MHz seems to be encoded like short 1 long = = 1 long 1 short 0 = 0 or vise versa) but the output was something like:0110011001000000010110010 etc. so the python thread is missing some 1s and 0s, I think.
has anybody an idea to get that Wireless input in my Program?
If you are running python I guess you are using some kind of linux on the Raspberry Pi, am I right?
Linux is not real time os, meaning your python loop does not run all the the time and can skip some GPIO data. You can solve it by either using a real time os like Chibios or use kernel module to stop all interrupts and sample the GPIO continuously as demonstrated in the Panalyzer project.