Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using PID to monitor/correct Xtal frequency wrt other/reference system. #75

Open
mungewell opened this issue May 30, 2023 · 2 comments
Open

Comments

@mungewell
Copy link

I have a project for an Open-Source LTC box, similar to Lock-it or Tenticle-Sync. Multiple boxes communicate 'time' with an audio signal and then are expected to remain in sync. The issue I have is the the Pico's clock is not precision, and I want to add some synchronization method....
https://github.com/mungewell/pico-timecode

The basics are that each box is effectively a cascade counter, implemented in the PIO blocks, which count according to the PIO clock divider. I have already implemented a way to adjust the divider, and to monitor the timing difference between 'local' LTC and that received from the reference. This kind of looks like this....

clock_adjust

When monitoring the moment each frame (local vs reference) starts I get a 'delta time' (in us). I tried feeding this into a PID instance, expecting the output to produce a 'correction' value which would stabilize over time to a non-zero value...

Q. Is this correct thinking? - because I couldn't get it to work like that.... it never seems to settle.

It's worth noting that the measured time value is from the local clock, so it would appear that the reference is wrong... but is in-fact the correct one.

When starting a session the units are 'Jam Synced' together; which gets the clocks and phase the same. After some time they will drift apart. I believe that if the clock rate(s) are the same, then we will not need to monitor/correct the phase as it will just be correct.

@mungewell
Copy link
Author

mungewell commented May 31, 2023

I continued to mess with the various gains, and after introducing some 'D' gain I seemed to get something a little more stable.

        pid = PID(-0.001, -0.00001, -0.001, setpoint=0)
        pid.auto_mode = False
        pid.sample_time = 60
        pid.output_limits = (-10.0, 10.0)
        sync_after_jam = False

and

                        # Update PID every 60s or so
                        if (g & 0xFFFF0000) != l:
                            if l:
                                if sync_after_jam == True:
                                    if pid.auto_mode == False:
                                        pid.set_auto_mode(True, last_output=eng.duty)
                                        
                                    eng.duty = pid(dave/len(dcache))

I get following, where blue is the delta measurement in 'us' (dave/len(dcache) is averaging a noisy signal) and red (scaled * 100) is the resultant duty factor used for correcting the clocks. Seems to settle around 0.66.

The fractional part of the output is used to toggle between adjacent fractional dividers (ie between 128/256 and 127/256), integer part (0 in this case) adds constant 1/256 and wraps whole divisor where appropriate.

20230530_A-B_30NDF

I'll keep experimenting with the gains...

@mungewell
Copy link
Author

Code is here, if anyone is interested. PID is used in main.py.
https://github.com/mungewell/pico-timecode/tree/adjust_clock_with_PID

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant