Disable screensaver/blanking on Raspberry Pi

For permanent display screens (e.g. digiclock) run by a Raspberry Pi it is useful to disable screen blanking and the screen-saver. These two config-edits seem to work: https://www.raspberrypi.org/forums/viewtopic.php?t=57552

In /etc/xdg/lxsession/LXDE-pi/autostart we want

@xset s noblank
@xset s off
@xset -dpms

And then in /etc/lightdm/lightdm.conf

xserver-command=X -s 0 dpms

New HTPC: Intel NUC 6i7KYK

I got a new computer for videos, games, music etc. on the TV. The Intel NUC 6i7KYK is a small barebone machine with an i7-6770HQ processor and Iris 580 graphics (should be OK for games) with HDMI (and others) output. It comes with a nice allen-key for the top cover screws, but the design language gives mixed messages when you turn the NUC over to open the back cover: here you need a plain vanilla Phillips screwdriver (not included).

I put 16 Gb of DDR4-SODIMM RAM in it and a 256 Gb M.2 SSD drive, The keyboard is a wireless Logitech K400+. So far no surprises - everything is working well.

Simple Mersenne prime search

For fun I tried to search for Mersenne primes with a very simple code (below). It finds the 20 first Mersenne primes (all known by 1961) in under a minute. After that it slows down quite a lot and finds the 26th prime (discovered in 1979) in about 5 hours.

mersenne_primes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import time
import math
 
# http://stackoverflow.com/questions/16004407/a-fast-prime-number-sieve-in-python
def prime_sieve(n):
    size = n//2
    sieve = [1]*size
    limit = int(n**0.5)
    for i in range(1,limit):
        if sieve[i]:
            val = 2*i+1
            tmp = ((size-1) - i)//val 
            sieve[i+val::val] = [0]*tmp
    return [2] + [i*2+1 for i, v in enumerate(sieve) if v and i>0]
 
# https://en.wikipedia.org/wiki/Trial_division
def trial_division(n):
    """Return a list of the prime factors for a natural number."""
    if n < 2:
        return []
    prime_factors = []
    for p in prime_sieve(int(n**0.5) + 1):
        if p*p > n: break
        while n % p == 0:
            prime_factors.append(p)
            n //= p
    if n > 1:
        prime_factors.append(n)
    return prime_factors
 
def is_prime_trial_division(n):
    return len(trial_division(n)) == 1
 
# https://en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test
def is_prime_lucas_lehmer(p):
    s = 4
    M = pow(2,p) -1
    for n in range(p-2):
        s = (pow(s,2)-2) % M
    return s==0
 
n=2 
t0 = time.time()
print "#\tp\ttime\tyear"
log_max_p=15
for p in range(1,pow(2,log_max_p)):
    if is_prime_trial_division(p):
        if is_prime_lucas_lehmer(p):
            elapsed = time.time() - t0
            print "%4d\t%4d\t%.1f s" % (n, p, elapsed)
            n=n+1

y-cruncher

I ran y-cruncher on a number of machines. Note the logarithmic y-axis. Lower is faster.

y-cruncher_results

  • i7-3537U, 2.5 years old Lenovo yoga laptop. Runs hot. Time to upgrade?
  • i5-4300U, ~1 year old work laptop, HP ultrabook. Runs much cooler.
  • i7-2600K, 3+ years old home desktop
  • i7-3770, 2.5 years old work desktop
  • Opteron 4334, Del R515 server, 1? year old.
  • i7-3930K, computing machine at work, 3+ years old
  • i7-5820K and i7-4770K newest lab computers, both 1 year old.

Intel Atom C255Xs

The Atom C255X is becoming a popular processor in not-so-demanding low power boxes.

Here's a pfsense SG-4860 router/firewall using a C2558 (15W) processor and 8 Gb of RAM. It comes with 4 Gb of on-board flash storage, so the external mSATA drive (lower edge, just above the Ethernet connectors) is not required unless you need to store very big pfsense logfiles. No moving parts, passive cooling only. Although pfsense-branded (running FreeBSD + pfsense), under the hood it's probably an ADI Engineering RCC-VE.
pfsense_sg-4860

Here's a SuperMicro 5018A-MLTN4 with a C2550 (14W) processor in a 1U 19" rack enclosure. SSD drive and 8 Gb of RAM. I suspect the front fan is quite overkill and could be slowed down a lot or completely removed. The built-in graphics produce not-so-great performance under Ubuntu, but with lubuntu-desktop it's usable as a lab server that you need to configure or check only once a week or so.
supermicro_5018A-MLTN4

NTP stratum-1 on Ubuntu 14.04LTS

Some (incomplete) notes on setting up a stratum-1 NTP server on Ubuntu 14.04LTS

To handle the upcoming leap-second we want a leapfile, from: http://www.ietf.org/timezones/data/leap-seconds.list

The path of the leapfile goes into /etc/ntp.conf
leapfile /etc/leap-seconds.list
But Ubuntu uses apparmor, so we must grant permission for the ntp service to read this file in /etc/apparmor.d/usr.sbin.ntpd by adding:
/etc/leap-seconds.list r,
To make apparmor parse and apply the new rules we do:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.ntpd
when the ntp service starts it is useful to look at /var/log/syslog where ntp will complain if it doesn't have permission to read the leapfile or if it is badly formatted.

Now let's edit the default options for the ntp service in /etc/default/ntp by adding:
NTPD_OPTS='-gN'
(-N runs ntpd at highest priority, -g makes it more robust agaist large time offsets, see man ntpd)

To get time in NMEA-format and a pulse-per-second (PPS) from gpsd we add two shared-memory (type 28) refclock drivers to /etc/ntp.conf

