Monday, 21 September 2015

ZEUS Safety Shift - Part 1

The 'Safety Shift' was a duty for all PhD. students working on the ZEUS experiment. This involved spending 8 hours at the detector hall, mostly in the control room, 8 floors underground. Although periodically you would take a walk around the site, checking the detector subsystems. The shift change-over times were 12am, 8am and 4pm. Shifts were on a rota and once you'd done 4 days in a row there would usually be a few weeks before your next one.

During a normal evening shift the only other person you'd see would be the shift leader who would be a more senior member of the collaboration. Personally, I think the safety shift had the better deal, at least we got to go and stretch our legs. During data taking the leader would have to be more or less continuously at the run control desk.

I loved the midnight until 8 shift. This was mainly because after about 1am you would have almost exclusive use of the ZEUS compute farm. And I did enjoy a bit the feeling of being stuck in a sci-fi set!

Here is a plan of the DESY site with the location of the experimental halls. ZEUS was located in the South Hall, just next to the Trabrennbahn. The South Hall complex was affectionately called "The Pit".

Scan of the back of the DESY Lageplan

You approached the hall through the Trabrennbahn car park. At midnight in the middle of winter this could be quite a lonely walk.


Once you swiped your entrance card you would enter the courtyard area and proceed through the small blue door into the hall itself.

Taking the lift down to the bottom you find the control room to your left. This picture was taken from the 2007 ZEUS shut down. The monitor at the bottom left was the desk for the safety shift.



The run control station for the shift leader is shown below. This was from a quiet evening in 1999.


If, instead of turning left, you exited straight out of the lift you would enter the main hall. The most obvious sight you'd see here was the Rucksack. This was a 3-story hut containing a large proportion of the trigger electronics. The whole hut was mounted on rails and could be moved to the right (in this picture) during access periods for the detector.

During normal operation, the detector itself was largely hidden from view by concrete shielding and the Rucksack itself. It was located to the left of the Rucksack in the above picture. Here is a view of the side facing the Rucksack.

Cabling between the detector and Rucksack was designed to be flexible and allow movement.


Part of the safety shift was to walk around the all with an eye out for any obvious problems. Professor Jon Butterworth, in his book Smashing Physics, tells of a time someone on safety shift found water dripping out from the concrete shielding. This wasn't the only time water got loose, my sister pointed out a leak from one of the pipes in the hall when I was giving her a tour. Her question was, "Is it supposed to be doing that?" With a significant amount of high voltage cables and delicate instruments around, this was not something to take lightly...

This view back from the top of the Rucksack stairs shows some of the remainder of the hall. (For orientation the lift was through the entrance where the blue doors can just be seen.)

Next time, I'll go into more detail about some of the checks we had to make, as well as visiting some of the (literally) darker corners of the pit.

Thursday, 10 September 2015

Remote Robot Arm

Earlier, I set up the Raspberry Pi to communicate with the Ardunio using a Python script. With this in place I can now start putting things together to make something more interesting; for example, controlling the Robot arm.

The first script itself was very basic, sending a few fixed characters with sleeps. To make this more interactive I need to be able to read characters from the keyboard.

I based my new controller script on an example in the Python FAQ. The main difference to the boilerplate sample is I write the character to the serial port that the Ardunio is listening on.

import termios, fcntl, sys, os, serial

ardiuno = serial.Serial('/dev/ttyUSB0')
fd = sys.stdin.fileno()

# Get state of tty and take a copy
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)

# Turn off echo, line buffering and special character processing
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO

termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
    while 1:
        try:
            c = sys.stdin.read(1)
            # repr() : Return a string containing a printable
            #    representation of an object
            ardiuno.write(c)
            print "Got character", repr(c)
        except IOError: pass
finally:
    # restore old state
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)

    tcntl.fcntl(fd, fcntl.F_SETFL, oldflags)


The Arduino code is based on my original robot arm controller project. The motors are now engaged by bytes read from serial input.

  • o and m : forward and backwards on channel A
  • l and k : forward and backwads on channel B
  • Space ' ' : Stop all movement


// Motor controlled by serial inputs
long ii = 0;
byte inByte;

void setup() {
   // initialise serial comms at 9600 baud
   Serial.begin(9600);
  
   //Setup Channel A
   pinMode(12, OUTPUT);    // Initialise Motor Channel A pin - DIRECTION
   pinMode(9, OUTPUT);     // Initialise Brake Channel A pin - BRAKE

   //Setup Channel B
   pinMode(13, OUTPUT);    // Initialise Motor Channel B pin - DIRECTION
   pinMode(8, OUTPUT);     // Initialise Brake Channel B pin - BRAKE
  
   Serial.println("Started");
}

