Mercurial > hg > beaglert
changeset 152:8f98b32d0e23 ClockSync
Last commit on this branch for a while. Overall not very succesful
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 05 Oct 2015 13:06:14 +0100 |
parents | e9c9404e3d1f |
children | |
files | core/ClockSync.cpp core/ClockSyncThread.cpp core/Pid.cpp core/VirtualClock.cpp include/ClockSync.h include/Pid.h projects/scope/render.cpp |
diffstat | 7 files changed, 128 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/core/ClockSync.cpp Tue Sep 22 04:10:07 2015 +0100 +++ b/core/ClockSync.cpp Mon Oct 05 13:06:14 2015 +0100 @@ -3,6 +3,7 @@ void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){ virtualClock=&aVirtualClock; } +Pid* gClockSyncPid; void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){ setVirtualClock(aVirtualClock); slave=thisIsSlave; @@ -15,6 +16,7 @@ receiveLoopTimeout=1e5; movingAverage.setLength(31); expectedClockSyncType=isSlave() ? kSync : kNone; + gClockSyncPid = &pid; } void ClockSync::resetTs(){ T1=-1; @@ -215,40 +217,9 @@ case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless T2p=clockSyncTimestamp; //TODO: evaluate things - double offset=(T1p-T1-T2p+T2)/2.0d; if(areTsValid()){ - processOffset(offset); - - /* - static int calls=0; - static double referenceOffset=0; - - if(calls<100){ // start by averaging everything - movingAverage.add(offset); - } else { //once we get an estimate, start discarding outliers - float maxOffsetDeviation=20; - float deviation=fabsf(movingAverage.getAverage()-offset); - if(deviation<maxOffsetDeviation){ - movingAverage.add(offset); - printf("w(end+1)=%4.1f;\n", movingAverage.getAverage()); - } else { -// printf("Out of range: %f \n", deviation); - } - } - printf("offset(end+1)=%f;\n", offset); - if (calls==100){ -// printf("Update reference\n"); - referenceOffset=movingAverage.getAverage(); - } else if (calls==200){ - calls=99; - } - calls++; -*/ - -// printf("%lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); -// if(T2-T1p<0){ -// printf("Negative: %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); -// } + offset = (T1p-T1-T2p+T2)/2.0d; + processOffset(); } else { printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); } @@ -261,7 +232,7 @@ } return 1; } -void ClockSync::processOffset(double offset){ +void ClockSync::processOffset(){ static int calls=0; // TODO: change the flow control below so that it can happen multiple times //(base it upon the length of movingAverage rather than the number of calls) @@ -280,43 +251,63 @@ static IirFilter iir(1); static bool init = false; if(init == false){ + //cutoff 0.05 // double coeffs[5]={0.00554271721028068, 0.0110854344205614, 0.00554271721028068, // -1.77863177782459, 0.800802646665708}; - double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113, - -1.56101807580072, 0.641351538057563}; + //cutoff 0.015 + double coeffs[5]={0.000537169774812052, 0.0010743395496241, 0.000537169774812052, + -1.93338022587993, 0.935528904979178}; +// double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113, +// -1.56101807580072, 0.641351538057563}; iir.setCoefficients(coeffs); init = true; } float expectedOffsetDifferenceMean = 0.2432; - float expectedOffsetDifferenceStd = 6.487; - float nlOffset; - static float pastOffset = 0; - float offsetIncrement = offset-pastOffset; - if ( fabsf(offsetIncrement) > 1*expectedOffsetDifferenceStd && calls>51){ + float expectedOffsetDifference = 3.5; + static float pastNlOffset = 0; + static float pastIncrement = 0; + float offsetIncrement = offset-pastNlOffset; + static int filteredOut=0; + if (calls>51 && (fabsf(offsetIncrement) > expectedOffsetDifference && filteredOut < 8)){ // non-linear filtering: remove outliers - nlOffset = pastOffset; + nlOffset = pastNlOffset; +// printf("this actually happened\n"); +//nlOffset=offset; // BYPASS non linear filter // printf("%f %f 0,0,0,0,0,0\n", offset,pastOffset); + filteredOut++; } else { nlOffset=offset; + filteredOut = 0; } - pastOffset=nlOffset; - float iirOffset = iir.process(nlOffset); + pastIncrement = nlOffset - pastNlOffset; + pastNlOffset = nlOffset; + iirOffset = iir.process(nlOffset); static float maxOffset=0; static float pastIirOffset=0; if( calls > 0 ) { maxOffset=fabsf(iirOffset) > fabsf(maxOffset) ? iirOffset : maxOffset; pid.setError(iirOffset); - float correction=pid.getOutput()*0.0001; + float correction=pid.getOutput(); static float oldSamplingRate=44100; - printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n", - offset, nlOffset, iirOffset, iirOffset - pastIirOffset, correction, oldSamplingRate); //unfiltered, filtered + if( (calls&0) == 0){ + printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n", + offset, nlOffset, iirOffset, iirOffset - pastIirOffset, + pid.getProportionalGain(), pid.getIntegralGain(), pid.getDerivativeGain(), pid.getGlobalGain(), + correction, pid.getIntegralError(), oldSamplingRate); //unfiltered, filtered + } pastIirOffset = iirOffset; float targetSamplingRate; + // Applit PID + targetSamplingRate = oldSamplingRate - correction; + if(targetSamplingRate> 44110) //clip the Pid ! + targetSamplingRate = 44110; + if (targetSamplingRate < 44090) + targetSamplingRate = 44090; + + // or use a naive hysteresis comparator static int direction=1; float thresholdL = -1; -// targetSamplingRate = oldSamplingRate - correction; float thresholdH = 3; - targetSamplingRate = 44100; if( (iirOffset > thresholdH && direction == 1) || @@ -330,7 +321,7 @@ (iirOffset < -thresholdL && direction == 1) ) { - iirOffset = 44102; + iirOffset = 44103; direction = 1; } #ifndef USE_JUCE @@ -362,7 +353,7 @@ if(isSlave()==true){ //printf("Waiting for a sync clockSync\n"); } else { //if this is master - usleep(30000); //this times (roughly) how often sync clockSyncs are being sent. + usleep(10000); //this times (roughly) how often sync clockSyncs are being sent. int ret=masterSendSync(); if(ret<=0) return -1; @@ -373,4 +364,9 @@ return 1; } - +float ClockSync::getOffset(){ + return offset; +} +float ClockSync::getIirOffset(){ + return iirOffset; +}
--- a/core/ClockSyncThread.cpp Tue Sep 22 04:10:07 2015 +0100 +++ b/core/ClockSyncThread.cpp Mon Oct 05 13:06:14 2015 +0100 @@ -23,7 +23,10 @@ stopThread(); #endif /* USE_JUCE */ } + +ClockSync* gClockSync; void ClockSyncThread::init(bool isSlave, int aPort, VirtualClock &aVirtualClock){ + gClockSync = &clockSync; setVirtualClock(aVirtualClock); listening=false; clockSync.init(isSlave, aPort, *virtualClock);
--- a/core/Pid.cpp Tue Sep 22 04:10:07 2015 +0100 +++ b/core/Pid.cpp Mon Oct 05 13:06:14 2015 +0100 @@ -13,8 +13,9 @@ error = 0; differentialError = 0; kp = 5; - ki = 2; - kd = 0.8; + ki = 2;// 2; + kd = 0.8; //0.8; + gain = 1; idleTimeout = 0; timeoutCount = 0; output = 0; @@ -32,12 +33,37 @@ ts = 1; //TODO: this should be passed as a parameter, unless setError() gets always called at constant intervals updateIntegralError(); updateDifferentialError(); - output= kp * error + ki * integralError + kd * differentialError; + output = gain * (kp * error + ki * integralError + kd * differentialError); // printf("%f %f %f %f %f %f %f\n", output, kp, error, ki, integralError, kd, differentialError); return output; } float Pid::getOutput(){ return output; } - - +void Pid::setProportionalGain(float proportionalGain){ + kp = proportionalGain; +} +void Pid::setDerivativeGain(float derivativeGain){ + kd = derivativeGain; +} +void Pid::setIntegralGain(float integralGain){ + ki = integralGain; +} +void Pid::setGlobalGain(float globalGain){ + gain = globalGain; +} +float Pid::getProportionalGain(){ + return kp; +} +float Pid::getDerivativeGain(){ + return kd; +} +float Pid::getIntegralGain(){ + return ki; +} +float Pid::getGlobalGain(){ + return gain; +} +float Pid::getIntegralError(){ + return integralError; +}
--- a/core/VirtualClock.cpp Tue Sep 22 04:10:07 2015 +0100 +++ b/core/VirtualClock.cpp Mon Oct 05 13:06:14 2015 +0100 @@ -80,11 +80,13 @@ } void VirtualClock::addOffset(double periodOffset){ +// printf("Clock was : %f ", elapsedPeriods); elapsedPeriods-=periodOffset; if(elapsedPeriods<0){ printf("ERROR: periodOffset adjustment of %f resulted in elapsedPeriods=%f\n", periodOffset, elapsedPeriods); exit(1); } +// printf("and now is: %f after a correction of %f", elapsedPeriods, periodOffset); movingAverage.reset(); } double VirtualClock::getPeriod(){
--- a/include/ClockSync.h Tue Sep 22 04:10:07 2015 +0100 +++ b/include/ClockSync.h Mon Oct 05 13:06:14 2015 +0100 @@ -51,7 +51,10 @@ VirtualClock *virtualClock; void resetTs(); bool areTsValid(); - void processOffset(double offset); + void processOffset(); + float offset; + float nlOffset; + float iirOffset; Pid pid; public: ClockSync(){}; @@ -67,6 +70,9 @@ void setType(int clockSyncType); void setTimestamp(myClock_t timestamp); void print(); + float getOffset(); + float getIirOffset(); + /** * sends a clockSync without blocking, checks results and returns the timestamp * immediately after the clockSync has been sent or -1 if there was an error or timeout expired.
--- a/include/Pid.h Tue Sep 22 04:10:07 2015 +0100 +++ b/include/Pid.h Mon Oct 05 13:06:14 2015 +0100 @@ -19,6 +19,7 @@ float kp; float ki; float kd; + float gain; float ts; int idleTimeout; int timeoutCount; @@ -29,6 +30,15 @@ float setError(float anError); void setIdleTimeout(int aIdleTimeout); float getOutput(); + void setProportionalGain(float proportionalGain); + void setDerivativeGain(float derivativeGain); + void setIntegralGain(float integralGain); + void setGlobalGain(float globalGain); + float getProportionalGain(); + float getDerivativeGain(); + float getIntegralGain(); + float getGlobalGain(); + float getIntegralError(); };
--- a/projects/scope/render.cpp Tue Sep 22 04:10:07 2015 +0100 +++ b/projects/scope/render.cpp Mon Oct 05 13:06:14 2015 +0100 @@ -4,6 +4,7 @@ #include <ClockSynchronizer.h> #include <cmath> #include <ClockSyncThread.h> +#include <Pid.h> float gPhase1, gPhase2; float gFrequency1, gFrequency2; @@ -56,7 +57,7 @@ gPhase1 = 0.0; gPhase2 = 0.0; - gFrequency1 = 200.0; + gFrequency1 = 441.0; gFrequency2 = 201.0; // testTime=BeagleRT_createAuxiliaryTask(testTimeFunction, 80, "testTimeTask"); @@ -67,7 +68,8 @@ // Input and output are given from the audio hardware and the other // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. - +extern Pid* gClockSyncPid; +extern ClockSync* gClockSync; void render(BeagleRTContext *context, void *userData) { virtualClock.sync(context->audioFrames); @@ -101,12 +103,32 @@ float phaseInc=gFrequency1/44100.0*2*M_PI; // rt_printf("phaseInc: %f, phase: %f\n",phaseInc,phase); for(unsigned int n=0; n<context->audioFrames; n++){ - context->audioOut[n*2]=sinf(phase);//context->audioIn[n*2]; - phase+=200.0/44100.0*2*M_PI; + context->audioOut[n*2]=sinf(phase) > 0 ? 1 : -1; + context->audioOut[n*2+1]=sinf(phase) > 0 ? 1 : -1; +// context->audioOut[n*2]= context->audioIn[n*2]; +// context->audioOut[n*2+1]= context->audioIn[n*2+1]; + phase+=phaseInc; if(phase>=2*M_PI) phase-=2*M_PI; - context->audioOut[n*2+1]=rand()/(float)RAND_MAX;//context->audioIn[n*2]; +// context->audioOut[n*2+1]=rand()/(float)RAND_MAX;//context->audioIn[n*2]; } + gClockSyncPid->setProportionalGain(context->analogIn[0]*10); +// gClockSyncPid->setIntegralGain(context->analogIn[1]); + gClockSyncPid->setIntegralGain(0); +// gClockSyncPid->setDerivativeGain(context->analogIn[2]); + gClockSyncPid->setDerivativeGain(0); + gClockSyncPid->setGlobalGain(context->analogIn[3]*1/0.828); + for (int n = 0; n < context->analogFrames; n++){ + context->analogOut[n*context->analogChannels + 0] = (gClockSync->getOffset() )/ 100 + 0.5; + context->analogOut[n*context->analogChannels + 1] = (gAudioCodec->getAudioSamplingRate()-44100)/20 + 0.5; + } + static bool pastSwitch = false; + bool thisSwitch = context->analogIn[4]>0.5; + if(thisSwitch && pastSwitch == false){ + rt_printf("--------------reset offset\n"); + virtualClock.addOffset(gClockSync->getIirOffset()); + } + pastSwitch = thisSwitch; count++; /* // if((count&262143)==0){