My life as an ScalaFx newbie!

Learning Scala coming from Delphi (object Pascal) and windows is an exercise in frustration. The fact that I haven’t done much programming since 2002 doesn’t help.

Why on earth do I keep learning Scala? Because its nice! Frustrating but nice! It is cross platform and has a nice syntax. It makes god looking code.

There is not a whole lot of newbie tutorials and examples out there when it comes to Scala itself. For ScalaFx there is even less…

After stumbling around in Scala and learning the very basic I decided to build an application that fetches temperature values from an Raspberry Pi at home and displays them.  Since Scala runs on Javas JRE , I started out with swing, then i turned to ScalaFx since it is more modern and has a lot of possibilities. Now it’s up and running. There is still a few snags to fix. But it’s there and it does what I intended.

The first hurdle was to decode the json output from the api on my webserver. As usual I didn’t have a clue, but stackoverflow once again came to my rescue. Here is the Q/A on stackoverflow.com.

I created a simple gui in ScalaFx and got stuck really fast. It makes no sense getting the temps from the Raspberry more often than once every minute. Easy peasy! An infinite loop whith a wait method should do the trick…. But creating an infinite loop was not the answer. In Delphi I would have dropped a Ttimer object on my window and problem would have been solved.
It took me some hours of googling and reeding before I found a timer function that solved the problem. Everything works as intended except for one annoying and important thing. It will not close! The gui shuts down alright but the timer function does not. If any one know how to handle an exit event in ScalaFx please help me out!!!! I can’t find anything in the ScalaFx documentation, stackowerflow or google.

I guess I figure it out after banging my head against it for a couple of weeks…

 

Internet Radio – Buttons and Usb sound card

I have made some progress with the Raspberry Pi Internet Radio. It is time to get a good casing and mount the hardware!

The audio from an Raspberry Pi is of fairly low quality with very high noise and low volume. Crappy sound is a no no so I bought a usb sound card, Roccat Juke. It worked right out of the box. Just plugged it in at booted up the Pi.

A Roccat Juke usb soundcard attached to a Raspberry Pi 2.
Roccat Juke Usb sound card

Unfortunately mpc could no longer change the volume. After googling around I tried using the alsa command line mixer “amixer” to change volume. It took a lot of trials and errors before i got the hang of it. “Man amixer” gave a lot of info but i couldn’t sort out increasing/decreasing the volume by steps. The answer was to set the volume step to x+/x- instead of +x/-x. Rather obvious, but it took a long time to figure that out.

I added 5 buttons connected to GPIO pins. So no I can control volume and change radio station!

Rasberry Pi 2, a usb sound card and a breadboard
Pi and breadbord

 

An LCD-display on a breadboard displaying date and channal on an internet radio
Internet Radio display

I gave up on scrolling text. Scrolling through 45 characters with a rate of 0.3 chars/second takes  13.5 seconds. Since the routine that listens for button presses is in the same continuous loop as the scrolling routine I had to ditch the scrolling. Now I have to find a better solution. For the time being I will only show the station name and the date.

I guess that running threads is a better solution. Learning about threads have to wait until I have found a case for the radio and mounted everything.

Swedish radio have channels  names that often are longer than 16 characters. Ex. “Sveriges Radio P1”. Since the three channels i listens most to, P1, P2 and P3, displays as “Sveriges Radio P” I chose to remove “Sveriges Radio” from the string.

To get the volume information from amixer I am using a loooonnnnggg bash command. Not pretty!

"amixer -c 1 -- get Headphone Playback | tail -n 1 | cut -d \"[\" -f1 | cut -d \":\" -f2 | cut -d \" \" -f3")

If someone has a more elegant solution I would be grateful if you could point me in the right direction. (I guess i have to learn awk ;-D)

/Jan

 

 

The source code to my internet radio:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Example code from Adafruit that I used as a template
# for displaying info from mpc/mpd streaming
import os
import time
import Adafruit_CharLCD as LCD
import RPi.GPIO as GPIO
from subprocess import *
from datetime import datetime

GPIO.setmode(GPIO.BCM)

GPIO.setup(5, GPIO.IN)
GPIO.setup(6, GPIO.IN)
GPIO.setup(13, GPIO.IN)
GPIO.setup(19, GPIO.IN)



