Sunday, September 12, 2010

Roguelike

During last 3 years I spent some of my time trying to learn how to write a roguelike. Roguelikes are cRPG games with no graphical mode, where environment is represented with ASCII characters (for example @ is player character). I discovered my first roguelike - ADOM when I was around 13 and I have always wanted to code one. I decided to write a post about developing a roguelike, because it's a way to summarize some things (and if I won't write it down it will rot on my hard drive for infinity).

I started by reading tutorials about writing games. In general it's very hard to find a good tutorial about game writing. Game development, like any other technical activity is about layers of knowledge - you begin with some simple functions that do only one thing, but you organize them into bigger structures that can provide complicated results. Most tutorials contain only the basic steps, but tell you nothing about the upper layers. The best tutorial about game writing I found is Philip Hanna's CSC207. It's a university course, and contains many good examples, as well as the game engine written in Java. The engine is written in a very generic way. It allows you to start your own project, but it's never optimized for it - so sooner or later it forces you to write your own engine - but at that time you already know what you want and how to achieve it. Very good teaching trick Mr Hanna!

I started my game using Philip Hanna's engine. At the beginning I really liked writing in Java. It was much faster to write than in C or C++. But after a while I became fed up with it - I had to create getter/setter methods for every variable, and the code was hard to change or read. Later I learned some tricks in the Eclipse IDE which helped a lot - automated refactoring and getter/setter creators. But I still wasn't happy with it. Then I found Python.

Python is probably the best language for hobbyists out there - it's fun to use, reasonably fast (at least I think so), and with quite good support. At the beginning Python webpage scared me off because there is some new version of Python 3.0 coming out, and no library works with it. But then I realised that nobody uses it yet, and everything works with Python 2.6 (it's a risky idea to make language backward incompatible).

I decided to start with Pygame - a library which is basically a binding to SDL library written in C. I read some basic tutorials, and started to port my earlier Java code to Python - mostly that meant holding DEL button for a long, long time. Python code is much shorter and easier to read than Java code (however some things are longer - like always including "self" as the first argument to a class method).

Below is a main class of my game - its temporary nickname is Towers :) :

  1. #File: game.py
  2. #Author: MW
  3.  
  4. import pygame, sys,os
  5. from pygame.locals import *
  6. from map import Map
  7. from input import Input
  8.  
  9. # Uncomment the lines below to enable profiling
  10. #import profile
  11. #import pstats
  12.  
  13. if not pygame.font: print 'Warning, fonts disabled'
  14. if not pygame.mixer: print 'Warning, sound disabled'
  15.  
  16. class Game:
  17.    
  18.     def __init__(self,width=800,height=600):
  19.         self._running = True
  20.         self.screen = None
  21.         self.screen_width = width
  22.         self.screen_height = height
  23.        
  24.     def game_init(self):    
  25.         pygame.init()
  26.         self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
  27.         pygame.key.set_repeat(200,50)
  28.         pygame.display.set_caption('Game')
  29.         self.input = Input()
  30.         self.map = Map(self,self.input,100,100)
  31.         self.clock = pygame.time.Clock()
  32.    
  33.     def game_input(self):
  34.         self.input.set_events(pygame.event.get())
  35.         if self.input.get_event(QUIT):
  36.                 sys.exit()
  37.  
  38.     def game_update(self):
  39.         self.map.update()
  40.  
  41.     def game_render(self):
  42.         self.map.render()
  43.         pygame.display.update()  
  44.      
  45.     def main_loop(self):
  46.         self.game_init()
  47.         while True:
  48.             self.time_passed = self.clock.tick(60)
  49.             self.game_input()
  50.             self.game_update()
  51.             self.game_render()
  52.      
  53.          
  54. if __name__ == "__main__":
  55.     towers = Game()
  56.     towers.main_loop()
  57.     # Comment 1 line above and uncomment the lines below to enable profiling
  58.     #profile.run('import game; towers.main_loop()', 'profile.tmp')    
  59.     #p = pstats.Stats('profile.tmp')
  60.     #p.sort_stats('cumulative').print_stats(10)
  61.  

