Now to the software:
Active programs running within Windows XP Pro for live capture and web
upload:
2 running versions of PCRPro1k (or other control software such as
TalkPCR - to control 2 x PCR 1000s)
Spectrum Lab v 2.5 (1st copy - live page)
Spectrum Lab v 2.5 (2nd copy - 1 hour plots)
Save2FTP (freeware automated FTP uploading)
Additional software :
MS Frontpage 2000 (web page editing)
FTP Voyager (manual file uploading)
Paint Shop Pro v 6 (image editing)
Windows Task Scheduler (automates various tasks)
Batchrun v 4.1 (automated file copying and archiving)
Windows Volume Control (input level control)
Quickmix (volume reset)
Software Details:
The two copies of Spectrum Lab are running (from the same .exe in the
same folder - the settings files are separate). The following is an image of the
Components (Circuits) window for them both. The left and right inputs
first meet the "black boxes" (?) which have had the noise
blankers activated. They then pass through with no further processing to
points L4 and R4. The signals then cross over using the mixing
amplifiers so that the Left input appears at R5 and the right input
appears at L5. This is so that I can display the higher frequency in the
top most part of the FFT trace, and the lower frequency in the bottom
part.

The
gains on the buffer outputs prior to L5 and R5 have been tweaked to balance the
channel levels. Levels are also corrected by using the volume controls
on the receivers, and the line-in and master record level controls in the
Windows Volume Control application.
The fast live plot uses the following display options settings.
NB: Not all sound cards support 48 or 96 kHz sampling.
UPDATE Jan 2005: A sample rate of 11025 Hz and FFT input size
16384 is fine for SSB 3kHz bandwidth.
Audio I/O:

FFT:

Spectrum:

Display settings:
Waterfall colour: Sunrise.pal
Contrast: approx 60%
Brightness: approx 50% (depends on input sound level)
Capture settings [modify to reflect your directory paths]:
Periodic capture string: capture("<path>latest.jpg")
Capture period 00:00 to 23:59, interval 1 minute.
SPECTRUM LAB PROGRAMMING
Spectrum Lab is a very sophisticated and capable piece of software. It
can be programmed in almost any way imaginable to assist in signal
analysis. Below are some details of what I've learnt during this web
page project. Please also read the SpecLab
help files in conjunction with these notes. I'm only covering the
functions I've used for my application of meteor counting. There are
many other applications which are not covered here.
Overview
Interpreter commands and functions can be run from almost anywhere. The
favourite places are in "Periodic Actions", "Scheduled
Actions" and "Conditional Actions". Here's a quick
overview of what these actions do.
Periodic Actions
Commands or functions appearing here will be carried out between the
times and at the period set, if the function is enabled. Many commands
or functions can be listed.
Scheduled Actions
Up to 48 times can be specified for actions to occur.
Conditional Actions
The "Conditional Actions" tab allows for 50 lines of
IF...THEN... programming. Each line is scanned every 200ms (5 times a
second). If a condition in the left column is true, then the commands or
functions in the right column are carried out. Tools available include
20 timers, which can be triggered in various ways to either loop in an
endless cycle, start on command and then expire, or start on command and
expire, but be commanded to restart before expiring if needed.
Here's the "quick" run down of what I do within SpecLab (this
may go on a bit,
so apologies...)
FFT display set to stereo input, 500ms waterfall scroll rate, 11025 Hz
sample rate, FFT input length 16384.
PERIODIC ACTIONS (every minute)
capture FFT (web image, fixed file name)
capture FFT again (archive image, date/time referenced filename)
capture plotter image
measure the noise levels of both channels
declare a variable to the value of the current time (minutes only)
SCHEDULED ACTIONS (every hour)
Daily capture of the 4 day plotter image to file
CONDITIONAL ACTIONS (tested
approx. every
200ms)
initialise all variables, start a 10 minute periodic timer (run once on
startup)
measure peak amplitudes of both channels (separately) and if >20dB
above noise, trigger
a 3 second timer (to expire before recording a ping)
if long signals total more than 15 minutes on either channel, declare Es
or Au
measure total durations of high signals for each channel per hour
count total pings per hour
count total pings per 10 minutes, and multiply by 6 to give an hourly
rate
declare activity levels depending on count totals and trigger email
alerts if necessary
(using external prog)
suppress a new email alert if one was issued in the last 6 hours
write and save 2 text files containing hourly and 10-minute count data
trigger image file copy routines for the activity indicators on the web page (external
prog)
drive the FFT display brightness based on the noise level
restart any timers that accidentally stopped or got corrupted!
write an RMOB text file 5 seconds before the hour (used by the
Colorgramme program)
Commands and functions
for meteor counting (see Spec Labs' help
file for all commands and functions)
When programming the conditional actions, every care should be taken to
avoid creating endless loops, especially when launching an
external file or making a sound happen is concerned!
IF functions can have AND and OR logic (AND = &&; OR =
||). But put each function in parenthesis, or it won't work! ie.
(A>B)&&(C>D).
THEN commands can be strung together by separating them with colons (:).

