Friday, November 23, 2012

Gimme some Pi... (Part I)

Hi there,
long time no post...sorry for that but now I'm back on track and today I will continue writing about my embedded project.
Like I mentioned in my last post the idea was to create some kind of a temperature monitor that is capable of measuring the temperature, visualizing it and send messages to a desktop client and/or mobile client.
First I thought I would only need the BeagleBoard to realize that but in the meantime I remembered that I also own a Raspberry Pi which leads me to a new solution. The following drawing should try to explain the new idea...


So the idea was like this, the Raspberry Pi should be used to measure the temperature and send the measured data to the BeagleBoard. For this job the Raspberry Pi doesn't need a display because it should simply start measuring and sending data as soon as it's switched on.
The BeagleBoard should act as some kind of control center which visualizes the data and defines a threshold for notification. It should also control the kind of notification that will be send to the connected clients. In addition the BeagleBoard should control a signal tower that indicates the current temperature. In my example I decided I would like to measure the room temperature and therefor I defined different temperature ranges like follows

  • RED       -> temperature between 0°C - 16°C (too cold)
  • YELLOW -> temperature between 16°C - 20 °C (a bit to cold but ok)
  • GREEN -  > temperature between 20°C - 24°C (perfect)
  • YELLOW -> temperature between 24°C - 28°C (a bit to warm but ok)
  • RED       -> temperature > 28°C (too warm)

These ranges should be visualized by the gauge on the lcd display and also by the signal tower which is cabable of showing GREEN, YELLOW and RED light. To be able to control the signal tower a USB relay card should be used.
The BeagleBoard now sends messages to another client (desktop or mobile) each time the temperature changes to another temperature range, or when the temperature exceeds a given threshold or goes back to "normal" (which means below the threshold).
So the Raspberry Pi should run on Java7 embedded and the BeagleBoard on Java7 in combination with JavaFX. On the desktop I will also use JavaFX to visualize the data.

So that was the plan...


Hardware needed for the Raspberry Pi setup

The Raspberry Pi Model B 256MB or 512MB (order it here) 32.88 €


The Edimax USB WiFi adapter (order it here) 10.80 €

The TM-RS232 temperature sensor (order it here) 20.40 €



The Serial-USB adapter with FTDI chip (order it here) 18.99 €

A powered USB hub (order it here)  24.99 €
That means you will get a temperature monitor that could be programmed in standard Java for around 110 € which is not to bad (if you don't need WiFi and a powered USB hub it's even only around 73 €).


Setting up the Raspberry Pi

  • Setup a SD card with a linux image
  • Install Java7 embedded
  • Install a WiFi USB stick
  • Attach a temperature sensor to USB
  • Write some code to measure the temperature and send the data
  • Setup autostart of the program
  • Setup autologin of the pi user

1. Setup a SD card with a linux image

  • To setup linux for the Raspberry Pi you have to download the Raspbian softfloat image from here.
  • To install the image on the SD card simply follow the instructions you could find here. (Resizing the partition is easy in this image because you could do it in the Raspberry config tool at the first boot).


2. Install Java7 embedded

  • Go the the Oracle Java embedded website and download the Java 7u6 for ARMv6/7, Linux - Headless EABI, VFP, SoftFP ABI, Little Endian. You could also use this link to download it.
  • To install Java on the Pi follow these steps

      First of all login to the Pi and create a folder for java

$ ssh pi@RASPERRY_IP mkdir /home/pi/java


      Copy the Java7u6 tar file to the Pi

$ scp ~/ejre-7u6-fcs-b24-linux-arm-vfp-client_headless-10_aug_2012.tar.gz pi@RASPBERRY_IP:/home/pi/java


      Login to the Pi and unpack the Java download

$ ssh pi@RASPBERRY_IP
$ cd /home/pi/java
$ tar -zxvf *.gz


      Remove the tar file

