Executing Gummiworms The trials and tribulations of a grumpy curmudgeonly old git


FossilPi — How to setup fossil scm on your Raspberry Pi

fossilpiFor a variety of reasons including that I am a bit of a contrarian whenever I need to keep a project under version control rather than use git and/or github I always turn to fossil http://fossil-scm.org As I can have a new project with bug tracker & wiki up and running in a few minutes. As I recently read a blog post about setting up a private git server on the raspberry pi I started to write up a long blog post about how to setup fossil on the raspberry pi to show how easy and how much nicer IMHO fossil is than git :) . However, after writing a really long blog post I compared my writing to the fossil documentation and the official fossil documentation is an awful lot better and easier to understand than what I wrote, so instead of what I was going to post i'll just link to the fossil quickstart and the up & running in 5 minutes doc with one addition which is to tell you that fossil is in the Raspbian repos so you don't need to compile it yourself :)

fossil quickstart: http://fossil-scm.org/index.html/doc/trunk/www/quickstart.wiki

fossil up and running in 5 minutes: http://fossil-scm.org/index.html/doc/trunk/www/fiveminutes.wiki (note: this doc uses windows file paths & names, but the process is the same on linux)

link to all the fossil documentation: http://fossil-scm.org/index.html/doc/trunk/www/permutedindex.wiki


[Isn't it nice when something is well documented :) ]


Completely meaningless stats about 2,500,000 Raspberry Pis

rp.o_qrcodeWhile i'm waiting for the kettle to boil so I can make a cup of tea I thought i'd do some calculations on how high & how long 2,500,000 Raspberry Pis are. I used the data from the FAQ and assuming that the number of Raspberry Pis sold is 2,500,000 (The last sales numbers quoted by the Foundation) if we stacked 2,500,000 on top of each other then we'd reach 52.5 kilometers, which is into the Mesosphere & approx 13 kilometers higher than Babbage reached on his highest trip into the sky.
(((number of Rpi sold * 21mm)/1000)/1000) = 52.5
(((2500000 * 21 )/1000)/1000) = 52.5KM



If we laid all the Raspberry Pis sold end to end along their X axis (85.60mm) then we'd have 214 kilometers of Raspberry Pis and if you drew a circle with a radius of 214 kilometers centered on Pi Towers then you could reach anywhere on the circumference of the green circle.


(((number of Rpi sold * 85.60mm)/1000)/1000) = 214
(((2500000 * 85.60 )/1000)/1000) = 214KM

If you laid all the Raspberry Pis sold end to end along their Y axis (56mm) then you'd have 140 kilometers of Raspberry Pis & you'd be able to reach any place on the circumference of the green circle.


(((number of Rpi sold * 56mm)/1000)/1000) = 140
(((2500000 * 56 )/1000)/1000) = 140KM

Finally if we were trying to weight all the Raspberry Pis sold it would take approx 28.125 female Asian elephants.

(2500000 * 45)/1000) =112500kg

112500kg/4000kg = 28.125 elephants.

[Note: all totals assume that all the Raspberry Pis were model Bs which isn't true but does it really matter? :) ]



Happy Birthday Raspberry Pi

rp.o_qrcodeIt's that time again. It's the 2nd annual Liziversary (Boy that never gets old does it? :) ). A time to celebrate the Raspberry Pi and what's been going on in RaspberryPiLand. In the year since the last Liziversary the total number of Raspberry Pis is well over 2.3 million (The last number quoted by the foundation) and i'd guesstimate that it's probably 2.5-2.75 million by now. Raspberry Towers has relocated up a floor or two to a much larger floor space, The Education team has expended from one-ish (Clive) to four-ish (Carrie Anne, Dave, Ben & Clive), Two Camera modules have been released (The "normal" camera & the pi-noir), Oracle has released a hardfloat version of Java for the Raspberry Pi, Mathematica & Wolfram Language for the Raspberry Pi has been released. NOOBS has been released, making it much easier to setup the Raspberry Pi. A couple of engineers have been hired & there is a artist in residence. Weston/Wayland has been ported to the Raspberry Pi & work is on-going to make it better. At least one new business has been started, Ryanteck LTD (WTG Ryan). Other small businesses, such as Pimoroni, ModMyPi, 4tronix, Cyntech have added more Raspberry Pi related products and expanded into other things (good going guys). Several under-18s have given talks and presentations of top notch quality (Amy Matt et al), there seems to have been a raspberry pi robot uprising. You can't turn around without tripping over a Raspberry Pi powered robot these days. The Foundation has pumped thousands of pounds into Open Source projects and there seems to be a gathering of raspberry Pi fans somewhere in the world every week, sometimes several gatherings and if you google "raspberry pi" you get "About 44,000,000 results (0.38 seconds) " -- phew that's a hell of a lot.