Python allows for both object-oriented and procedure-oriented programming, but my code is rather oo-way. The object of the Game class is created in the if statement at the end of the file. After that the main_loop method is called. At first it calls game_init method and initializes Pygame objects: display and clock. It also creates input object which is a wrapping over Pygame's event module, and map object which contains the rest of the game. Then it loops infinitely through three methods: game_input, game_update and game_render. Such design separates game logic (game_update) from gathering player input and displaying the game on the screen.

So much writing and code still does nothing, but that's the beauty of the OOP - you don't need to know what's inside the object (the implementation) to write a proper code.

Sunday, June 13, 2010

UBI Summer School

Last week I attended 1st UBI Summer School in Oulu, Finland. It was organized as a part of Ubiquitous Oulu Project. Its main topic was ubiquitous and urban computing. The School comprised of six workshops. I took part in workshop E - "IP-based sensor networks" by Zach Shelby. It was the most geeky and technical workshop of all - other workshops were much more human and application oriented.

The main focus of the IP-based WSN workshop wasn't 6LoWPAN (as one could expect), but CoAP - Constrained Application Protocol. CoAP is an application protocol (ISO OSI layer 7) designed for WSN operation - it's RESTful, it features subscribe/notify mechanism and service discovery and it has a very small header. HTTP has neither of these. CoAP is still only an IETF draft, but taking into consideration the absence of open standards in the area it might really catch on.

I've got to admit that two weeks ago I didn't know what REST really was, but I like the RESTful approach very much - it's not based on some complicated messages, but rather on availability and state of resources. I find this philosophy coherent with Unix/Linux systems, where every device, or process is represented by a file in a system tree.

Other features of CoAP: subscription and discovery are even more interesting. Subscription is a must for communication with WSN nodes that are asleep most of the time. Service discovery makes application deployment for such nodes much easier - and it also makes maintenance and network expansion a lot more simple (maybe someday google will start to index your WSN nodes too :) ).

According to other participants of the UBI school the REST way is the only way for WSN (except one guy who did research into SOAP and EXI, but stupid airlines lost his luggage, and he was forced to leave the school before he could show us the results). But some of the people weren't convinced that new protocol is really necessary - people will still use old and clumsy (but more diverse and supported) protocols, and not a specialized thing like CoAP. Being more of a hardware guy I still can't present my own opinion in the area. Time will tell.

Sunday, May 16, 2010

Breakout boards - first test

Yesterday my wife went binge drinking (bachelorette party) so I finally had some time to assemble my Meshnetics breakout boards. They contain only five elements each, but assembling them is a real PITA because of the Meshnetics modules. I soldered them with normal soldering iron and used solder wick to remove any jumpers. Afer soldering I tested the boards with a multimeter set to beep. For the power supply I used two AA NiMH batteries in nice battery holder with a switch (sadly it has no place for screws). I measured the output voltage of the battery packs - it was around 2.6V for each. Meshnetics need between 1.8V and 3.6V to work properly. After assembling I connected the modules to the AVR Dragon JTAG programmer, and tried to read their signatures using AVR Studio. It worked perfectly - photo:



Breakout boards can be programmed and tested without any additional hardware, so they can be used as a very primitive WSN nodes. I didn't include any sensors and actuators on them - even LEDs or microswitches - so using them in such way would be really painful. However for a single module I can use AVR Dragon for fake I/O so it should be possible to run some software tests without designing and building target boards.

In the meantime I've also been thinking about some name for my devices. In my opinion name is a very important thing - human brain needs names to process data, and a bad name might be harmful to entire project. I'm not a native English speaker so inventing a good name is not so easy. At first I thought about "smartlets" - like smart droplets :). However it has already been taken up by Apple - from a totally different angle - smart outlets. I need to think a bit more.

Now the coffee for my wife...

Friday, May 7, 2010

WSN-intro and Meshnetics breakout boards

A couple of years ago, first news about Wireless Sensor Networks started to appear on the Web. At the beginning there were scattered pieces of information, but slowly it became a recognizable and popular research direction. I really like the idea of wireless sensor networks - tiny, simple devices called "motes" with limited sensing abilities, and processing power are used to collect data about physical and social phenomenons. Single mote has very little usefulness, but a network of them can support really innovative projects. It really sparks up imagination.

