Advertisements

Speech Synthesis on the Raspberry Pi

Now that I can get sound out of my Raspberry Pi (RPi), the next logical step for me is speech synthesis … Right?  I foresee my RPi being used as a controller/gateway for other devices (e.g. RPi or Arduino).  In that capacity, I want the RPi to provide status via email, SMS, web updates, and so why not speech?  Therefore, I’m looking for a good text-to-speech tool that will work nicely with my RPi.

The two dominate free speech synthesis tools for Linux are eSpeak and Festival (which has a light-weight version called Flite). Both tools appear very popular, well supported, and produce quality voices.  I sensed that Festival is more feature reach and configurable, so I went with it.

To install Festival and Flite (which doesn’t require Festival to be installed), use the following command:

sudo apt-get install festival
sudo apt-get install flite

Festival

To test out the installation, check out Festival’s man page, and execute the following:

echo "Why are you in front of the computer?" | festival --tts
date '+%A, %B %e, %Y' | festival --tts
festival --tts Gettysburg_Address.txt

Text, WAV, Mp3 Utilities

Festival also supplies a tool for converting text files into WAV files.  This tool, called text2wave can be executes as follows:

text2wave -o HAL.wav HAL.txt
aplay HAL.wav

MP3 files can be 5 to 10 times smaller than WAV files, so it might be nice to convert a WAV file to MP3.  You can do this via a tool called lame.

lame HAL.wav HAL.mp3

Flite

Flite (festival-lite) is a small, fast run-time synthesis engine developed using Festival for small embedded machines. Taking a famous quote from HAL, the computer in the movie “2001: A Space Odyssey

flite "Look Dave, I can see you're really upset about this. I honestly think you ought to sit down calmly, take a stress pill, and think things over."

Depending how the software was built for the package, you find that flite (and festival) has multiple voices. To find what voices where built in, use the command

flite -lv

To play a specific voice from the list, use the -voice parameter in the command

flite -voice kal "I'm now speaking kal's voice. By the way, please call me Dr. Hawking."

In my case, the default voice appears to be “kal”, which sounds somewhat like Stephen Hawking.  “slt” appears to be a female version of the “kal” voice.

flite_time is a talking clock that can speak things like “The time is now, exactly two, in the afternoon.”

flite_time 14:00
flite_time `date +%H:%M`

Documentation

The documentation for Festival and Flite isn’t all that great but there does seem to be multiple sources.  Here is what I found most useful:

Advertisements

Getting Audio Out Working on the Raspberry Pi

I want to deliver sound from my Raspberry Pi’s (RPi) Audio Output 3.5mm jack.  I’ll need to get audio drivers working on Audio Out, and to test it, I’ll need some sound files and players.  I’m choosing the Advanced Linux Sound Architecture (ALSA) drivers because its widely supported and because ALSA not only provides audio but  Musical Instrument Digital Interface (MIDI) functionality to Linux.   I’ll also be using the popular command line MP3 players, mpg321 and the WAV player that comes with ALSA, aplay.

To get things going, I installed ALSA, a MP3 tools, and a WAV to MP3 conversion tool via the following commands:

sudo apt-get install alsa-utils
sudo apt-get install mpg321
sudo apt-get install lame

Enabling the Sound Module

Reboot the RP and when it comes back up, its time to load the Sound Drivers.  This will be done via loadable kernel module (LKM) which are object file  that contains code to extend the Linux kernel.  lsmod is a command on Linux systems which prints the contents of the /proc/modules file.  It shows which loadable kernel modules are currently loaded.  In my case, lsmod gives me:

The snd-bcm2835 module appears to be already installed. RPi has a Broadcom  BCM2835 system on a chip (SoC) which is a High Definition 1080p Embedded Multimedia Applications Processor.  snd-bcm2835 is the sound driver.  If  lsmod doesn’t list the snd-bcn2835 module, then it can be installed via the following command:

sudo modprobe snd-bcm2835

Enabling Audio Output

By default, the RPi audio output is set to automatically select the digital HDMI interface if its being used, otherwise the analog audio output. You can force it to use a specific interface via the sound mixer controls.  amixer allows command-line control of the mixer for the ALSA driver.

You can force the RPi to use a specific interface using the command amixer cset numid=3 N where the N parameter means the following: 0=auto, 1=analog, 2=hdmi.  Therefore, to force the Raspberry Pi to use the analog output:

amixer cset numid=3 1

Sound Check