generic cialis

oh and there doesn't seem to be a month where 2 or 3 Raspberry Pi related books haven't been published. You could probably build a small house using all the Raspberry Pi books as bricks by now :)

I could go on and on about the Raspberry Pi & the good things that have happened but here in NYC it's brass monkeys weather so i'm going to get back under the blankets with a couple of hot water bottles and a cat or two warming my feet. But first i'll let you know what i've been upto that is Raspberry Pi related.

As per normal I have about 10 to 15 currently unfinished projects waiting for me to get around to finishing them when i can get a quiet couple of days. The 3 or 4 I most want to finish off sooner rather than later are shoving a couple of raspi's into various computer cases and using their keyboards and other peripherals with the raspberry pi e.g. into a Camputers Lynx case, into a Tandy Model 100 & using a PiTFT instead of the model100s LCD (unless i can findout how to drive the tandy lcd with a raspberry pi & a timed & motion sensitive lock box (reward system) and a couple of other things. I also have some software to write for the raspberry pi to help teach protocols, protocol design & networking and another project I have just started to get telehash running on the Raspberry Pi (and other ARM devices)

However I did complete 1 project and am almost finished with another. The project I finished was tech editing the 2nd revision of the Raspberry Pi user guide. I loved doing that, I was quite sad when i'd finished and if anyone needs a tame tech editor & pedant i'm available :)

I am also co-authoring a book (can't tell you what it's about yet but as i'm sure you'll all guess it's Raspberry Pi related) and it's not as much fun as the tech editing and has been a long hard slog. I'm not too far from completion, a couple of weeks or so I hope as long as I don't decide I don't like it and start again with revision 56.1 :) -- that actually is the real revision number of one chapter :) although I think I like what I am currently writing so the fortnight seems about right.

Anyway it's been a good year for the raspberry pi & on the whole it's been an ok one for me.


Happy Birthday Raspberry Pi


Installing termcoin on a Raspberry Pi

Dogecoin_logo_large_verge_medium_landscapeA few days ago while taking a break from other things I tried out Multidoge on one of my Raspberry Pis and although it ran ok I really didn't like it as most of my Pis are headless and I really don't like running Xwindows & vnc'ing into my Pi just for one program so I started looking around for a cryptocurrency wallet that was text based and would run on the console or via ssh and I found a node.js app called termcoin that is a userfriendly wrapper around bitcoind that can also be used with other cryptocurrency daemons. As the dogecoin wallet doesn't come with dogecoind, at least it didn't when I downloaded the wallet it didn't I first had to download the dogecoin wallet source & build that.

git clone https://github.com/dogecoin/dogecoin.git
cd dogecoin/src
make -f makefile.unix USE_UPNP=1

and when the build has finished move dogecoind to /usr/local/bin

sudo dogecoind /usr/local/bin

and create a conf file in ~/.dogecoin/cogecoin.conf

Mine, after removing the password, use your own :)


As termcoin is written in node.js and the copy of node.js in the raspbian repos is ancient I did a quick google for recent instructions on how to install the latest node.js onto a Raspberry Pi as I knew i'd seen some a few months back but had forgotten to bookmark it. Google returned quite a few results but the one I ended up picking was http://revryl.com/2014/01/04/nodejs-raspberry-pi/ which is very clear and had node.js installed and tested in about 90 seconds.

I then installed termcoin from github and installed the UI library it uses, blessed and the qrencode program.

git clone https://github.com/chjj/termcoin.git
cd termcoin/bin
npm install blessed
sudo apt-get install qrencode

Once everything is installed and because i'm using putty and do want pretty line/box drawing characters I added


to my .bashrc and also as i didn't want to logout and in again I also exported it from the command line.

Once everything above has been completed you can then run termcoin to use dogecoind rather than bitcoind by using the -c option thus

./termcoin -c dogecoin





Why I like Dogecoin.

