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:
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.