With this done, you should be ready for a simple test.  Plug a speaker into the (RPi) Audio Output 3.5mm jack.  I used a simple battery powered iHM60 iHome speaker.  The jack will not deliver much power, so the speaker needs to be powered.

To test the RPi audio, you can play a WAV file (download this … excellent for user-error notification) with aplay, mpg321 for MP3 files, or use the speaker-test command if you don’t have a WAV/MP3 file.

aplay numnuts.wav
speaker-test -t sine -f 440 -c 2 -s 1
mpg321 "Mannish Boy.mp3"

More on the ALSA Sound Drivers and Utilities

While ALSA is a powerful tool, it documentation appears is very weak.  Also, it appears that the capabilities of ALSA drivers and utilities are very  dependent on the hardware used.  The best sources of documentation that I found include Advanced Linux Sound Architecture (ALSA) project homepage,  archlinux Advanced Linux Sound Architecture, and ALSA-sound-mini-HOWTO.

You can find useful information in the directory /proc, which is a “virtual” file system (meaning that it does not exist in real life, but merely is a mapping to various processes and tasks in your computer).

    • /proc/modules gives information about loaded kernel modules.  The command lsmod | grep snd will list modules relevant to the sound system.
    • You can check the existence of a soundcard by looking  at cat /proc/asound/cards.

The amixer command can provide useful information (sometimes):

    • You can look at the mixer settings by typing amixer without any arguments. This command lists the mixer settings of the various parts of the soundcard. The output from amixer can greatly differ from card to card. Unfortunately  you can’t find much documentation on how to interpret the out.
    • The RPi doesn’t have a “Master” control only “PCM”.  So commands like amixer set Master... will not work.  You must use amixer set PCM ...
    • You can mute /unmute the sound via these commands: amixer set PCM mute and amixer set PCM unmute
    • As of August 2012, there appears to be a known bug in RPi ALSA driver that ignores volume settings at the start of playback and always plays at max volume.  Therefore, commands like amixer set PCM 50% unmute will not set the volume to 50%, at least until this bug is fixed.  Maybe this isn’t really a bug but a limitation of the hardware because there is a workaround for this …. see below.

Volume Control

The RPi built-in sound chips don’t have a “master volume” control, and as a result, you must control the volume via software.  I guess the RPi views itself as a preamplifier (preamp) and volume controls would be supplied down stream.  ALSA provides a software volume control using the softvol plugin.

The /etc/asound.conf file is a configuration files for ALSA drivers (system-wide).  The main use of this configuration file is to add functionality. It allows you to create “virtual devices” that pre or post-process audio streams. Any properly written ALSA program can use these virtual devices as though they were normal devices.  My RPi  /etc/asound.conf file looks like this:

For most changes to /etc/asound.conf you will need to restart the sound server (ie. sudo /etc/init.d/alsa-utils restart) for the changes to take effect.

I attempted to implement the software volume controls outline in a softvol how-to that I found, but I couldn’t get it to work.  I did some additional digging, and I found a solution buried within a python script for a Adafruit project.  The following works for controlling the volume (in this case, reducing the volume to 80% of maximum):

amixer cset numid=1 -- 80%

Note that you can use this command to change the volume while sound is being played an its effect takes place immediately.  Also, I noticed that once the volume has been adjusted, its effect remains even after a reboot.

WAV and MP3 Conversion

The MP3 player mpg321 can convert MP3 files to WAV files but the WAV player, aplay, can not do a conversion.  To make a MP3 file from a WAV file, you’ll need the tool lame.

    • To convert from WAV to MP3: lame input.wav output.mp3
    • To convert from MP3 to WAV:  mpg321 -w output.wav input.mp3

Bottomeline

While you can get ALSA working on the Raspberry Pi, it appears only partly supported, maybe buggy, and poorly documented.  If you just want to simply get sound out of the device (like I do), you’ll be fine.  But if you have some desire to do some sound processing with ALSA, your likely to be very frustrated.

Epilogue

This specific post has gotten about 25% of all the viewings of my blog. I’m not sure why this is the case but I speculate that there are many people tying to make RPi into a Media Player and looking for answers to their technical problems.

At this point in time, others have done some additional postings and they are more instructive than my post. You should check out:

Dropbox for the Raspberry Pi (sort of)

I’m presently using Dropbox as a service for quick & easy movement of files between multiple PCs I use.  Its copy & paste operation is very intuitive on a Windows PC. I would like the same on the Raspberry Pi (RPi), particularly for moving files from my PC to the RPi.  I wanted the same utility on my RPi, but at the same time, I want the Linux command line paradigm supported and not be force to run X Windows on the RPi.

