R-Pi Clock Radio – Zeroed!

clock_radio_20160909_smallWe had a really old alarm clock in our bedroom. Β Really old. Β The LED number segments, which were a nice dim red in color, had been dying at the rate of 1 segment a year and it was getting hard to read the time. Β My wife finally had enough of my “I’ll get a new one real soon” excuse and bought a new big, bright, blue LED clock to replace the old clock. Β It was blue … and *really* bright … even in its dim-mode πŸ™ Β It had to go!

My converted 1942 Crosley Radio was collecting dust on my workbench. Β I hadΒ finally received a Raspberry Pi Zero and Zero4U USB hub to play with but was already lusting after the new R-Pi Zero with camera port. Β I recently upgraded the audio-output on my Mac from anΒ old USB HiFiMan Express DAC to Β a Schiit Modi DAC. Β  Hmmmmm, seemed like I had the ingredients to makeΒ a BIG clock “radio” with alarm(s) and great stereo audio?

I had neglected my old media-center radio which had an original Raspberry Pi as its “heart”. Β The R-Pi connected via HDMI to a display board driving a 9.7 inch, 1024 x 768, iPad LCD screen (non-touch). Β Audio output was via the audio-jack to a smallΒ stereo amp. Β The video was great but sound was mediocre.

radio_back_20160901
Dusty, old media-center radio with old R-Pi removed. Just waiting for the Zero!

My first step was to see if I could get decent sound out of the Zero via my HiFiMan Express HM-101 USB DAC. Β After much Googling and research, I had an approach. Β One of the best resources for configuring USB audioΒ underΒ Jessie OS is at Adafruit.Β  If you don’t want or need to use a USB DAC, just ignore this part πŸ˜‰ Β You can use the “normal” audio-out jack on the R-Pi 1, 2 or 3 and omxplayer app. Β As I was using a Zero, I needed another way to get audio out. Plus, I was after “good” audio, not just adequate. Β I useΒ the ALSA compatible mpg123 and mpg321 apps for audio playback. Β These provide different options including various types of random playlist support.

I now had a working system with audio and video. Β I added an Edimax WiFi dongle and Β a Logitech wireless keyboard/trackpad via a UUGear Zero4U USB Hub. Β The hub sits on top of the Zero with no soldering required.

hifiman_dac_201609
Zero connected via Zero4U USB hub to WiFi, keyboard & HiFiMan DAC

 

OK, I might have lost sight of the original goal — which was a bedroom clock. Β I startedΒ thinking about displaying the time andΒ complete weather forecast, while playingΒ music. Β I ran the idea by my wife who again informed me that “we” wanted a not-too-bright, readable-across-the-room, simple clock. Β I did get her to agree that displaying (just)Β the outside temperature might be useful!

How best to show a clock and display temperature? Β I needed to use an externalΒ resource of some kind to obtainΒ the local outside temperature. Β I was tempted to use another R-Pi with some kind of sensor HAT but I wanted something simple and quick. Β I had investigated Weather Underground APIs for weather info in the past and still had an active developer account. Β Providing I kept APIΒ calls to under 500 per day, it would be free. The Weather Underground APIs return data as JSON so I needed a way to GET and extract the temperature data. Β I thought about a Python app but I’ve been doing some web development lately and decided to use a web “app” — i.e. use a browser to display a web page with associated JavaScript functions callingΒ the JQuery JavaScript library. Β The web page withΒ associated scripts and CSS could be local toΒ the R-Pi or remotely located and downloaded from a server.

I needed a browser that could be run in kiosk mode so there were no distracting elements. Β I chose kweb. Β The latest version I found was 1.7.4. Β There’s a PDF doc that does a great job describing kweb and all its options by GΓΌnter Kreidl –Β here. Β Providing you have the Jessie OS and a GUI installed, i.e. not a minimal Jessie image, you can install kweb:

cd ~
mkdir kweb
cd kweb
wget http://steinerdatenbank.de/software/kweb-1.7.4.tar.gz
tar -xzf kweb-1.7.4.tar.gz
cd kweb-1.7.4/
./debinstall

