I'm new to raspberry pi, trying to send a stream of bits from sender to receiver. However bits are not received in correct pattern most of the times, they seems to be shifted a little. I think i'm unable to synchronize them properly. Does anyone how I can sync the clocks
Python Code is here
# Sender
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.OUT)
while True:
GPIO.output(23, GPIO.HIGH)
time.sleep(1)
GPIO.output(23, GPIO.LOW)
time.sleep(1)
# .... some more bits here
# Receiver
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
while True:
bit = GPIO.input(17)
print bit
time.sleep(1)
You should not try to synchronize the sender and the receiver based on time. You should choose the frequency of sending on the sender side, and let receiver just sit there and wait for the bits to come, without sleeping. Because sleeping makes you miss stuff.
Use:
GPIO.add_event_detect(17, GPIO.BOTH, callback=my_callback)
to listen to a change on the PIN, and execute my_callaback
when it happens.
You can also choose to wait for rising edge via GPIO.RISING
or the falling via GPIO.FALLING
.
For your example, here is something to start with, not tested or anything:
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
def readbit(channel):
bit = GPIO.input(17)
print bit
GPIO.add_event_detect(17, GPIO.BOTH, callback=readbit)
while True:
sleep(1) # do something useful here
This probably won't be enough, since you can't detect bits that don't change the state. To tackle this, you have quite a few options, and I will only mention two most simple ones:
You can use another PIN as a control signal, and use it to trigger the reads on the receiver. This way, you trigger the read on the rising edge of the control pin, and read the value of the data pin.
On the sender:
def send_bit(pin, bit):
GPIO.output(24, GPIO.HIGH) # first send the control bit
GPIO.output(pin, bit): # then the data on another pin
while True:
send_bit(23, GPIO.HIGH)
time.sleep(1)
send_bit(23, GPIO.LOW)
time.sleep(1)
On the receiver:
DATA_PIN = 17
CONTROL_PIN = 18 # or whatever
def readbit(channel):
bit = GPIO.input(DATA_PIN)
print bit
GPIO.add_event_detect(CONTROL_PIN, GPIO.RISING, callback=readbit)
Another solution, if you don't want to use two wires, is to create a simple protocol. For example:
This might be complicated, but it actually isn't. All you need to do now is to trigger the reading on the rising edge, and read the data somewhere between 0.1 and 0.9 seconds after that. Let's make it 0.5 seconds, to be sure we are in the middle of this time.
On the sender:
def send_bit(pin, bit):
GPIO.output(pin, GPIO.HIGH) # send the control bit first, always HIGH
GPIO.output(pin, bit) # send the actual data bit
while True:
send_bit(23, GPIO.HIGH)
time.sleep(1)
send_bit(23, GPIO.LOW)
time.sleep(1)
# .... some more bits here
On the receiver:
def readbit(channel):
time.sleep(0.5) # waiting to be in the safe time for read
bit = GPIO.input(17)
print bit
GPIO.add_event_detect(17, GPIO.RISING, callback=readbit)