cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
The Discovery Summit 2025 Call for Content is open! Submit an abstract today to present at our premier analytics conference.
Choose Language Hide Translation Bar
View Original Published Thread

Craige_Hales
Super User
New Project Data Points

The clock project finished up a year ago. This is the start of a new project, which might turn into some sort of power monitor.

 

Here's a picture of two waveforms on an old-school scope from ~1990.

Sine wave is volts, pulse is ampsSine wave is volts, pulse is amps

 

If the units and scales are right, the integration of volts * amps is the real power being used by the load. I did that, eye-balling it, and got 47 watts. That was a little disappointing because this is the device under test.

 

30W CFL bulb30W CFL bulb

 

If that was an incandescent bulb, the volts and amps would be very similar waveforms, neatly aligned. But most of today's electronics demand power during a fraction of a voltage cycle.

View more...
My notes

current: peak is 85 mv on 30 ohms. e/r=i, .085/30 = .0028 amp
x500 -> 1.4Amp
That max current is when Volts = 4, current ramps to zero as volts ramps to 6.
The volts are actually (xformer ratio 230/8.6 no load) x26.75, so 4*26.75 = 107V to 6*26.75 = 160.5V 
the ramp is about 1/4 of the cycle.
treat the sine wave as a linear ramp too.
begin of ramp is .0028A * 107V
end of ramp is 0.0A * 160V
average is 1.4A * 133.5V = 186.9 volt-amps (watts)
but only 25% duty cycle
187/4 = 47W​
All of those numbers are estimates, off the screen, or off of data sheets. Some will change, below.

Here's the JSL I used to digitize some points. The data arrays were not filled in initially; those are my answers. This is single-use code; I took a short cut and made the first and last point have special meanings, further below.

View more...
img = New Image( "z:/scope.jpg" );
img << rotate( 1 );
{nx, ny} = img << size;
New Window( "", gb = Graph Box( framesize( 900, 600 ) ) );
volts=[ 24.6814218645205 25, 39.4366197183099 58.0851063829787, 42.186452045607
        65.531914893617, 44.1985244802146 69.3617021276596, 46.2776659959759
        72.6595744680851, 48.692152917505 73.2978723404255, 51.5090543259557
        72.6595744680851, 56.8075117370892 61.3829787234043, 74.6478873239437
        25.8510638297872];
amps=[  42.713423397528 50.5777501131734, 43.1254191817572 62.5531914893617,
        43.7865286959854 59.4881167949298, 45.0384848775191 58.3055681303757,
        45.8433138513621 55.4454504300589, 46.8908690236658 53.6853779990946,
        48.4238765928907 51.1827750113173, 50.1229599821149 50.7702580353101,
        51.7102615694165 50];
gb[framebox(1)]<<addgraphicsscript(
    handle(volts[1,1],volts[1,2],volts[1,1]=x;volts[1,2]=y);
    handle(volts[2,1],volts[2,2],volts[2,1]=x;volts[2,2]=y);
    handle(volts[3,1],volts[3,2],volts[3,1]=x;volts[3,2]=y);
    handle(volts[4,1],volts[4,2],volts[4,1]=x;volts[4,2]=y);
    handle(volts[5,1],volts[5,2],volts[5,1]=x;volts[5,2]=y);
    handle(volts[6,1],volts[6,2],volts[6,1]=x;volts[6,2]=y);
    handle(volts[7,1],volts[7,2],volts[7,1]=x;volts[7,2]=y);
    handle(volts[8,1],volts[8,2],volts[8,1]=x;volts[8,2]=y);
    handle(volts[9,1],volts[9,2],volts[9,1]=x;volts[9,2]=y);

    handle(amps[1,1],amps[1,2],amps[1,1]=x;amps[1,2]=y);
    handle(amps[2,1],amps[2,2],amps[2,1]=x;amps[2,2]=y);
    handle(amps[3,1],amps[3,2],amps[3,1]=x;amps[3,2]=y);
    handle(amps[4,1],amps[4,2],amps[4,1]=x;amps[4,2]=y);
    handle(amps[5,1],amps[5,2],amps[5,1]=x;amps[5,2]=y);
    handle(amps[6,1],amps[6,2],amps[6,1]=x;amps[6,2]=y);
    handle(amps[7,1],amps[7,2],amps[7,1]=x;amps[7,2]=y);
    handle(amps[8,1],amps[8,2],amps[8,1]=x;amps[8,2]=y);
    handle(amps[9,1],amps[9,2],amps[9,1]=x;amps[9,2]=y);
);

gb[framebox( 1 )] << addimage( image( img ), bounds( top( 90 ), Left( 10 ), bottom( 10 ), Right( 90 ) ) );
imgSeg = gb[framebox( 1 )] << FindSeg( PictSeg( 1 ) );
imgSeg << lock( 1 );

That one degree rotation makes the image x-y line up with the screen.

Scope traces as image in a JMP graph. The tiny black square boxes on the traces are the handles.Scope traces as image in a JMP graph. The tiny black square boxes on the traces are the handles.

After dragging the points into place, with the first and last voltage points defining a full cycle and the first and last current points defining the length of the pulse, I used this.

View more...