Dogecoin_logo_large_verge_medium_landscapeI'm not much of a meme kinda guy. I do like a viral video or a funny picture as much as the next guy but i really don't get most memes, I just don't see the point or I find out about them about 3 weeks after they've gotten really annoying but recently i've been messing around with the meme turned cryptocurrency Dogecoin, http://dogecoin.com Mostly i've been tipping people using the twitter dogecoin tipbot @tipdoge, mining a few, a very few, less than a couple of thousand in 2 weeks, as part of a pool using an idle core on my computer & reading the dogecoin subreddit. The thing that first attracted me to the dogecoin was that the community that seemed to grow up around this altcoin didn't take itself too seriously and the fact they used the currency as a currency to be nice to people. rather than just saying thanks or well done they'd show it "physically" (should that be virtually) by throwing a few doge to the recipient of the kudos and although they could already have done that using bitcoin or litecoin isn't it nicer to receive something basically worthless other than the fact someone liked something you've said or done with a whole something than a fraction of a fraction of a something? even though they have the same monetary value i'm much prefer to receive 10 doge than 0.00001890 btc. i actually lie as i am trying to build up my reserves of bitcoin just on G.P. as I always get a bit annoyed that in 2009 I tried to mine bitcoin on at the time was an ok computer and after 5 months I hadn't even got an accepted share let alone a block. Luck played a very large part of bitcoin in the early days but 5 months of bad luck was enough to turn me off cryptocurrencies  for a while so if you happen to have a few satoshi lying around that you don't know what to do with then you could always bung them my way (btc address: 1E8EPZcDHqBv7Cdd2RMJkeUVaWb9XDrKvF ). But i digress. The reason I like dogecoin, and a few of the other altcoins such as kittehcoin & primecoin is that I see them as then almost as the Raspberry Pi of the cryptocurrency world. In the future I think that cryptocurrencies are going to become more important for many reasons that are too numerous to list here but they are something that even non-geeks will need to know about and altcoins like dogecoin are a cheap (currently and even with the market manipulation I think it'll remain cheap for a long time yet), fun way to teach kids about economics, the currency market, banking fees, ... Obviously with my obvious Raspberry Pi bias i'd prefer some sort of Raspberry Pi mineable only cryptocurrency, The Babbage? as that would have added safeguards to stop things getting crazy with it's value, fractions of a penny rather than fractions of the pound (dollar) rather than let but to design something that could only be mined using raspberry pi is as near as damn it impossible and would need to combine proof of work, with proof of ownership & proof of stake which could get complicated and there is the downside that if the ability to mine is limited to just the Raspberry Pi then it might not have much uptake and could fail in a variety of ways including and not limited to not enough miners to keep the blockchain healthy

So unless and until there is a Raspberry Pi altcoin i'll keep tipping with dogecoin, for as long as I have any. if you'd like to donate a few doge to me so i can keep passing them out then my doge wallet address is D7c4ovMoEZ8KTnR2bhTXSiJpuBhGake6f7 , and while the dogecoin community remains a reasonably pleasant community, when I see someone say or do something nice and if I run into kids who I think would have fun with altcoins & maybe learn something (with their parents permission of course) give them a dogecoin or kittehcoin or ... paperwallet and a few tips on where to go to find out more about cryptocurrency.


Holiday Competition

CAM00323Earlier this year I started work on writing a holiday quiz but due to the circumstances beyond my control e.g. wife & I spending most of the last few months doing reasonable impersonations of typhoid mary & having every kind of -itus you care to name and doing a bit of tech editing and co-authoring  that i just never got around to writing the quiz. However, I do want to do something if only to be able to clear out some space in my bits and bobs boxes and my odds and sods drawers so i've decided to have a "how many words can you make from this sentence" competition. The prize is lousy, some Raspberry Pi stickers, a Parallax RFID reader, a little USB blinky LED thing, a couple of patches, a 3G Dongle, USB SD card Reader, a LEV Circuit V1.0 kit and whatever else comes to hand when i'm packing the box to send to the winner, probably a Zipit Z2, an unknown circuit board with at least a Rabbit CPU on it and ???.

The rules are quite simple.

1. My decision is final

2. Any complaints see 1

3. No cheating

4. I can change the rules at any time

5. make as many words as you can from the given sentence, highest number of valid words that are in MY dictionary wins. But i'll accept both American and British spelling.

6. In the case of a tie then i'll (or i'll ask someone to) use the tie breaker question to decide

