element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Spring Clean!
  • Challenges & Projects
  • Project14
  • Spring Clean!
  • More
  • Cancel
Spring Clean!
Projects Under control! Finishing the bode plotter
  • News
  • Projects
  • Forum
  • Members
  • More
  • Cancel
  • New
Join Spring Clean! to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: strb
  • Date Created: 8 Jun 2025 2:34 PM Date Created
  • Views 178 views
  • Likes 11 likes
  • Comments 2 comments
  • bode plotter
  • spring cleaning
Related
Recommended

Under control! Finishing the bode plotter

strb
strb
8 Jun 2025

The quest to achieve frequency response measurements in my home lab began around one and half years ago, with this Rohm buck converter roadtest. After that, I made a followup trying to measure the loop response on that specific board but I got mixed results. With passive circuits (RC filters) it worked decently but it was kind of useless for measuring anything more complex.

Then, as usual, life went on and many other things happened. I changed jobs, bought an apartment and moved in with my lovely girlfriend. All of this was great but finding the time to work on hobby projects became a luxury so I had to put this goal on hold. However, that time has come again! The timing of this spring clean competition is perfect for giving me the push I need to finish this long-overdue project!

How I left things up

Last time I left this project only partially functional, but I had a great conversation with michaelkellett on how to improve my setup: moving the post processing to the pc, by acquiring many more periods and using dft to extract amplitude and phase information. This is exactly what I'm going to do now.

The measurement setup

The measurement setup remained unchanged from the previous attempt, and consists of a signal generator to stimulate the DUT, an isolation transformer, the scope to acquire input and out waveforms and a PC to coordinate the instruments and to elaborate the data.

image

This is the same setup, just with augmented reality Slight smile

image

The script

This is the main point of the project. I started with the old script and evolved it, fixing along the way some minor bugs I left last time to keep things more interesting Slight smile. The following flow chart illustrates what I have in mind.

image

To avoid navigating through a km long script to modify a couple parameters, I decided to leave most of the instruments setup on the instruments themself, relying on the script only for essential parameters (such as number of points per acquisition or signal amplitude). Once manual preparation is complete, the script can be launched and it will control the signal generator and the scope, adapting horizontal and vertical scale as required.

I decided to avoid real time graph plotting and opted for a simpler post processing once all the data has been gathered.

It's far from perfect, but after a few iterations I managed to produce something that works reasonably well (more on that later).

Fullscreen 2845.bode_fft r02 phase wrapper.txt Download
/*NOTE:
    
    IMPORTANT: needs scilab 6.0.x to run! does not work on newer versions
    
    Program to control in conjunction a scope and a function
    generator to create a bode plot.
    
    Needs visa toolbox, use atomsInstall("visa") to install it
    If the toolbox does not start automatically, you have to load it manually!
    
    Setup done by script set up section
    
    For "advanced" set up (as trigger noise reject ecc...) it must be done 
    directly on the scope, not inserted in this script
    
    IMPORTANT:
    This version of the program uses scilab to calculate the fft instead of 
    relying only on amplitude and phase measured by the scope
    
    Known ISSUES:
    
*/

xdel(winsid());//note: xdel will be deprecated in future versions
clear;
clc;

disp("Script started");

//----------------------SCRIPT SET UP PARAMETERS------------------------------

NaN = %nan;

//select between linear and log frequency sweep, plot will be affected as well
//choose one or the other
//sweep_type = "LIN";
sweep_type = "LOG";

//select between linear and log amplitude plot
//choose one or the other
//y_type = "LIN";
y_type = "LOG";

//start and stop frequency
f_start = 1000;
f_stop = 100000;

//number of points
sample_n = 20;

//delays (in milliseconds)
wait_meas_time = 4000;//default value, will be adjusted for every measure
meas_safety_factor = 2.5;
wait_set_time = 300;
wait_channel_vscale_setup = 2000;//allow for AC coupling stabilization

//max number of measure attempts for each frequency point
max_measure_attempts = 8;

//target number of periods to capture

//----------------SCOPE PARAMETERS
//scope address
scope_addr = "USB0::0x1AB1::0x04CE::DS1ZA211403170::INSTR";//My scope address