# Raspberry Pi pin configuration:
lcd_rs        = 27  # Note this might need to be changed to 21 for older revision Pi's.
lcd_en        = 22
lcd_d4        = 25
lcd_d5        = 24
lcd_d6        = 23
lcd_d7        = 18
lcd_backlight = 4


# Define LCD column and row size for 16x2 LCD.
lcd_columns = 16
lcd_rows    = 2

lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7,
                                                        lcd_columns, lcd_rows, lcd_backlight)
showClock = True

def convertoutString(inString):
# Replaces åäö and ÅÄÖ with aa ae oe
   outString = inString
   outString = outString.replace("Å", "Aa")
   outString = outString.replace("å", "aa")
   outString = outString.replace("Ä", "Ae")
   outString = outString.replace("ä", "ae")
   outString = outString.replace("Ö", "Oe")
   outString = outString.replace("ö", "oe")
   outString = outString.replace("Sveriges Radio ", "")
   return outString

def scrollDisplay(text, intervall):
    # preparing the text so the lenght is a multiple of 16. 
    # The extra blank is for to be shure that there is a space between 
    # the begging and end of the text when scrolling.
    # To ensure that strings longer than 40 char is displayed correct
    # I only display the first 16 char
    message = text
    message = message + " "
    raknare = len(message) + ((16-len(message) % 16))
    lcd.message(datetime.now().strftime('%y%m%d %H:%M:%S \n'))

    # Adding blanks to make the string a multiple of 16
    # This assures that the scrolled line is empty before
    # iterating again
    message = message + " " * raknare
    lcd.message(message[:16])
    time.sleep(1)
    for i in range(raknare-1):
    # Moving first charachter to the end of the string and then
    # writes the first 16 chars to LCD
        lcd.clear()
        primus = message[:1]
        message = message[1:] + primus
        lcd.message(datetime.now().strftime('%y%m%d %H:%M:%S \n'))
        lcd.message(message[:16])
        time.sleep(intervall)
    return

def run_cmd(cmd):
    #Preparing to rund shell commands
    p = Popen(cmd, shell=True, stdout=PIPE)
    output = p.communicate()[0]
    return output


lcd.clear()
#replacing åäö
message = convertoutString(" Internetradio! \n      Busk      ")

#print(message)
lcd.message(message)
time.sleep(1)
lcd.clear()

#Getting radio station information from the MPD server
cmd = "mpc current | cut -d \":\" -f1"

lcd.clear()

while 1:
#Sending the mpc information to the LCD
  mpcstatus = run_cmd(cmd)
  mpcstatus = convertoutString(mpcstatus)
  lcd.clear()
  lcd.message(datetime.now().strftime('%y%m%d %H:%M:%S \n') + mpcstatus)
  #scrollDisplay(mpcstatus, 0.3)

  # Listening for button pressed
  if (GPIO.input(5)==False):
    os.system('mpc prev')
    time.sleep(0.1)
    lcd.clear()

  if (GPIO.input(6)==False):
    os.system('mpc next')
    time.sleep(0.1)
    lcd.clear()

  if (GPIO.input(13)==False):
    os.system('amixer -c 1 -- set Headphone Playback 10-')
    mpcvolume = "Volym: " + run_cmd("amixer -c 1 -- get Headphone Playback | tail -n 1 | cut -d \"[\" -f1 | cut -d \":\" -f2 | cut -d \" \" -f3")
    lcd.clear()
    lcd.message(mpcvolume)
    time.sleep(0.5)
    lcd.clear()

  if (GPIO.input(19)==False):
    os.system('amixer -c 1 -- set Headphone Playback 10+')
    mpcvolume = "Volym: " + run_cmd("amixer -c 1 -- get Headphone Playback | tail -n 1 | cut -d \"[\" -f1 | cut -d \":\" -f2 | cut -d \" \" -f3")
    lcd.clear()
    lcd.message(mpcvolume)
    time.sleep(0.5)
    lcd.clear()

 

Displaying on Rasberry Pi internet radio!

Writing station and song information to the LCD-display has not really worked out for me. I used the example from https://github.com/adafruit/Adafruit_Python_CharLCD.git to have a as a starting point.

