Welcome to Blue Monday
/Today is supposed to be "Blue Monday", the unhappiest day of the year. So I thought it might be the perfect day to fill in my tax return and then go and get a flu jab. Worked for me.
Rob Miles on the web. Also available in Real Life (tm)
Today is supposed to be "Blue Monday", the unhappiest day of the year. So I thought it might be the perfect day to fill in my tax return and then go and get a flu jab. Worked for me.
Yesterday I was writing C programs badly. Today I'm writing Python code, perhaps less badly. I took the Hull Pixelbot terminal program, the thing you can use to put programs into a robot, and I just copied the source code from my Windows PC onto a Raspberry Pi. And it just worked.
I'm actually rather chuffed about this.
I've been working on the Hull Pixelbot for what seems like ages (You probably think I've been blogging about it for roughly as long. Don't care. My blog.)
Anyhoo, today I learned the perils of "in band error signalling". The phrase "In-band" is a radio term. It means that control information is sent in the came channel as the data. My "in-band" errors worked like this:
int findVariablePos (char * name)
{
int result;
/* Stuff happens in here to find the variable */
return result; // return the offset of the variable */
}
The function findVariablePos returns the offset into the variable name table of the variable with the given name. In a program a variable is a named location that you can use to store data that is used as the program runs. If my program does this:
i = 99
- this is an attempt to store 99 in a variable called 'i' for no readily apparent reason. The thing running the program needs to have a way of finding out where in the computer the variable i is actually stored. That's the job of findVariablePos. Deep inside the program that actually runs the Hull Pixelbot script there is a statement like this:
int iPos = findVariablePos ("i")
The statement above (we're writing C by the way) would get me the position in the variable table of the variable with the name 'i'. "Aha", you say. "What if the program doesn't contain a variable called 'i'. ". Well, in that case the findVariablePos function returns the value -1 to indicate that the name was not found. This is kind of sensible, because you can't have anything at the position -1 in a table, negative numbers are meaningless in this context. All good. To make things clearer I even did this:
#define VARIABLE_NOT_FOUND -1
This gives meaning to the value, so that I can write tests that make sense:
if (iPOS==VARIABLE_NOT_FOUND)
{
Serial.println("Variable not found");
}
All good. Works fine. Then I re-factor the code and add a bunch of new error codes. I then decide it would be nice to have a set of numbers that the user (and other programs) can use to make sense of error messages. And I make the following change:
#define VARIABLE_NOT_FOUND 2
This makes sense in the context of fiddling with my error numbers, but it means that if the program ever puts a variable in location 2 in the variable table, the program will completely fail to find it because every time it gets the offset value this will be regarded as meaning that no variable was found.
Which is of course what happened. The problem in caused by a bad design decision (using the data value as a means of signalling errors) and then doing something without considering the consequences. The latest version of findVariablePos looks like this:
int findVariablePos (char * name, int * position)
{
int result;
/* Stuff happens in here to find the variable */
*position = result;
return FOUND_OK;
}
The result of the call is returned via one channel (the result of function) and the position value is returned by the method setting the value of the second parameter, which is a pointer to the variable. The call is a bit more complicated:
int iPos;
if (findVariablePos ("i", &iPos) == FOUND_OK)
{
Serial.println("Found the variable");
}
However, it now doesn't matter what the error numbers are, and whether or not they clash with any valid variable positions.
"In-band" error handling is great if your'e in a hurry and you're trying to keep the code simple and quick. But they also leave you open to problems further down the tracks.
I've been doing some work to try and improve the reliability of the distance sensor on the Hull Pixelbot. Not that it isn't particularly reliable, but I got to worrying about all the interrupts and timers that are going off as it takes its readings.
I did some tests today and discovered, to my alarm, that the distance reading was being horribly affected when I turned the motors on to move the robot. This was a problem. I spent a lot of time turning on and off different parts of the software, and getting more and more confused. I'd got to the point where just turning on one port seemed to be affecting the signals on another, completely different, port. Ugly.
Then I remembered. This is hardware. Hardware is not like software. It's, well, harder. Weird things happen in hardware. Things that end with comments in the code like "I'm not sure why this statement is here, but if it isn't here the device doesn't work".
When I turn the motors on, this makes the robot take quite a bit more juice from the power supply. If you're careful with your cash, like me, then you run your robot of the PC USB cable when you can, and keep the batteries disconnected. Which means that when the motors fire up the supply voltage takes a bit of a nose dive. Now, it turns out that my distance sensor is rather sensitive to low supply voltage, so this seems to offset all the readings.
In other words, I could fix my broken program just by turning the power on.
I've signed up as a speaker on the Community Connect Portal. If you want "The Rob Miles Experience", feel free to invite me over.
The speakers are ordered alphabetically by default, so you'll have to scroll down a bit to find me. I suppose I could have changed my name to "Aaron Aardvark" before registering, but I'd have to get rid of all my monogrammed towels if I did that.....
The Begin to Code with Python book now has its own tools page. This has links to the downloads for Python implementations, the code samples, and also a rather nifty guide that maps the book content onto the skills for the Microsoft MTA: 98-381 Python exam.
And you can find a link to Amazon as well, so you can buy your own copy.
The code editor for the Hull Pixelbot scripts is coming along nicely. It now behaves itself if you change the size of the window. The program above is for a "hand-wavy" game for the robot. You can make the robot move by waving your hand in front of it. First to the finish wins.
I'm putting together some Hull Pixelbot kits and one of the components that I need is a set of spacers to separate the circuit boards from the perspex base and top. You can of course buy these, but I'm too mean to do this, and I happen to have a 3D printer that I can play with.
I wanted to print all the spacers as a single item, so that I don't have to count them into each kit. One way to group a bunch of components together is to print using a "brim". A brim extends around the base of a piece and helps it stick to the printer base. If components are placed close together the brim merges to form a single sheet which holds all the components together. This works well but it can be quite a pain to then peel the brim off the items once they are printed, particularly if the items are small, like the washers above.
The solution I've come up with is to print a single layer which sticks all the elements together, followed by another layer on top of that which stiffens the support layer. If you look at the picture above you'll see that the top layer doesn't go all the way up to side of each spacer, there's a tiny gap around each one. This lets you "snap" the spacer out of the base.
One other trick that I'm using with my spacers is to print the first layer of the spacer with a hole which is slightly smaller than the others. This means that the spacer will grip onto a bolt, so that they are a bit easier to fit onto the robot when you are building it.
Way back when we used to go to Hornsea on New Year's Day. We didn't manage it this year, the weather wasn't good enough to tempt us out of the house, but we did go today. Of course I took a few pictures. I took the one above on Hornsea Mere. I love the way that the pier creates a calm region of water on the right of the picture. This might be a nice metaphor for people in these fractious times.
I spent a chunk of today making some carefully considered changes to the Hull Pixelbot software that turned out not to be necessary and didn't work afterwords. Oh well, thank heavens for version management.
Before Christmas we went to see the new Star Wars movie. Lots of bangs, crashes, people turning to the Dark Side (or not - who cares), more bangs, more crashes. The end. It was OK.
On Wednesday we went to see the new Paddington Bear movie. It was awesome. A tale of a bear always trying to do the right thing, striving to see good in everyone and managing to find it in a variety of beautifully realised situations.
I've got nothing but warm memories of this film. I'm finding it hard to remember much of the Star Wars one. Paddington rules. Go see.
We had a great hardware meetup tonight. I showed off a bit of the latest Hull Pixelbot scripting stuff (once I'd got it to work - note to self - don't turn up with a machine and think you can install the software and it will just work. Doesn't happen).
Then we talked a bit about Lora (or low powered radio to you). I've blogged a bit about this in the past but now we want to take things a bit further, and get going making Lora stuff. We've got all kinds of plans, none of them involving world domination. At least that's what we're saying for now.
Anyhoo, expect to hear more about our Lora plans in the not too distant future. It looks like a great technology to get in on the ground floor of. If you fancy getting involved you should come along to our next meetup and utter the magic phrase "I fancy getting involved". You can sign up for the next meetup here.
One of my New Years resolutions should have been "I must stop buying cheap and useless gadgets". But since I haven't made that resolution, and I found myself in the local grocers looking at the bits and bobs on offer, I ended up buying a little dashboard camera for a tenner.
It comes with a mounting for your windscreen, a power connector and even a little lithium battery so it can be used away from the car (I want to attach it to a Hull Pixelbot).
It works really well. The camera is reasonable quality, the controls a bit clanky, there's some HF whistle (which I can't hear) when it's switched on. But overall a win.
Except for one tiny flaw that I've yet to resolve. You need to add an SD card which is used to store the video. When I take the card out of the camera and try to use it in my computer the files on it are not recognised. I hope it isn't using "write only memory" technology.
One of "Robert's Rules" of programming is that things that sound simple often aren't. And things that sound complicated often aren't. A while back I had an idea for a simple scripting language that could be used to control Hull Pixelbots (or anything else embedded). It sounded simple. It's not.
I've been playing around with the language and I've just about got it going. It's not as simple as I might like, but it does work. The biggest change that I've made from previous versions is to use the "Python" style of code blocks. I did have "endif" keywords to mark the end of conditions but I found these really irritating (I kept missing off the endif and then wondering why the program wouldn't compile). So now you indicate which statements are controlled by a condition (or a loop) by just indenting the statement. Want to see some sample code?
begin
move 100 wait
turn 180 wait
move 100 wiat
end
This program would move the robot forward 100, make it turn 180 degrees and then move back. The wait element means "wait for this move to complete before performing the next statement". If the wait element is omitted the program starts the action and then moves onto the next statement immediately. We can make more interesting behaviours:
begin
forever
green
move 100
if @distance < 100
red
turn 90 wait
end
This program makes the robot move forwards. As the robot moves it checks the value returned by the distance sensor . If the program detects an object less than 100 mm away it turns the robot 90 degrees and then continues moving forward. The red and green commands change the colour of the pixel. The indenting above tells you that the red and turn 90 statements are only obeyed if the distance is less than 100.
The programs are compiled and executed inside the robot. I've written a tiny Python program to send them via the USB port.
Update: I've made some tiny changes to the way that the wait behaviour works after showing someone the language and realising that it could be better.
I'm not a huge fan of New Year's Resolutions. And resolving to do more to keep fit is probably not a good plan on a day spent watching telly and eating.
Oh well. At least I haven't used the video monitor gag this year.
Happy New Year everyone.
New Year Sieve.
Note: I may have used this gag before. I don't care. I still like it. And it's my blog.
In between other games, I've played a bit of Zookeeper. Above is my finest hour so far. The boss is normally quite rude to me. Below is one of my favourite insults...
Another game I've been playing with over the break is Mario and Rabbids on the Nintendo Switch. It's a fun little game that was on offer at a temptingly low price over the Christmas break. I like it because it's turn based. You give your characters their instructions and then watch the action unfold as they get into position and shoot at the enemy. Then the enemy takes their move, and your carefully laid out plans collapse before your eyes. Although that might be just me.
I really like the way that there's no limit on how long you can spend thinking about what to do next. I'm rubbish at most "shooty" type games because I have a habit of standing and thinking, never a good plan when there are snipers about. But with this game I can spend as long as I like choosing who to send into battle, which of the wonderful weapons to give them and what to make them do when they get there. There seems to be a huge depth to the action too, with stuff laid around the levels that really encourages you to go back and play them again once you've levelled up a bit.
If you've got a Nintendo Switch you really should get this game I reckon.
Number one son has brought his Playstation 4 Pro along for the Christmas break. And he's bought Dark Souls III
I'm finding it great fun to watch him play it. There's a lot of death involved. Quite a bit of it involves the player. It seems that you learn the right thing to do in every battle by doing the wrong thing first and finding out that it kills you. The graphics are impressive, if a bit murky, and the animations and actions of the different forms of the evil hordes that you need to kill are very well realised. The voice acting of the characters is well done, and the story is suitably preposterous. Worth a look if you've got the patience of the un-dead.
Lovers of games involving strategic play, intense plot and mental strength should look away now. Lovers of idiotic fun though, that's a different matter....
We didn't playtest this at all is daft. It's the kind of game you can win by being the shortest player. Or lose by being eaten by a dragon. Or not touching your nose the right number of times. The games are short, furious and fun. I can't imagine spending an entire evening playing this game, but for a bunch of mad fun before you start playing Coup I reckon it would be hard to beat.
Rob Miles is technology author and educator who spent many years as a lecturer in Computer Science at the University of Hull. He is also a Microsoft Developer Technologies MVP. He is into technology, teaching and photography. He is the author of the World Famous C# Yellow Book and almost as handsome as he thinks he is.