I did some searching and found things like Dropbox’s Linux distribution (which I wasn’t confident would work “out of the box” for the RPi’s ARM architecture, but source is provided),  GoodSync or Owncloud (which wouldn’t access my existing Dropbox files but instead create an alternative), python or  bash shell based up/down loaders (appears to behave like a simplified FTP tool), or the Secure SHell File System (SSHFS) based approach (the PC’s Dropbox directory is mounted on the RPi).

While the Dropbox’s Linux distribution is likely the ultimate way to go, I didn’t want to commit myself to the effort it would potentially require.  I settled on the SSHFS based approach.  I’m running my RPi headless and access it via my PC using Cygwin/X and Secure Shell (ssh).  With the SSHFS approach, I could make the Dropbox directory available for mounting at boot-up or mount it at will.  I only envision using the RPi-based Dropbox when I’m doing development and I will be doing that from my PC.  So this SSHFS approach seems fine for the way that I operate.

The SSHFS approach means files will not really be replicated on the RPi, like Dropbox does.  The files will reside within my PC’s Dropbox folder (and replicated on my other PCs via the Dropbox service) but accessible by the RPi via the SSHFS file mount.  This means I can’t have any applications I run on the RPi depend on files located in its Dropbox directory since it may not be always mounted.  I’m OK with this limitation, and in fact is consistent with the ad-hoc purpose I have for the Dropbox directory.

Installation Required on the PC

For me, nothing needs to be done here.  I already have Dropbox running on my PC, and via Cygwin/X, I have the foundations required for the host side of the SSHFS solution.  If you need help with this, signup for Dropbox here and find out how I’m using Cygwin/X here.

Installation Required on the RPi

On the client side of the solution, you’ll need to install SSHFS and FUSE. FUSE is the user-space filesystem framework and is the foundation on which SSHFS resides. FUSE allows user-space software, SSH in this case, to present a virtual file system interface to the user; something generally only done by the Linux kernel.  SSHFS connects to the remote system and provide the look and feel of a regular file system interface for remote files. On the RPi, install SSHFS via the command:

sudo apt-get install sshfs 

FUSE appear to be already installed on the RPi or maybe comes with SSHFS. Next you need to add required users to the FUSE usergroup.  In my case, that is the user pi.  You can see the existing groups pi is part of via the command groups pi.  You can validate that the FUSE user group has been created by using the command cat /etc/group | grep fuse.  To add pi to the FUSE user group, use the command:

sudo gpasswd -a pi fuse

The fuse group lets you limit which users are allowed to use FUSE-based file systems, in my case the Dropbox. This is important because FUSE installs setuid programs, which always carry security implications.

Configuring the Dropbox File System

Now its time to make your Dropbox directory on the RPi, and mount it to the PC’s instance of Dropbox. On the RPi, use this command to create the Dropbox:

mkdir ~/Dropbox

The next thing to do is to make sure that you can connect to the PC via ssh.  When I installed Cygwin, my focus was on using it as an X Server and making ssh connections from the PC to RPi.  I never tried the inverse (connect from the RPi to the PC) and that is what SSHFS is effectively doing.  So check for two things:

    • Is the ssh server running on the PC?  You can check for its status via the command cygrunsrv -Q sshd. In my case it was running, so its fine.
    • Is the port used by the ssh server on the PC open? You’ll need to open SSH port 22 for ssh services to work.  You can check its status by attempting to use it.  In my case, this was ssh Jeff@HomePC.home.  If this command appears to hang or time out (as it did for me), the port is likely blocked.  You’ll need to go to your Windows Firewall and open port 22.

There is another Cygwin sublimity that has to be taken into consideration.  When using the Cygwin, Windows drive letters are mapped to a special directory.  In my case, the Dropbox directory appears to Cygwin to have the following path: /cygdrive/c/Users/Jeff/Dropbox.

With this all addressed, reboot the RPi, and then you can now fire up you RPi Dropbox via:

sshfs Jeff@HomePC.home:/cygdrive/c/Users/Jeff/Dropbox ~/Dropbox

After you supply the PC’s password, you should now be able to access the Dropbox directory on the PC.  If you wish, you can remove the file system connection to the PC via the command:

fusermount -u ~/Dropbox

This connection will stay established as long as you don’t do the fusermount -u or reboot the RPi.  If you wish to mount the file system upon boot-up, and avoid executing the sshfs when you log-in, you can follow the procedure outline in the article that initially inspired me: Dropbox on Raspberry Pi via SSHFS