I like to have a variety of fonts, including the Microsoft core set:

Install the font installer πŸ˜‰ and then run the installer when prompted. Β You can then list all fonts installed:

cd ~
sudo apt-get install ttf-mscorefonts-installer
fc-list

To hide the distracting cursor while in browser kiosk mode, you can use “unclutter”:

sudo apt-get install unclutter

For a clean clock display, you need to create a kweb configuration file that loads the clock web page and hides all UI elements, including the cursor – while leaving the keyboard active. Β I suggest creating a file, “mykiosk” in your pi home directory that contains:
pi@PiZero:~ $ cat mykiosk

#!/bin/sh
xset -dpms
xset s noblank
xset s off
matchbox-window-manager &
unclutter &
kweb -KHUAJ+-zbhrqfpoklgtjneduwxyavcsmi#?!., file:///home/pi/clock/index.html

Create a directory with the web page and associated script and CSS files:

cd ~
mkdir clock
cd clock

The directory should contain 3 files as listed below. I have made a zip file containing these 3 files plus the “mykiosk” config file that you can download from here. Β NOTE: you need to get your own API key from Weather Underground and determine your location string. Β See below.

html file “index.html”:

<!DOCTYPE html>
<html>
<head>
<title>Time and Temp</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="script.js"></script>
</head>
<body onload="getTime(); getTemp()">
<div id="time_txt" class="timediv"></div>
<div id="temp_txt" class="tempdiv"></div>
</body>
</html>


CSS file “style.css”:

/*
style.css
for use with HTML clock
Andy Felong
08 Sep 2016
*/

body, div {
	font-family: Verdana, Geneva, sans-serif; 
	font-size: 320px;  /* adjust to preference and display size */
	background-color: #000000;
	color: #881200;  /* dim scarlet */
}

.timediv {
	font-size: 100%; 
	max-width: 1024px; /* use the width of the display */
	text-align: center;
}

.tempdiv {
	font-size: 60%;
	max-width: 1024px; 
	text-align: center; 
}


JavaScript file “script.js”

/*
script.js
for use with HTML clock
Andy Felong
09 Sep 2016
*/


// can't use "const" in IE -- so use "var"
var CLOCK_CHECK_SECS = 20 * 1000; // 20 seconds
var TEMP_CHECK_MINS = 10 * 60000; // 10 minutes
var WU_URL = "http://api.wunderground.com/api/XXXX_UW_API_KEY_XXXX/geolookup/conditions/q/XXX_STATE_XXX/XXX_YOUR_CITY_XXX.json";
var TEMP_UNITS = "temp_f"; // WU temperature units: Fahrenheit ("temp_f") or Celcius ("temp_c")


function getTime() {
    var today = new Date();
    var hrs = today.getHours();
    if (hrs > 12) { // use 12-hour clock, not 24
        hrs -= 12;
    } else if (hrs === 0) {
        hrs = 12;
    }
    var mins = today.getMinutes();
    if (mins < 10) {
        mins = "0" + mins; // will convert num to string but that's OK
    }
    document.getElementById('time_txt').innerHTML = hrs + ":" + mins; // update time div
    var t = setTimeout(getTime, CLOCK_CHECK_SECS);
}


// getTemp() - uses JQuery library to GET and parse JSON - included by index.html
// <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

function getTemp() {
    jQuery(document).ready(function($) {
        $.ajax({
            url: WU_URL, // Weather Underground URL with key and location
            dataType: "jsonp", // cross-domain JSON request
            success: function(parsed_json) {
                var location = parsed_json['location']['city']; // could use city string if desired
                var temp_f = parsed_json['current_observation'][TEMP_UNITS]; // temperature of city passed in URL
                temp_f = Math.round(temp_f); // round temp to nearest degree
                var theTemp = temp_f + "&deg;";
                document.getElementById('temp_txt').innerHTML = theTemp; // update temperature div
            }
        });
    });
    var tmp = setTimeout(getTemp, TEMP_CHECK_MINS);
}

 

