Showing posts with label Perl. Show all posts
Showing posts with label Perl. Show all posts

Sunday, May 20, 2012

Measurement Automation: How to Save Screens of 86100C DCA-J, SDA830 and E4440A/E4445A to Local PC Through GPIB

Picture from agilent.com
Measurement automation can save you a lot of pain in many cases on top of the advantages of higher productivity and greater accuracy in case of performing repeated day-to-day test and measurement tasks. Several examples using simple GPIB commands to capture screen pictures from different instruments to a local PC are given in this article with the complete workable VEE codes shown how to implement. They are easily portable with any programming languages such as Matlab and C or scripts like Perl and Python. If you are interested in how to:

  • Save screen image from Agilent DCA-J 86100C to local PC as GIF files.
  • Save screen image from LeCroy SDA830ZI-A to local PC as PNG files.
  • Save screen image from Agilent E4440A/E4445A spectrum analyzer to local PC as GIF files.
  • Dump raw spectrum data from Agilent E4440A/E4445A spectrum analyzer to local PC as text files.
  • Dump raw phase noise log plot data from Agilent E4440A/E4445A spectrum analyzer to local PC as text files.

Please read on here ...


Thursday, January 6, 2011

Perl "for-loop" floating number issue and its solution

Today, a logic error in piece of my newly created Perl code caught my attention. Since similar codes worked well before,  I isolated them for a closer examination. It turned out to be a floating variable comparison issue that may give you unexpected results when used in a for-loop. Below is the sample codes for the debug and illustration purpose.

    print "\n1st for-loop: start -> -0.05; stop -> 0.15; step -> 0.05 ...\n";
    my $loop_cn=0;
    my $tmp_start=-0.05;
    my $tmp_stop=0.15;
    my $tmp_step=0.05;
    for(my $tmp=$tmp_start; $tmp<=$tmp_stop; $tmp+=$tmp_step)
    {
      $loop_cn++;
      print "loop $loop_cn meets condition $tmp <= $tmp_stop with a step of $tmp_step\n";
    }

    print "\n2nd for-loop: start -> -0.5; stop -> 1.5; step -> 0.5 ...\n";
    my $loop_cn=0;
    my $tmp_start=-0.5;
    my $tmp_stop=1.5;
    my $tmp_step=0.5;
    for(my $tmp=$tmp_start; $tmp<=$tmp_stop; $tmp+=$tmp_step)
    {
      $loop_cn++;
      print "loop $loop_cn meets condition $tmp <= $tmp_stop with a step of $tmp_step\n";
    }

    print "\n3rd for-loop: start -> -0.06; stop -> 0.1; step -> 0.02 ...\n";
    my $loop_cn=0;
    my $tmp_start=-0.06;
    my $tmp_stop=0.1;
    my $tmp_step=0.02;
    for(my $tmp=$tmp_start; $tmp<=$tmp_stop; $tmp+=$tmp_step)
    {
      $loop_cn++;
      print "loop $loop_cn meets condition $tmp <= $tmp_stop with a step of $tmp_step\n";
     # print sprintf("%.${10}g\n", $tmp);
     # print "\n";
    }

The execution results are shown as below:

1st for-loop: start -> -0.05; stop -> 0.15; step -> 0.05 ...
loop 1 meets condition -0.05 <= 0.15 with a step of 0.05
loop 2 meets condition 0 <= 0.15 with a step of 0.05
loop 3 meets condition 0.05 <= 0.15 with a step of 0.05
loop 4 meets condition 0.1 <= 0.15 with a step of 0.05

2nd for-loop: start -> -0.5; stop -> 1.5; step -> 0.5 ...
loop 1 meets condition -0.5 <= 1.5 with a step of 0.5
loop 2 meets condition 0 <= 1.5 with a step of 0.5
loop 3 meets condition 0.5 <= 1.5 with a step of 0.5
loop 4 meets condition 1 <= 1.5 with a step of 0.5
loop 5 meets condition 1.5 <= 1.5 with a step of 0.5

3rd for-loop: start -> -0.06; stop -> 0.1; step -> 0.02 ...
loop 1 meets condition -0.06 <= 0.1 with a step of 0.02
loop 2 meets condition -0.04 <= 0.1 with a step of 0.02
loop 3 meets condition -0.02 <= 0.1 with a step of 0.02
loop 4 meets condition 6.93889390390723e-018 <= 0.1 with a step of 0.02
loop 5 meets condition 0.02 <= 0.1 with a step of 0.02
loop 6 meets condition 0.04 <= 0.1 with a step of 0.02
loop 7 meets condition 0.06 <= 0.1 with a step of 0.02
loop 8 meets condition 0.08 <= 0.1 with a step of 0.02

It is very clear that the 1st and the 3rd loop is not working as expected while the 2nd loop works fine. Judged by the output of the 3rd for-loop “loop 4....” where the expected “0” is represented by a small number at the order of 1E-18, we know that the problem is caused by the inexact representation of the floating numbers due to limited machine precision. Thus, the attempt of using string comparison “le” in place of “<=” will not work either in this case.

Inspired by the solutions from:  http://docstore.mik.ua/orelly/perl4/cook/ch02_04.htm , this issue can be addressed following:
1. Create a sub-routine for numerical comparison named as less_eq
sub less_eq
{
    my ($A, $B, $dp) = @_;
    return sprintf("%.${dp}g", $A) <= sprintf("%.${dp}g", $B);
}
2. Replace the line $tmp<=$tmp_stop in the original code with less_eq($tmp,$tmp_stop,2)

The revised codes will give you the expected results for all cases as shown below:
 
1st for-loop: start -> -0.05; stop -> 0.15; step -> 0.05 ...
loop 1 meets condition -0.05 <= 0.15 with a step of 0.05
loop 2 meets condition 0 <= 0.15 with a step of 0.05
loop 3 meets condition 0.05 <= 0.15 with a step of 0.05
loop 4 meets condition 0.1 <= 0.15 with a step of 0.05
loop 5 meets condition 0.15 <= 0.15 with a step of 0.05
2nd for-loop: start -> -0.5; stop -> 1.5; step -> 0.5 ...
loop 1 meets condition -0.5 <= 1.5 with a step of 0.5
loop 2 meets condition 0 <= 1.5 with a step of 0.5
loop 3 meets condition 0.5 <= 1.5 with a step of 0.5
loop 4 meets condition 1 <= 1.5 with a step of 0.5
loop 5 meets condition 1.5 <= 1.5 with a step of 0.5
3rd for-loop: start -> -0.06; stop -> 0.1; step -> 0.02 ...
loop 1 meets condition -0.06 <= 0.1 with a step of 0.02
loop 2 meets condition -0.04 <= 0.1 with a step of 0.02
loop 3 meets condition -0.02 <= 0.1 with a step of 0.02
loop 4 meets condition 6.93889390390723e-018 <= 0.1 with a step of 0.02
loop 5 meets condition 0.02 <= 0.1 with a step of 0.02
loop 6 meets condition 0.04 <= 0.1 with a step of 0.02
loop 7 meets condition 0.06 <= 0.1 with a step of 0.02
loop 8 meets condition 0.08 <= 0.1 with a step of 0.02
loop 9 meets condition 0.1 <= 0.1 with a step of 0.02