The most popular standard in the WSN area nowadays is the Zigbee. It is supported by Zigbee Alliance - association of many international companies (among them Cisco, Atmel, TI and many other). However there are many other standards around - both open and proprietary. I recently became interested in 6LoWPAN - it's a collection of standards maintained by IETF - an international non-profit organization, that also maintains IP, and other Internet-related standards. 6LoWPAN makes it possible to use IP (only v6) on low-power radio links used in WSN.

After doing some research I determined that probably the easiest way to start doing some 6LoWPAN research is to use Contiki OS - operating system for embedded devices from SICS. Contiki already supports many 6LoWPAN concepts and many other are being actively developed. Contiki is available for many different platforms, but I think that MSP430-based devices are best supported. Contiki is equipped with java-based network simulator Cooja - so it's possible to start doing research without actually having any motes. I am getting ready to test that approach - I already installed Ubuntu Linux, and I hope to start some tests soon.

Regardless of the simulator I plan to do some test with real motes. For my development platform I chose Atmel/Meshnetics Zigbit ATZB-24-A2 modules. They are quite cheap, available in Poland and contain a microcontroller, a transceiver and an on-chip antenna. I found a very good French site which contains many useful comments about these modules. My first step was to design a breakout board for the Zigbit modules. Zigbits are quite difficult to solder without hot-air station. I don't have such a station, so I plan to solder the modules once and for good to these breakout boards, and connect the boards to other devices with simple pin headers. My breakout boards will also contain JTAG and power-supply connectors - so I should be able to do some simple programming and debugging only with breakout boards. Here is the picture of the finished board next to a Zigbit module:



I made some rookie mistakes with the design - I got the description printed over the pads, but in general it looks just like I wanted :) . Now I'll have to come up with an idea how to solder it right. Any suggestions?

Thursday, March 4, 2010

Project #1 - PCB Design

With electronic schematic ready I created a PCB from it. The process was rather straightforward - Eagle created the PCB project automatically ("Board" button). Then I had to set my PCB size, and place all the elements on the board. I also had to use "Mirror" command on every SMD component to transfer them to the bottom side of the board - so that all the connections are on one side of the board (blue color is default for connections on the bottom).

I decided not to use autorouter, so routing was a rather lengthy process - like a huge jigsaw. At first I wanted to conform to placement and routing rules in Atmel AVR042 Note (place decoupling capacitor as close to μC as possible, etc.) and in DS1307 RTC datasheet (do not route any wires under DS1307 RTC circuit). But eventually I gave up on these precautions - I wasn't sure if they really matter with home-made PCBs. Also I lacked some Eagle skills to implement them properly (for example how to create ground planes). I'll try to learn these things next time.

One more thing to check when developing non-professional PCB is route spacing, and element pad size. Narrow routes placed near to each other may cause problems with etching. Small element pads are more prone to damage from drilling. I know no easy way to change size of pads in Eagle - probably the only way is to modify the symbol of the element.

The result is below - as you can see I already took into consideration dimensions of casing that I am going to use - that's why there is a hole in the middle.


Board file.

Monday, February 1, 2010

Project #1 - circuit diagram

I finished doing the circuit diagram for my thermostat. Screenshot below:


Full schematic here (for Eagle 5.6).

I eventually chose Atmega16 for my CPU. It has enough memory and processing power for my needs (at least I hope so). Power is supplied from +5V 1.2A switching-mode power supply connected to SV3. Such power supply is noisy so to stabilize input voltage I use C1 and C12 capacitors (one tantalum 10uF and one simple ceramic 100nF). Q2 crystal together with C10 and C11 caps are used to generate clock signal and SV1 is used to program Atmega in ISP mode.

On the diagram there are two ICs, which perform the functions needed by a thermostat. IC1 is DS1307, a Real-Time Clock chip. It will be used to keep track of the time flow. The other IC is DS1721, a Digital Thermometer. It will be used to monitor the temperature in the room. Both chips communicate with Atmega16 by TWI (Two-Wire Interface).

