Tuesday, July 23, 2013

Running From an External Hard Drive

The SD card of the Raspberry Pi is required for booting.  While you may not be able to boot from an external hard drive, moving the root partition there will significantly speed up the Raspberry Pi.  There are many uses where this configuration particularly useful.  File servers and media servers are good examples.  I use a system like this for a MySQL database server.


There are a number of variations to the process, but basically, the steps are:
o  Install OS on SD Card and boot 
o  Plug in external hard drive
o  Partition and Format hard drive
o  Copy system to hard drive
o  Mount the new system and modify configuration to use the hard drive

I decided not to re-invent the wheel.  The following instructions are just my variations on the instructions provided by Rattus here: 

http://www.raspberrypi.org/phpBB3/viewtopic.php?f=26&t=10914&p=129474&hilit=resizefs#p122476  
Note about the sudo command:  All of the following must be done as root.  You must put sudo before each of the commands.  Or, you can follow the (not recommended, bad practice) habit I have and just enter sudo bash to run a shell as root and skip saying sudo all the time.

Load SD Card with Raspbian in the usual way. Update the system software and firmware with the following three commands. This can take quite a while to complete.
apt-get update
apt-get upgrade
rpi-update
reboot


List the partitions This should show only the /boot and / partitions on the SD card.
fdisk –l

Plug external hard drive into USB and list the partitions again. This should show another HD probably at /dev/sda

Modify the partition table for the external drive.
fdisk /dev/sda
Delete partitions by entering “d” and then the number of the partition to delete. Delete all the partitions. Entering “p” will list the partitions.

At this point, you have a few options.
    a) Create a single partition and move the root there. This will leave the swap file on the SD card.
    b) Create a root partition that fills most of the drive and a small swap partition.
    c) Create a partition for the OS, a small swap partition, and a large partition for application data.

I am using the third option.  The following instructions are fairly easy to change to use one of the other options.  While still in the fdisk program, do these steps.

- Create the root partition:  I made mine 16GB.  Enter “n” to create a partition, “p” to select primary partition and then “1” to select partition number one.  Select the default start sector.  Enter +16G to specify the size.  
- Create the swap partition:  Enter “n” to create a partition, “p” to select primary partition and then “2” to select partition number two.  Select the default start sector.  Enter +2G to specify the size.  Enter “t” to set the type of a partition.  Enter “2” and then “82” to make this one a swap partition.
- Create the data partition:  Enter “n” to create a partition, “p” to select primary partition and then “3” to select partition number three.  Select the default start sector and default end sector to fill up the rest of the disk.  
- Enter “p” to list the partitions and verify things are like you expect.
- Enter “w” to write the new partition table and exit.

Create (format) the data partition with an EXTv4 file system. This command takes a few minutes to finish. There is no need to format the first partition since we are going to do a raw copy of an existing file system over it anyway.
mkfs.ext4 /dev/sda3

Initialize the swap partition
mkswap /dev/sda2

Mount the new root partition.
mount /dev/sda1 /mnt

Use rsync to clone the root partition from the sdcard to the new partition on your hard disk, Note the exclude of /mnt. This takes a while.
rsync -avz --exclude '/mnt' / /mnt

Change the mount configuration file on the new root.
vi /mnt/etc/fstab

Change the root device /dev/mmcblk0p2 to be /dev/sda1

Add /dev/sda2 as a swap partition by adding this line.
/dev/sda2 none swap sw 0 0

