Wednesday, 27 January 2016

Remote Robot Arm, properly

Being able to control the Robot arm using a VNC client to connect to the Raspberry Pi is all very good but it's not a very elegant form of remote control. So, I decided to build an Android App on top of the work to date.

The App should have the following behaviour:
  1. It should be able to display a stream from a web cam attached to the Raspberry PI.
  2. Control of the robot would be by pressing down on buttons on the screen. Releasing the button should stop the robot.
  3. At this point I only need to control this over the local network.

Remote Connection

Requirement 3 meant a simple TCP Client-Server model would suit me well.

As this is only on the local network, I have control over the IP address assigned by the router. I hard-coded the host name and port on both Server and client.

On the robot-arm server it's only a matter of adding a few lines to enable TCP

   import socket

   TCP_IP = "192.168.0.12"
   TCP_PORT = 5005
   BUFFER_SIZE = 20 # Normally 1024, but we want a fast response

   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.bind((TCP_IP, TCP_PORT))
   s.listen(1)

   conn, addr = s.accept()

and in the loop

   while 1:
      data = conn.recv(BUFFER_SIZE)
      if not data: break
      # send the chractera to the arduinos


On the client side I created a new java.net.Socket and use a PrintWriter to send the control characters:

   Socket socket = new Socket(hostName, port);
   PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
   out.println(ch);


Note that as this is an Android App, it's mandated that sockets are not opend on the main thread. It is very simple to extend AsyncTask and implement the doInBackground method.

Finally, we need to add Internet permission to the Android manifest file:

<uses-permission android:name="android.permission.INTERNET" />

Streaming a Video feed

Keeping things simple I thought an HTTP stream would be lightweight and easy to implement. It turns out most solutions described on the web introduce a large latency of several seconds.
Fortunately however, I found a solution in the PiStreaming project on GitHub https://github.com/waveform80/pistreaming.git 

Following the install instructions and starting with python server.py I was able to view the stream from the camera with sub-second latency.

Building the App

The app has two regions, the top half shows the video stream while the bottom has the buttons to control motion




I use a WebView to show the video stream. In OnCreate it's configured with the following:

   WebView piWebView = (WebView)findViewById(R.id.webview);
   WebSettings webSettings = piWebView.getSettings();
   webSettings.setJavaScriptEnabled(true);
   piWebView.setWebViewClient(new WebViewClient()
   {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url)  
      {
         return false;
      }
   }); 

   piWebView.loadUrl("http://192.168.0.12:8082");

Java script must be enabled because the HTTP server uses it and the override shouldOverrideUrlLoading was added to stop the stream spawning a new web browser window.

To implement the required behaviour of the buttons, I used the OnTouchListener. The MotionEvents ACTION_DOWN and ACTION_UP capture the button press and release

m_upButton.setOnTouchListener(new OnTouchListener(){
   @Override
   public boolean onTouch(View v, MotionEvent event) {
    try
    {
     if (event.getAction() == MotionEvent.ACTION_DOWN)
     {
      new TcpClient().execute("o");
     }
     else if (event.getAction() == MotionEvent.ACTION_UP)
     {
      new TcpClient().execute(" ");
     }
    }
    catch(Exception ex)
    {
     return false;
    }
  
    return true;
   }
  });

There are a couple of problems here. I shouldn't need to create the TCP client each time and there is an intermittent but where the ACTION_UP pipeline doesn't fully make it to the robot, in this case the arm continues moving until I tap another button.

Running the App to control the robot

On the Raspberry PI start both the web server and the robo-server. Then open the Robot Arm App. Touching the buttons cause the appropriate motors on the arm to move, releasing the button stops movement.

The video shows a demo of it in action. I'm using a low spec Android phone and hadn't connected all the motors but it gives an impression of how this works


The code for the Android App has been added to the git repository https://github.com/jscott7/Robot-Arm.git 

Tuesday, 26 January 2016

It was the best of Linux, the worst of Linux