[Above: part of my own quite complicated conditional actions script]
This list is in no particular order, and uses examples that are not
necessarily in my own script... Plan your script on paper first to make
sure it will behave properly! Include test variables that can be viewed
in the "watch window" whilst testing it. SAVE the conditional
actions to a file and press "APPLY" every time you change
something. You do not need to enter the words "IF" and
"THEN" - just put your commands and functions in the correct
columns!
| Command,
function or action |
Syntax
(or note) |
Example |
| Noise
measurement (dB) |
<variable>=noise([ch],<freq1>,<freq2>)
"ch" = #1 or #2.
Don't specify if in mono mode! |
n1=noise(#1,400,1850)
n2=noise(#2,950,1020) |
| Amplitude
measurement (dB) |
<variable>=peak_a([ch],<freq1>,<freq2>) |
K=peak_a(#1,700,860)
J=(peak_a(950,1020) |
Register
a ping?
(NB - if unchecked, "a" will increment by 1 every
200ms whilst the signal is high) |
|
IF
(K>n1+20) THEN a=a+1 |
| Time
as a variable |
str("yyyyhhmmss",now) |
h2=str("hhmm",now) |
| Periodic
timer (auto restart) |
timerX.periodic(duration
seconds)
(20 possible, so X can be 0-19) |
timer15.periodic(600) |
| Timer
(non-restartable) |
timerX.restart(duration) |
IF
D>250 THEN timer14.start(21600) |
| Timer
(restartable) |
timerX.restart(duration) |
timer2.restart(3) |
Add
one to a variable if timer expired,
and reset variable "a" to 0 |
(Note:
separate commands with colons) |
IF
timer2.expired THEN b=b+1:a=0 |
| Copy
variables to each other |
(new
variable)=(original variable) |
b=a |
| Compare
variables |
-- |
a>b;
a<b; a=b |
| Launch
external file |
exec(path/filename) |
|
| Open
a file for writing |
fopenX
(20 possible, so X can be 0-19) |
fopen0 |
| Write
some data or text to a file |
fpX(variable,"text",variable,"blah"),a
("a" means "append" to the file) |
fp1(h1,",",b) |
| Close
a file after writing (don't forget this!) |
fcloseX |
fclose1 |
| Suppress
counting if noise is high |
Set
a stop flag "st0" if noise >-30dB
Add one to "b" if timer expired AND flag=0
Reset flag after noise goes below -50dB |
IF
n1>-30 THEN st0=1
IF timer2.expired && st0=0 THEN b=b+1
IF n1>50 THEN st0=0 |
| Read
a variable whose value is a time |
(Note
placeholders "####") |
val(h2,"####")=5955 |
| Make
a sound if ping detected |
sound(freq,duration) |
IF
timer2.expired THEN sound(440,0.2) |
| Numerical
computations |
See
help files! |
(+
- * / and many more) g=f*6 |
Write
some data to the FFT display
(NB. To only
do it once and not repeat the write each time a new FFT line is
drawn, nest the command within incrementing variables. See
below) |
sp.print("<text>",variable) |
sp.print("Last hour=",D) |
Nesting
variables to avoid loops
(Protects you against loops and repeats,
and saves using up
timers and processor time) |
1.
Set a variable to "0" at start.
2. When some condition is met (timer expired etc.) add one to
the variable.
3. Where you want to print to the FFT, make a condition IF
<variable>=1.
Under "THEN", write sp.print(etc)
followed by <variable>=<variable>+1
4. At the time when the original condition has gone, reset
<variable> to "0" again. |
1.
IF initialising THEN m=0
2. IF a>20 THEN m=m+1
3. IF m=1 THEN sp.print(F): m=m+1
4. IF... THEN m=0 |
Mmmm, lots there, but to
make things happen properly, these commands need to work together in
some way. I'll now attempt to write some script extracts (modules, if
you like) to demonstrate how to do the various tasks I do. Each
"module" should work on its own, or mixed with other
"modules". The examples are for mono - single channel -
reception. For dual channel, #1 or #2 need to be inserted in the
"noise" and "peak_a" functions as in the above
examples. Choose your own variable names to suit you task. Some
combinations of letters and numbers won't work for variable names, so
some experimentation may be needed if things don't work first time.
Single letters or a letter followed by a number are good starting
points.
Note: This has been revised since I first posted it to the web, as there
were a few errors in the original version! See the page revision date at
the top of the page!
1.
Counting pings - with protection from variable rx noise and
constant carriers (Conditional Actions).
Variables: a1 (stop flag) | a2 (a2=1 so result always true) | A
(rx noise in freq range dB) | B (peak amplitude in freq range
dB) | C and D (high signal counters) | E (ping counter) |
| IF |
THEN |
| initialising |
a1=1:a2=1A=0:B=0:C=0:D=0:E=0:L=0:K=0:t1=0:timer2.periodic(300) |
| a2=1 |
A=noise(400,1850):B=peak_a(850-950):q2=str("YYYYMMDDhh",now) |
| (A<-40)||(D<400)** |
a1=1 |
| (A>-40)||(D>400)** |
a1=0 |
| (B>(A+15))&&(a1=1) |
C=C+1:D=D+1:timer1.restart(3) |
| timer1.expired |
E=E+1:C=0 |
| **
Note parenthesis around each function |
2.
Create a string variable to monitor time (minutes and seconds)
Variables a2 (always=1, so that the command is always run!) | h1 (time mmss) |
| a2=1 |
h1=str("mmss",now) |
| |
3.
Write hourly count to a text file 5 seconds before every hour
(append, not overwrite) and reset E to 0. Also checks and resets
incremental variable t1 which prevents repeats whilst h1 still
equals "5955".
File is a monthly dated filename (eg.
"count200504.txt"). The data written may look like
this: 20050401 , 12, 124
Variables: L (2 digit hour) | M (year-month-day) | t1 (incremental
variable) |
| val(h1,"####")=5955 |
t1=t1+1 |
| t1=1 |
[This
goes all on one line...]
L=str("hh",now):M=str("YYYYMMDD",now):fopen0("count"+str("YYYYMM",now)
+".txt"),a:fp0(M.",",L,",",E):fclose0:E=0:t1=t1+1 |
| val(h1,"####")=0000 |
t1=0 |
4.
Drive the FFT display brightness based on noise level each 5
minutes. Function stops if noise is very low or very high.
Variable: n1 (noise calculation variable) | timer2 (periodic
timer - 300 secs) |
| a2=1 |
n1=0-A-75 |
| timer2.expired |
cfg.Wat1ClBrightns=126+n1 |
| |
|
5.
Write RMOB compatible text file for use with Colorgramme for
Spectrum Analyser.
Specify a file path after the first quote if needed, It will be
saved in the SpecLab folder by default. Note also that there is
a limit to the number of characters in the THEN column (approx
255? I've not counted!) |
| t1=1 |
fopen3("RMOB-"+str("YYYYMM",now)+".dat",a):fp3(q2,",",L,",",E):fclose3:t1=t1+1 |
Output
appears like this...
(YYYYMMDDHH , HH , count) |
2005040100 , 00 , 85
2005040101 , 01 , 87
2005040102 , 02 , 99
2005040103 , 03 , 91 |
| 6.
Capture FFT images and plotter to file (in "Periodic
Actions" - set your capture interval here if you wish) |
capture("latest.jpg")
capture(str("YYYYMMDDhhmm",now)+".jpg")
plot.capture("plotter.jpg") |
| 7.
Simple auto brightness control for the FFT display |
In
Periodic Actions (period 20 secs)
In Conditional Actions
initialising
n<-80 )
n>-20 )
n>-90&&<-20 )
a=0
|
n=noise(400,1250)
n=0:m=0:a=0
cfg.Wat1ClBrightns=150:a=1
cfg.Wat1ClBrightns=70:a=1
a=0
m=0-n-75:cfg.Wat1ClBrightns=135+m |
This list is not exactly
complete, but that's it for now. If you want more information please contact me.
To finish, here are some additional notes about timers from Spectrum
Labs' author, Wolf Buescher on avoiding loops:
"Consider this:
if( E=0 ) then timer5.start(300)
if( timer5.expired(1) ) then sound(400,0.1):etc...
[E is a status variable from my script]
What happens if E=0 ? The
"timer5.start" command checks, if this timer is
expired, in that case it immediately starts the again. Then, in the
next line, which is
executed a few milliseconds later, the timer will never
be expired when polled ( not as long as E=0). Is this what you
wanted ?
If you exchange these two lines
(...which can be done easily by holding the mouse down on the line number
in the table, and then moving it...), things
look different and behave different:
if( timer5.expired(1) ) then
sound(400,0.1):exec("...activity0.brs")
if( E=0 ) then timer5.start(300)
With this sequence, the
"timer5.expired"-flag is checked first, and the flag
is cleared if it was set. Then, in the next line, if E is zero the
timer will be started
again. Anyway
this is still not the best solution, because if timer5 expires
exactly
"between" the two lines, you will lost one 300-second interval
during which the batch
file will not be run. I am thinking about solution
where all timer-flags are updated once before the user commands
are handled. Here,
this would mean that the timer's "expired" flags are
updated once before
handling the commands in the table, but not during a single
over. This would also make it unnecessary to care about the
difference between
"timerX.expired(0)" and "timerX.expired(1)", because
all
"expired"-flags would remain unchanged until the last line in
the table
is finished.
(The more I think about it while
writing this, the more convinced I become
.. especially when taking into account that certain interpreter
commands may take very
long to execute, namely the "exec"-command).
Wolf...."
Good luck!
Andy.
|