Posts Tagged RPi

Monthly Science: WWVB Reception Sample

Further results from the SDR-based WWVB receiver:

60 kHz Receiver - preamp HIT N3 Pi3 - attic layout

60 kHz Receiver – preamp HIT N3 Pi3 – attic layout

Seven hours of mid-January RF, tight-zoomed in both frequency and amplitude, from 0350 to 1050 local:

WWVB waterfall - N3 - 2017-01-24 1050 - composite

WWVB waterfall – N3 – 2017-01-24 1050 – composite

The yellow line of the WWVB carrier comes out 2 ppm high, which means the local oscillator chain is 2 ppm low. We know the WWVB transmitter frequency is exactly 60.000 kHz, translated up by 125 MHz to the N3’s tuning range; you can, ahem, set your clock by it.

The blue band marks the loop antenna + preamp passaband, which isn’t quite centered around 60.000 kHz. Tweaking the mica compression caps just a bit tighter should remedy that situation.

Given that input, a very very tight bandpass filter should isolate the WWVB carrier and then it’s all a matter of fine tuning…



Leave a comment

WWVB Receiver: First Light!

All the blocks for a WWVB receiver, lined up on the attic floor:

60 kHz Receiver - preamp HIT N3 Pi3 - attic layout

60 kHz Receiver – preamp HIT N3 Pi3 – attic layout

The dramatis personae:

The headless Pi connects to the house WLAN through its built-in WiFi link, so I can run the whole mess from the Comfy Chair at my desk through Remmina / VNC.

Recording 24 hours of WWVB shows it works:

WWVB - 24 hr reception AGC - 2017-01-16 to 17 - cropped

WWVB – 24 hr reception AGC – 2017-01-16 to 17 – cropped

The wavy line along the left edge looks like a birdie formed by a local oscillator in the attic, because the frequency varies (inversely) with temperature. It’s probably a signal on the Pi board, rectified by some junction, and translated in-band by some Ham-It-Up harmonic. Whatever.

The other traces come out bar-straight, suggesting that the 0.5 ppm (presumably, per °C) temperature-compensated oscillators along the whole RF chain behave as they should.

There’s a slight frequency shift, on the order of a few parts-per-million, between the absolutely accurate WWVB carrier and the indicated display. Not a big deal.

The broad, albeit irregular, orange band down the middle shows the loop antenna / preamp bandwidth, which is on the order of 2 kHz at -3 dB and a few kilohertz more down to the noise level.

The broad horizontal gashes seem to come from the N3’s on-board hardware AGC reacting to signals far outside the waterfall. Various birdies appear & disappear, even in this limited view, so you can just imagine what’s happening off-screen; anything popping up within the SDR’s tuning range clobbers the gain, which becomes painfully visible when zoomed this far in along both frequency and amplitude. Turning AGC off should stabilize things; perhaps software can tweak the SDR gain based on a very narrowband filter around 60.000 kHz.

The upper half of the waterfall shows decent reception for most of the night. The bottom half shows there’s basically nothing goin’ down during the day, which is about what I’d expect based watching the Alpha Geek Clock for seven years.

In any event, another 24 hours with the AGC turned off looks better:

WWVB 24 hr waterfall - Thumbnet N3 - 2017-01-19

WWVB 24 hr waterfall – Thumbnet N3 – 2017-01-19

Various sources still clobber the receiver response, but it’s not quite so dramatic.




Raspberry Pi CPU Temperature Watcher

Having just put a headless Raspberry Pi in the attic, the chip temperature is of some interest. Doing this in an SSH session comes in handy:

watch 'echo "scale=1 ; d = $(cat /sys/class/thermal/thermal_zone0/temp) / 1000 ; print d , \" °C\n\" " | bc'
# blank line to ensure the underscore displays correctly

Raspbian doesn’t have the bc calculator by default, so do that first.

For whatever it’s worth, the Pi starts out at 10 °C and warms over 60 °C under heavy load:

Every 2.0s: echo "scale=1 ; d = $(cat /sys/class/thermal/thermal_zone0/temp) / 1000 ; print d , \" °...  Sat Jan 14 19:58:59 2017

61.7 °C

It ticks along in the mid 30s under light load.

You can run all that in one tab of a terminal window through VNC. If you’ve got that much GUI goin’ on, just add a thermal monitor in the panel and be done with it.



Raspberry Pi vs. Avahi

It turns out that the various Avahi daemons performing the magick between whatever.local names and dotted-quad addresses for Raspberry Pi descend into gibbering madness when confronted with:

  • One name corresponding to multiple IP addresses
  • One IP address used for multiple MAC addresses
  • Multiple names for one IP address
  • Multiple names for one MAC address
  • Multiple IP addresses for one MAC address
  • Multiple MAC addresses for one IP address
  • Any and all combinations of the above at various times

The least of the confusion involved an incorrect IP address linked to a familiar name pulled from deep history by a baffled daemon doing the best it can with what it thinks it knows. Despite what I concluded, rather early in the process, there’s no real error, other than my performing what amounted to a self-inflicted fast-flux nameserver attack.

Anyhow, I devoted the better part of an afternoon to sorting out the mess, which involved labeling all the streaming radio players with their MAC addresses and rebooting them one-by-one to allow all the daemons time to recognize the current situation:

Raspberry Pi 3 - WiFi MAC address