Jumpers JP3 to JP6 are necessary to connect buttons. I will put buttons on the separate board, to make it easier to attach them to the casing. JP2 is used to connect standard 2x16 LCD with Hitachi HD44780 controller. Buttons and LCD Display together form user interface of the thermostat.

I added MAX3232 to the schematic. I don't plan to use it now, but it's very easy to implement some basic communication in RS232 standard, so it might come in handy in the future. I also added SV2 jumper for 1-wire, so I'll be able to plug in additional digital thermometer later (DS1820).

Finally there is K1 - electromechanical relay. It is the only output of my thermostat, and it will be used to control the boiler. T1 transistor is protected against voltage spikes by D2 diode.

Monday, January 18, 2010

Project #1 - input voltage

It seems that sometimes your experience in some subject is your worst enemy. I started drawing my schematic, and because ARM microcontrollers need +3.3V input voltage I automatically assumed that AVR need it too. So I put inside LM1117 voltage regulator and other unnecessary components. Today my colleague told me, that AVR works fine with +5V. I scrapped 50% of the schematic and started again.

Immediately I discovered that +5V circuits are cheaper than +3.3V (for example when you compare MAX232 and MAX3232). Later I found also that AVR may work faster on +5V - 16MHz. On +3.3V it may work with 8MHz only. Not that I need 16MHz anyway for my PRT (Programmable Room Thermostat).

Sunday, January 17, 2010

Project #1 - electronic CAD

To make a simple PCB by etching, I don't need any software, or special equipment - just some good chemical solvent (for cleaning the copper) and permanent marker (for drawing connections). But it's extremely hard to make anything more complicated that way - it's a medieval-book-writing-monk type of work.

Using specialist CAD software helps a great deal. What does PCB CAD essentially do? It connects the logical design of the circuit with physical design of the PCB. First I make an electronic schematic of my circuit - using logical symbols like resistors, capacitors, ICs and connectors. Every time I need to use a part I open part database, choose a suitable element, and place its symbol onto the schematic. Then I connect the parts using wires (lines). When I'm done, I click "PCB Design", and the program opens another window, where once again I place symbols of my components. But this time I place physical parts - with proper dimensions, pinouts and packages - the program automatically assigns physical symbol to every logical symbol. After that I route wires between the symbols and it's done. Optionally I may generate CAM files used to manufacture my PCB on CNC machine.

There are many free PCB CAD programs on the web. These are often connected to some big part suppliers. This is probably the most complete list available. For my project I chose a program called Eagle by German company CADSoft. It's free for hobbyists, and has some limitations, but they are not important in small projects. Eagle was fully independent software some time ago, but it has been purchased by Farnell - big part supplier. I expect some new version of Eagle with integrated Farnell part base to appear. However Farnell is quite expensive when buying small quantities of parts (ex. single ICs), so a hobbyist like myself won't be using this kind of integration much. It's quite sad, because integrated part base would make my life much easier. Maybe in a country like US people may put any part they want into their projects, but here in PL I have to carefully check availability of every part. Otherwise I'll either wait 2 months to get it, or pay 2 times the price, sometimes both.

