component sinesweep "Generate a linear or logarithmic sine sweep"; pin in float amplitude=0.0 "Amplitude of the output sine"; pin out float output "sine sweep output"; pin out float current_frequency "Current frequency"; pin io bit start "Set to 1 to start the sweep. The component will reset this pin to 0 when done"; param rw float start_freq=10.0 "Start frequency"; param rw float end_freq=500.0 "End frequency"; param rw float sweep_duration=20.0 "Duration of the sweep in seconds"; param rw bit log_sweep=1 "TRUE: use a logarithmic sweep. FALSE: use a linear sweep"; variable float angle; variable float curr_freq; variable float startf; variable float endf; variable int prev_start=0; variable int busy=0; function _; description """ Linear/logarithmic sine sweep generator, can be used as an excitation signal to find mechanical system resonances. """; license "GPL"; // indicates GPL v2 or later author "DaBit (dabitATicecoldcomputingDOTcom)"; ;; #include #define PI2 6.283185307179586476925286766559 // http://www.codeproject.com/Tips/311714/Natural-Logarithms-and-Exponent double Exp(double Exponent) { double X, P, Frac, I, L; int limitctr=0; X = Exponent; Frac = X; P = (1.0 + X); I = 1.0; do { I++; Frac *= (X / I); L = P; P += Frac; if (limitctr++ > 30) break; }while(L != P); return P; } double Ln(double Power) { double N, P, L, R, A, E; int limitctr=0; E = 2.71828182845905; P = Power; N = 0.0; // This speeds up the convergence by calculating the integral while(P >= E) { P /= E; N++; } N += (P / E); P = Power; do { A = N; L = (P / (Exp(N - 1.0))); R = ((N - 1.0) * E); N = ((L + R) / E); if (limitctr++ > 30) break; } while(N != A); return N; } double Log10 (double Power) { return Ln(Power) / 2.3025850929940456840179914546844; } FUNCTION(_) { if (prev_start == 0 && start) { start = 1; prev_start = 1; busy=1; angle = 0.0; if (log_sweep) { startf = Log10(start_freq); endf = Log10(end_freq); } else { startf = start_freq; endf = end_freq; } curr_freq = startf; } else { if (!busy) { prev_start=0; output = 0.0; current_frequency = 0.0; } } if (busy) { curr_freq += (((endf-startf)/sweep_duration)*fperiod); if (log_sweep) current_frequency = pow(10.0, curr_freq); else current_frequency = curr_freq; if (curr_freq > endf) { busy=0; start=0; prev_start=0; } else { angle += PI2*current_frequency*fperiod; output = (amplitude*sin(angle)); } } }