Tutorial : Saving RF level monitoring to a file for Matlab Processing

Activity_over_night_zoom

Introduction

In this tutorial we showed how to measure activity on 20M and report the values as a visual gauge to remote clients.

We will now show how to save the measurements to a CSV file and process the results with Matlab® or  the open-source equivalent Octave to see the trends and produce nice plots like this one:

Activity_over_night_zoom

Step 1 : updating the script

We refer to the acquisition script oncapture_done.js presented in this tutorial.

Change it as follows:

// this function transforms a string to a buffer object and adds line feed
function txtLine(str) {
  var i ;
  var buf = new ArrayBuffer(str.length+1); // bytes for each char + new line
  var bufView = new Int8Array(buf);
  for(i=0, strLen=str.length; i<strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  // add new line 
  bufView[i++] = 10 ;
  
  return buf;
}

// this function is called automatically when the capture is done
// parameter <id> is the internal unique Id of the capture that
// was just performed
function dataReady(id ) {
	//	
	var frequency = CaptureEngine.getCenterFrequency(id);		
	var power = CaptureEngine.getRMS( id );
	var BW = CaptureEngine.getCaptureBandwidth( id ); 
	
	//print('RMS power at F= ' + frequency + ' MHz , BW='+BW+' p is =' + power );
	// publish an indicator for this value
	CloudSDR.sendIndicatorValue( '20Meters', 'dBm', power ); 
	
	// save to file
	var newCSVLine = now() + ";" + frequency + ";" + BW + ";" + power ;
	IO.fappend( '20Meters.txt', txtLine(newCSVLine) );
	
	// reschedule another capture 
	CaptureEngine.proceedCaptures( 10000 );
}

We basically call the SDRNode function IO.fappend() function that appends a raw buffer of bytes to a file (created if not exiting). As we are creating data from a simple string, the function txtLine() just converts to a Buffer() object.

Now we have a file on disk where the measurements are stored. Here are some lines of the file :

16/09/2016-23:57:49;14.02;20000;-68.55413818359375
16/09/2016-23:58:05;14.02;20000;-68.47654724121094
16/09/2016-23:58:22;14.02;20000;-68.5374526977539
16/09/2016-23:58:38;14.02;20000;-68.48772430419922
16/09/2016-23:58:55;14.02;20000;-68.84260559082031
16/09/2016-23:59:11;14.02;20000;-68.52120971679688
16/09/2016-23:59:28;14.02;20000;-68.49142456054688
16/09/2016-23:59:44;14.02;20000;-68.4538345336914

We can now process this file for graphing.

Step 2 : import data and process

We use the ‘import data’ assistant in Matlab to generate the .m file (be careful to properly specify the date format : ‘dd/MM/yyyy-HH:mm:ss’ ), and we save the generated script to import_csv_rms.m for reuse.

The processing script becomes quite simple

clear all;
[date_mesure,vrms] = import_csv_rms('20Meters.txt');
figure;
plot( date_mesure, vrms );
xlabel 'Date';
ylabel 'RMS from RTLSDR';
grid on;

Here is what we get :

Activity_over_night_raw

Measurements are quite noisy, that is logical : we tuned just in the middle of the CW band and take 1s of signal. Of course if one strong station is in QSO during the capture, the power will be important… To smooth a bit the chart, we will add a 5 min moving average.

Remember that the measurements were performed every 15 seconds and there are 20 measurements over 5 minutes. So will average over 20 values and replot, that’s basically what the following script is doing

clear all;
[date_mesure,vrms] = import_csv_rms('20Meters.txt');
interval = 15000 ; 
mesures_per_5_minutes = 5*60*1000/interval;
coeffs = ones(1, mesures_per_5_minutes)/mesures_per_5_minutes;

avg = filter(coeffs, 1, vrms);
L = length(coeffs);
plot( date_mesure(L:end), [vrms(L:end) avg(L:end)] );
title 'Activity measurement with Cloud-SDR';
legend('RMS power on 20m','5 minute Average','location','best')
xlabel 'Date';
ylabel 'RMS from RTLSDR';
grid on;

Giving us:

Activity_over_night

Zoomed :

Activity_over_night_zoom