Taking an update and upgrade on the Raspberry PI, I had a problem with unmet dependencies for raspberrypi-bootloader.

I ran the suggest fix of apt-get install -f and thought nothing more of it.

Unfortunately as it turns out there were problems....

I shutdown as always ( sudo shutdown now ) but when I tried to restart a couple of days later nothing.

I didn't get any response at all, connecting to the TV via HDMI yielded a blank screen but at least when I plugged the SD card into my laptop I did see all the files, so at least the card hadn't died.

This gave me an opportunity to copy over the files and re-image the card from the ISO that I still had from the original install.

I still use Win32DiskImage to setup the SD card, but as Windows only sees the boot partition I couldn't format it. The DiskManagement tool allowed me to format both, but not to remove the partitions.

Fortunately, there's a command line tool DISKPART that has much more control
  1. Open an Administrator command prompt
  2. Run diskpart to open the tool
  3. Enter list disk to see which disk is the SD card
  4. Important point here, make sure you choose the right disk or you could wipe your OS
  5. If your SD is disk is #1 enter select disk 1
  6. Enter clean to format and clear all the partitions. 
I then copied my image back onto the SD card, plugged it back into the PI and I was back up and running. The final steps were to setup WiFi, run the update/upgrade and copy back my files. All in just over an hour.

So the worst of Linux; I've never had a machine be rendered unusable from an update, on any flavours of Windows

But the best of Linux; It took me just over an hour to restore the OS, then take the updates and have all my applications and development in precisely the state it was when things went wrong. Without multiple reboots.

Monday, 14 December 2015

Keeping old data alive, building CERNLIB


Updated 28/4/1016 with additional link and clarification

Analysis of the data from the ZEUS experiment was performed using Fortran programs. These used the CERNLIB software libraries and data was stored in structures known as Ntuples.
I used Column-wise Ntuples, which are saved in a binary format. So when at the end of my Ph.D. analysis, I saved the old Ntuples to 11 CDs these became largely useless immediately I left Physics.
The Digital dark age therefore came to me sooner than I anticipated.
Fortunately with the source being made freely available and the necessary compilers being included in gcc I thought I'd have a try at building these on my Linux laptop.
At the time of this exercise I was running version 11.10 of Ubuntu.
Here are the steps I took, based on instructions from this page. One major issue I had with Lubuntu was that many of the dependency packages were not installed and I had to discover and apt-get them all. For this reason it's better not to try this on a cut down Linux.


  • Install gfortran (this is part of gcc, I have version 4.6.3)
  • Copy and unpack the CERNLIB binaries
  • Because I had a cut down Linux, I needed to build LessTif
  • Get xutils-dev package for imake
  • Set up the  build environment
     cd to the cern folder
     ~$ export CERN_ROOT=CERN_PATH/VERSION
     ~$ export CVSCOSRC=$CERN_ROOT/src
     ~$ mkdir $CERN_ROOT/build
     ~$ cd $CERN_ROOT/build
     ~$ export PATH=$CERN_ROOT/bin;$PATH
  • Update $CVSCOSRC/config/linuc.cf This file has some operating system specific information, I changed the following
    • #define hasgfortran
    • Change CcCmd to gcc
    • Check #define X11Includes
      This needs to point to the location of the X Window headers, these can be installed using
      sudo apt-get install xserver-xorg-dev
  • Run $CVSCOSRC/config/imake_boot to create the Makefile from the imake files
  • Run gmake bin/kuipc to build kuipc – this is built to /cern/new/bin
  • Add kuipc to path because this is required for the next build
  • Run gmake 
When I finally succeeded I was able to write a simple Fortran program that was able to load my old ntuple files.

A couple of other tips

link gmake to make using sudo ln -s /usr/bin/make /usr/bin/gmake

 

Problems and errors

There were a couple of errors in the main build that needed fixing:

#1
Conflicting types for _XmDrawShadow /usr/local/include/xm/DrawP/h Previous declaration is obsolete


Fix: Remove _XmDrawShadow(); from iconwidget.c
 