Adafruits Adafruit_CharLCD library has a scroll function that seemed to be a good solution if a string is longer then 16 characters. I kind of worked. It displays the text, but it looks like shit if the string is longer than about 40 characters.

After some fiddling around I decided to write my own routine to scroll text on the display. Another annoying issue is Swedish characters like “åäö”. I can’t find a way to make them show on the display. The quick and dirty solution is a function that replaces them. Å becomes Aa. Ä becomes Ae and Ö becomes Oe. There are still characters that don’t display as expected. For example: ‘ becomes ? on the display. So there is still work to be done.

Here is my source code!

I am sure that there is better and more efficient ways of doing this. If you have a better solution or have a question please feel free to make comment.

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Examplecode from Adafruit that I used as a template
# for displaying info from mpc/mpd streaming
import time
import Adafruit_CharLCD as LCD
from subprocess import *
from datetime import datetime



# Raspberry Pi pin configuration:
lcd_rs        = 27  # Note this might need to be changed to 21 for older revision Pi's.
lcd_en        = 22
lcd_d4        = 25
lcd_d5        = 24
lcd_d6        = 23
lcd_d7        = 18
lcd_backlight = 4


# Define LCD column and row size for 16x2 LCD.
lcd_columns = 16
lcd_rows    = 2

lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7,
                                                        lcd_columns, lcd_rows, lcd_backlight)

def convertoutString(inString):
# Replaces åäö and ÅÄÖ with aa ae oe
   outString = inString
   outString = outString.replace("Å", "Aa")
   outString = outString.replace("å", "aa")
   outString = outString.replace("Ä", "Ae")
   outString = outString.replace("ä", "ae")
   outString = outString.replace("Ö", "Oe")
   outString = outString.replace("ö", "oe")
   return outString

def scrollDisplay(text, intervall):
    # preparing the text so the lenght is a multiple of 16. 
    # The extra blank is for to be shure that there is a space between 
    # the begging and end of the text when scrolling.
    # To ensure that strings longer than 40 char is displayed correct
    # I only display the first 16 char
    message = text
    message = message + " "
    raknare = len(message) + ((16-len(message) % 16))
    lcd.message(datetime.now().strftime('%y%m%d %H:%M:%S \n'))

    # Adding blanks to make the string a multiple of 16
    # This assures that the LCD shows only blanks before
    # iterating again
    message = message + " " * raknare
    lcd.message(message[:16])
    time.sleep(1)
    for i in range(raknare-1):
    # Moving first charachter to the end of the string and then
    # writes the first 16 chars to LCD
        lcd.clear()
        primus = message[:1]
        message = message[1:] + primus
        lcd.message(datetime.now().strftime('%y%m%d %H:%M:%S \n'))
        lcd.message(message[:16])
        time.sleep(intervall)
    return

def run_cmd(cmd):
    #Preparing to rund shell commands
    p = Popen(cmd, shell=True, stdout=PIPE)
    output = p.communicate()[0]
    return output


lcd.clear()
#replacing åäö
message = convertoutString(" Internetradio! \n      Busk      ")

#print(message)
lcd.message(message)
time.sleep(1)
lcd.clear()

#Getting information from the MPD server
cmd = "mpc current"

lcd.clear()

while 1:
#Sending the mpc information to the LCD
  mpcstatus = run_cmd(cmd)
  mpcstatus = convertoutString(mpcstatus)
  scrollDisplay(mpcstatus, 0.3)

 

Another internet radio project

We moved in to a new apartment about a month ago from an open plan solution to a more traditional to bedroom flat with a separate kitchen. Not being able to use our home theatre receiver, my wife wanted a radio in the kitchen and that was all it took to get me in Pi mode.

I googled and found a ton of projects with some really good links, almost all based on adafruits tutorials. Adafruit internet radio overwiev and Adafruit touchscreen internet radio

The parts list is still a work in progress. I had an 16×2 lcd display and a Raspberry Pi 2 laying around so I decided to put them to good use in this project. Speakers, sound card and is still to bee decided.

I have followed the touchscreen tutorial as far as choosing mpc/mpd as the software for my internet radio. This tutorial from Rolf van Gelder at CAGE web design helped me getting started.

Displaying info from mpc to the LCD-display haven’t worked out as well as I hoped so I’ll get back to that in the next post.

/Jan