Something to Keep in Mind

While for the most part, moving between Windows/DOS and the Linux file systems isn’t a problem, there is one thing to remember. Windows-based text editors put one set of special characters at the end of lines (i.e. carriage return and line break = ‘\r\n’), while Unix/Linux puts other characters (i.e. line break = ‘\n’).  This odd anomaly is normally harmless, but some applications on a Linux cannot understand these characters and can cause Linux to not respond correctly.

The best example of Linux behaving badly (and the only one I know) is the execution of “shebang” or the “#!…” at the top of a bash, python, perl, etc. script.  If you edit these files in DOS, then move them to Linux, shebang will stop working.  Editing them under DOS is the origin of the problem, since a DOS based text editor will inject the extra carriage return character at the end of the text line.

To fix this problem, you can quickly convert an ASCII text file from DOS format (carriage return and line break) to the Unix format (line break), you can use the tool dos2unix.  Run this utility on the effected file and shebang should work once again.

Epilogue

At its foundation, SSH functions as a protocol for authenticating and encrypting remote shell sessions.  SSH can be thought of as much more than just a secure shell.  Using SSH’s foundation, SSHFS creates a new capability.  To learn more, check out the link SSH: More than secure shell.

Key sources I consulted to write this include:

SendEmail as a Messaging Tool for the Raspberry Pi

In the projects I envision for the future, I’ll be using my Raspberry Pi (RPi) as a gateway/server/controller for several other devices.  There is likely to be a need to generate status reports/messages and mail them out. It could be as simple as a notification that the deck lights have been turned-on. I don’t need a full fledged mail client on the RPi to receive mail or manage a mailbox, just a command line utility to send email.  Also, I would like to send short text messages via (SMS) to my cell phone.  Linux does have a nice solution for this.

You do need an established email account with some email provider. I want to keep my personal email and my RPi’s email separate  so I setup a special email account on gmail.  This will be used only by my Raspberry Pi’s (or other intelligent devices). There exist some open SMTP relay mail servers (mail servers that will not require a login nor a password) but many open mail relays have become unpopular and closed due to their exploitation by spammers and worms.

SendEmail

SendEmail is a lightweight, completely command line based, SMTP email agent. It is written in Perl and designed to be used on the command line, in bash scripts, Perl programs, within web sites, etc.

I installed SendEmail on my RPi via this command:

sudo apt-get install sendemail

Testing sendEmail

When I ran sendEmail the first time, it complained about some missing libraries.  I installed the missing libraries and this cleared the error.  Clearly, the sendEmail package needs some work since this dependency should have been taken care of by apt-get.

I ran it again using this command:

sendEmail -f pi@RedRPi -t my_user_name@verzion.net -u "Test Email from RedRPi" -m "My test message." -s smtp.gmail.com:587  -o tls=yes -xu my_user_name -xp my_password

With this, sendEmail threw an error message:

invalid SSL_version specified at /usr/share/perl5/IO/Socket/SSL.pm line 332

I did a web search and found that this is a reported bug within sendEmail (bummer), but I also found a simple patch for the problem (lucky break).  I applied the fix, executed the command again, and succeeded in sending the email.

One of the key parameter used here is the SMTP mail relay specified in  “-s smtp.gmail.com:587“.  In this case, Gmail uses port 587 for relay email.  The default port to use is 25 but not all email servers use this port.

Another key parameter is “-o tls=yes“. This specifies that the Transport Layer Security (TLS) protocol will be used to provide communication security over the Internet.  This is important since your including a plain-text password in the command.

SMS Messaging

Another messaging mechanism that I plan to use is Short Message Service (SMS).  To do this, you can use a SMS gateway which will transform an email into an SMS message.  The down side is that there isn’t a single gateway but one for each of the cellular carries.

Here is an example for AT&T cell phones:

sendEmail -f pi@RedRPi -t cell_phone_number@txt.att.net -u "Test Email from RedRPi" -m "My test message." -s smtp.gmail.com:587  -o tls=yes -xu my_user_name -xp my_password

WiFi (with WEP security) on Raspberry Pi

The Raspberry Pi Linux distribution I’m using is Adafruit’s Occidentalis.  It supports WiFi out of the box and appears easy to configure.  But as noted by Adafruit, adding peripherals to the RPi may increase the loading on the power supply to your board and this, in turn, may affect the voltage presented to the RPi.