#2
Pawlib/paw/cpaw/bugrep.c L_cuserid undeclared.
Fix: It should be in <stdio.h> but add #define L_cuserid 9 in the file

Finally, Liblapack3.a is required for PawX11
Fix: Download and build BLAS & LAPAC

Of course now in 2015, CERNLIB is available from the Ubuntu software manager.

Tuesday, 1 December 2015

Linux on a new Dell Laptop


I've now got a new Dell Inspiron Laptop (Woo hoo!) and decided to set it up to dual boot Linux and Windows 10.

This post is really for my own reference and benefit, although lessons learnt may well be more widely useful.

Installation

I decided to install Linux Mint with Cinnamon. This was really quite painless.

The drive has approx 1.8 TB of useable space, so I shrunk the Windows C: drive to just over 1TB leaving about 750GB for Mint.

To do this, I entered Disk Management into the windows search box which matched with "Create and Format hard disk partitions" as best match.

Open up this tool, right click on the C:\ drive and select Shrink Volume...

I also needed to disable secure boot in the BIOS. This was easy, simply restart the machine hit F2 on start-up. Then when the BIOS configuration screen appears, navigate to Secure Boot and check disable.

I'd previously created a Linux Mint DVD from the Linux mint downloads page. To boot the Linux disk, restart and hit F12 on start-up.

This should start the LiveCD version which has a desktop icon to install. Double click on this and start the installation.

The important point comes when you are prompted to select the Installation type. At this point check "Something else"

You now enter the screen to manage partitions, select the free space from the earlier shrink and click on +
You will be presented with a dialog to configure the partitions, I created 3 (Repeat the process in this order)
  • 50GB Logical for the Linux core, Root : '/'
  • 690 GB Logical for Root: 'home/'
  • The remainder for Swap, about 7GB
Then run the install. This asked for a few configuration settings, for example Wifi login and language settings. Wait about 15 minutes and finally reboot.

The last thing I did was to run sudo-apt get update and sudo apt-get upgrade to bring the packages up to date.

Video driver

My graphics card is an AMD Radeon R5 M335. This seems to have been released in October 2015 and at the time of writing there were no proprietary Linux drivers for this.

The open source AMD driver doesn't seem to handle the card either. I get the following pop-up on the desktop and errors are shown in the logs (obtained using the dmesg command)



dmesg | grep drm

returns the following

[    1.759698] [drm] Radeon Display Connectors
[    1.759763] [drm] Cannot find any crtc or sizes - going 1024x768
[    1.761755] [drm] fb mappable at 0xC0242000
[    1.761756] [drm] vram apper at 0xC0000000
[    1.761757] [drm] size 3145728
[    1.761758] [drm] fb depth is 24
[    1.761758] [drm]    pitch is 4096
[    1.761942] radeon 0000:01:00.0: fb1: radeondrmfb frame buffer device
[    1.796379] [drm:si_dpm_set_power_state] *ERROR* si_upload_sw_state failed
[    1.796420] [drm] Initialized radeon 2.39.0 20080528 for 0000:01:00.0 on minor 0
[   21.908902] [drm] probing gen 2 caps for device 8086:9d10 = 1724843/e
[   21.908908] [drm] PCIE gen 3 link speeds already enabled
[   21.911907] [drm] PCIE GART of 1024M enabled (table at 0x0000000000040000).
[   22.488470] [drm:r600_ring_test] *ERROR* radeon: ring 0 test failed (scratch(0x850C)=0xCAFEDEAD)
[   22.488474] [drm:si_resume] *ERROR* si startup failed on resume
[   22.489091] [drm:si_dpm_set_power_state] *ERROR* si_upload_sw_state failed


But Linux is reverting to Intel graphics

lspci  | grep VGA returns  00:02.0 VGA compatible controller: Intel Corporation Device 1916 (rev 07)

The machine seems to be working well at the moment so I'm not too worried about this. (I'm not interested in heavy graphics work on this machine) I'll keep a look out for news and will post any updates I see to this page.