void loop() {

  while (Serial.available() > 0)
  {
     inByte = Serial.read();
     
     if (inByte > 0)
     {
       Serial.println(inByte);
     }
    
     if (inByte == 108) // 'l'
     {  
       digitalWrite(12, HIGH);  // Establish forward direction of Channel A
       digitalWrite(9, LOW);    // Disengage the break for Channel A
       digitalWrite(8, HIGH);   // Engage the Brake for Channel B
       analogWrite(3,244);      // Spin the motor on Channel A at full speed
     }
     if (inByte == 107) // 'k'
     { 
       digitalWrite(12, LOW);    // Establishes backward direction of Channel A
       digitalWrite(9, LOW);     // Disengage the Brake for Channel A
       digitalWrite(8, HIGH);    // Engage the Brake for Channel B
       analogWrite(3, 244);      // Spin the motor on Channel A at half speed
      }
      if (inByte == 111) //'o'
      {
        // digitalWrite(13,HIGH);
        digitalWrite(13, HIGH);  // Establish forward direction of Channel B
        digitalWrite(8, LOW);    // Disengage the break for Channel B
        digitalWrite(9, HIGH);   // Engage the Brake for Channel A
        analogWrite(11,244);     // Spin the motor on Channel B at full speed   
      }
    
      if (inByte == 109 ) //'m'
      {
        // digitalWrite(13,LOW);
        digitalWrite(13, LOW);    // Establishes backward direction of Channel B
        digitalWrite(8, LOW);     // Disengage the Brake for Channel B 
        digitalWrite(9, HIGH);    // Engage the Brake for Channel A
        analogWrite(11, 244);     // Spins the motor on Channel B at half speed
      }
    
      if (inByte == 32) //' '
      {
        digitalWrite(8, HIGH);    // Engage the Brake for Channel B
        digitalWrite(9, HIGH);    // Engage the Brake for Channel A  
      }
   }

}

That's really all there is to it. It's amazing what can be done with such a small amount of code! 

To move the Robot, I log on to the Raspberry Pi using VNC from the laptop. Then run the python script and hit the control keys to engage (or stop!) the motors. As I'm connecting to the Raspberry Pi over wifi, there is no need for the control to be near the robot.

Of course with only a dual channel motor controller I've not got much flexibility in what I can do with the arm but I hope to add another ardunio/controller.

Here is the completed set-up.


Tuesday, 18 August 2015

Windows Update woes

My Windows computer is a 5-year old Dell laptop, running Windows 7. At the time it was built the GB hard drive was partitioned into a C: and D: drive. C: is the Windows partition and has a size of 60GB.

I've noticed over the years the amount of available space on the C: drive has continuously reduced by more than I'd expect from my usage. The available space when right clicking on C: in Explorer and looking at the properties is now often lower than 5GB.

There are a few tools available that visualise and provide detailed information about drive usage. I use WinDirStat

After a recent scan I noticed the two highlighted boxes which come from C:\Windows\Installer and C:\Windows\SoftwareDistribution amounted to over 35% of the files on the C: drive.

Unfortunately it's not recommended to delete these files since this belongs to the InstallerCache which is used for uninstalls, updates and repairs.

From what I've seen on forums the Microsoft response to questions about the size of this cache is quite glib:

a. Move the download folder to another drive.
b. Empty recycle bin
c. Uninstall the applications that you no more use.
d. Perform disk cleanup.

The download folder just has 500MB, so that's not going to save much and Disk cleanup doesn't reduce this folder.

But, my big problem is with the recommendation to uninstall applications. We get updates all the time through Windows update so even if my system is running with the minimal suite of applications at some point in time the cache will expand and leave me with no space. I don't want to uninstall what I've currently got. I do want to be able to use the machine in 2, 3 or more years time. Why can't I at least allow it to live on another drive? I understand the update service gets upset if a link is created for this folder. Why?

PS. The big green files are the page file and hibernate file - don't touch these!