7. You have until 1 minute past midnight on the 1st of January 2014 to enter.

ok so the sentence to use to make as many words as possible from

"The Raspberry Pi is a credit-card sized computer that plugs into your TV and can do amazing things."

[ok that should give lots and lots of words]


and the tie breaker question is the best sentence that contains the phrase Raspberry Pi that says why it is great, or what you have done or are doing with it or just happens to mention the raspberry Pi :)


"______________Raspberry Pi  ____________________________________"


Good Luck & Happy Holidays


Quick & Dirty hack to modify raspbian before 1st boot

rp.o_qrcode[Disclaimer: This is a quick & dirty hack that serves it's purpose but there is no security, it can & almost certainly will screw up your image in weird and wonderful ways if you don't know what you are doing AND there are much better ways to do it but this works for our needs -- you probably want to ignore this and if you do use this i'm not responsible for anything that happens.]



I've recently been helping a friend who travels around with several raspberry pi's and often finds himself giving impromptu demos, lectures and teaching sessions about them & python and although he does carry extra kit with him he sometimes finds himself in locations where he doesn't have full control of the environment where he is. he often finds that he needs to change the wifi settings on 20+ raspberry pi's or install a piece of software or modify a file so everything will work but doing it manually and/or without the ability to ssh into raspberry pi can take quite a while so he asked me to knock him up something that he could use to make the task less onerous and would work without a network connection at the time he needs to make the changes.


So I knocked him up a modified version of raspbian that he can put onto a virgin sd card and will look for a tarball in the FAT /boot partition, extract it and run a script from the tarball to make changes to before he has access to a prompt.


Basically I took a freshly downloaded copy of raspbian, mounted the rootfs partition and inserted the following into the default raspbian /etc/rc.local after the display IP address commands and before the exit 0 on rc.local's last line

if [ ! -e /etc/setup_done ]; then
        if [ -e /boot/setup.tar.gz ]; then
                echo "setup tarball exists"
                TEMPDIR=`/bin/mktemp -d`
                tar xzf /boot/setup.tar.gz -C $TEMPDIR
                rm /boot/setup.tar.gz
                cd $TEMPDIR
                if [ -e ./run.sh ]; then
                        . ./run.sh
                        rm -rf $TEMPDIR
                        echo "" > /etc/setup_done
                echo "setup tarball does not exist"

What this does is
looks to see if the file /etc/setup_done exists and if not looks to see if the file /boot/setup.tar.gz exists and extracts it to a temporary directory, changes to the temporary directory and runs the script run.sh (warning: run.sh is run as root user and can do anything that the root user can do so is very dangerous) after run.sh has finished it deletes the temporary directory, creates the /etc/setup_done file and then ends.

After making that modification I made some other mods that are none of your business :D that he needs for his basic needs, his demo software, and some other odds and sods I unmounted the fresh raspbian image & sent him a copy which he now uses to create the sd cards he carries around with him and uses for his demos or for teaching and now when he gets to a location where he needs to make some changes to the wifi settings or something else he grabs one (or more) of his fresh sd cards, knocks up a quick tarball on his windows laptop with the changes he needs and dumps it to the FAT partition on the sd card and then boots the raspberry pi with that sd card. At the end of the session he puts the sd cards he used into his recycle pile ready to be reimaged from the modified raspbian image and grabs another stack of fresh sd cards ready for the next time.

[yes i know this is probably the wrong way to do this, it should probably be done using a script in init.d, downloading the tarball from a server would be better & more secure, but we can never guarantee that he'll be able to do that and well this is really mickey mouse and an unusual situation and basically useless but i thought someone might find it useful.]



Setting up sftp on the raspberry pi (and on other linux systems)

rp.o_qrcodeOne of my websites is only of interest to about 10 people  worldwide but it is the main place to go to get documents & software for the Camputers Lynx microcomputer. As i'm in the States & all my Lynx stuff is in various attics & basements  located around the British Isles I rely on the others to supply the content & for years (& years) because i'm sometimes a bit slow in posting the stuff they send me i've been promising to setup some way for them to upload software & pdfs directly so a couple of weeks ago I moved the site from my main host to a raspberry pi (very few users so the server doesn't need to run on a 4 core 2Ghz, 3GB ram server with lots of bandwidth).

Now it's not that I don't trust my fellow Lynxians, they are all generally sensible people however at least one of them is a tiny bit weird :) with at different times various shades of hair colour ranging from blue to red to purple and back to blue again & while he has an EE P.hd he spends his time husbanding trees, redesigning computer components all whilst juggling & riding a unicycle. He also has a very developed sense of humour :) so no way am I going to give him shell access to the raspberry pi, no way not going to happen!!!! and if he isn't going to get shell access then none of the others will either so they'll have to be satisfied with chrooted sftp.