//scope channels
scope_in_ch = "1";//dut input signal
scope_out_ch = "2";//dut output signal
scope_unused_chA = "3";//unused channel
scope_unused_chB = "4";//unused channel

//measurement decision parameters
n_of_period = 50;//minimum number of periods to be acquired for one measure
v_up_th = 0.95;//threshold to increase vertical scale
v_down_th = 0.35;//threshold to decrease vertical scale

//scope vertical options
vscale_opt = [0.001;0.002;0.005;0.01;0.02;0.05;0.1;0.2;0.5;1;2;5];//option list. 5mV, 2mV and 1mV only for x1 probes!
vscale_opt_n = size(vscale_opt);//get vector size
actual_vscale_in_opt = 11;//index for the in channel actual option, start at 2V/div
actual_vscale_out_opt = 11;//index for the out channel actual option, start at 2V/div
vscale_div = 8;//number of divisions


//scope horizontal options
hscale_opt = [1e-6;2*1e-6;5*1e-6;1e-5;2*1e-5;5*1e-5;1e-4;2*1e-4;5*1e-4;0.001;0.002;0.005;0.01;0.02;0.05;0.1;0.2];//option list
hscale_opt_n = size(hscale_opt);//get vector size
actual_hscale_opt = hscale_opt_n(1,1);//index for the actual option
hscale_div = 12;//number of divisions

//scope memory depth
mem_depth = 6000;//std value for rigol scope using two channels, do not exceed 15625!!! this is due to ASCII double formatting

//----------------SIGGEN PARAMETERS
//function generator address
siggen_addr = "USB0::0xF4EC::0x1102::SDG2XFBX7R1988::INSTR";//My signal generator address

//siggen channel
siggen_out_ch = "C1";//output channel

//output voltage peak to peak
out_amplitude = 1;//in V, peak to peak, HiZ (by default, can be changed in the instrument)

//------------------------DATA MEMORY PREPARATION-----------------------------

f_vect = zeros(sample_n,1);//frequency vector
phase_in_vect = zeros(sample_n,1);//input phase data vector
phase_out_vect = zeros(sample_n,1);//input phase data vector
gain_vect = zeros(sample_n,1);//gain data vector
phase_vect = zeros(sample_n,1);//phase data vector

//choose frequency spacing
if sweep_type == "LIN" then
    f_vect = linspace(f_start,f_stop,sample_n);
else
    f_vect = logspace(log10(f_start),log10(f_stop),sample_n); 
end
f_vect = f_vect';//traspose the vector

//-------------------------CHECK INSTRUMENTS---------------------------------

[status,deviceAddr] = findAllInstruments();//use to find all instruments
[nrow,ncol] = size(deviceAddr);//get how many instruments are connected

//check for connected scope
flag = 1;

for i = 1:nrow
    if deviceAddr(i) == scope_addr then
        flag = 0;
    end
end

//if scope not found, launch an error message and abort code execution
if flag == 1 then
    disp("Scope not found, quitting script");
    abort;
end

//check for connected signal generator
flag = 1;

for i = 1:nrow
    if deviceAddr(i) == siggen_addr then
        flag = 0;
    end
end

//if siggen not found, launch an error message and abort code execution
if flag == 1 then
    disp("Signal generator not found, quitting script");
    abort;
end

disp("Instruments found");

//-------------------------CONNECT INSTRUMENTS----------------------------

[status,defaultRM] = viOpenDefaultRM();//open a session

[status,scopeID] = viOpen(defaultRM, scope_addr, viGetDefinition("VI_NULL"),viGetDefinition("VI_NULL"));//connect to scope
[status,siggenID] = viOpen(defaultRM, siggen_addr, viGetDefinition("VI_NULL"),viGetDefinition("VI_NULL"));//connect to scope

disp("Instruments connected");

//-------------------------SETUP INSTRUMENTS----------------------------

//----------setup scope "output" channel
//enable output channel
[status, count] = viWrite(scopeID,":CHANnel"+scope_out_ch+":DISPlay ON");
sleep(wait_set_time);