So, resigning myself to this, I use the following strategies to minimise C: drive usage:
  • OK so do uninstall unused applications. It makes for a cleaner experience anyway although I've pretty much exhausted that option now.
  • Save my own documents onto the D: drive
  • When installing applications and if prompted, save them onto the D: drive. (Of course if you're iTunes then when you run your own software update you reinstall back to C: </sigh>)
  • Staying with iTunes, the iPhone backup file can be saved onto the D: drive by setting up a symbolic link from C:\Users\Username\AppData\Roaming\Apple Computer\MobileSync to another one on D: . I used mklink. (dir /AL /S C: is a nice command that lists all your links)
  • Regularly run the Disk Cleanup tool (including the System cleanup). Note that sometimes it doesn't automatically check everything to cleanup. For example the Service Pack Backup files checkbox was blank when I cleaned up after a failed Windows 10 install.
  • Regularly clean the Chrome cache. This does seem to be greedy.

Now, onto Windows 10...

I have no intention of installing Windows 10 on this machine, in part due to the disk space issues and in part due to compatibility concerns with my existing application suite. But in any case it's just too soon.

Microsoft on the other hand have other ideas...

I've made sure I've ignored the upgrade nagware and have never tried to reserve a new copy. Here is its current state.





But when taking a look after a particular nasty slowdown I saw the hard drive had dropped to only 600MB and these two failed attempts to install Windows 10.




Very naughty.

As I'd no warning the update was about to happen I stood a very real risk of losing data that hadn't been backed up. This whole sorry episode with Windows Update has severely dented my trust in Microsoft not to force poor design decisions on users.

The failure code incidentally is 80240020. "The update did not finish downloading or installing" in this case because there was insufficient disk.

Monday, 20 July 2015

Communicating with the Arduino

After connecting the Raspberry Pi to the Arduino, the next step was to communicate with it programmatically rather than simply uploading sketches.

As a first attempt I decided to try using Nanpy. This is a library that allows you to drive the Arduino from the Raspberry Pi using Python scripts. The version I tried to install was v0.94.

This wasn't successful. When I ran a simple script to blink the on-board LED on the Arduino I got the following error:

nanpy.serialmanager.SerialManagerError: Serial timeout

I edited the Nanpy sketch to enable some basic "Logging", again using the LED. This resulted in the discovery that the serial communications were not being set-up correctly. In particular:

if (ComChannel::available()))

was not evaluating to true.

I wasn't able to discover why so I've decided to park Nanpy for the time-being. If I get it working then I'll post full details for setting it up.

But there are always many ways to solve a problem in computing, without even harming any cats! I checked serial communication was working by running the ASCIITable example sketch on the Arduino IDA and viewing data in the Serial Monitor. This was OK, so I could try writing some code to simply switch on the on-board LED using Python.

I uploaded this sketch to the Arduino

// SerialTest
byte inByte;

void setup() {
   // initialise serial comms at 9600 baud
   Serial.begin(9600);
   pinMode(13,OUTPUT);

   // The on-board LED is explicitly off. 
   digitalWrite(13, LOW);
}

void loop() {
  while (Serial.available() > 0)
  {
     inByte = Serial.read();
     // If the byte is a digit in the range 0-9, light the LED
     // otherwise, turn it off
     if (inByte > 47 && inByte < 58)
     {
         digitalWrite(13, HIGH); 
     }
     else
     {
        digitalWrite(13, LOW);
     }
  }
}

Finally I wrote a very simple python script to write characters to the serial port. This should wait 5 seconds, turn on the LED, wait 5 seconds and turn off the LED, and repeat.

from time import sleep
import serial
arduino = serial.Serial('/dev/ttyUSB0')

sleep(5)
arduino.write('5')
sleep(5)
arduino.write('x')
sleep(5)
arduino.write('2')
sleep(5)
arduino.write('x')

I ran the script and the LED turned on and off as expected.

Monday, 13 July 2015

Halo?

It's always worth looking up every so often because there are often surprises when you least expect it. Saturday was a nice summer's day, warm but not hot and with a fair few clouds. However when I got home from shopping I saw a very well pronounced arc of a halo. It's not something I've seen too often, especially with the sun high in the sky, so I had to get the camera out.



* These pictures were taken from London on the 11th July 2015 at 11:40 BST.

So, what's going on here? There's quite a bit on the internet about the science of halos. On this day there was a lot of high level cirrus cloud as well as the Cumulus in the pictures. The ice crystals in the high-altitude cirrus are perfect for creating these optical effects.