Normally setting up a chroot jail is a bit of a PITA, making the directory tree, copying lots of files & libs and testing a few times because you've forgotten to copy that one important lib however sftp has the ability to chroot "builtin".


First of all create a new group that all the people you want to give sftp access to will be in.

groupadd sftpusers

then add a new user  (or you can modify an existing one).

useradd -g sftpusers -d /uploads -s /sbin/nologin lynxfriends


usermod -g sftpusers -d /uploads -s /sbin/nologin existinguser

[change lynxfriends or existinguser to your desired usernames]


and set or change the password for that account

passwd lynxfriends

check that the account has been created or modified correctly by checking the relevant entry in /etc/passwd

grep lynxfriends /etc/passwd

test that you can't login

ssh lynxfriends@
lynxfriends@'s password: 
This service allows sftp connections only.
Connection to closed.

Now that the user that is to be allowed to use sftp is created or modified we now need to configure the sftp server. We need to user the builtin sftp server rather than an external program so we need to  edit the sshd configuration file /etc/ssh/sshd_config and comment out the line that says

Subsystem sftp /usr/libexec/openssh/sftp-server

and add the line

Subsystem       sftp    internal-sftp

it should look like

grep sftp /etc/ssh/sshd_config
#Subsystem      sftp    /usr/libexec/openssh/sftp-server
Subsystem       sftp    internal-sftp

we now need to add a rule to sshd_config so that only the users that are in the sftpusers group are placed in the sftp chroot jail so we need to add

Match Group sftpusers
        ChrootDirectory /sftp/%u
        ForceCommand internal-sftp

to the end of /etc/ssh/sshd_config which will look for users in the sftpusers group and then place them in a directory /sftp/<their username>

we now need to create the home & uploads directories for the users

mkdir -p /sftp/<username>/uploads

Finally we need to set the correct permissions on the newly created directories [my username is lynxfriends, change where you see that to the usernames you created]

chown lynxfriends:sftpusers /sftp/lynxfriends/uploads

it should look something like

pi@raspberrypi ~ $ ls -ld /sftp/lynxfriends/uploads
drwxr-xr-x 2 lynxfriends sftpusers 4096 Aug 6 13:06 /sftp/lynxfriends/uploads
pi@raspberrypi ~ $ ls -ld /sftp/lynxfriends/
drwxr-xr-x 3 root root 4096 Aug 6 13:06 /sftp/lynxfriends/
pi@raspberrypi ~ $ ls -ld /sftp/
drwxr-xr-x 3 root root 4096 Aug 6 13:05 /sftp/
pi@raspberrypi ~ $

You have now finished the setup and all that is left is to restart the sshd server & test


/etc/init.d/ssh restart
root@raspberrypi:/home/pi# sftp lynxfriends@
lynxfriends@'s password: 
Connected to
sftp> pwd
Remote working directory: /uploads
sftp> cd /
sftp> pwd
Remote working directory: /
sftp> ls
sftp> quit

You now have an sftp chroot jail setup on your raspberry pi (or other computer).