//set voltage range to default value
[status, count] = viWrite(scopeID,":CHANnel"+scope_out_ch+":SCALe "+string(vscale_opt(actual_vscale_out_opt,1)));
sleep(wait_set_time);

//----------setup scope "input" channel
//enable input channel
[status, count] = viWrite(scopeID,":CHANnel"+scope_in_ch+":DISPlay ON");
sleep(wait_set_time);

//set voltage range to default value
[status, count] = viWrite(scopeID,":CHANnel"+scope_in_ch+":SCALe "+string(vscale_opt(actual_vscale_in_opt,1)));
sleep(wait_set_time);

//----------disables unused channels
[status, count] = viWrite(scopeID,":CHANnel"+scope_unused_chA+":DISPlay OFF");
sleep(wait_set_time);
[status, count] = viWrite(scopeID,":CHANnel"+scope_unused_chB+":DISPlay OFF");
sleep(wait_set_time);

//----------set memory depth
[status, count] = viWrite(scopeID,":ACQuire:MDEPth "+string(mem_depth));
sleep(wait_set_time);

//---------- scope measure setup
//input Vpp
[status, count] = viWrite(scopeID,"MEASure:ITEM VPP,CHANnel"+scope_in_ch);
sleep(wait_set_time);

//output Vpp
[status, count] = viWrite(scopeID,"MEASure:ITEM VPP,CHANnel"+scope_out_ch);
sleep(wait_set_time);

//----------setup siggen
//set sinewave
[status, count] = viWrite(siggenID,siggen_out_ch+":BaSic_WaVe WVTP,SINE");
sleep(wait_set_time);

//set amplitude
[status, count] = viWrite(siggenID,siggen_out_ch+":BaSic_WaVe AMP,"+string(out_amplitude));
sleep(wait_set_time);

disp("Instruments ready");


//-------------------------START MEASURE----------------------------

//enable siggen out
[status, count] = viWrite(siggenID,siggen_out_ch+":OUTPut ON");
sleep(wait_set_time);

disp("Measure start, do not touch");