vmax = Max( volts[0, 2] ); // sine top
vmin = Min( volts[0, 2] ); // sine bottom
vrange = vmax - vmin; // sine range
amax = Max( amps[0, 2] ); // similar for pulse
amin = Min( amps[0, 2] );
arange = amax - amin;
minx = Min( volts[0, 1] ); // length of sine cycle
maxx = Max( volts[0, 1] ); // because point 1 and 9 at begin and end
pulselength = amps[9, 1] - amps[1, 1]; // length of 1 of 2 pulses
pulseduty = 2 * pulselength / (maxx - minx); // 2 pulses per cycle
dt = pulselength / 16384; // small dt improves answer
n = 0; // count the dt intervals
sum = 0;
For( t = amps[1, 1], t < amps[9, 1], t += dt, // step thru the pulse
    y = Interpolate( t, volts[0, 1], volts[0, 2] ); // get the volts
    v = 125 * 1.414 * (2 * (y - vmin) / vrange - 1); // map the volts
    y = Interpolate( t, amps[0, 1], amps[0, 2] ); // get the amps
    a = 1.4 * ((y - amin) / arange); // map the amps
    sum += a * v; // watts for this dt
    n += 1;
);
sum = sum / n;
sum = sum * pulseduty;
Show( sum );

to get

sum = 25.8513297218601;

 

It took a bit of rethinking; rather than use the transformer's poorly defined turns ratio and the scope's ancient calibration, I assumed my house voltage is 125V rms and used the 1.414 factor to get the peak-to-peak voltage the sine wave should match. That seems close enough. Now to make the ESP32 digitize the points directly...

 

Comments
Craige_Hales
Super User

The version 0 boards arrived just before the end of the year and have served their purpose. I'm expecting the version 1 boards tomorrow. Here's the version 0 board showing the voltage sine wave on a 240x320 2.8 inch display and an extra board. The bottle cap is for scale; look at the tiny capacitor in the yellow circle. The pcb vendor mounts that; I'm pretty sure I can't.

The display is mounted to the red card, which plugs in to a connector mounted to the vertical row of holes at bottom left-center.The display is mounted to the red card, which plugs in to a connector mounted to the vertical row of holes at bottom left-center.

Testing the wifi connection while waiting for the version 1 boards suggests 40K to 50K bytes per second is a sustainable data rate with everything else this computer needs to do. I want to look at both the voltage and current channels, so about 20KB/sec for each digitized wave forms. At some point I'll want to use an FFT on the data, and I started thinking about buffer sizes. FFTs really like power of 2 sizes. How much? Here's some test code:

dt = New Table( "Untitled", "invisible", New Column( "size" ), New Column( "time" ) );

dt << New Column( "factors",
	character,
	formula(
		primes = [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113
		127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257
		263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409
		419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571
		577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733
		739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907
		911 919 929 937 941 947 953 967 971 977 983 991 997 1009];
		start = size;
		ip = 1;
		q = primes[ip];
		result = "";
		While( start > 1,
			If( Mod( start, q ) == 0,
				result = result || Char( q ) || ",";
				start = start / q;//
			, //
				ip += 1;
				q = primes[ip];
				If( q * q > size, Break() );
			)
		);
		If( start > 1,
			result = result || Char( start )
		);
		result;
	)
);

For( i = 2, i <= 2 ^ 19, i += 1,
	x = 0;
	x = J( i, 1, Random Uniform() );
	start = HP Time();
	FFT( {x} );
	end = HP Time();
	dt << addrows( 1 );
	dt:size[N Rows( dt )] = i;
	dt:time[N Rows( dt )] = (end - start) / 1e6;
	If( i == 10,
		dt << Graph Builder(
			Size( 1709, 424 ),
			Show Control Panel( 0 ),
			Variables( X( :size ), Y( :time ) ),
			Elements( Points( X, Y, Legend( 5 ) ) ),
			SendToReport(
				Dispatch(
					{},
					"Graph Builder",
					FrameBox,
					{Marker Size( 0 ), Marker Drawing Mode( "Normal" )}
				)
			)
		);
		Wait( .1 );
	);
	If( Mod( i, 100 ) == 0,
		Wait( 0 )
	);
);

The table looks like this:

2 is great,3 and 5 nice, maybe 7.2 is great,3 and 5 nice, maybe 7.

It makes a pretty graph:

The fast buffer sizes, near the bottom, don't have large factors.The fast buffer sizes, near the bottom, don't have large factors.

What's in that odd stack of points around 9500? Select, subset, take a look...

Bigger factorsBigger factors

 

Looks like JMP will be able to make a real time dashboard if I use a 1024 or 2048 sample buffer.

Very fast.Very fast.

Even at 60 times a second, it is under 1%. I may run the FFT on the esp32. Then, instead of sending complete waveforms, maybe just send the top N frequency bins and amplitudes. Bunch of tradeoffs to consider.

 

Craige_Hales
Super User

Plugging along. The ESP32 is streaming FFT frequency domain samples to a JMP graph. 60Hz is, by far, the dominant frequency, followed by the first few odd harmonics.

 

Craige_Hales
Super User

Still going. Freshly calibrated using a 160Ω dummy load, this is a nominal 13 watt CFL. The ESP32 is using wifi to create the graphs and meters in a web browser.

ThirteenWattCLF.mp4
Video Player is loading.
Current Time 0:00
Duration 0:19
Loaded: 50.51%
Stream Type LIVE
Remaining Time 0:19
 
1x
    • Chapters
    • descriptions off, selected
    • captions off, selected
    • default, selected
    (view in My Videos)

    the wifi signal strength transmitted by the ESP32 adds noise to the digitized voltage. With it turned down like this, the sine curve looks pretty smooth. The FFT graph is overlayed...that's not the Y axis, it is the 60Hz bin for the FFT. This FFT has a linear Y axis scale.