Finally, stop the system from using the swap file that it normally uses.
rm /mnt/etc/rc?.d/*dphys-swapfile

And delete the old swap file.
rm /mnt/var/swap

Use your editor of choice (I use vi) to modify the boot configuration to use the new root partition. First make a backup copy.
cp /boot/cmdline.txt /boot/cmdline.orig
vi /boot/cmdline.txt
Change /dev/mmcblk0p2 to be /dev/sda1

Now the system is ready to reboot. It should come up normally with the external hard drive mounted as root.
reboot

If the system fails, use another machine to copy /boot/cmdline.orig to /boot/cmdline.txt and then reboot again.
One problem that some people have run into is controllers that take too long to complete the USB discovery. This can be compensated for by adding delays in the /boot/cmdline.txt file with the bootdelay and rootdelay options.

Saturday, July 13, 2013

Pulse Width Motor Control

My last project had me digging through old robotics parts to find an H-Bridge Motor Controller.  I found one that had several TTL chips on the circuit as well and it reminded me of a trick some of you may find useful.

First, lets define pulse width modulation (PWM.)  It refers to the duty cycle (how long the line is high vs how long it is low) of a pulse stream.

A duty cycle of 50% looks like this:


A duty cycle of 25% looks like this:


And 75% looks like this:


What use is this for controlling motors?  If you have ever tried controlling a motor by simply turning it on and off, you quickly realize how little control you have.  Your robot goes from stopped to zooming at full speed with nothing in between.  If, however, you use PWM to power your motor, then it will be on at full power very briefly and then off, repeatedly.  With PWM you can provide much finer motor control and have your robot move at whatever speed you like.  The higher the duty cycle of the pulse stream, the more power your motor will output.

There are several ways to produce PWM signals from the Raspberry Pi.  The simplest is to turn a GPIO pin on and off in a loop with delays controlling the pulse width.  This is very CPU intensive and not always consistent.  You can use libraries or device drivers to produce PWM from the GPIO that will be consistent and will use virtually no CPU.  Or, you can use external hardware to produce PWM.

Here is how I have done it in the past. (I haven't built a robot using a Pi yet, but did it with simpler microcontrollers years ago.)  Use six GPIO pins:

  • Enable (motor is on or off)
  • Direction (forward or reverse)
  • Power 0
  • Power 1
  • Power 2
  • Power 3

The four power bits control the duty cycle of a pulse stream and allow 16 different power levels.  Below is a block diagram of the circuit I used to do this.
I used a 555 chip for the pulse generator, a 74161 counter, and a 7485 comparator.  Other chips can be used to achieve similar results.  I built my own H bridge circuit back then, but I recommend checking out some of the motor controller chips available now, such as the SN754410 chip.



Gotta Know When to Fold 'em


For the past few months, I have burned up a lot of hobby time trying to build an interface to control the Orbit 58874 sprinkler control valve.  These simply connect in-line with standard water hose connectors and cost about $20.  However, they turned out to be quite complicated to control.


The valve connects with two wires.  Sending a 24V pulse in one polarity will cause the valve to latch open.  Sending it in the reserse polarity will cause it to latch closed.  At least in theory.  And, as a wise professor once told me:  "In theory, practice and theory are the same.  But in practice, they sure as hell aren't."

I had a 24V power supply, but it was a little too powerful.  If you leave the valve powered for more than a second, you can burn out the solenoid coil.  After melting one of my H-Bridge motor controllers, burning out several valves, and losing a couple of months, this project was officially no longer fun.

Fortunately, someone else has already gotten this working.  If you are interested in this, check out http://rayshobby.net/ where you can find interfaces to these valves for Raspberry Pi and Arduino.  I may just break down and buy his OpenSprinklerPi interface.

But now it's time to throw in the towel and move on to other projects.

UPDATE:  I was mistaken about the OpenSprinklerPi.  It will only support standard valves.  That's easy - apply voltage and they turn on.  Stop and they turn off.

So I have returned to this and will be building an entirely new interface board for the sprinklers.  It will probably include an H-Bridge to control output polarity and relays for each sprinkler.

Friday, June 7, 2013

Problems and Distractions

I haven't been able to post in quite a while - far too many things in real life distracting me.  But now that I have gotten back to hobby time, I am expanding my system with an I2C interfaced GPIO extender.  Everything worked great on the workbench, but refused to work at all once installed.  It appeared that the bi-directional buffer chip that I used to connect the Pi to I2C wasn't working, which made no sense.

I broke down and pulled the interface board down and brought it to the workbench.  Under the magnifier, the problem was immediately obvious.

Soldering is an art.  It takes practice, and I was terribly out of practice when I started this blog (and made this board.)  Bottom line, the SDA and SCL lines were shorted by some over-zealous soldering.  Since I hadn't used I2C, it was never a problem.

I have a feeling I am going to replace this board with a completely re-designed version before too long.

Friday, March 8, 2013

USB Hub Modified to Back Feed Power

Most powered USB hubs will not feed power back into the host system.  This is normally a good thing.  However, it is possible to power the Raspberry Pi by back feeding power from a powered USB hub.
Note:  Doing this bypasses the fuse on the Pi, so it is possible to damage it if too much power is drawn into it.  Since all my peripherals will be connected to the hub and GPIO will not be used, then there is little risk of this occurring.  Another note:  The rev 1 Raspberry Pi boards have fuses on the USB ports.  These will provide some protection but will also reduce the power.  I expect that a typical powered USB hub will have adequate power such that this will not be a problem.

Below is a simple modification to make a USB hub backfeed.  The power connector on the hub I used has +5V on the outside of the barrel, and ground on the inside.  There are three connectors on the power socket - one ground and two power connectors.  When the power plug is inserted then power is drawn from the power supply instead of from the host.  This can be overcome by simply connecting the two power connections on the socket.




Now the 2A power supply for the USB hub will power all of the periperals as well as the Raspberry Pi itself.

I need this much power in order to connect an external hard drive.  The purpose for this system will be described in my next blog post.

Thursday, March 7, 2013

Low Memory Automatic Reboot

Below is my solution to the memory leak problem that I discovered in the frame buffer interface used by my digital picture frame.  My first thought was to simply schedule a reboot at midnight, but the Raspberry Pi has no internal clock.  My picture frame is not connected to the network, so it never really knows what time it is. Also, the low memory system hang may occur in less than 24 hours.

The better solution is to monitor the amount of free system memory and reboot when it gets too low.  I use the /proc file system to access the system memory status, the awk command to pull out the value that I need, and a bash script to tie it all together.

lowmemreboot.sh

#!/bin/bash
declare -i fmem
while [ true ]
do
        fmem=` awk '/MemFree/ { print $2 }' /proc/meminfo`
        if [ "$fmem" -lt "10000" ]
        then
                echo FREE MEMORY IS LOW----FORCING REBOOT
                reboot
                exit
        fi
        sleep 60
done


Note that the command that awk runs is surrounded with single quotes.  The entire command is surrounded with back quotes.  This causes the output of the command to be saved in the fmem variable.

This script is run from /etc/rc.local the same way that wait-for-gpio-trigger.sh is run.  When the free system memory drops below 10K, the system will reboot and all is well again for a while.  Now I can just let the picture frame run forever and not worry about it.

I would like to see someone write a real slideshow program that does multiple transition types and supports controls such as pause and reverse.  I have too many more interesting projects on my mind, but maybe someone will find the time to do this.


Monday, February 4, 2013

Jumbo Digital Picture Frame

What do you do with a spare flat panel monitor?  If you are a Raspberry Pi hobbyist, you turn it into a jumbo size digital picture frame.  Photography is another of my hobbies and this is a great way to display my work.

Hardware Part 1 - Modify the Monitor Power Supply

This section requires some knowledge of power supplies and delicate soldering skills.  This step is totally optional and can be skipped.  I didn't want a second wire hanging from the picture frame for the Raspberry Pi power supply, so I tapped 5V off of the monitor's power supply.  You can power the Pi normally.  If you are really lucky you will have a monitor with a built in USB hub and you can power it from there.

I completely disassembled the monitor and located 5V and ground on the back side of the power supply where one of the connectors attached.  The wires in the lower right of this image show the power lines that I attached.

I shouldn't need to say this, but: DANGER.  Make sure the power supply is unplugged when you work on it.  Mains power can kill you!


Hardware Part 2 - The Control Panel

The monitor outputs 5V even if it is turned off, because it isn't really off - just in standby.  I added a power switch and LED as well as a push button to signal the Pi to shut down.  A simple script will monitor the pushpbutton and execute a halt when it is pressed.




If you only want to install the shutdown button, just connect it to a GPIO pin and to ground.  The pinouts that I used are shown here.  Don't be concerned about the inconsistency in the GPIO pin numbers.  This is explained below and is due to differences in the pin numbering used by the Raspberry Pi developers, the native pin numbers on the BCM chip, and the WiringPi library.



Hardware Part 3 -Build a case and put it all together

I used the plastic from the case to an old backup tape.  These are more flexible and a lot less brittle than most plastic CD cases.  I was able to use scissors to cut the plastic to fit the curved shape on the rear of the monitor.  Machine screws hold the case together tightly enough to keep the Raspberry Pi in place.  It is mounted so that the SD card extends a little bit below the monitor.  I would have liked to have it all hidden, but there wasn't room and this does make it easier to remove and insert the SD card.

Both the case and the control panel are held in place with Velcro   This allows me to peel the case loose so that I can plug a network cable in if needed.  Tie wraps are used to hold the HDMI cable and power cable neatly in place.  It is a very tight fit.

A added a short length of rope for hanging which is attached to the top two VESA mounting screws.  My frame is 21 inches and is quite a bit heavier than a typical painting, so I wanted something stronger than a typical picture hanger on the wall.   My work of art wouldn't be happy crashing to the floor.  I was very lucky and found a stud in the wall exactly where I wanted to mount the frame.  If you have to use drywall anchors, then I recommend using two about four inches apart and make the rope long enough to go over both.  If your walls are stucco, then I wish you luck.

System Preparation

Windows only recognizes the first partition on removable media and I wanted a large FAT partition to put the pictures on when the SD card is plugged in to my Windows laptop.  That means I had to use the /boot partition for this purpose.

  1. Load Raspbian as usual. Shut down the Pi and remove the sdcard.
  2. Install "Minitool Partition Wizard Home Edition" on a windows system with an sdcard slot. http://download.cnet.com/MiniTool-Partition-Wizard-Home-Edition/3000-2094_4-10962200.html
  3. Run the partition wizard and move the second partition (the system partition) all the way to the end of the disk space.  You could shrink the partition first but I didn't bother.
  4. Expand the first partition to fill the remaining space.
  5. Put the SD card back into the Pi, boot up, and log in.
  6. Update the apt database using:  sudo apt-get update
  7. Install the Linux Frame Buffer Interface using:  sudo apt-get install fbi
  8. Create a directory to hold the pictures that the frame will display:  sudo mkdir /boot/PICTURES 
  9. Create a new user named "slideshow" which is a member of the "video" group:  sudo adduser slideshow --ingroup video
  10. Change the inittab file to automatically log on the slideshow user:  sudo nano /etc/inittab   Find the line that begins 1:2345:respawn:/sbin/getty --noclear 38400 tty1  Comment out that line by placing a # in front of it and then add this line:  1:2345:respawn:/bin/login -f slideshow tty1 </dev/tty1 >/dev/tty1 2>&1
  11. Create a script to run the slideshow:  sudo nano /boot/slideshow.sh  which includes this one line: fbi -noverbose -m 1920x1080 -t 10 /boot/PICTURES/*.jpg   
  12. Some notes about the fbi command line:  The -m option specifies the resolution to use on the monitor.  This may need to be changed to display better for the monitor that you use.  The mode specified must be in the /etc/fb.modes  file.  I had to add the mode I needed, which is shown below.  The -t 10 option causes the program to run a slideshow with a 10 second period for each picture.  The -a option causes the program to automatically resize the images to fit the screen.  When I first tried this I was using 10 mega pixel images (about 3800 pixels across) and the Pi was taking 8-10 seconds to perform the resize.  To prevent this I removed the -a option and used FastStone Image Resizer to resize all the pictures for my slideshow to fit into a 1920x1080 screen.  You can find that utility here: http://www.faststone.org/FSResizerDownload.htm
  13. Make the script executable:  sudo chmod 775 /boot/slideshow.sh
  14. Edit the bash login script for the slideshow user:  sudo nano ~slideshow/.bashrc  and add this line to the end:   /boot/slideshow.sh
  15. Once all of the above has been done, you can reboot and the system will automatically run the slideshow.  You can stop it by pressing Control-C on the keyboard.
  16. Of course, you have to put some pictures in the pictures directory.  You can do this many ways, but I re-partitioned the sdcard so that I could plug it into my laptop and copy pictures directly to the sdcard.  The fbi command will support formats other than JPG, so don't feel that you are limited to that format.  You do need to realize that Linux is case sensitive with file names, so be sure to rename them all consistently. 

Here is the block that I added to the /etc/fb.modes file:


mode "1920x1080"
    geometry 1920 1080 1920 1080 32
    timings 0 0 0 0 0 0 0
    accel true
    rgba 8/16,8/8,8/0,0/0
endmode


The default fb.modes file did not include a 1920x1080 resolution so I had to find this example.  Fortunately it  works fine with my monitor.  More information about the fb.modes file can be found here:

Trigger Shutdown Script 

The drawing above shows the shutdown switch connected to GPIO-1.  I normally refer to the GPIO pins using the WiringPi numbering scheme.  However, I am not using WiringPi for this project.  We will access the GPIO pin via the /proc filesystem.  WiringPi GPIO-1 is GPIO-18 to the system.

Create a script to monitor the pin and perform a shutdown: sudo nano /etc/ini.d/wait-for-trigger.sh   
The contents of the script is this:


#!/bin/bash

# monitor GPIO pin 18 (wiringPi pin 1) for shutdown signal

# export GPIO pin 18 and set to input with pull-up
echo "18" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio18/direction
echo "high" > /sys/class/gpio/gpio18/direction

# wait for pin to go low
while [ true ]
do
if [ "$(cat /sys/class/gpio/gpio18/value)" == '0' ]
then
echo "SHUT DOWN NOW *****"
        halt &
        exit 1
fi
sleep 1
done


First, the GPIO pin is configured for input with a pull-up resistor enabled.  Then the scripts loops once a second and checks if the pin is pulled low from the push button being pressed.  If it is, then it executes the halt command and exits.

This script must be run at startup.  The easiest way to accomplish this is to add it to the end of the local startup script:  sudo nano /etc/rc.local
Add this line at the end of the file:
/etc/ini.d/wait-for-trigger.sh &
The & at the end of the line makes the command run in the background.  Without it, the local.rc script would not exit and the system would hang on startup.

All Completed:




Saturday, January 5, 2013

All cleaned up and re-mounted

A nice clean board (actually, i just flipped the old one over) and all components re-mounted.  System is up and running 24/7 now.
The Cleanly Re-Mounted Alarm/Automation System

Reading Temperature With Thermistors

My first interest for an analog input is a probe to read the temperature in my beer fridge. (I am a home brewer and occasionally need closely controlled temperature for fermenting lagers.) There were a couple of 10K ohm thermistors in my box of misc components, so I decided to try those. Something like the TMP36 sensor may be a better choice, and I will try some of those soon.

A thermistor is a special type of resistor that changes resistance with temperature.  A 10KΩ thermistor is 10KΩ at 25°C.  The first problem to solve is how to use the thermistor to produce a voltage that the MPC3008 analog to digital converter can read.  A simple voltage divider, as show in the diagram here, will do the trick.

The thermistor is R1, R2 is 10KΩ, and Vin is 5V.  This will make Vout = 2.5V at 25°C.  The chart for this thermistor shows that it should vary from 1.3V at 32°F to 2.9V at 95°F.  Setting the reference voltage on the MPC3008 to 3.3V will provide the best resolution for this range. I took test measurements by placing the thermistor in an insulated cup of water ranging from ice water to very warm.  Well, that was the plan anyway.  Reminder to self: when using a thermistor or other sensor in water, shrink tubing won't cut it.  I got a rude reminder of this when I first tried to do a calibration.


My solution to the waterproofing was to simply encase the thermistor and connecting wire in epoxy.  I formed a small mold using wax paper, filled it with freshly mixed epoxy, and pushed the sensor into the epoxy.  Once it dried, I trimmed it and it came out looking like this.














I took test measurements successfully and put the data into Excel. The plot of this data shows, as expected,  a very linear curve.  Putting this data into a Least Squares Fit function produced a slope of 0.13239 and an intercept of -14.402.  This gives me parameters to convert from counts to degrees with reasonable accuracy.  Once in use I will probably need to tweak the intercept value for individual sensors due to variations in the components.

The MPC3008 is a 10 bit ADC, meaning that it will output a value between 0 and 1023.  This corresponds to zero and reference volts.  For example, if the reference is 5V, an input of 2.5V would give an output of 512 counts.  To convert from counts to volts:

            V = Vref *counts/1024

Now that I have the data from my earlier calibration, I can simply use that to convert directly from counts to degrees F.

           Temp = -14.402 + (Counts * 0.13239)

My automation/alarm software has now been enhanced to read the analog data and convert it to real values using the provided conversion parameters.  I am now monitoring the temperature in my beer fridge and once I set up a large relay to control the power, I will be able to finely control the temperature and maybe brew a decent lager.