[Dprglist] PID-tuned Clock in Python?

David Anderson davida at smu.edu
Thu Feb 18 20:22:02 PST 2021


Kipton,

Bingo!   That is so cool.

thanks for the link.

David


On 2/18/21 8:42 PM, Kipton Moravec via DPRGlist wrote:
>
> An option we are looking at for a work project is the STM32MP1XX 
> family of processors.
>
> It has a Arm A7 and Arm M4 in the same chip. The A7 runs Linux, and 
> the M4 is for the real-time stuff. They have a bus between the two 
> processors so they can look at the other's peripherals and memory.
>
> They have a development board that is under $69 you could base a Robot 
> around.
> https://www.mouser.com/ProductDetail/STMicroelectronics/STM32MP157A-DK1/?qs=9r4v7xj2LnkgRwGGD4%252BIjQ%3D%3D
>
> It is relatively new, and not for the faint of heart. I would 
> recommend getting to understand the M4, the ST CubeIDE development 
> tools, and how ST does things with the HAL before you jump into this 
> beast. To program the M4, the IDE connects to Linux with Ethernet 
> copies it over, and the A7 writes to the M4 memory.
>
>
> When I was doing a resonant power supply we had a PID loop that was 
> executed every clock, between 25 and 100 kHz.  Our goal was to adjust 
> the input voltage (on a slower loop) so the frequency was 50 kHz 
> (resonance most efficient) and the clock by clock loop would deal with 
> abrupt current changes by changing the frequency higher to shed power 
> and make the frequency lower to provide more power. We had to 
> compensate for the sample time in the PID equation.  It is possible to 
> do. But Python would not do it.
>
> We were dealing with a power supply for a laptop PC. Where to save 
> power they would shut parts of the processor and peripherals 
> completely off when not needed, lowering the current, and turning 
> things on quickly when needed causing the current to increase. These 
> events would happen randomly sometimes multiple times a second.
>
> Kip
>
> On 2/18/21 3:58 PM, David Anderson via DPRGlist wrote:
>> Howdy,
>>
>> Not to be overly pedantic...
>>
>> But another solution to these timing problems is to use a micro 
>> controller that is not running Linux to do your real time stuff.  The 
>> STM32 Nucleo board I'm using with an RTOS has a context switch time 
>> which is reliably less than 10 us (which is actually the least I can 
>> measure).
>>
>> I understand the arguments for using Linux.  I've been using it both 
>> at work and home since the early 1990s.  But not on robots.  If the 
>> argument is that it makes robotly things easier, I'm not sure 
>> anyone's experience bears that out.
>>
>> Right tool for the job, as the old guys use to say.
>>
>> cheers!
>> dpa
>>
>>
>> On 2/18/21 11:03 AM, John Swindle via DPRGlist wrote:
>>>
>>> */[EXTERNAL SENDER]/*
>>>
>>> Going back to a previous topic regarding jitter in timing intervals.
>>>
>>> Why can't parameters used in calculations be scaled by the actual 
>>> sample interval? I understand 50ms is chosen because it gives 
>>> optimum control without undue overhead. When the actual interval is, 
>>> say, 47ms, why not scale the time-related parameters to 47/50 of 
>>> what they nominally are, just for that interval? If the next 
>>> interval is 74ms, scale the parameters to 74/50. Is this 
>>> impractical? Is the uncertainty of measuring the time interval too 
>>> large? This is, if Python says the time interval is 47ms, is the 
>>> error, say, +/- 10ms?
>>>
>>> Related to this: If the sample-to-sample timing error is large or 
>>> jittery, but if you have confidence that the long-term timing is 
>>> 50ms per interval, then why can't the current calculations be 
>>> smoothed, assuming that each calculation is jittery due to timing 
>>> inaccuracy? Does the robot really make snap decisions based on a 
>>> single interval?
>>>
>>> Most CPU datasheets require the clock to have 50 to 100ppm accuracy. 
>>> That sounds good, but for audio processing, it means streams coming 
>>> from different sources will beat with one another. I have to 
>>> resample the streams to match the actual sample rate of one of the 
>>> streams. I use a metronome signal that each gadget processes. That 
>>> doesn't mean any of the timings are correct (including the timing of 
>>> the metronome). It just means they are all forced to look like they 
>>> are the same. I say this because resampling is like what I'm 
>>> suggesting: Scale the calculations to the actual interval.
>>>
>>> Am I missing something here?
>>>
>>> John Swindle
>>>
>>> -----Original Message-----
>>> From: Murray Altheim via DPRGlist <dprglist at lists.dprg.org>
>>> To: Chris N <netterchris at gmail.com>; dprglist at lists.dprg.org 
>>> <dprglist at lists.dprg.org>
>>> Sent: Thu, Feb 11, 2021 4:06 am
>>> Subject: Re: [Dprglist] PID-tuned Clock in Python?
>>>
>>> On 11/02/21 3:13 pm, Chris N wrote:> I don’t think you have a “clock 
>>> accuracy” issue. I’m pretty sure
>>> > the hardware clocks, as in crystal + PLL etc., in things like the
>>> > Pi, are plenty accurate for our needs.
>>>
>>> Hi Chris,
>>>
>>> First, thanks very much, I appreciate your thoughtful reply.
>>>
>>> Yes, I understand that it's not the accuracy of the Raspberry Pi's
>>> system clock that is in question, but the accuracy of time loops
>>> when implemented in a Python application using a single or multiple
>>> threads, executing within a time-sharing operating system like Linux.
>>>
>>> This is clearly where a microcontroller (like an Arduino, STM32,
>>> ESP32, Pico RP2040, etc.) has its advantages. As I noted, my
>>> MacBook was actually worse than my Raspberry Pi, which in this
>>> light is perhaps not so surprising, i.e., the MacBook's processor
>>> is a lot busier.
>>>
>>> My 3.5GHz multi-core i7 workstation is clearly giving at least a
>>> whole core to the Python application and not struggling, so its
>>> performance is very close to expected norms. But that's not the
>>> case on the Pi, where I'll actually be using this timing loop.
>>>
>>> [...]
>>> > Now regarding the PID idea:
>>> >
>>> > Say we have a loop that we want to run at a fixed rate. Say 20Hz / 
>>> 50.0ms.
>>> >
>>> > Using PID to improve the timing accuracy of such loops is certainly
>>> > an interesting idea, but I believe PID makes things worse in this 
>>> case.
>>>
>>> I'm not clear that this is the case yet. My observation was the the PID
>>> loop was improving things somewhat significantly, but more on that 
>>> below.
>>>
>>> > See output from your clock_test.py below.   I ran this on my Pi 3.
>>> > I deliberately used a tough background load to amplify the effect
>>> > (stress –vm 4 –vm-bytes 128M) , but even with normal loads the
>>> > negative effect of the PID can be observed, just the errors would
>>> > be much smaller.
>>>
>>> Agreed, understood.
>>>
>>> > In line 6 you can see the 27ms error.
>>> > [...]
>>> > The reason I think PID is a bad idea here is because the nature of
>>> > the disturbance is simply too random and its very intermittent.
>>> > The best you can do really is to use basic loop timing logic to
>>> > ensure that the next iteration starts at the right time, despite
>>> > the fact that this iteration took an unusual amount of time or
>>> > sleep() took an unusual amount of time. With PID you end up  > 
>>> over-compensating and you are effectively hurting the timing of
>>> > subsequent iterations.
>>>
>>> I certainly agree based on both logic and my observations that the
>>> disturbances are intermittent, and from the perspective of the
>>> Python program (i.e., it not knowing what else is running), would
>>> appear entirely randomly.
>>>
>>> But I'm not clear the PID loop is over-compensating in those cases.
>>> When a disturbance is within one 20Hz clock cycle, there is no real
>>> fix for that in software. I entirely agree with you in those cases.
>>> But when the CPU is really busy with some longer-term process and
>>> that activity extends say over several seconds, the PID (I believe)
>>> would tend to compensate better than with no PID.
>>>
>>> > There are straight forward ways to deal with the fact that
>>> > time.sleep(x) doesn’t sleep for exactly x amount of time, and the
>>> > fact that the amount of work which needs to be done every iteration
>>> > is not 100% constant.  A python version of such a fixed-rate loop 
>>> > is here: https://github.com/nettercm/timing 
>>> <https://github.com/nettercm/timing%C2%A0%C2%A0>I typically use
>>> > similar loop timing logic in other languages and sometimes even
>>> > on a microcontroller.
>>> >
>>> > In pseudo python it looks as follows. [...]
>>> If I'm reading your code correctly, this is kinda what I was doing
>>> before I adopted the PID into the mix. I had a fixed trim value on
>>> the Rate, and when the 50ms loop was consistently a bit slow or a
>>> bit fast I'd just modify the trim value. It was trying to auto-correct
>>> that trim value that led me to using a PID loop. Now, a fixed trim
>>> would obviously not take into account those nasty intermittent surges
>>> or lags, but is certainly simpler to implement and a lot less
>>> mysterious in use than a PID loop.
>>>
>>> So if the PID turns out to be causing actual problems as you suggest,
>>> I can set the flag to disable it, and maybe re-implement the fixed
>>> trim. I've been setting the PID's kp constant from an RGB LED
>>> potentiometer like:
>>>
>>> https://shop.pimoroni.com/products/rgb-potentiometer-breakout
>>>
>>> so if I end up disabling the PID I could manually set the trim from
>>> the potentiometer, then just fix it in my YAML configuration. This
>>> would be a "best guess" on a fixed, constant trim value.
>>>
>>> I think we both agree that there's nothing anyone can do to get a
>>> truly consistent loop using Python on Linux, but if I'm willing to
>>> accept that those intermittent <50ms disturbances are also unfixable,
>>> then the PID does still at least (IMO) manage the longer lags and
>>> surges of the clock. This *seems* to be what I'm seeing in the
>>> console outputs.
>>>
>>> The whole subject of PID is all a bit dream-catcher, Voynich Manuscript,
>>> ouija board, patchouli incense kind of thing... verra-mysterious.
>>>
>>>
>>> Cheers,
>>>
>>> Murray
>>>
>>>
>>> ...........................................................................
>>> Murray Altheim <murray18 at altheim dot com>                      = 
>>> =  ===
>>> http://www.altheim.com/murray/                                     
>>> ===  ===
>>>                   = =  ===
>>>     In the evening
>>>     The rice leaves in the garden
>>>     Rustle in the autumn wind
>>>     That blows through my reed hut.
>>>             -- Minamoto no Tsunenobu
>>>
>>> _______________________________________________
>>> DPRGlist mailing list
>>> DPRGlist at lists.dprg.org <mailto:DPRGlist at lists.dprg.org>
>>> http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org
>>>
>>> _______________________________________________
>>> DPRGlist mailing list
>>> DPRGlist at lists.dprg.org
>>> http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org
>>
>>
>> _______________________________________________
>> DPRGlist mailing list
>> DPRGlist at lists.dprg.org
>> http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org
>
> _______________________________________________
> DPRGlist mailing list
> DPRGlist at lists.dprg.org
> http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dprg.org/pipermail/dprglist-dprg.org/attachments/20210218/8678c247/attachment-0001.html>


More information about the DPRGlist mailing list