About Eagle - it has some pros and cons - I'll describe them briefly:
(+)
  • Has decent database (I usually find what I'm looking for) and user-made libraries
  • Easy to use (it has a command line for hard-core users)
  • Many resources on the web
(-)
  • Pathethic database searching (it's 2010 now, everybody has autocompletion and search-as-you-type in their programs, and here I have to type name in little window and press Enter)
  • Shortcut - not Windows compatible
  • Tediousness - for example as a hobbyist I want electrical pads in my projects a bit larger than default - I don't know how to achieve it without modifying every single symbol

With this post I finished the introduction to my project. The information contained here is obvious for most people, but I felt that it's necessary to describe it, as it's part of the project too. With the next post I hope to move on to some technical details.

Sunday, January 10, 2010

Project #1 - choosing microcontroller

In every project there are some decisions to make at the beginning which influence all further steps. In small embedded project probably the most important choice is about the microcontroller. At first I wanted to use ARM microcontroller, more specifically Atmel SAM7X. I have experience in programming these μCs in C, they are reliable, powerful, not very expensive, and you don't need any external programmer to program them (thanks to SAM-BA). I have a minimodule based on SAM7X256 I bought to play with it, but never made anything useful of it, so I thought I'd put it into the thermostat. But on Friday evening I checked everything up once again, and I totally changed my mind. Atmel SAM7X256 is at least 20 times too powerful for a simple project like mine - it would be stupid to waste it to click a relay two times a day.

My natural second choice was Atmel AVR. These μCs are extremely popular in PL among hobbyists. Professionals also widely use them - in commercial applications engineers usually have to cut their costs and use reliable solutions. There are tons of code and resources for AVR on the web, and also official application notes on Atmel's webpage. I did one little project with AVR Atmega8 about six years ago - it was a basic mobile robot. I used very cheap LPT programmer, and coded robot behaviour in BASCOM - simple BASIC-like language for beginners. Nowadays LPT port is quite uncommon. Luckily I have an ISP programmer, which I bought to play with some other stuff, but never made anything useful of it (there seems to be some pattern here). I'm also not going to use BASCOM anymore - I feel that C has the right power to ease of use ratio for me.

After choosing μC I decided that I'll be making my circuit board from scratch by etching. I always did my circuits on protoboards using greenwire (kynar) to make point-to-point connections. It's great for prototyping, but it's slower and less reliable. Using a protoboard is also bad psychologically - I want to finish my thermostat fast, not prototype it forever.

The next step is to choose some CAD software for PCB design, and get to some real work.

Tuesday, January 5, 2010

Project #1 - controlling the boiler

At the beginning of the project I need to make some important decisions how to build the thermostat, and what components to use. The first problem is how to control the boiler. I checked the manual of my boiler, and I found a schematic (version in Spanish, but quite obvious):


On the schematic there is a jumper P1 which connects terminals 6 and 9. The boiler was supplied with the jumper in place. Removing the jumper turns off the heating circuit of the combi-boiler, even if heating is enabled on control panel (and domestic water works normally). That's very good news, because the only thing I need to do is to replace the P1 jumper with a relay, and I don't have to care about electrical compatibility of my thermostat and the boiler. Well I just have to choose a relay big enough for the voltage and current present in the circuit.

I measured the voltage between terminals 6 and 9, and my ancient multimeter shows 28V. Quite strange value, but it doesn't matter - 125V or 250V relay will work perfectly.

Saturday, January 2, 2010

Project #1 - programmable thermostat

My first project is a programmable thermostat for a boiler mounted in my apartment. In a town where I live there is a small CHP power station (combined heat and power). It was built long ago to support the industry with hot water for technical processes, and actually generates very little electricity (6MW in winter, during other seasons even less). The station supplies almost all apartment and commercial buildings in the area with hot water for heating and washing purposes. My building is probably the only exception. Such solution is both blessing and curse, as it gives me better control over heating, but is not forgiving of any mistakes ($$$).

The boiler is 24kW Nike Mini from Italian company Immergas, not the latest model, but still quite new. It is a combi-boiler - it produces hot water for both heating and domestic uses. The boiler can be set to provide domestic water only, or both heating and domestic water. Domestic water flows through heat exchanger and then directly to taps. Water for heating flows in a closed circuit and it's moved by electrical pump. The temperature of the heating water is measured by a sensor, and when it's too low, the boiler ignites itself and works for some time (it's either fixed time or until the temperature raises to acceptable value - I don't know).

The problem is that the boiler doesn't measure the temperature inside the apartment, so it doesn't switch off even if the temperature reaches preferred value. It also has no means of time-related programming, so it runs all the time, even when nobody's home. That's why the programmable thermostat is necessary. This device switches the boiler on only when the current temperature in the apartment (precisely in one of the rooms) is lower than value set in thermostat's memory.

Of course Immergas sells all kinds of thermostats for its boilers. Small electronic companies and workshops also sell thermostats which can easily be adapted to control my boiler. But by making it I hope to learn some new skills and test some solutions which might be useful later.