for i = 1:sample_n
    
    [status, count] = viWrite(scopeID,":RUN");//start acquisition
    sleep(wait_set_time);
    
    try_counter = 1;//count how many times a measure has been attempted
    
    //calculate appropriate horizontal scale
    flag_time = 1;
    for j = 1:hscale_opt_n(1,1)//check for all possible values
        if flag_time == 1 then //if not found yet execute
            if hscale_opt(j,1)*hscale_div > (n_of_period/f_vect(i,1)) then //if the scale is correct
                flag_time = 0;
                actual_hscale_opt = j;//save the option
            end 
        end
        
        if j == hscale_opt_n(1,1) && flag_time ==1 then
            actual_hscale_opt = j;//if timebase overflow, set maximum timescale
        end
    end
    
    //apply appropriate horizontal scale
    [status, count] = viWrite(scopeID,":TIMebase:MAIN:SCALe "+string(hscale_opt(actual_hscale_opt,1)));
    sleep(wait_set_time);
    
    //calculate measurement delay time
    wait_meas_time = hscale_opt(actual_hscale_opt,1)*hscale_div*1000*meas_safety_factor;//time in ms
    
    //set output frequency
    [status, count] = viWrite(siggenID,siggen_out_ch+":BaSic_WaVe FRQ,"+string(f_vect(i,1)));
    sleep(wait_set_time);
    
    //show measure status (not using mprintf)
    if i == 1 then
        disp("Step "+string(i)+" out of "+string(sample_n));
    else
        disp("");//to align removed lines
        clc(2);//remove lines
        disp("Step "+string(i)+" out of "+string(sample_n));
    end
    
    //measure and if it's not valid, repeat!
    flag = 1;
    while flag == 1
        
        if try_counter > 1 then//restart the acquisition on retry
            [status, count] = viWrite(scopeID,":RUN");//start acquisition
            sleep(wait_set_time);
        end
        
        sleep(wait_meas_time);
        [status, count] = viWrite(scopeID,":STOP");//stop acquisition
        sleep(wait_set_time);
        
        //---------- scope measures
        //input Vpp
        [status, count] = viWrite(scopeID,"MEASure:ITEM? VPP,CHANnel"+scope_in_ch);
        [status, bufferOut, count] = viRead(scopeID, 255);
        amplitude_in_temp = strtod(bufferOut);//save measured data
        
        if amplitude_in_temp == NaN then//if amplitude is NaN -> saturating, assign full scale value
            amplitude_in_temp = vscale_div*vscale_opt(actual_vscale_in_opt);
        end
        
        //output Vpp
        [status, count] = viWrite(scopeID,"MEASure:ITEM? VPP,CHANnel"+scope_out_ch);
        [status, bufferOut, count] = viRead(scopeID, 255);
        amplitude_out_temp = strtod(bufferOut);//save measured data
        
        if amplitude_out_temp == NaN then//if amplitude is NaN -> saturating, assign full scale value
            amplitude_out_temp = vscale_div*vscale_opt(actual_vscale_out_opt);
        end
        
        //--------------check for dynamic ranges (in and out channels) flags
        flag_in = 1;//used during in channel dynamic range check
        flag_out = 1;//used during out channel dynamic range check
        
        //--------------check for dynamic range on the output channel
        if (amplitude_out_temp > vscale_opt(actual_vscale_out_opt,1)*vscale_div*v_up_th) || (amplitude_out_temp < vscale_opt(actual_vscale_out_opt,1)*vscale_div*v_down_th)then 
            //if acquired data is saturating or too small on the actual vertical scale, calculate new scale
            flag_scale = 1
            
            //check for repeated measure when saturating
            if (actual_vscale_out_opt == vscale_opt_n(1,1)) && (amplitude_out_temp > vscale_opt(actual_vscale_out_opt,1)*vscale_div*v_up_th) then//I'm already at max scale and saturating?
                //if so, don't repeat measure
                flag_scale = 0;
                flag_out = 0;
            end
            
            //I'm already at min scale and going down?
            if (actual_vscale_out_opt == 1) && (amplitude_out_temp < vscale_opt(actual_vscale_out_opt,1)*vscale_div*v_down_th) then
                //if so, don't repeat measure
                flag_scale = 0;
                flag_out  = 0;
            end
            
            for j = 1:vscale_opt_n(1,1)//check for all possible values
                if flag_scale == 1 then //if not found yet execute
                    if vscale_opt(j,1)*vscale_div*v_up_th > amplitude_out_temp then //if the scale is correct
                        flag_scale = 0;
                        actual_vscale_out_opt = j;//save the option
                    end 
                    
                    if j == vscale_opt_n(1,1) then //full scale?
                        actual_vscale_out_opt = j;//save the option, to avoid full scale values to not set max scale
                    end
                end
            end
            
            //set output channel voltage range
            [status, count] = viWrite(scopeID,":CHANnel"+scope_out_ch+":SCALe "+string(vscale_opt(actual_vscale_out_opt,1)));
            sleep(wait_channel_vscale_setup);

            try_counter = try_counter+1;//increase by one the counter
            
        else
            flag_out = 0;//no problem on this channel
        end
        
        //--------------check for dynamic range on the input channel
        if (amplitude_in_temp > vscale_opt(actual_vscale_in_opt,1)*vscale_div*v_up_th) || (amplitude_in_temp < vscale_opt(actual_vscale_in_opt,1)*vscale_div*v_down_th)then 
            //if acquired data is saturating or too small on the actual vertical scale, calculate new scale
            flag_scale = 1
            
            //check for repeated measure when saturating
            if (actual_vscale_in_opt == vscale_opt_n(1,1)) && (amplitude_in_temp > vscale_opt(actual_vscale_in_opt,1)*vscale_div*v_up_th) then//I'm already at max scale and saturating?
                //if so, don't repeat measure
                flag_scale = 0;
                flag_in = 0;
            end
            
            //I'm already at min scale and going down?
            if (actual_vscale_in_opt == 1) && (amplitude_in_temp < vscale_opt(actual_vscale_in_opt,1)*vscale_div*v_down_th) then
                //if so, don't repeat measure
                flag_scale = 0;
                flag_in  = 0;
            end
                        
            for j = 1:vscale_opt_n(1,1)//check for all possible values
                if flag_scale == 1 then //if not found yet execute
                    if vscale_opt(j,1)*vscale_div*v_up_th > amplitude_in_temp then //if the scale is correct
                        flag_scale = 0;
                        actual_vscale_in_opt = j;//save the option
                    end
                    
                    if j == vscale_opt_n(1,1) then //full scale?
                        actual_vscale_in_opt = j;//save the option, to avoid full scale values to not set max scale
                    end
                end
            end
            
            //set input channel voltage range
            [status, count] = viWrite(scopeID,":CHANnel"+scope_in_ch+":SCALe "+string(vscale_opt(actual_vscale_in_opt,1)));
            sleep(wait_channel_vscale_setup);

            try_counter = try_counter+1;//increase by one the counter
            
        else
            flag_in = 0;//no problem on this channel
        end
        
        if (flag_in == 0) && (flag_out == 0) then//both channels are ok?
            flag = 0;//if so, exit repeat loop for this measure
        end
        
        if try_counter > max_measure_attempts then//if reached max number of retry, go on (to avoid infinite loop)
                flag = 0;
        end
        
    end//while repeated measure end
    
    //--------------acquire waveforms
    //input channel
    [status, count] = viWrite(scopeID,"WAVeform:SOURce CHANnel"+scope_in_ch);//set input channel
    [status, count] = viWrite(scopeID,"WAVeform:MODE RAW");//read waveform from internal memory
    [status, count] = viWrite(scopeID,"WAVeform:FORMat ASCii");//data as double
    [status, count] = viWrite(scopeID,"WAVeform:STARt 1");//read all points: from first to last
    [status, count] = viWrite(scopeID,"WAVeform:STOP "+string(mem_depth));
    [status, count] = viWrite(scopeID,"WAVeform:DATA?");//read the data
    [status, bufferOut, count] = viRead(scopeID, mem_depth*14);//12+1(separator) ascii codes for each number + 1 as margin... 
    
    [ind, which] = strindex(bufferOut, ",");//find separators
    ind = ind';//rotate vector, just to make my life easier
    data_in = zeros(mem_depth-1,1);
    //extract all data points, remove first because first number has 11 added chars that are constant... It's just easier to remove based on separator
    for j = 2:mem_depth-1
        minindex = ind(j-1,1)+1;
        maxindex = ind(j,1)-1;
        data_in(j-1,1) = strtod(part(bufferOut,[minindex:maxindex]));
    end
    
    //output channel
    [status, count] = viWrite(scopeID,"WAVeform:SOURce CHANnel"+scope_out_ch);//set input channel
    [status, count] = viWrite(scopeID,"WAVeform:MODE RAW");//read waveform from internal memory
    [status, count] = viWrite(scopeID,"WAVeform:FORMat ASCii");//data as double
    [status, count] = viWrite(scopeID,"WAVeform:STARt 1");//read all points: from first to last
    [status, count] = viWrite(scopeID,"WAVeform:STOP "+string(mem_depth));
    [status, count] = viWrite(scopeID,"WAVeform:DATA?");//read the data
    [status, bufferOut, count] = viRead(scopeID, mem_depth*14);//12+1(separator) ascii codes for each number + 1 as margin... 
    
    [ind, which] = strindex(bufferOut, ",");//find separators
    ind = ind';//rotate vector, just to make my life easier
    data_out = zeros(mem_depth-1,1);
    //extract all data points, remove first because first number has 11 added chars that are constant... It's just easier to remove based on separator
    for j = 2:mem_depth-1
        minindex = ind(j-1,1)+1;
        maxindex = ind(j,1)-1;
        data_out(j-1,1) = strtod(part(bufferOut,[minindex:maxindex]));
    end
    
    
    //--------------calculate fft, gain and phase
    //calculate fft
    fft_in = fft(data_in);
    fft_out = fft(data_out);
    
    //find theoretical index
    center_index = ceil(hscale_div*hscale_opt(actual_hscale_opt)*f_vect(i,1));
    
    //find magnitude peak around the center index, it's the same for both in and out
    offset = 3;
    [Amax_in iAmax] = max(abs(fft_in(center_index-offset:center_index+offset)));
    iAmax = iAmax + center_index - 1 - offset;//the actual index, -1 because scilab index system starts from 1 and not from 0
    //find out max
    Amax_out = max(abs(fft_out(iAmax)));
    
    //get phases
    p_in = atan(imag(fft_in(iAmax)),real(fft_in(iAmax)));
    p_out = atan(imag(fft_out(iAmax)),real(fft_out(iAmax)));
    
    //calculate gain and phase
    gain_vect(i,1) = Amax_out / Amax_in;
    phase_vect(i,1) = (p_out - p_in)*180/%pi;//phase in degree
    
    