This is clearly the case, even for the tiny  OURlink WiFi (802.11b/g/n) USB Adapter (uses the RTl8192cu chip which is supported by Debian Linux) I purchased from Adafruit.  When I plugged it into the RPi, it became unstable and crashed.  Adafruit advises that you can over come this by attach the RPi’s USB port to a powered hub.  (Note that all USB hubs aren’t powered or powered sufficient, and therefore, not all are  recommended.  I used a Dynex 4 Port Hub with a 5V 2.1A power adapter and all seem fine.)  If you find using a using a USB hub completely unacceptable, you could make some RPi board modifications to the polyfuses, but this isn’t the “official/supported” approach for this power problem …. but first …. see the Epilogue below.

My First Attempt (Unsuccessful)

Once I got the RPi USB port properly powered, I followed the Adafruit’s instructions.  I updated the/etc/network/interfaces file with the following:

########## DID NOT WORK FOR ME ##########
# The loopback network interface
auto lo
iface lo inet loopback

# The primary (wired) network interface
iface eth0 inet dhcp

# The wifi (wireless) network interface
auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
     wpa-ssid YOUR_SSID
     wpa-psk YOUR_WEP_KEY

I ran  ifconfig -a and got the following:

This tells me that Linux sees the WiFi device and assigned it device name wlan0. It also says there isn’t an IP address assigned and no data is moving.  Appears that network interface wlan0 isn’t running so I tried bring it up with sudo ifup wlan0 and I got the following:

No IP assigned … now what?

This Worked … But

After the typical thrashing about, it came to me that I’m not using WAP security (which is implied by the/etc/network/interfaces file content) but I’m using WEP.  I did some web searching and found a site that claimed to address Debian WiFi WEP configuration.  This provided me the needed command syntax for the solution.   I updated the/etc/network/interfaces file with the following:

# The loopback network interface<
auto lo
iface lo inet loopback

# The primary (wired) network interface
iface eth0 inet dhcp

# The wifi (wireless) network interface
auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
       wireless-essid YOUR_SSID
       wireless-key YOUR_WEP_KEY

I then ran sudo ifup wlan0 to start the wireless networking (Note: you can use sudo ifdown wlan0 to turn-off the wireless network).  This time DHCP discovery appeared to work.  I then ran ifconfig -a giving me the display below with an assigned wireless IP.

The wireless device now has an IP address and data seems to be flowing.  In an effort to further convince myself that the WiFi was working, I disconnected the wired ethernet connection and attempted to re-login in via ssh -X pi@RedRPi.local, over the wireless interface. This failed, giving the message:

ssh: Could not resolve hostname RedRPi.local: hostname nor servname provided, or not known

Working For Sure

I suspected (after more thrashing about) it was Ssh or Avahi/Bonjour or both that was getting in the way.  So I did the following:

    1. I cleaned out the ~/.ssh/known_hosts file on the PC from which I’m accessing the RPi (I’m using Cygwin with Openssh). With the entries in the file removed  ssh keys would need to be recreated on next login.
    2. I then logged into the RPi in via ssh -X pi@RedRPi.local. The login created an entry the ~/.ssh/known_hosts file on the PC.
    3. Using vi, I edited the  ~/.ssh/known_hosts file.  I duplicated the one existing record but changed the  IP address to the wireless address.
    4. I restarted the openssh on the PC.  (I terminated all the Cygwin window and restarted them.  I could get anything else to work short of a PC reboot).
    5. I then logged in using ssh -X pi@192.168.1.7. Now I’m wireless!!

My ~/.ssh/known_hosts file looks like this:

Epilogue

I have found that if  I don’t use a USB  powered hub and I plug in the OURlink WiFi (802.11b/g/n) USB Adapter while the RPi is up and running, the RPi will crash.  The good news is that, once the RPi reboots, it runs fine without the powered hub.

So, go ahead and use the WiFi USB Adapter, without the powered hub, but make sure the adapter is plugged in when you boot up …. problem solved!

Conky for the Raspberry Pi

Conky  is a Linux system monitor tool using X Windows.  Conky is highly configurable and is able to monitor many system variables including the status of the CPU, memory, swap space, disk storage, temperatures, processes, network interfaces, battery power, system messages, e-mail in-boxes  Linux updates, runs many popular music players, and much more. Unlike system monitors that use high-level widget tool-kits to render their information, Conky is drawn directly in an X window, allowing it to consume relatively fewer system resources.

To install the standard Conky package, use the following:

sudo apt-get install conky-std

