Beyond All Repair
The goings on of a computer scientist
The goings on of a computer scientist
Aug 11th
Anybody who has ever used MATLAB before will probably be aware that using loops is incredibly slow. It is advised that you write as much of your code as possible using matrices and vectors. However, if like me, your brain gets easily tangled into knots by multiple dimensions, or you want to do something particularly complicated, using matrices may not seem like a particularly attractive prospect. I came across this problem (not for the first time) earlier today, and I decided I’d have a go at trying to solve it.
In these situations, execution time can be greatly reduced by writing and compiling C or FORTRAN functions, which you then call from MATLAB. The form I will discuss here are C MEX files. Simply by porting a loop from MATLAB to C, I managed to reduce the execution time of a simulation I was running from over 260 seconds, to about 20 (I’m working on getting it down to less than 10).
The original MATLAB code is below. For those who are interested, it calculates the expected cost for buying a certain amount of energy at a given time, rather than waiting until closer to the time that energy is required for each discrete amount of energy one can buy.
for i = 1:length(amountToBuyInFM)
cost(i) = amountToBuyInFM(i) * FMPrice
+ dot(consumptionDistribution(distroRange <= amountToBuyInFM(i)),
(distroRange(distroRange <= amountToBuyInFM(i)) - amountToBuyInFM(i)
).*(FMPrice-SBP_Delta))
+ dot(consumptionDistribution(distroRange >= amountToBuyInFM(i)),
(distroRange(distroRange >= amountToBuyInFM(i)) - amountToBuyInFM(i)).*(FMPrice+SSP_Delta)
);
end;
This code is slow because MATLAB interprets the cost(i)= … function for every i in the range 1 to the length of amountToBuyInFM. If we write this language in a compiled language it’ll be much faster, more fun, and probably a lot less ugly.
So… How do we code this in C++ in a way that MATLAB will understand? Fairly easily, actually. All you actually need is a function with the following signature.
#include "mex.h" // Don't worry about finding this file -- this is sorted out later. void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray * prhs[]);
Where, nlhs is the number of output parameters, plhs is a pointer to an array of the output parameters, nrhs is the number or input parameters, and prhs is a pointer to an array of input parameters. This is called by MATLAB when your function is executed. That’s pretty much it… There are just a couple of types, and functions that I’ve found quite useful, which I will discuss next. By way of an example I’ll paste the code I wrote earlier (this is by no means the most efficient way of writing this code – but it is a LOT faster than running it in MATLAB…). Those of a nervous disposition are welcome to skip over this, to the explanation that follows.
#include<stdio.h>
#include <gsl/gsl_cblas.h>
#include "mex.h"
#include "matrix.h"
#include <math.h>
#define DEBUG
#define AssertDouble( no ) if (! mxIsDouble (prhs[ no ] ) ) { mexErrMsgTxt( "Function 'MexGetCosts' requires parameter " #no " to be of type Double"); }
inline int find(const double * haystack, const double needle, const int haystacklength)
{
for(int i =0; i < haystacklength; i++)
{
if(haystack[i] >= needle)
{
return i;
}
}
return -1;
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray * prhs[])
{
/* List of Arguments:
1) Consumption Distribution (array)
2) Distribution Range (array)
3) Amount To Buy in Forward Market (array)
4) Forward Market Price (scalar)
5) Sell Delta (scalar)
6) Buy Delta (scalar)
*/
//If the number of right hand side parameters is < 6 there is an error
if(nrhs < 6)
{
mexErrMsgTxt("Function 'MexGetCosts' requires 6 arguments\n");
}
AssertDouble(0);
AssertDouble(1);
AssertDouble(2);
AssertDouble(3);
AssertDouble(4);
AssertDouble(5);
const double * consumptionDistro = mxGetPr( prhs[0]);
const double * distroRange = mxGetPr( prhs[1]);
const double * amountToBuyInFm = mxGetPr( prhs[2]);
const double * fmPrice = mxGetPr( prhs[3]);
const double * sDelta = mxGetPr( prhs[4]);
const double * bDelta = mxGetPr( prhs[5]);
const mwSize * distroRangeSize = mxGetDimensions(prhs[1]);
const mwSize * fmAmountSize = mxGetDimensions(prhs[2]);
//Creating the output matrix
plhs[0] = mxCreateDoubleMatrix(1,fmAmountSize[1], mxREAL);
//Give it a friendly alias
double * output = mxGetPr(plhs[0]);
//Now perform the calculation of the cost for each amount bought in the forward market
int j;
double acc = 0;
double min = INFINITY;
for(int i = 0; i < fmAmountSize[1]; i++)
{
//Get the first index in the distribution that gives us
//the correct amount of power.
j = find(distroRange, amountToBuyInFm[i],distroRangeSize[1]);
if(j < 0)//Not found ...
{
output[i] = 0;
continue;
}
output[i] = amountToBuyInFm[i] * fmPrice[0];
acc = 0;
//Dot product up to that amount (expected cost in wasted elec).
for(int k = 0; k < j; k++)
{
acc += consumptionDistro[k] * (distroRange[k]-amountToBuyInFm[i]);
}
output[i] += acc* (fmPrice[0] - bDelta[0]);
acc = 0;
//Dot product over that amount (expected cost of late purchases).
for(int k = j+1; k < distroRangeSize[1]; k++)
{
acc += consumptionDistro[k] * (distroRange[k] - amountToBuyInFm[i]);
}
output[i] += acc * (fmPrice[0] + sDelta[0]);
if( output[i] < min)
{
min = output[i];
}
}
//If we have more than one output argument, we'll output
//the minimum in the second argument.
if(nlhs > 1)
{
plhs[1] = mxCreateScalarDouble(min);
}
}
In order to create a double precision m-by-n matrix of real numbers, simply use the mxCreateDoubleMatrix(m, n, mxREAL), which returns an mxArray * pointing to your m-by-n matrix with all elements initialised to 0. If you’d like to create a matrix of imaginary numbers, simply substitute mxREAL for mxCOMPLEX. In order to obtain a pointer (double *) to the memory allocated to the real components of the matrix, you must use mxGetPr( mxArray * ), and for the imaginary components of complex matrices, mxGetPi.
In order to create a scalar value, simply use mxCreateScalarDouble, which takes a parameter stating what the value should be initialised to. Easy.
In UNIX this seems to be fairly easy too. Simply use the ‘mex’ tool. mex -help will give you a list of switches you can use, but I compiled the above code with the following command…
mex -lgslcblas mexcost.cpp
where mexcost.cpp is the filename of the source code in the previous box.
Nice and easy
There’s a lot more to creating these functions. For further information, see the Mathworks website. A lot of mathematical functions have already been implemented by developers (surprisingly enough…). In particular, check out BLAS, and Boost.
May 5th
Just a quick update on the South Lettings/South Residential saga. They have agreed to use the dispute resolution service, which is good of them. Hopefully we’ll be able to get this all sorted (and even more hopefully, the guys at the deposit protection place will find in my favour
).
Before I continue, may I just apologise for the recent down-time this site experienced. It would appear the web-server wasn’t feeling up to hosting this site, so I’ve moved it to its own server, which should hopefully cope better (fingers crossed).
This afternoon I visited some solicitors just to confirm my legal rights with regards to the charges being imposed by South Lettings (if you haven’t heard the saga so far check out my other post). I was told that it sounded like what they were doing was trying to impose new terms in the contract after it had been signed (the new terms being the new charges). A relevant case in UK law is that of ‘Thornton vs Shoe Lane Parking Ltd‘, which basically seems to boil down as follows…
Mr Thornton parked in a car park, received a ticket to park, then upon returning to his car was injured. To my understanding, Shoe Lane Parking claimed they were not liable to pay compensation because on the ticket was written words to the effect of ‘Terms and Conditions Apply’.
The judge ruled that because Mr Thornton had not been made aware of the terms before entering in to the contract (which was concluded by him accepting the ticket), he is not bound by them.
To quote
He was committed at the very moment when he put his money into the machine. The contract was concluded at that time. It can be translated into offer and acceptance in this way: the offer is made when the proprietor of the machine holds it out as being ready to receive the money. The acceptance takes place when the customer puts his money into the slot. The terms of the offer are contained in the notice placed on or near the machine stating what is offered for the money. The customer is bound by those terms as long as they are sufficiently brought to his notice before-hand, but not otherwise. He is not bound by the terms printed on the ticket if they differ from the notice, because the ticket comes too late. [cited from http://en.wikipedia.org/wiki/Thornton_v_Shoe_Lane_Parking_Ltd]
In my case, I believe the contract was entered in to when I signed the tenancy agreement (some time in August), and although I didn’t even receive the letter referring to the £35 fees, it was dated mid-September, and therefore came after the contract had been entered into (and as for the £15, there was no mention on that even in the letter detailing the £35 fee as far as I can tell).
Anyway, more updates to come soon
Apr 30th
Before I start this rant, I want to make clear that these views are my own, and do not necessarily reflect the views of my University. While I’ve tried to ensure all facts are accurate, shamefully I’ve not been keeping a detailed log, so where possible please try to verify any claims with your own research, rather than just taking my at my word (i.e. please don’t try to libel me…).
I strongly advise anyone against renting from South Lettings (aka South Residential it would seem). Ever since I signed my contract with them I’ve had nothing but problems. They were incredibly slow in sending out my reference forms, in fact we only received them through email after much nagging, a couple of days before my tenancy began. Before I continue, I should note that when I first moved in to the property I was informed that the landlord was the current manager of the property, but South Lettings were taking over management of the building.
When looking around the flat I noted that there was electric heating, and I was informed that they were on a timer, upon moving in I discovered that the `timer’ was the Eco7 circuit, which turned the storage heaters on all night (off during the day), but the direct heat elements, when enabled, were on all the time (my electricity bill was £770 for 6 months, and I suspect a the heating contributed a large part towards that). To their credit when people complained about the heating, they did arrange for an electrician to come over and demo how to use it efficiently.
When I moved in to my flat (which I was told would have been professionally cleaned before I moved in) the flat was filthy. The work surfaces in the kitchen were covered with plaster dust, as were the sofas, carpets and parts of the wall. I noticed there was an uncovered socket on the wall and reported it to the agents, then 6 months later (at the end of my tenancy) it was still uncovered.
The flat I was in was quite new, and I was informed that some workmen would come in to install a closing pump on the front door (which I agreed to). Upon returning from University later that day, I came home to find my front door unlocked and the flat unoccupied (with the new pump installed). Also, while I was living at the flat, there were some damp problems in the kitchen/living room, I informed the estate agent’s and a couple of days later I came home to find an electric fan heater plugged in to my wall set on full power, blasting air at my wall. The estate agents did not ask permission to use my electricity supply, and did not even inform me that that would happen, as I don’t know exactly how long the heater was running for before I came back, I have no idea how much it cost me.
Upon moving out, I spent the day cleaning the flat to make it look presentable, ready for the next day, when I would do the checkout with the agent. During the checkout, the agent noted a couple of spots on the kitchen work surface that I was told I needed to clean, otherwise they would have charged me for hiring professional cleaners (some spots behind the oven, and just to give the fridge shelves a wipe down). I told the agent that I didn’t have any cleaning products on me, but as she told me she had another checkout to do, I’d go down to the local shops, buy some cloths etc. then come and fetch her when I was done cleaning the flat.
When leaving the flat, we agreed that I wouldn’t be charged for any cleaning or damages, but the agent noted that there would be a £35 checkout fee that I was told was in my contract. I couldn’t recall any mention of a £35 checkout fee, but I didn’t mention it at the time, assuming that I had just forgotten about it.
After getting home and re-reading my contract I saw no mention of any fees. About a week later, I signed in to the deposit protection scheme website to find that they had charged me £58. When phoning the agents, I was informed that was £35 checkout fee, plus a £15 fee for the estate agent going back to check the flat, and then VAT on top of that.
After informing them that there was no mention of a £35 fee in my contract I was told that I was in fact told about it in a letter they sent to me (presumably after I had signed the contract). I had no recollection of this letter and asked them to send me a photocopy of it showing my signed agreement. About one month later, and having still not received this letter as I was promised, I phoned them up again.
It is also interesting to note that there’s no mention of the checkout fees on their website either (see the screenshot below).
While on the phone to them, I informed them that I would not be paying the fees as they “cannot charge me random fees without informing me of them first”, to which they replied “yes we can”. After having spoken to some solicitors, I’ve confirmed that no, they can’t. I have just received a copy of the supposed letter via email, and I can confirm that I have never seen it before.
So if you want to avoid all of this hassle, I advise you against South Lettings, and South Residential, who seem to be the same company (at least they have the same director according to companies house).
The saga continues.
Apr 24th
I’ve been busy since I last spoke about my lamp. I’ve added code to put the lamp into various modes – so far I’ve implemented modes for ‘white’ (needs some calibration), randomly changing colours, randomly fading in and out with random colours, and of course just off.
Modes are changed by sending characters to the arduino over the serial connection, so that’s fairly easy. In fact I decided that was too easy, and also too inconvenient for me (I don’t want to have to echo characters to the lamp every time I want to turn it on). Therefore, to make changing modes easier I wrote a web interface, which contained some PHP code that echoed characters to the lamp based on which button had been pressed by the user. This was all hosted locally to the lamp, so echoing characters to it was fairly easy. The next step was to let users control the lamp remotely (i.e. across the internet). This turned out to be a lot more challenging (or at least I overcomplicated it to the point that it became challenging), and this is the main focus of the article.
Simply allowing users to change the mode of my lamp over the internet would normally be really simple – open up port 80 on the server that’s hosting my lamp to the internet – however shamefully I’m on a network whose firewall blocks pretty much every inbound port, so hosting the interface locally isn’t an option.
Another simple option would be to have the lamp periodically poll a location on the internet to decide which mode to use, that way the web interface can just set the value of a file, then when the lamp reads that file, it will set its mode appropriately. The downside with this is that the update time for the lamp would be quite slow and it would create a lot of http requests to the server.
So, to summarise
I’ve done work with chat bots before, and I just so happen to have access to a Jabber server so I decided I’d try to allow users to communicate with the lamp through Jabber. This was actually fairly easy, although I admit I’m cheating in so far as the actual Jabber code isn’t running on the arduino, but instead a SheevaPlug (plug computer that runs linux).
The client side code is pretty simple – just a quick PERL script. Jabber communication was enabled through the Net::Jabber.
#!/usr/bin/perl -w
use strict;
use Net::Jabber;
my $server = "-----";
my $port = 5222;
my $username = "-----";
my $password = "-----";
my $client = new Net::Jabber::Client();
my $device = '/dev/ttyUSB0';
my $allowFork = 1;
my $allowFaffage = 1;
#Try to fork the process, then kill the parent process
#leaving only the child process running. This detaches
#the process from the terminal.
if($allowFork == 1 && fork())
{
exit();
}
#Tells the XMPP librabry which functions should be
#called when certain events happen.
$client->SetCallBacks(message=>\&msgReceived, onauth=>\&authenticated);
#Connect to the server
$client->Execute(hostname=>$server,
tls=>0,
username=>$username,
password=>$password,
resource=>"lamp",
register=>0);
#Sends a message to a user
sub send { my($to,$body) = @_;
$client->MessageSend(to=>"$to",subject=>"Cheese",body=>"$body");
}
sub sendHelp { my($to) = @_;
my $body = <<END;
I'm Harry's Lamp
Talking to me turns me on, and makes me change colours etc. Here are the commands that are enabled atm.
white - Just boring, white light
random - Makes me randomly fade to colours
fade - Makes me fade in and out with random colours
off - Turns me off
END
&send($to, $body);
}
#Once the lamp bot is up and ready,
#send a message to the owner to tell them.
sub authenticated{
&send('admin@-----','Lamp bot online');
}
sub msgReceived { my ($err,$message) = @_;
my $body = $message->GetBody();
my $from = $message->GetFrom();
$from =~ s#/.*$##; #Get rid of anything after bleh@wahtever.com
$body =~ s/[^a-zA-Z0-9]//g; #Get rid of characters that arent alphanumeric
$body = lc($body); #Make $body all lower case.
if($body eq "?" or $body eq "help")
{
sendHelp($from);
}
elsif($allowFaffage == 1)
{
if($body eq "random")
{
`echo 'r' > $device`;
}
elsif($body eq "white")
{
`echo w > $device`;
}
elsif($body eq "off")
{
`echo o > $device`;
}
elsif($body eq "fade")
{
`echo i > $device`;
}
}
#Admin things... Enable and disable the lamp
#so people can't wake you in your sleep.
if($from eq 'admin@-----')
{
if($body eq "quit")
{
exit();
}
elsif($body eq "enable")
{
$allowFaffage = 1;
&send($from,'Faffing enabled');
}
elsif($body eq "disable")
{
$allowFaffage = 0;
&send($from,'Faffing disabled');
}
}
}
If you’re unfamiliar with PERL, the above script might be pretty horrific, but hopefully the comments in the code will help you work out what’s going on. If you’d like to learn more about programming in PERL, there’s a ton of information on the internet, including the PERL documentation.
Most of the logic is in the msgReceived function, which is executed whenever a message is received. The algorithm is very basic – get the body of the message we just received, then sanitise it, then compare it to various strings until we know what the user wants to happen. Simple… The above code runs locally on my plug computer, next I’ll take you through the code that runs on the server.
The server is actually running two pieces of code – a PERL script, which is similar to the one above and is used to communicate with the client over Jabber; and a PHP script which generates the user interface, and communicates with the PERL script when users choose to perform an action.
This might seem (and probably is) over complicated, but I’ll quickly explain my reasons for choosing this architecture.
To fix this I decided that it would be nice to have a single script that is always connected to the jabber server, and can be communicated with using local Unix sockets.
This code is fairly similar to the code above, so I won’t explain too much about it. I’ll jump straight to talking about the well named ‘doyourshiz’ subroutine. Avert your gaze if you are of a nervous disposition.
#!/usr/bin/perl
use Net::Jabber;
use Data::Dumper;
use Socket;
my $server = "-----";
my $port = 5222;
my $username = "-----";
my $password = "-----";
my $client = new Net::Jabber::Client();
my $allowFork = 0;
my $insockpath = "/home/freud/lampsocket";
#Detatch from the terminal if we're allowed to.
if($allowFork == 1 && fork())
{
exit();
}
$client->SetCallBacks(message=>\&msgReceived, onauth=>\&authenticated);
$client->Execute(hostname=>$server,
tls=>0,
username=>$username,
password=>$password,
resource=>"lamp",
register=>0);
sub send { my($to,$body) = @_;
$client->MessageSend(to=>"$to",subject=>"Cheese",body=>"$body");
}
sub msgReceived{
print Dumper @_;
}
sub authenticated{
print "Authenticated";
#We're ready to send messages to the lamp,
#Start listening for incomming comands from
#the local socket.
&doyourshiz();
}
sub doyourshiz{
#Create a socket
socket(INSOCKET, PF_UNIX, SOCK_STREAM, 0) or die("$!");
unlink($insockpath); #Delete the file we're binding to if
#it already exists...
bind(INSOCKET,sockaddr_un($insockpath)) or die("$!");
listen(INSOCKET,SOMAXCONN) or die("$!");
#accept blocks (makes the program wait) until someone
# connects to the socket.
for( ;accept(Client,INSOCKET); close Client)
{
open(INPUT, "<&Client");
#Open the client's input stream to 'INPUT' then
# read from INPUT and send it to the lamp until we've
# read everything that was sent to us.
while(defined($line = <INPUT>))
{
chomp $line;
&send('lamp address',$line);
}
close(INPUT);
#close the input. (the Client connection is closed in the for loop
# definition above.).
}
}
OK… The doyourshiz subroutine contains the main application loop. To start with it opens a Unix Socket, which appears as a special file on your file system (in the example above it has the path /home/freud/lampsocket). Any applications wanting to communicate with the above script can connect to that socket by using that special file (this will become clearer when I show you the PHP). The socket is identified inside the script by it’s identifier INSOCKET (the first argument to the socket command).
Whenever anything connects to that socket the script just relays whatever is sent to it to the lamp via Jabber. Note that at the moment, the code above will only actually accept one connection at a time (which I realise conflicts with one of my requirements above), ideally the code within the for loop above would be executed in a new thread to allow new users to connect. I’ll probably implement this soon…
Now you’ve seen the server’s PERL (which is by far the most complicated bit), it’s time to look at the PHP code.
I started by writing a wrapper class that handled connecting and sending to the socket for me, keeping the main bulk of PHP free from socket code.
<?php
class HSocket
{
private $socket;
public function __construct($path)
{
$this->socket = socket_create(AF_UNIX,SOCK_STREAM,0);
socket_connect($this->socket,$path);
}
public function __destruct()
{
socket_close($this->socket);
}
public function send($data)
{
socket_write($this->socket,$data,strlen($data));
}
}
?>
As you can see, the code is fairly simple. It’s pretty much the same as the PERL code above. The constructor takes an argument, which is the path to the socket you’re connecting to, and (dis)connecting is all done for you when instantiating and destroying objects from that class.
When sending data to the socket, we use the command socket_write, which takes three parameters – the socket you’re sending to, the data to be sent, and the size of the data in bytes. If you’d like to read more about socket programming in PHP check out the PHP Documentation and for those of you who would like to learn more about PHP, a good place to start is the PHP Manual, and of course Google.
Finally, the code that the user actually executes is below. This contains the buttons the user presses and it also processes the user’s actions to determine what values should be sent to the PERL script (and ultimately the lamp).
<?php
if(isset($_GET['do']))
{
include('HSocket.php');
$s = new HSocket("/home/freud/lampsocket");
//This switch statement makes sure we don't send anything
//malicious to the lamp.
switch(strtolower($_GET['do']))
{
case "off":
case "white":
case "random":
case "fade":
$s->send($_GET['do']);
break;
}
}
?>
<html>
<head>
<title>
Light Controls
</title>
</head>
<body>
<h1>Mood Lamp</h1>
<form action='index.php' method='get'>
<input name='do' type='submit' value='Off' />
<input name='do' type='submit' value='White' />
<input name='do' type='submit' value='Random'/>
<input name='do' type='submit' value='Fade' />
</form>
</body>
</html>
You’ll probably be overjoyed to notice that the code above is really quite simple. It creates a socket with the same path as was used in the PERL script above, and then sends data to it depending on the value of the ‘do’ GET variable. The switch statement helps to make sure that a malicious user can’t send data to the lamp that could be used to compromise either the server, plug, or lamp.
And there you have it. If you’d like to see the code in action, check out the online control panel. Currently you can’t see the state of the light (so you’ll just have to trust me that its working), but my next step is to get a webcam pointed at it, and also to add a feature to allow users to pick a specific colour for the lamp.
If you have any questions, or any suggestions as to what I can do next, please feel free to comment below. I’ll try to respond as soon as I can. If you want to steal any of the code above, then go ahead (it would be nice if you linked back to this post).
Apr 13th
Since I first got my Arduino and some RGB LEDs I’d wanted to build myself a mood lamp with some funky features (note that I used the word funky and not useful). Well, I’ve finally done it, and here is the blog post describing how.
For this project I used the Ikea Grönö, which was £4.99 when I bought it. It quite a nice matt glass finish, which helps to diffuse light, and also it comes with the glass shade and the actual light fitting separate from one another (I put the light fitting to one side as I won’t be using it in this project).
As well as that I used…
The brightnesses above were only chosen because they were the highest that were available at a fairly reasonable cost. It might be better to match the brightnesses of all LEDs, although if memory serves, human eyes aren’t as sensitive to blue light as they are red and green, so it might be worth getting a brighter blue LED (I advise doing some more research).
Anyway, on with the build…
Firstly, LEDs tend to be highly directional (i.e most light goes in front of the led). There seem to be lots of diffusing and mixing lenses available at various shops, but I decided I’d have a go at just scuffing the LEDs with some sandpaper. I was quite happy with the diffusion of light after having done that, so my next step was to breadboard the LEDs out. I arranged them into a triangular shape with a common ground rail on the breadboard, and individual positive rails for each diode.
In this project I’ve used the 5V supply from the arduino, my LEDs however were expecting
Therefore resistors must be added to stop the components from being ‘popped’ (trust me, blown up LEDs stink). The required resistance can be easily calculated using Ohms Law – V = IR.
V = The potential difference across the resistor (Volts).
I = The current in the circuit in series with the resistor (Amps).
R = The resistance of the resistor (Ohms).
So, we need the following values.
Simple… Here’s a video of the lamp shade placed over the breadboarded leds.
Although you can’t see it in that video, with only one LED of each colour it was far too hard to see when the surrounding light levels were high so I decided I’d add another led of each colour so they were arranged as in the following diagram.
I used three TIP122 NPN Transistors to allow the LEDs to draw more current than if I were just feeding them directly from the PWM outputs on the Arduino. The diagram below shows the circuit design as it was breadboarded out. This is in fact basically the same as the final circuit diagram (except with an Cat 5 patch cable separating the transistors from the resistors and LEDs).

The breadboarded mood lamp circuit. Numbers in circles correspond to the digital output pins on the Arduino. R1 = 100 Ohms, R2 = 47 Ohms, R3 = 330 Ohms.
Note the resistors and LEDs in parallel. Now that the LEDs are in parallel, the series part of the circuit must have twice the current required by the LEDs (Red: 100mA, Green and Blue 40mA). Therefore we require the following resistances.
You could of course just go to the next resistor size up, but I like to make things complicated so I decided I’d try to get as close as I can with the resistors that I had at my disposal. When combining resistors in parallel, the total resistance of the resistors in parallel is 1/R = 1/R1 + 1/R2 + … + 1/Rn
In the above diagram, R1 = 100 Ohms, R2 = 47 Ohms, R3 = 330 Ohms, meaning that the resistances above are
So, after breadboarding that and finding everything worked, I soldered everything to two breadboards. One containing the LEDs and Resistors, another containing the transistors and leads to connect to the arduino. I also soldered some RJ45 sockets on to the boards, to allow me to connect the two components together over long distances (I could have used other means, but I have miles of patch cable lying around). Something to remember when soldering the RJ45 sockets is that if you don’t plan on using crossover cable, you should solder the two sockets in reverse to one another as in the diagram below.
Once you’ve done that, connect everything up and make sure everything works before glueing the LEDs to the bottom of your lamp. Then you’re pretty much done (except for coding the actual Arduino). The code I have so far is very simple, it simply fades between colours.
const int led[] = {3,5,6};const int delayTime = 10;#define RG 0#define GB 1#define BR 2void setColour(const int * led, const int * colour){for(int i = 0; i < 3; i ++){analogWrite(led[i],colour[i]);}}void cycle(int which, const int * led){int a;int b;switch(which){case RG:a = led[0];b = led[1];break;case GB:a = led[1];b = led[2];break;default:a = led[2];b = led[0];}for(int i = 0; i <= 255; i ++){analogWrite(b, i);analogWrite(a, 255 - i);delay(delayTime);}}void setup(){for(int i = 0; i < 3; i++){pinMode(led[i],OUTPUT);}}void loop(){cycle(RG, led);cycle(GB, led);cycle(BR, led);}
And the moment you’ve all been waiting for – a video of the final product…
Apr 2nd
The N150 is a relatively new netbook from Samsung sporting the new Intel Atom N450 processor. After my last laptop died and after a brief mourning period I decided I’d buy an N150 as a replacement. Why did I buy a netbook rather than a ‘normal’ laptop? Well, firstly netbooks are cheaper, and also I don’t need anything particularly high spec as all I plan on doing with it is writing LaTeX and browsing the internet.
I’ve heard stories of people having trouble with netbook keyboards, and although to begin with it does feel a bit odd typing on a reduced size keyboard, it doesn’t take long to get used to it (I’m typing this post on it at the moment).
Another thing I was worried about is that the laptop would be very sluggish, but it seems to be running quite well so far with the AC supply plugged in. When running on battery however, I’ve noticed that youtube videos can be a bit jittery, and input into the wordpress post editor seems to be a bit laggy (maybe due to frequency stepping).
I’ve not been pushing it very hard – just some light web browsing and MSN – but so far I’m very impressed by the battery life, which so far has been 5 hours with an estimated 2 hours remaining. The lithium ion battery charged in about an hour from whatever state it was in when it left the box. I also notice there is a utility that lets you choose whether to allow the laptop to charge the battery to 100% or 80% of its capacity (where charging to 80% supposedly increases the life-span of your battery).
The laptop ships with Windows 7 Starter Edition, but I see that Ubuntu Linux has been reported to run on it ( https://wiki.ubuntu.com/HardwareSupport/Machines/Netbooks#Samsung%20N150 ), so I’ll probably be installing that once I get back to university. I’m interested to find out whether the multi-touch gestures work under linux, or whether they’re only implemented in the windows driver for the touchpad. An interesting point is that although this is running a 64bit processor, only a 32bit version of windows is installed.
Anyway, those are my thoughts after living with the laptop for a couple of hours. Expect another post soon with photos, more information, and whether or not the laptop has survived a couple of day’s use.