[although /bin/nologin allows you to configure a message to be displayed when people try to login to account that has /bin/nologin as it's shell actually having such a message causes problems with sftp logins so if you have one already you should delete it. if you really want to have one you should use rssh & scponly rather than the simple chrooted sftp.]


OSHW Document Jam

oshw-logo-200-pxIn 26 days, the weekend of April 26th the OSHWA, Open Source Hardware Association, is holding a Document Jam at ITP-NYU in NYC to help standardize and improve the how Open Source Hardware projects are documented so that others can replicate them and so that future generations of hackers, tinkerers and makers won't lose the knowledge previous generations have discovered. Unfortunately i'll probably not be able to make it and I really don't have the skills that will be needed as although I am often asked to help friends by proof reading and idiot proofing, I am darn good at it too even if I do say so myself, My super power is that i'm a tiny bit of an OCD pedant when it comes to typos & grammer in other peoples documents. I really don't have any hardware skills other than following instructions and even then it'll probably take me a few goes to get it right & even though I could probably help with some of the documentation and design stuff I really don't do well in crowds so Hack-a-thons & Jams are things I try to avoid. I can cope with crowds in large open spaces but i'd be a gibbering wreak anywhere else.

However if you think you can contribute, the problem statement is here and the how to contribute is here and if you have an account on Trello you can help with some of the pre-event stuff here. I'm not seeing many people using the Trello board so if you think you can help check it out and start using it.

The Guidelines for Participation to the First OSHW Doc Jam can be found here




RaspberryHunt Part 2

CAM00148The stepper motor I want to use to move the TSL2561 sensor along a track arrived on Thursday and i've wired it up and tested it and it works very well for what I want however, i'm going to be busy for a few days so i'll not be able to build the track, case and transfer the circuits to veroboard until next weekend at the earliest. So rather than leave anyone hanging if they are interested in this I thought i'd write up what I have so far so they can replicate it if they want.

As far as the hardware is concerned what I did was combine two circuits available from Adafruit. The "using an L293D" circuit from lesson 10 by Simon Monk   and a RaspberryPi'd version of the circuit wiring the TSL2561 by LadyAda and just for kicks bunged an LED on the Raspberry Pi's GPIO pin 21. As you can see from the photo below (and above) it is a bit of a rat's nest but it worked first time so I have to be doing something right especially as so far touch wood no computers have yet been harmed.

Once I move this to veroboard the TSL2561 board & the LED will be put on a small piece of veroboard with some longish wires mounted on a track to be moved along it by the stepper motor and the stepper motor circuit will be mounted on to of the Raspberry Pi somehow.

For the software I used a slightly modified & wiringPi'd & C'd version of Adafruit's Arduino TSL2561 C++ code, the header & the functions, along with Gordon Drogon's wiringPi library and knocked up a very quick & dirty program that sort of works well enough for testing.

pi@raspberrypi ~/raspberryhunt $ cat raspberryhunt.c
* RaspberryHunt version 0.4a *
* By Russell "ukscone" Davis *
* 2013-03-22 *
* Portions Copyright Adafruit, wiringPi is GPL3 Gordon Drogon *
#include http://ccair.org/online/

#include "Adafruit_TSL2561.h"
#include "wiringPi.h"
#include "wiringPiI2C.h"

/* Global Variables */
typedef int bool;
#define true 1
#define false 0

int _fd;
int _addr;
int _gain;
int _integrationtime;
bool _autogain;

#define VER "0.4a"

#define LED_PIN 21
#define ON 1
#define OFF 0
#define setupLed pinMode
#define led digitalWrite

#define ENABLE_PIN 18
#define COIL_A_1_PIN 4
#define COIL_A_2_PIN 17
#define COIL_B_1_PIN 23
#define COIL_B_2_PIN 24

#define gpioDirection pinMode
#define powerCoil digitalWrite

/* Stepper Motor Handling */

void setupStepperMotor(void) {
gpioDirection(ENABLE_PIN, OUTPUT);
gpioDirection(COIL_A_1_PIN, OUTPUT);
gpioDirection(COIL_A_2_PIN, OUTPUT);
gpioDirection(COIL_B_1_PIN, OUTPUT);
gpioDirection(COIL_B_2_PIN, OUTPUT);

void doStep(int s1, int s2, int s3, int s4) {
powerCoil(COIL_A_1_PIN, s1);
powerCoil(COIL_A_2_PIN, s2);
powerCoil(COIL_B_1_PIN, s3);
powerCoil(COIL_B_2_PIN, s4);

void stepForward(int delay_ms, int steps) {
int i;
for(i=0; i<=steps; i++) {
doStep(ON, OFF, ON, OFF);
doStep(OFF, ON, ON, OFF);
doStep(OFF, ON, OFF, ON);
doStep(ON, OFF, OFF, ON);

void stepBackward(int delay_ms, int steps) {
int i;
for(i=0; i<=steps; i++) {
doStep(ON, OFF, OFF, ON);
doStep(OFF, ON, OFF, ON);
doStep(OFF, ON, ON, OFF);
doStep(ON, OFF, ON, OFF);

/* TSL2561 Functions (Copied from Adafruit_TSL2561.cpp at https://github.com/adafruit/Adafruit_TSL2561) */
/* enable TSL2561 by setting the control bit to 0x03 */
int enable() {
return wiringPiI2CWriteReg8(_fd, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,\

/* turn off the TSL2561 to save power */
int disable() {
return wiringPiI2CWriteReg8(_fd, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, \

void getData (uint16_t *broadband, uint16_t *ir)

/* Wait x ms for ADC to complete */
switch (_integrationtime)

/* Reads a two byte value from channel 0 (visible + infrared) */
*broadband = wiringPiI2CReadReg16(_fd, TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);

/* Reads a two byte value from channel 1 (infrared) */
*ir = wiringPiI2CReadReg16(_fd, TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);

/* Turn the device off to save power */

void setIntegrationTime(int time)

/* Update the timing register */
wiringPiI2CWriteReg8(_fd, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | _gain);

/* Update value placeholders */
_integrationtime = time;


void setGain(int gain) {

wiringPiI2CWriteReg8(_fd, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _integrationtime | gain);
_gain = gain;

void enableAutoGain(bool enable)
_autogain = enable ? true : false;

uint32_t getFullLuminosity()

switch (_integrationtime)

uint32_t x;
x = wiringPiI2CReadReg16(_fd,TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
x <<= 16;
x |= wiringPiI2CReadReg16(_fd,TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);


return x;

void getLuminosity (uint16_t *broadband, uint16_t *ir)
bool valid = false;

/* If Auto gain disabled get a single reading and continue */
getData (broadband, ir);

/* Read data until we find a valid range */
bool _agcCheck = false;
uint16_t _b, _ir;
uint16_t _hi, _lo;
int _it = _integrationtime;

/* Get the hi/low threshold for the current integration time */
_hi = TSL2561_AGC_THI_13MS;
_lo = TSL2561_AGC_TLO_13MS;
_hi = TSL2561_AGC_THI_101MS;
_lo = TSL2561_AGC_TLO_101MS;
_hi = TSL2561_AGC_THI_402MS;
_lo = TSL2561_AGC_TLO_402MS;

getData(&_b, &_ir);

/* Run an auto-gain check if we haven't already done so ... */
if (!_agcCheck)
if ((_b < _lo) && (_gain == TSL2561_GAIN_1X))
/* Increase the gain and try again */
/* Drop the previous conversion results */
getData(&_b, &_ir);
/* Set a flag to indicate we've adjusted the gain */
_agcCheck = true;
else if ((_b > _hi) && (_gain == TSL2561_GAIN_16X))
/* Drop gain to 1x and try again */
/* Drop the previous conversion results */
getData(&_b, &_ir);
/* Set a flag to indicate we've adjusted the gain */
_agcCheck = true;
/* Nothing to look at here, keep moving ....
Reading is either valid, or we're already at the chips limits */
*broadband = _b;
*ir = _ir;
valid = true;
/* If we've already adjusted the gain once, just return the new results.
This avoids endless loops where a value is at one extreme pre-gain,
and the the other extreme post-gain */
*broadband = _b;
*ir = _ir;
valid = true;
} while (!valid);

uint32_t calculateLux(uint16_t broadband, uint16_t ir)
unsigned long chScale;
unsigned long channel1;
unsigned long channel0;

/* Make sure the sensor isn't saturated! */
uint16_t clipThreshold;
switch (_integrationtime)
clipThreshold = TSL2561_CLIPPING_13MS;
clipThreshold = TSL2561_CLIPPING_101MS;
clipThreshold = TSL2561_CLIPPING_402MS;

/* Return 0 lux if the sensor is saturated */
if ((broadband > clipThreshold) || (ir > clipThreshold))
return 0;

/* Get the correct scale depending on the intergration time */
switch (_integrationtime)
chScale = TSL2561_LUX_CHSCALE_TINT0;
chScale = TSL2561_LUX_CHSCALE_TINT1;
default: /* No scaling ... integration time = 402ms */
chScale = (1 << TSL2561_LUX_CHSCALE);

/* Scale for gain (1x or 16x) */
if (!_gain) chScale = chScale << 4;

/* Scale the channel values */
channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE;
channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE;

/* Find the ratio of the channel values (Channel1/Channel0) */
unsigned long ratio1 = 0;
if (channel0 != 0) ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0;

/* round the ratio value */
unsigned long ratio = (ratio1 + 1) >> 1;

unsigned int b, m;

#ifdef TSL2561_PACKAGE_CS
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C))
{b=TSL2561_LUX_B1C; m=TSL2561_LUX_M1C;}
else if (ratio <= TSL2561_LUX_K2C)
{b=TSL2561_LUX_B2C; m=TSL2561_LUX_M2C;}
else if (ratio <= TSL2561_LUX_K3C)
{b=TSL2561_LUX_B3C; m=TSL2561_LUX_M3C;}
else if (ratio <= TSL2561_LUX_K4C)
{b=TSL2561_LUX_B4C; m=TSL2561_LUX_M4C;}
else if (ratio <= TSL2561_LUX_K5C)
{b=TSL2561_LUX_B5C; m=TSL2561_LUX_M5C;}
else if (ratio <= TSL2561_LUX_K6C)
{b=TSL2561_LUX_B6C; m=TSL2561_LUX_M6C;}
else if (ratio <= TSL2561_LUX_K7C)
{b=TSL2561_LUX_B7C; m=TSL2561_LUX_M7C;}
else if (ratio > TSL2561_LUX_K8C)
{b=TSL2561_LUX_B8C; m=TSL2561_LUX_M8C;}
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T))
{b=TSL2561_LUX_B1T; m=TSL2561_LUX_M1T;}
else if (ratio <= TSL2561_LUX_K2T)
{b=TSL2561_LUX_B2T; m=TSL2561_LUX_M2T;}
else if (ratio <= TSL2561_LUX_K3T)
{b=TSL2561_LUX_B3T; m=TSL2561_LUX_M3T;}
else if (ratio <= TSL2561_LUX_K4T)
{b=TSL2561_LUX_B4T; m=TSL2561_LUX_M4T;}
else if (ratio <= TSL2561_LUX_K5T)
{b=TSL2561_LUX_B5T; m=TSL2561_LUX_M5T;}
else if (ratio <= TSL2561_LUX_K6T)
{b=TSL2561_LUX_B6T; m=TSL2561_LUX_M6T;}
else if (ratio <= TSL2561_LUX_K7T)
{b=TSL2561_LUX_B7T; m=TSL2561_LUX_M7T;}
else if (ratio > TSL2561_LUX_K8T)
{b=TSL2561_LUX_B8T; m=TSL2561_LUX_M8T;}

unsigned long temp;
temp = ((channel0 * b) - (channel1 * m));

/* Do not allow negative lux value */
if (temp < 0) temp = 0;

/* Round lsb (2^(LUX_SCALE-1)) */
temp += (1 << (TSL2561_LUX_LUXSCALE-1));

/* Strip off fractional portion */
uint32_t lux = temp >> TSL2561_LUX_LUXSCALE;

/* Signal I2C had no errors */
return lux;

/* main() */
void main(void) {
_addr = TSL2561_ADDR_FLOAT;
_fd = wiringPiI2CSetup(_addr);
_integrationtime = TSL2561_INTEGRATIONTIME_402MS;

uint32_t shot;
uint16_t broadband, ir;
int hits;

int forever = true;
int sensitivity = 100; /* this is a percentage */

wiringPiSetupGpio ();
setupLed(LED_PIN, OUTPUT);


printf("Welcome to RaspberryHunt version %s\n",VER);
printf("By Russell \"ukscone\" Davis 2013-03-22\n");

uint32_t baseline_lux;
getLuminosity(&broadband, &ir);
baseline_lux = calculateLux(broadband, ir);

hits = 0;

while(forever) {
stepForward(10, 10);
getLuminosity(&broadband, &ir);
shot = calculateLux(broadband, ir);
led(LED_PIN, OFF);
if (shot > (baseline_lux+((baseline_lux/100)*sensitivity))) {
led(LED_PIN, ON);
printf("*** Hit *** Current number of hits=%d\n",hits);

As you can see from the video below the stepper motor, sensor & led all work together and once it's all mounted nicely in a pretty case and solid, stable track with some proper software it should be quite good & the same hardware should work for a variety of light based experiments such as my original goal.

YouTube Preview Image

As I said at the top of this post i'm going to be busy with some other projects that have a greater priority for a week to ten days but if anyone has any questions or wants to do something like this drop me a line & i'll try to help.

[note: please don't laugh at the code, i knw it's rubbish but it does what I need for the time being and i'll eventually write a nice pretty SDL version with lots of sound effects and pretty graphics and use events rather than a big loop with individual checks of the sensor & small movements of the motor.]