It could have been a 22' circular halo, which is the most common. However, the sun in this case wasn't in the centre of the arc; it was instead just off to the top left corner of these pictures. The rule of thumb that 22 degrees is the size of your outstretched hand at arms length also wasn't quite right here, as well as the fact that there was no red/blue hues on the inner and outer edges and the inner sky didn't appear darker.

On the left of the arc as seen here there was a tiny hint of a red/blue spectrum (seen best in the top image). So putting this together with the rest of the observations perhaps I was seeing a Parhelic circle. The small spectrum being a fragment of a 22' halo intersecting it.

A Parhelic circle is rarer than the 22' halo and caused by millions of vertical ice crystals reflecting the sun's light.

I'm no expert and perspective can play tricks so I'm not a hundred percent confident in this but it does make some sense (to me at least!)

Never look directly at the sun. Also, a camera will likely suffer damage when the sun is high and never, ever look through a SLR viewfinder or other optics at the sun. 

Saturday, 20 June 2015

Putting things together

After parking the Robot Arm on top of a bookcase for several months, I've decided to see if I can make something a bit more complex (and useable).

In addition to the Arduino, I also have a Raspberry Pi and the Windows 7 Laptop I use to create this blog so I thought it might be a good idea to put all these together. Now, I don't really need to use the Raspberry Pi for this particular project, but it's small, hardly draws any power and there's an increasing amount of community support for robotics.

So, Step 1, connect the Pi to the PC

Note I've installed Raspbian onto my particular Pi. To begin with, I want to connect via VNC. There are plenty of instructions on the web for setting up a VNC server. Instructions like these should be sufficient

I installed UltraVNC Viewer on the laptop which is a useful free viewer with very unobtrusive advertising.

PuTTY is also a useful tool to have installed as you can use this to connect to the Raspberry Pi from the command line. Especially handy to check what went wrong with configuring VNC.

It's important you don't use the default login credentials of User: pi, Password: raspberry, so change it using the command passwd from the command line

Step 2, Setup Wifi for the Pi

I didn't want to have to connect my Raspberry Pi to the PC everytime I use it, so I bought a cheap and low power USB Wifi dongle.
There's a lot of information about how to setup Wifi on the web. This is what I did.

Edit the /etc/network/interfaces file (I use nano for this)
auto lo
iface lo inet loopback

# Ethernet
iface eth0 inet dhcp

allow-hotplug wlan0
auto wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

iface default inet dhcp


Create a new /etc/wpa_supplicant/wpa_supplicant.conf file
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid=”YourWifi”
scan_ssid=1
proto=WPA
kep_mgmt=WPA-PSK
pairwise=TKIP
group=TKIP
pas=”password”
}

Restart the Pi to setup the connection.

Obviously setup the connection information as per your own circumstances. One thing I did do was setup a static IP address for the Pi on my router. This did save quite a bit of pain getting DHCP working.

Step 3, Connect the Pi to the Arduino
The Arduino client software is installed using sudo apt-get install arduino

The default setting wasn't compatible with my Arduino board. When I tried to upload a sketch to the board I got this wonderfully informative message:

error: avrdude stk500_getsync() not in sync resp=0x00

The fix was to set the Board from the Tools -> Board menu to Arduino Diecimila or Duemilanove w/ ATmega168 on Serial Port /dev/ttyUSB0

I then uploaded the Blink sketch to the Arduino to prove it worked.

Finally, I connected using a powered USB hub to confirm that worked as well. The images below show both the direct Raspberry Pi to Arduino and USB hub connection.

The latter will be useful in future as this will help minimise power consumption issues.



Thursday, 14 May 2015

Fixing an old Multimeter


I have an old multimeter, a Metrix MX 001B. I believe this was made sometime in the 1970s. by a French company, Metrix, now Chauvin Arnoux Metrix. This had been gathering dust in the garage for several years until I started working on my Robot Arm Controller project.



The sensor wasn't working on one of the channels so I wanted to use the multimeter to test the circuit. Needless to say, when I dusted it off and tried to use it, nothing happened.

First, it needed two 2x LR1 Size-N batteries (duh!).

Second and more serious, the connection to the negative battery terminal had snapped off. Fortunately, it was relatively simple to solder a new connection onto the board.

And here it is working.


Not perhaps the most exciting video in the world!
(Uploaded to Blogger instead of YouTube so this isn't high definition. You have to kind of imagine seeing the needle move.)

Update 4th Jan 2016
In response to Halil Karakose's comment, I thought I'd include a view of the inside. This is all wonderfully simple and at a human scale compared to some modern circuits!