end//measurement loop end

//disable siggen out
[status, count] = viWrite(siggenID,siggen_out_ch+":OUTPut OFF");
sleep(wait_set_time);

disp("Measure completed");

//-----------------------CLOSE CONNECTIONS------------------------------------
viClose(scopeID);
viClose(siggenID);
viClose(defaultRM);


//----------------------------ELABORATE DATA------------------------------------

//--------------calculate gain (dB scale)
if y_type == "LOG" then
    for i=1:sample_n
        gain_vect(i,1) = 20*log10(gain_vect(i,1));
    end
end

//--------------"wrap" phase into +- 180°
for i=1:sample_n
    
    while phase_vect(i,1)>180 || phase_vect(i,1)<-180
        if phase_vect(i,1)>180 then
            phase_vect(i,1) = phase_vect(i,1)-360;
        end
        if phase_vect(i,1)<-180 then
            phase_vect(i,1) = phase_vect(i,1)+360;
        end
    end
    
end

//--------------plot
f = figure(0);
f.background = 8;
//plot magnitude
subplot(2,1,1);
if sweep_type == "LIN" then
    plot2d(f_vect,gain_vect);
else
    plot2d("ln",f_vect,gain_vect);
end
if y_type == "LIN" then
    ylabel("Magnitude []");
