How to sync clock in Raspberry Pi?
I'm new to raspberry pi trying to send a stream of bits from sender to receiver. Most of the time, however, the bits are not received in the correct order, they seem to be shifted a little. I think I cannot sync them properly. Anyone how can I sync my watch
Python code 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)
source to share
You should not try to synchronize the sender and receiver based on time. You have to choose the sending frequency on the sender side and let the receiver just sit there and wait for the bit to come, awake. Because sleep makes you miss things.
Using:
GPIO.add_event_detect(17, GPIO.BOTH, callback=my_callback)
to listen to the PIN change and execute my_callaback
when it does. You can also wait for the front to increase with GPIO.RISING
or fall through GPIO.FALLING
.
For your example, here's how to start, not tested and nothing:
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 will probably not be enough as you cannot detect bits that do not change state. To deal with this, you have quite a few options, and I will only focus on the two simplest ones:
Control signal
You can use another PIN-code as a control signal and use it to start reading on the receiver. Thus, you start reading 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 recipient:
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)
One wired protocol
Another solution, if you don't want to use two wires, is to create a simple protocol. For example:
- Each transmission consists of two bits: 1 and X
- The data bit to be transmitted is X, while the first bit is always 1 and serves as a trigger for the receiver.
- The X bit is expected to be active 0.1 to 0.9 seconds after the first rising edge of the bit.
It can be tricky, but it really isn't. All you have to do is start a reading on the leading edge and read the data somewhere between 0.1 and 0.9 seconds after that. Let's do this for 0.5 seconds to make sure we're 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 recipient:
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)
source to share