Two sites you will want to read, beyond the Conky manual page are the lists of Config Settings and Variables. You use the Config Settings to describe general features of how you want your Conky to appear, and the variables to define what actually gets displayed.

The color names that are used within Conky are the X11 colors located in /usr/share/X11/rgb.txt.  There isn’t a standard set of colors to be found on any X Window system, so you’ll need to inspect this file to get some idea of what color names you can use.  This X color name list, which appears to be larger than what is in the RPi’s rgb.txt file, could help you visualized the colors.

Conky uses a configuration file location in $HOME/.conkyrc.  Conky can be configured in an amazing number of way but I’m using the following configuration on the RPi:


# --------------------------------------------------------------------------------------------- #
#
# .conkyrc - derived from various examples across the 'net
#
# Some of the sites that proved most usful include:
#   http://mylinuxramblings.wordpress.com/2010/03/23/how-to-configure-the-conky-system-monitor/`
#   http://crunchbanglinux.org/wiki/conky
#   http://lusule.wordpress.com/2008/08/07/how-to-4/
#
# --------------------------------------------------------------------------------------------- #

# -------------------- Conky's Run Time Parameters -------------------- #

update_interval 2.0                     # Conky update interval in seconds
total_run_times 0                       # Number of updates before quitting.  Set to zero to run forever.
no_buffers yes                          # Subtract file system buffers from used memory?
cpu_avg_samples 2                       # Number of cpu samples to average. Set to 1 to disable averaging
net_avg_samples 2                       # Number of net samples to average. Set to 1 to disable averaging

# -------------------- Conky's General Look & Feel -------------------- #

# --- defualt values --- #
default_color grey                      # Default color and border color
default_bar_size 0 6            # Specify a default width and height for bars.
default_gauge_size 25 25        # Specify a default width and height for gauges.
default_graph_size 0 25         # Specify a default width and height for graphs.
default_outline_color green     # Default border and text outline color
default_shade_color yellow      # Default border and text shading color

# --- predefined colors - http://www.kgym.jp/freesoft/xrgb.html --- #
color0 FFFFFF                           # white
color1 FFA500                           # orange
color2 B22222                           # firebrick
color3 696969                           # dim gray
color4 D3D3D3                           # light gray
color5 2F4F4F                           # dark slate gray
color6 FFEC8B                           # light golden rod
color7 54FF9F                           # sea green
color8 FF8C69                           # salmon
color9 FFE7BA                           # wheat

# --- window layout & options --- #
own_window yes                          # Conky creates its own window instead of using desktop
own_window_type normal          # If own_window is yes, use type normal, desktop, or override
own_window_transparent yes      # Use pseudo transparency with own_window?
own_window_colour blue          # If own_window_transparent is no, set the background colour
double_buffer yes                       # Use double buffering (reduces flicker)
use_spacer right                        # Adds spaces to stop object from moving
maximum_width 600                       # Maximum width of window in pixels
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager

# --- window placment --- #
alignment top_right

# --- borders, margins, and outlines --- #
draw_graph_borders yes          # Do you want to draw borders around graphs
border_inner_margin 9           # Window's inner border margin (in pixels)
border_outer_margin 5           # Window's outer border margin (in pixels)
gap_x 10                                        # Gap between borders of screen and text (on x-axis)
gap_y 40                                        # Gap between borders of screen and text (on y-axis)
border_width 10                         # Window's border width (in pixels)

# --- Text --- #
draw_outline no                         # Do you want ot draw outlines
draw_shades no                          # Do you want to draw shades
draw_borders no                         # Do you want to draw borders around text
uppercase no                            # set to yes if you want all text to be in uppercase
use_xft yes                                     # use the X FreeType interface library (anti-aliased font)
xftfont Monospace:size=8:weight=bold    # Xft font to be used

# -------------------- Conky's Displayed System Monitoring Parameters -------------------- #
TEXT
# Title / Banner message
${color5}
${alignc 40}${font Arial Black:size=22}${time %H:%M:%S}${font}
${alignc}${time %A} ${time %B} ${time %d}, ${time %Y}
$color

# General system information
${color1}SYSTEM INFORMATION ${hr 2}$color
${color0}System: $color$nodename ${alignr}${color0}Uptime: $color$uptime
${color0}Kernel: $color$kernel${alignr}${color0}Arch: $color$machine
${color0}Frequency: $color$freq MHz
${color0}Serial No.: $color${execi 99999 grep Serial /proc/cpuinfo | awk '{ print $3 }'}
${color0}MAC Address: $color${execi 99999 cat /sys/class/net/eth0/address }