$ rm /home/pi/java/*.gz


3. Install the WiFi USB stick

  • Getting WiFi to work on the Raspberry Pi is not that easy but fortunately for the adapter I bought you could find a very nice script created by Mr. Engman that does the whole setup for you. You could find it including instructions here or the version I used is also available on my dropbox. Please make sure that you plug the WiFi USB stick to the powered USB hub.
  • To edit your WiFi settings please do the following
      Open the interfaces file with nano
$ nano /etc/network/interfaces

      Make sure you have the following text in the file
auto wlan0
iface wlan0 inet dhcp
wpa-ssid "YOUR WIFI SSID"
wpa-psk "WIFI PASSWORD"
  • Disconnect the Raspberry Pi from the wired network and reboot it. Now you should see the Pi on your network. To get the local IP address on the Pi you could type in the following command.
$ sudo /etc/rc.local


4. Attach the serial temperature sensor
  • To attach the serial temperature you simply have to put the Serial-USB adapter in the powered USB hub and connect the TM-RS232 sensor to the adapter.
  • The device should now appear under /dev/ttyUSB0
  • The sensor will measure automaticaly every 10 seconds the temperature in °C. You could verify this by starting a terminal program and connect to /dev/ttyUSB0 with the parameters 9600, 8, 1, NONE

5. Write some code to read and send the data
  • To read the serial data I use the RXTX library. To get it running on the Pi you need to install the native part by executing the following command
$ sudo apt-get install librxtx-java
  • In Java you simply have to link the RXTXcomm.jar file to your project and you should be good to go.
  • Because the temperature sensor simply sends something like this "+022.3C" + ENTER you could read it with a BufferedReader. The code I use for this looks similar to the following...
    BufferedReader br = 
      new BufferedReader(new InputStreamReader(inputStream));
    String line;
    while (running) {
      try {
        while((br.ready()) && (line = br.readLine()) != null) {
          if (line.length() > 6 && line.endsWith("C")) {
            try {
              double value = 
                Double.parseDouble(line.substring(1, 6));
              setCelsius(value);
            } catch (NumberFormatException exception) {}
          }
        }
      } catch (IOException ex) {
        System.out.println("Error reading serial port: " + ex);
      }
    }

      The setCelsius(double value) method simply sets a celsius property 
      which will fire a PropertyChangeEvent.

      That is in principle the measuring part, now let's take a look at the sending
      part. To send data across the network I use the XMPP protocol. 
      The eXtensible Messaging and Presense Protocol is an open technology for
      real-time communication. It was developed within the Jabber community. 
      It's ideal for event based systems, it's fast and extensible. To use it in my
      example I needed to setup 2 jabber/xmpp accounts on a public server.
      I used the open jabber server from the german Chaos Computer Club but
      you could also use any other or your own (Ignite Realtime offers a nice
      Java based free xmpp server named OpenFire. So I created one account
      for the Raspberry Pi and another for the receiver (the BeagleBoard in my
      case). To use xmpp in Java Ignite Realtime also offers a very slick library
      named smack. You could either download the jar's from their website or
      from my dropbox (smack.jar and smackx.jar).
      I don't have the time to explain the whole xmpp thing here but I can say
      that this protocol rocks and gives you a lot of nice features. In my example
      I just measure the temperature in °C but I would like to have it also in °F.
      So this is fairly easy to do, I just calculate the temperature in Fahrenheit
      each time I measure a new value and simply add a the value as property
      to the xmpp message. The code to do this looks like this...

    Message msg = new Message();
    msg.setProperty("celsius", celsius);
    msg.setProperty("fahrenheit", fahrenheit);
    msg.setBody("Current temperature: \n" 

                 celsius + " °C\n"
                 fahrenheit + " °F");
    Chat chat = 
      chatManager.createChat(receiverJID, messageListener);
    chat.sendMessage(msg);

      As you can see adding properties to a xmpp message is really easy and
      of course it's the same with reading the properties back on the receiver
      part. The body of the message is typically the text you will see in a chat-
      program. Means if you would like to use it only with a Pi and e.g. your
      iOS or Android device, you just need a chat client that is able to speak
      jabber/xmpp and the Pi will send you the temperature messages to your
      mobile device.

      Please find a NetBeans project with the code that runs on my Pi at github.


6. Setup autostart of the program
Now that you have your hardware attached and the code running it would be nice to simple power on the Raspberry Pi and it starts measuring and sending.
  • Create a shell script that looks similar to this 
/home/pi/java/ejre1.7.0_06/bin/java -jar /home/pi/TempMonitor.jar

  • Make the shell script executable
$ sudo chmod +x /home/pi/temperature.sh

  • Add the following line to the /home/pi/.bashrc for autostart
sudo bash /home/pi/temperature.sh


7. Setup autologin for the pi user
  • Install mingetty with the following command
sudo apt-get install mingetty

  • Edit the /etc/inittab file and change
1:2345:respawn:/sbin/getty 38400 tty1
      to
1:2345:respawn:/sbin/mingetty --autologin <USER_NAME> --noclear tty1


Now you should be ready to go and the Raspberry Pi should start measuring and sending data as soon as you power it up.

I recorded a little video that shows the complete setup working...

That's it for Part I of the blogpost...I hope you will enjoy Java on embedded devices as much as I do...

Keep coding...

2 comments:

  1. Han.Solo,

    I have a basic question about programming with the Pi. I am light on Linux knowledge, and building my Java knowledge daily. Your article here reminded me of my question.

    Running a piece of code that triggers 7 Raspberry Pis to play a video, all at the exact same second so the video are in sync.

    Any ideas?

    ReplyDelete
    Replies
    1. Hi Arie,
      If the videos should be exactly in sync it won't be easy to realize, you need to send a message to all pi's that will trigger the start of the video but you still have network latency which might be different for each pi etc.
      To be really in sync you will need a realtime capable system but I have no hint for you here, sorry.
      Cheers,
      Gerrit

      Delete