# GPS Serial data reference
server 127.127.28.0 maxpoll 3
fudge 127.127.28.0 time1 -0.230 refid GPS

# GPS PPS reference
server 127.127.28.1 prefer maxpoll 2
fudge 127.127.28.1 refid PPS

(the time1 adjustment number needs to be calibrated somehow..).

Finally we let ntp distribute time to the outside world by adding this line to /etc/ntp.conf (this is usually at the end of the file).
restrict default noquery

Now let's set up gpsd. The service configuration file is /etc/default/gpsd, and as suggested in the file we edit it with the utility:
sudo dpkg-reconfigure gpsd
The options that worked for me are device /dev/ttyS0 and options -n (don't wait for clients to connect). After running the utility /etc/default/gpsd should look something like:

START_DEAMON="true"
GPSD_OPTIONS="-n"
DEVICES="/dev/ttyS0"
USBAUTO="false"
GPSD_SOCKET="/var/run/gpsd.sock"

You can verify that gpsd is working with cgps, xgps, or gpsmon.

This should result in Ubuntu automagically starting gpsd and ntpd in the correct order at bootup, and ntpq -p should show something along the lines of:
Screenshot - 06262015 - 10:18:31 AM

If you want to manually restart (or just start or stop) the services, required e.g. after any changes are made to /etc/ntp.conf, it is done with
sudo service ntp restart
sudo service gpsd restart

Rack PC Build - Part Two

Another rack-PC put together this week. Intel X99-chipset with LGA2011-3 CPU socket. Only PCI-e slots, no legacy PCI-slots.

Again I didn't get the polarity of the HDD-LED and Power-LED wires right on the first try. How come the industry cannot agree on a standard connector for the bundle that has the power-switch, reset-switch, HDD-LED, and Power-LED?

Another glitch was that this board has 8 slots for RAM, and the two RAM-sticks I got need to be installed exactly in the right slots - otherwise it won't even boot into the BIOS. Some reading of the motherboard manual was required.

After installing Ubuntu 14.04LTS (from USB-stick! No CD/DVD required) the NVIDIA-drivers (for the GTX750TI) were not automatically detected. I downloaded the latest driver from NVIDIA and installed it manually. This requires logging in to a text-only console (CTRL-ALT-F1), and then killing X for the duration of the install (sudo service lightdm stop)

NTP failure detection

Update: Here's how the graph looks like when NTP traffic is enabled again:
ntp

A computer that doesn't receive NTP traffic for a while will have its system time drift quite a lot.

In the absence of NTP (UDP port 123) traffic, we can try to roughly ask for the current time over HTTP using wget from google with this shell script:

#!/bin/sh
/usr/bin/wget --no-cache -S -O /dev/null google.com 2&gt;&amp;1 | \
    /bin/sed -n -e '/ *Date: */ {' -e s///p -e q -e '}'

This outputs a string such as "Sat, 23 Nov 2013 09:14:45 GMT"

Now we can put together a python script that calls this shell script, converts the text-format time-stamp into UTC seconds, and compares against the system time. For plotting we then store the time-error in an RRDTool database. This script is called once per minute using cron.

import subprocess 
import time
import datetime
import rrdtool
import syslog
 
args = ['googletime.sh']
datetimestring = subprocess.check_output(args)
syslog.syslog( "googletime {0}".format(datetimestring))
 
# input: Sat, 23 Nov 2013 09:18:02 GMT
# output: 1385191082.0  (seconds since 1.1.1970)
timestamp = time.mktime( time.strptime(datetimestring, '%a, %d %b %Y %H:%M:%S GMT\n'))
 
# system time, e.g.: 1385191082.0
stime = time.mktime( time.gmtime() )
 
# should be zero, if all is well
terror = stime-timestamp
 
# store the measured error in a database
datastring = 'N:{0}'.format(str(terror)) # 'N:1234'
syslog.syslog( "rrd update: {0}".format(datastring) )
ret = rrdtool.updatev( "time_error.rrd" ,datastring)
syslog.syslog( "rrd updatev: {0}".format(ret) )

Once we have all the values in our time_error.rrd database we can plot them with rrdtool graph. This is what I get:
system_vs_google_time
There is about -4 seconds of drift during 24 hours, or 46 us/s (46 ppm). If the drift is steady we can guess that the computer was on time 14/4 = ~4 days ago.

The script for creating the rrdtool database is this:

import rrdtool
import time
 
# DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max
data_sources=[ 'DS:TERROR:GAUGE:70:U:U']
# RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows
 
utcsecs = int( time.time() )
pts_day= 24*60
primary = 'RRA:AVERAGE:0.5:1:{0}'.format(pts_day) # 2016 points
rrdtool.create( 'time_error.rrd',           # filename
                 '--start', str(utcsecs),   # when to start
                 '--step', '60',            # step between datapoints
                 data_sources,
                 primary)

And the graph is created by this script. I am using the simple python-rrdtool python bindings - the object-oriented python-pyrrd may have neater syntax and be more pythonic.

import rrdtool
import time
 
graphname = '/var/www/test.png'
day = 24*3600
span = 1*day
starttime = int(time.time()-span)
endtime = int( time.time() + 0.1*span)
updatestamp = time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime(time.time()))
graphtitle = '192.168.1.55 System time - google.com time upated: '+updatestamp
rrdtool.graph(  graphname,
               '--start', str(starttime),
               '--end',str(endtime),
               '--title',graphtitle,
               '--width',str(1024),
               '--height',str(600),
               '--full-size-mode',
               '--upper-limit',str(20),
               '--lower-limit',str(-20),
               '--vertical-label','Error (s)', 
               '--right-axis', '1:0',
               'DEF:terror=time_error.rrd:TERROR:AVERAGE',
               'LINE2:terror#FF0000')