# CPU information
${color1}CPU ${hr 2}$color
${color0}Avg. Load: $color $loadavg
${color0}CPU Temperature: $color${acpitemp}°C
${color0}CPU Usage:$color $cpu% ${color7}${cpubar}
${cpugraph 0000ff 00ff00}$color

# Top running processes
${color1}TOP 5 PROCESSES ${hr 2}$color
${color0}Processes:$color $processes  ${color0}Running:$color $running_processes
${stippled_hr 2}
${color0}CPU Usage$color
${color3} NAME              PID    CPU %   MEM$color
${color2} ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1}$color
 ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2}
 ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3}
 ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4}
 ${top name 5} ${top pid 5} ${top cpu 5} ${top mem 5}
${stippled_hr 2}
${color0}Mem Usage$color
${color3} NAME              PID    CPU %   MEM$color
${color2} ${top_mem name 1} ${top_mem pid 1} ${top_mem cpu 1} ${top_mem mem 1}$color
 ${top_mem name 2} ${top_mem pid 2} ${top_mem cpu 2} ${top_mem mem 2}
 ${top_mem name 3} ${top_mem pid 3} ${top_mem cpu 3} ${top_mem mem 3}
 ${top_mem name 4} ${top_mem pid 4} ${top_mem cpu 4} ${top_mem mem 4}
 ${top_mem name 5} ${top_mem pid 5} ${top_mem cpu 5} ${top_mem mem 5}

# Memory and swap space untilization
${color1}MEMORY & SWAP ${hr 2}$color
${color0}RAM Usage: ${color}$mem / $memmax
$memperc% ${color6}${membar}$color
${stippled_hr 2}
${color0}Swap Usage: ${color}$swap / $swapmax
$swapperc% ${color6}${swapbar}$color

# File System utilization
${color1}FILE SYSTEM ${hr 2}$color
${color0}SD Card:$color ${fs_used /} / ${fs_size /}
${fs_used_perc /}% ${color8}${fs_bar /}$color
${stippled_hr 2}
${color0}Reads: $color$diskio_read/s${alignr}${color0}Writes: $color$diskio_write/s
${color8}${diskiograph_read 20,100 33FF00 FF3333 scale -t}$color${alignr}${color8}${diskiograph_write 20,100 33FF00 FF3333 scale -t}$color

# Ethernet utilization
${color1}NETWORKING ${hr 2}$color
${color0}Wired (${addr eth0})
${color0}Down:$color ${downspeed eth0}/s ${alignr}${color0}Up:$color ${upspeed eth0}/s
${color0}Total:$color ${totaldown eth0} ${alignr}${color0}Total: $color${totalup eth0}
${color0}${downspeedgraph eth0 25,120 000000 00ff00} ${alignr}${upspeedgraph eth0 25,120 000000 ff0000}$color
${stippled_hr 2}
${color0}Wireless (${addr wlan0})
${color0}Down:$color ${downspeed wlan0}/s ${alignr}${color0}Up:$color ${upspeed wlan0}/s
${color0}Total:$color ${totaldown wlan0} ${alignr}${color0}Total: $color${totalup wlan0}
${color0}${downspeedgraph wlan0 25,120 000000 00ff00} ${alignr}${upspeedgraph wlan0 25,120 000000 ff0000}$color

# Print the tail of the Linux message log
${color1}LOG FILES ${hr 2}$color
${color0}Linux Message Log$color
${color4}${font Arial:size=6}${execi 30 tail -n3 /var/log/messages | fold -w50}$color$font

Debugging Conky

An easy way to force Conky to reload your ~/.conkyrc configuration file is to us the command killall -SIGUSR1 conky. This saves you the trouble of having to kill and then restart.  I also discovered that  while conky is running and your concurrently editing the .conkyrc file in vi, saving the file appears to cause conky to restart and read the new .conkyrc … nice.

Controlling and Viewing the Raspberry Pi GPIO via PC Browser

I discovered a post that concerned controlling the Raspberry Pi’s GPIO via a browser. This idea of controlling my Raspberry Pi (RPi), and the things its networked with, via an internet browser is at the heart of what I would like to do with the assortment of Arduino and Xbee devices I’m assembling.  To explore how best to do this, I’m considering using WebIOPi, which is a web application used to control your RPi’s GPIO.  I believe it could be useful as a test tool, but more importantly, I suspect that I could learn how to engineer my application by studying its design.