You need to include your specific Weather Underground API key as well as location for temperature disaply in the JavaScript file, “script.js” for the URL — variable “WU_URL”. In the U.S., the location is usually “2-letter state” + “/” + city — with underline substituted for a space.

Example:

var WU_URL = "http://api.wunderground.com/api/0123456789abcdef/geolookup/conditions/q/CA/Los_Angeles.json";

You should also set the browser width to your display width in the CSS file, “style.css”. Look for “max-width” and set this to your screen width. Change the font size inside the “body” section of CSS. Look for:

font-size: 320px; /* adjust to preference and display size */
and
max-width: 1024px; /* use the width of the display */

If you have installed kweb, setup the mykiosk configuration file, created the clock directory with the html, CSS and script files, you should be able to launch your clock with temperature via:

cd ~
xinit ./mykiosk

You can quit the display by hitting ALT-Q on your keyboard or by killing the process via ssh login.

Added window tint film
The LCD screen backlight was a bit bright in a dark room. I used Tap Plastics Window Tint Film to reduce “glare”. There was a slight color-shift but, for a clock-radio, this was not a concern.
clock_radio_20160909_small
Finished clock-radio. Easy to see across the room and not too bright!

33 thoughts on “R-Pi Clock Radio – Zeroed!”

  1. Pingback: Old radio converted into a bedroom clock using a Raspberry Pi Zero – Raspberry Pi Pod

    1. yes, setting “max-width: 100%” should work for all size screens BUT, I found that the kweb browser window may be larger than the screen and clip the right side. My quick & dirty fix was to set “max-width”. If you have configured kweb page-size correctly, you can and should use “max-width: 100%”. Check out the kweb docs. You could use the global “M’ or “N” arguments and set screen size.

    1. John,

      You are correct it would be pretty simple to use a one-wire temperature sensor. Adafruit has a great how-to for this. I approached this project thinking about a “complete” weather forecast read-out and then scaled back to just the temperature to keep the display simple and clean — and easy to read across the room. Also it takes NO hardware πŸ˜‰

      – Andy

  2. Great project. I should bring down my RPi s and Arduinos and we should build some stuff together. I’m starting to get into the ESP8266 which is a really inexpensive Arduino with a wi-fi module. And it’s really hard to use.

  3. I’ve done something very similar myself, using the official Raspberry Pi touchscreen, some clear red acrylic cut-to-order from eBay, and Python’s `pygame` framework for the software, running on the console rather than X11. It only took an evening to learn enough `pygame` and Python to do the job.

    Previously, I’d used a cheap Android tablet running a kiosk web browser, but it wasn’t reliable enough, and the font and graphics handling turned out much easier to get right with pygame, even though I have about twenty years more web experience (or even Xlib) than Python.

    Before that, I used large 7-segment displays from Adafruit.

    Recently, I’ve converted it to use MQTT for the sensors, letting me have a second identical RPi and screen on the other side of the room so I don’t have to turn over in bed to see it — yes, I’m just that lazy!

    With a plethora of sensors I have noticed that the humidity, pressure and even temperature readings are only useful as relative gauges: even temperature seems to vary Β±2ΒΊC depending on which sensor I consult. Regardless, rapid _change_ of barometric pressure is a migraine trigger for me, which is the whole point of this early warning system…

    Right now I’m trying to figure out how to read an outside temperature/humidity sensor over 433 MHz and Raspberry Pi GPIO, so I can loop that in too.

    The Pi also acts as a central hub for controlling 433MHz power sockets for lights and fan, a servo I’ve hacked to tilt the venetian blinds, two “ShuttleXpress” remote control consoles. I’m working on a 3D printed fitting to connect a stepper motor to a blackout roller blind (again, for the migraines) All of these features (all MQTT enabled) are also presented via a Bootstrap-structured web control panel that’s the homepage on my tablet and laptop browsers.

    The current display: https://www.instagram.com/p/BBk9We4l4zP
    Newly boxed: https://www.instagram.com/p/BIdCxJFh0zB
    The venetian blind controls: https://www.instagram.com/p/8aMGuzl46N

    Anyway, sorry for going on a bit… great job on your project, Andy… you’ve done a much nicer job on the case than my random Maplin black ABS box! πŸ™‚

  4. Pingback: Build Your Own Raspberry Pi-Powered Clock Radio - Lifehacker Guru

  5. Pingback: Build Your Own Raspberry Pi-Powered Clock Radio

  6. Great Project idea for a lot of expansions, see above. I’m already on search after this simple solution to display time and other datas on a Raspi Screen. There’s only one thing I missed and that is to display the actual date, perhaps with the weekday. How can I expansion the code to see this ?

    Thanks for your support

    Yours
    Peter

    1. Peter, look in “script.js”. You’ll see the variable “today”. This has the ISO date/time. You can see where I extracted hours (“hrs”) and minutes (“min”). You could also get date and or day-of-week:

      theyear=date.getFullYear // returns 4 digit yesr
      themonth=date.getMonth() // return 0-11 for month
      monthday=date.getDate() // returns 0-31 for day of month
      weekday=date.getDay() // returns 0-6 for day of week

      handy functions for display can be found on this webpage

  7. Nice project! But how did you control the back lighting for the LCD? I build something similar with white numbers on a black background. But can’t reduce the back lighting enough to keep the display from causing a glow in a dark room.

    My display uses fluorescent so maybe I need to install LED back lighting instead?

    1. Hi Randy, most LCD display screens have light leakage, even on “black background”. To get “real black”, you can use what’s known as “blackout film” to cover the LCD front glass. This may alter colors a bit but works great for my dedicated clock & temperature display. It’s hard to find just small sizes of this film. Look on Amazon or Google for: “dark tint blackout film” or better: “dark tint black 50% static film”. I suggest using “static film” as opposed to “self-adhesive” as it is way easier to put on and take off.

      You can see some options at Tap Plastics. They sell film by the foot πŸ™‚

      — Andy

      1. I’ve already tried that. Used car window tinting material. In fact two layers of it! Viewing straight on, the background looks black. But walking by the display with it on a lower shelf and there is a real glare.

        Think I’ll try replacing the tube backlight with LEDs. Found a replacement kit on ebay that has a dimmer control.

        Another problem I have to fix is on initial power up. The LCD driver circuit comes up before the HDMI output of the Pi. This results in the display not recognizing the resolution of the Pi. If I do just a reboot of the Pi while leaving the LCD driver powered on, it works fine. Makes for a good way to know if the power has been out while at work!

  8. Great project. I had Something similar planned: a raspberry pi alarm clock that can play music and control a smart lightbulb. After going through a lot of similar projects, your solution seems to be the best for me: despite my almost non-existent programming skills (and total lack of patience in these matters), I understodd your code and managed to replace the temperature reading by the calendar date with a different format (I know that sounds like nothing but it took me hours to get it).
    Have you got plans to add an alarm function within the script?

    1. Hi Fremi, I do plan on adding alarm clock functionality but it gets a bit tricky if you want to be able to change date/time and/or alarm sound/music. It is pretty easy to just play sound/music for short duration at the same time every day πŸ™‚ More work with lots of code and UI to recreate a “normal” alarm clock πŸ™

  9. I’m having trouble with the screen blanking. I have the code in my mykiosk file exactly how you have it, but the screen still goes blank. It stays on, but there is nothing displayed on it. I’ve scoured the web, and tried multiple things, but nothing seems to work. Any suggestions?

    Thank you for the great tutorial!

    1. Hi Dan, I’M assuming the clock works for a while before blanking? If so, check that you have “xset” installed. At the command line you can do: “which xset”. You should see “/usr/bin/xset” as the response. If not, install this package: “sudo apt-get install x11-xserver-utils”. If you do have “xset” installed, please check the mykiosk file to see this line, exactly: “xset -dpms”.

      LMK, Andy

  10. Andy,

    Thanks for your response. Unfortunately I had to take a break from working on my clock for a while. But, I’m back on the project now!

    The clock does work before the screen goes black, and continues to work while it is black. The screen stays powered on, but goes blank. When I tap a key or move the mouse, it comes back immediately with the correct time and everything.

    I checked “which xset” and did get the “/usr/bin/xset” response. I then checked the mykiosk file and have “xset -dpms” in there exactly. I’ve searched the web for a solution and it seems many people have this issue. I’ve tried changing different files and adding code, installing a screensaver and setting it to not come on, among other “fixes.” I don’t understand why the code isn’t working. Maybe it’s a bug of some sort?

    Thank you!

    1. Have you tried adding the following line to /etc/rc.local ?

      sudo sh -c “TERM=linux setterm -blank 0 >/dev/tty0”

      1. Gary,

        I added the command you posted above in my rc.local file and the screen is still blanking. Do you have anything else installed that could be helping? I’m at a total loss as to why my screen won’t stay on for more than 10 minutes. I’ve tried different monitors just to make sure, and all of them go off at the 10 minute mark.

        Maybe you could copy and paste your rc.local file here? I’d also like to have it set to start when I boot the pi, that seems like a great idea.

        Thanks for your help!

        Dan

        1. Dan, permissions have recently changed with an X update. Try using “sudo” in front of the “xset” commads. Do this manually and try-it-out before placing in your script(s) — i.e.

          $ sudo xset s off
          $ sudo xset -dpms
          $ sudo xset s noblank

          – Andy

          1. Andy,

            I tried entering those commands at the prompt, but just received the following after each one:

            xset: unable to open display “”

            Dan

  11. Haha, I was wondering if many other people made these. You put a lot more effort into you clock than I did, and got a much nicer result. That DAC add-on was a nice touch.

  12. How do other people get kweb to autostart on boot up? I’ve added xinit to the rc.local script and it loads the page with the time ok but the weatherunderground api is not working.

    1. Hi Gary, does the webpage show weatherunderground info if you start manually? If so, check user/owner/permissions and PATH — if you are not starting as the same user these might be things to look at. Are you using full path names for references inside your HTML, JS and CSS files? LMK, Andy

      1. Hi Andy, thanks for the suggestions.

        I’ve now fixed the issue by adding a delay before I call xinit in my /etc/rc.local script.

        sleep 10
        su -l pi -c “xinit ./mykiosk”

        Apparently rc.local gets run very early in the boot sequence so i guess networking or something was not setup when kweb was trying to make the ajax call to WU api.

  13. Really stupid question. I built this project last year and it is still up and running.

    I’m modifying it some what and that’s all fine.

    However I cannot for the life of me tell why it works at boot. nothing in the rc.local file relevant to this.

    Can you help?

    1. Hi Ken, You have me scratching my head πŸ˜‰ My setup does not auto-start the clock. Check your raspberry pi configuration using “raspi-config” and check that “Boot Options” is set to “CLI”. You would then start the clock, etc. with “sudo xinit .mykiosk”

  14. High Guys.
    Andy I don’t know if you are still monitoring this Forum but I have found it whilst searching for months and months for exactly your excellent clock piece here in the UK.

    I have no programming knowledge except for what I have taught myself over the years from the sinclair spectrum up to now my Dell laptop and from reading problem Forums like this one.

    I, so far, have your clock installed on a Raspberry P zero W with a 3.5″ tft display and mounted it an old clockwork alarm clock I used to use when I worked in the Middle East in the early 80’s, every time I look at it the memories come flooding back, now I can do that every day with it alongside my bed.

    I’ve not been able to get the temperature to work yet but it’s still an ongoing project and I will have a go at adding the date and I thought maybe a picture for the clock face..

    I hope the guy with the blanking screen has sorted it by now, the first thing I do to a Pi is install xscreensaver and stop the blanking, it sounds to me like it’s something to do with that if it comes back when he moves the mouse, like I said I’m no programmer, I call myself a copier and paster apart from smaller stuff.

    It’s taken a while to get the clock so that I can use it, I had huge issue’s with the little screen (it worked on the Pi but as soon as you wanted it for other things say, like your clock it would just show a white screen, nothing else but I found a small script on line that booted it up).

    Thanks for sharing your great project I shall keep an eye on the Forum now and see what else is going on.

    Stay safe and be well everyone.
    C.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top