Raspberry Pi 3 – WiFi MAC address

That label corresponds to the Pi 3’s on-board WiFi adapter.

For Pi 2 boxen, the MAC address travels with the WiFi adapter jammed into a USB port:

SunFounder WiFi Adapter - MAC address

SunFounder WiFi Adapter – MAC address

I didn’t label the (unused) Ethernet jacks, figuring I’d solve that problem after it trips me up.



Raspberry Pi Streaming Radio Player: Room Customization

Sometimes you (well, I) want a bit of late-night music, which is now one button press away. However, I initially set things up so the Raspberry Pi’s startup code executed a Python script on a network share from the file server in the basement, which shuts down around midnight after the daily backup.

Keeping a local copy meant having to update that copy whenever I tweak the code, a nuisance not to be tolerated. This Bash (or whatever) code in /etc/rc.local figures out if the server is up and, if so, updates the local copy from the server. If the server isn’t up, then it just runs with what it has:

# was !/bin/sh -e

... snippage ...


ping -c 1 $server
if [ $? -eq 0 ]
  mount -o ro ${server}:/mnt/bulkdata/Project\ Files/Streaming\ Media\ Player/Firmware/ /mnt/part
  rsync -auv /mnt/part/ /home/pi
  umount /mnt/part

sudo -u pi sh -c 'python /home/pi/ any' &

N.B.: you must remove the -e from the shebang, because otherwise the script jams to a stop when the ping fails. Took me a while to figure that out, yup.

Use raspi-config to force the startup sequence to wait until the network is available. Turns out that the DHCP process can stall for half a minute, so fixed timeouts don’t work.

Hardcoding the server IP address eliminates a whole bunch of mysterious failures apparently due to whatever handles the translation from mollusk.local to the dotted quad. Maybe that’s not really a problem, but I’ll run with it.

Now the streamers fetch the Latest and Greatest version whenever they’re on during the day and run their local copy, with the room parameter telling it where it lives.

Life is good!



Raspberry Pi Streaming Radio Player: Command Line Parsing

Some experience suggested different default stations & volume settings for the streamers in various rooms, so the Python code now parses its command line to determine how to configure itself:

import argparse as args

cmdline = args.ArgumentParser(description='Streaming Radio Player',epilog='KE4ZNU -')
cmdline.add_argument('Loc',help='Location: BR1 BR2 ...',default='any',nargs='?')
args = cmdline.parse_args()

I should definitely pick a different variable name to avoid the obvious clash.

With that in hand, the customization takes very effort:

CurrentKC = 'KEY_KP7'
MuteDelay = 8.5         # delay before non-music track; varies with buffering
UnMuteDelay = 7.5       # delay after non-music track
MixerVol = '15'         # mixer gain

Location = vars(args)['Loc'].upper()
print 'Player location: ',Location'Player setup for: ' + Location)

if Location == 'BR1':
  CurrentKC = 'KEY_KPDOT'
  MixerVol = '10'
elif Location == 'BR2':
  MuteDelay = 6.0
  UnMuteDelay = 8.0
MixerVol = '5'

The Location = vars() idiom returns a dictionary of all the variables and their values, of which there’s only one at the moment. The rest of the line extracts the value and normalizes it to uppercase.

Now we can poke the button and get appropriate music without having to think very hard.

Life is good!

The Python source code, which remains in dire need of refactoring, as a GitHub Gist:


1 Comment

Read-Only MicroSDHC Card

I iterated this sequence three times before I caught on:

  • ssh into Raspberry Pi
  • Edit /etc/rc.local, save changes
  • Reboot, observe the changes had no effect
  • cat /etc/rc.local shows no changes

Then I:

  • Edited / saved
  • Listed the file to verify the changes
  • Rebooted, observe no effect from changes
  • Listed the file again: the changes were gone


Defunct 8 GB MicroSDHC card

Defunct 8 GB MicroSDHC card

It turns out the card went read-only without warning, so I was displaying the contents of the file cache buffers after the edit, not the data stored on the card. Rebooting started with empty caches, read the previous file contents, and behaved accordingly.

The F3 utilities now live in the Ubuntu repository and no longer require compiling from source. The result:

sudo f3probe --time-ops /dev/sdb
F3 probe 6.0
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

WARNING: Probing normally takes from a few seconds to 15 minutes, but
         it can take longer. Please be patient.

Probe finished, recovering blocks... Done

Bad news: The device `/dev/sdb' is damaged

Device geometry:
	         *Usable* size: 0.00 Byte (0 blocks)
	        Announced size: 7.35 GB (15415296 blocks)
	                Module: 8.00 GB (2^33 Bytes)
	Approximate cache size: 0.00 Byte (0 blocks), need-reset=no
	   Physical block size: 512.00 Byte (2^9 Bytes)

Probe time: 164.4ms
 Operation: total time / count = avg time
      Read: 107.1ms / 4098 = 26us
     Write: 56.6ms / 2049 = 27us
     Reset: 0us / 0 = 0us

That card has been kicking around for a while and started out as a no-name generic in some random gadget. Of course, those fancy Sony MicroSD cards weren’t shining examples of durability, either.

I’m mildly astonished the streaming player worked perfectly with what amounts to a read-only filesystem, but that’s what caching is all about: there was no need to write the data to “disk”.