Install WebIOPi

When installing WebIOPi on my RPi, I followed the installation instructions for the Apache version.  I choose this version since  I’ll be using the Apache web server for other features as my project evolves. Note that there is a small error on the instructions if you use a symbolic link to the webiopi directory.  Create this link using

sudo ln -s /home/pi/webiopi /var/www/webiopi

Immediately after installation,  you can test to see if you can render a web page.  Assuming that your  Raspberry Pi is connected to your network  and its named raspberrypi, you can open a browser to http://raspberrypi/webiopi/ with your network PC.  It might work but your likely to get a error, something like “…Could not reliably determine the server’s fully qualified domain name…” and the solution is to give your web server a name.

To do this,  create this Apache config file:

sudo vi /etc/apache2/conf.d/fqdn

Enter ServerName raspberrypi into this file and restart Apache using

sudo /etc/init.d/apache2 restart

Installing GPIO Utilities

While checking on the status of of the Python based GPIO package on the RPI using the command dpkg -l | grep gpio, I concluded that the  Occidentalis distribution I’m using doesn’t have any Python libraries for GPIO.

Picking up some tips from Raspberry Pi E-mail Notifier Using LEDs.  I determined that I need to install several python packages first.  I did this via

sudo apt-get install python
sudo apt-get install python-dev
sudo apt-get install python-pip

With this done, now its time to install the required Python libraries but first, update the Python distribution by running

sudo easy_install -U distribute

Finally you can install the Raspberry Pi GPIO (General Purpose Input/Ouput) library:

sudo pip install RPi.GPIO

What did I find

WebIOPi  supports binary GPIOs, in both input and output.  That is, you can set a GPIO output pin high/low via a browser pick.  Also, you can see the state of a GPIO pin.  Equally important to me is that WebIOPi auto-refreshes, via WebAPI, REST, JSON and AJAX I assume.  Therefore, when the GPIO pins change state, the browser automatically is updated with the new status.  And this happens for all browsers displaying WebIOPi.  You can demonstrate this by opening two browsers pointing at WebIOPi.  Action performed in one browser will also appear in the other.

Test Script

I used this code to generate some random activity on the GPIO pins and test WebIOPi.

#!/usr/bin/env python

import RPi.GPIO as GPIO, time

BLINK_FREQ = 3                  # refresh GPIO pins every 3 seconds

GPIO.setmode(GPIO.BCM)
GPIO.setup(0, GPIO.OUT)
GPIO.setup(1, GPIO.OUT)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.setup(10, GPIO.OUT)
GPIO.setup(9, GPIO.OUT)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(23, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(25, GPIO.OUT)
GPIO.setup(8, GPIO.OUT)
GPIO.setup(7, GPIO.OUT)

i = 0
while True:
                if i == 0:
                                GPIO.output(0, True)
                                GPIO.output(1, False)
                                GPIO.output(4, False)
                                GPIO.output(17, True)
                                i = i + 1
                elif i == 2:
                                GPIO.output(0, False)
                                GPIO.output(1, True)
                                GPIO.output(4, True)
                                GPIO.output(17, False)
                                i = i + 1
                elif i == 1:
                                GPIO.output(7, False)
                                GPIO.output(8, True)
                                GPIO.output(25, True)
                                GPIO.output(23, False)
                                i = i + 1
                elif i == 3:
                                GPIO.output(7, True)
                                GPIO.output(8, False)
                                GPIO.output(25, False)
                                GPIO.output(23, True)
                                i = i + 1
                elif i == 4:
                                GPIO.output(21, True)
                                GPIO.output(22, False)
                                GPIO.output(10, False)
                                GPIO.output(9, True)
                                GPIO.output(11, True)
                                GPIO.output(18, True)
                                i = i + 1
                elif i == 5:
                                GPIO.output(21, False)
                                GPIO.output(22, True)
                                GPIO.output(10, True)
                                GPIO.output(9, False)
                                GPIO.output(11, False)
                                GPIO.output(18, False)
                                i = i + 1
                else:
                                i = 0
                time.sleep(BLINK_FREQ)

Alternative Approaches

The use of a Web page to control the RPi seems useful enough but what if the target environment for launching control messages is a cell phone?  Maybe a phone app would be a better approach.  Check out the post  Raspberry Pi + iPhone: Control a RPi with an iPhone in 2 Minutes.

Blog Stats

  • 611,037 hits

Join 58 other followers

Jeff’s Skinner Box Gravatar

%d bloggers like this: