1

How can I code two Pi Picos to send/receive data accurately to 10 milliseconds a bit using LED/Photodiode pairs? I am trying to send data from one PiPico to another wirelessly. I am on a bit of a time crunch and have unsuccessfully tried getting my photodiode circuit to output the correct voltage swings to use pico's UART pins. There must be a way to to this more simply.

Right now I am using utime.sleep(), and when I blink my LEDs faster than 0.1 seconds a bit, I get an inaccurate byte or two quite often. I am very new to microcontrollers but dont think I should be loosing so much information at 0.01 seconds. I thought it might be that the Pi pico clocks weren't synced at first, but I'd think 0.01s is slow for the clocks to be so out of sync.

Here is my code: Pico Sending Bits through LEDs:

    for i in range (0, len(finalBitString)): 
            if finalBitString[i]=="1":
                led(1)  
            elif finalBitString[i]=="0":
                led(0)
            utime.sleep(.01)

Receiving Pi Pico:

    while True:
           utime.sleep(.005)   #sample diode every 0.01 seconds
           value = SaqDiode.read_u16()*3.3 / 65536
           if (bitCutoff <= value):      #read saq diode and determine 1 or 0
              bit=1  
           elif (value <= bitCutoff):
              bit=0
           utime.sleep(.005)

1 Answers1

3

There are several problems with your approach:

  1. You only perform a single sample during each period, which means any slightest lack of sync between the two devices' clocks will corrupt the transmission.
  2. It looks like your diode is hooked to an ADC, but you don't take in to account the time it takes to read the ADC.
  3. You have no means to synchronize transmitter and receiver, I assume you rely on your ability to hit the reset button on both at the same time. That is not Accurate enough!
  4. You are using Python, which is not great for time sensitive projects like this one.

Basically, this approach is too simplistic, and relies on too many conditions being "just right", which they seldom are.

To solve the synchronization issue, you should use a "Self-clocking signal".

One example that should be easy to implement in your case would be the "Manchester code".

You should check the spec on PiPico ADC and your diode, and increase the sampling rate as much as possible.

You should than take multiple samples and monitor when transition between a series of on samples and off samples occurs.

It would be even better to get rid of the ADC all together, and rig the diode signal to be either low or high so you can put it on a digital pin that supports interrupts.

Than, instead of a loop polling the diode, you can have your code fired by the system on state transition, which will be a lot more accurate.

Here is a tutorial on how to do the interrupt part: https://microcontrollerslab.com/pir-motion-sensor-raspberry-pi-pico-external-interrupts-tutorial/

Unfortunately, without knowing what kind of photo diode you are using, it is impossible to say how to wire it to work with a digital instead of analog pin.

Lev M.
  • 6,088
  • 1
  • 10
  • 23
  • Interesting answer for a more software-oriented person like myself. Thank you. Maybe a silly thought, but would another possibility be to have 2 (maybe differently coloured LEDs) and then use one as the *"clock"* and read the other when it's on? – Mark Setchell Aug 26 '22 at 06:36
  • 1
    @MarkSetchell I am a software oriented person my self, who only a while ago began playing with Arduinos, and learned a lot of this stuff from youtube videos. I strongly recommend this channel: https://www.youtube.com/c/BenEater To answer your questions: many wired communication protocols use a separate line / wire for clock signal, making the data transfer simpler (no need for special encoding). But I have no idea how to implement such a thing with LEDs, without getting interference. – Lev M. Aug 27 '22 at 15:42
  • 1
    Thank you so much! I realized after reading your answer that there is a whole world of asynchronous communication protocols that I didn't know well enough. I ended up using the ADC pins for now, and maxed out the ADC sampling rate for each bit, with some other interrupt-type functions. Im going to learn Manchester code next to see if I can get more accuracy. Thanks again! – gradStudent Aug 29 '22 at 18:54
  • @gradStudent you may also want to look in to parity, and other error checking and correction methods. With a few extra bits, you can often recover some transmission errors, or at least the receiver can know it got bad data. Good luck! – Lev M. Aug 30 '22 at 18:26