else
    ylabel("Magnitude [dB]");
end
xlabel("Frequency [Hz]");
xgrid(1);
//plot phase
subplot(2,1,2);
if sweep_type == "LIN" then
    plot2d(f_vect,phase_vect);
else
    plot2d("ln",f_vect,phase_vect);
end
ylabel("Phase [°]");
xlabel("Frequency [Hz]");
xgrid(1);

Comparison: old vs new approach

Overall, I'm pleased with the outcome. It's easier to explain the improvement obtained with a couple of images.

imageimage

Comparison measuring a RC filter

image

image

Comparison measuring loop stability of a buck converter

As it stands, this setup allows to get a complete acquisition with 40 points (two decades, 20 points per decade) in just under six minutes. It's not fast, but it's fast enough for all of my purposes.

imageAccelerated view during a sweep

The project within the project: fixing scope probes

During the script development, I spent quite a bit of time searching for the cause of inconsistent results and lack of repeatability. After some time, unable to find the corporate inside my code, I decided to check my scope probes, finding a surprisingly inconsinstent contact resistance when set to 1x (but it was also visible in 10x). The correct resistance for my probes (tip to BNC) is around 200Ω, but it was jumping around up to hundreds of kΩ at times.

Luckily, the probe tip/cable are intact and the problem was found in the hook tip, which was making bad contact with the rest of the probe. A cleanup with some contact cleaner somewhat improved the situation, but the final solution was mechanical: dismantling the hook tip and adding some insulation tape around the contact point to improve its stability.

                        imageimage

Probe tip dismantled and the "repair"

It's kind of funny I was able to bring to conclusion with success this project thanks to a small piece of tape Slight smile. And thanks to the  e14 community that pushed me to start on again on this topic with this great challenge!

  • Sign in to reply
  • strb
    strb 4 days ago in reply to DAB

    Thank you Slight smile

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB 8 days ago

    Nice project.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube