donderdag 4 oktober 2012

A journey to Arduino for a Java programmer

Yesterday was the Devnology Arduino workshop at the TU Delft (Civiele Techniek en Geowetenschappen) where Rolf Hut (@RolfHut) taught us all the basics of using the Arduino. For the last few nerds among us that don't know Arduino, read all about it here. To sum it up, it's a really low entrance platform to building your own sensor-equipped embedded system. And even more important, using it is fun and easy, even kids are able to use it according to Rolf.

Arduino unit (image source Wikipedia)

I teamed up with Arne (@arnetim) to take up the challenge of proving that we are at least as skilled as a bunch of school kids. We are trained software engineers, we can do this :-)
Yet, only seconds after opening the box with the components, we realized that the Electrical Engineering skills we learned at school were very deeply hidden inside our brains. This was gonna be a lot harder then we expected....

The first assignments consisted of checking the hardware and running some example programs for our first construction; the fading LED. And step by step the electrical knowledge came back into our minds.
Some example code in the editor:
Arduino IDE (image source Wikipedia)

 Compiling, installing and running your code on the Arduino unit is just a matter of one click (or short-key).

The second assignment meant creating a Knight Rider kind-of LED bar, meaning the LEDs had to light up one after the other. At first we made it to automatically lit them up with a timed loop , later we decided to use a potentiometer to select/enable the LED's by turning the knob (where voltage was modulated to a LED).
 We  took Rolf's advice and decided to focus on the hardware and not the software since we're 'software guys' and we already code more then enough on a normal day.

this is not our construction but a similar one from youtube

After these first assignments we really started to enjoy working with it and wanted to test all sensors. Realizing construction after construction. For instance we invented a 'musical instrument' that allowed you to control the sound/tone by the amount of light provided to the light sensor. This was also referred to as a 'refrigerator simulation' or a 'parking-assistance', for daylight parking only :) 



And our masterpiece; the birthday cake simulation. This entailed a couple of LEDs that were lit, representing the candles, but by blowing into the speaker (which was connected to function as a crappy mic) you could blow out the candles one-by-one.



To sum the experience up; Arduino is a really cool platform and it really has a low learning curve. We 'Java programmers' (although we both had done C in the past) were able to realize all kinds of  constructions within only two and a half hours. Also the hardware and software did seem pretty mature/stable. With every construction we'd hold our breath whether it would blow up the Arduino or work as expected. But since it did never explode we either made no mistakes (which is highly unlikely) or it just is a really robust devkit.


maandag 10 september 2012

Game of Clojure Life

Last weekend was the 2012 edition of the Devnology weekend. One of my goals for this weekend was to write my first non-trivial Lisp/Clojure app. I had been willing to give that a try for a long time, but the interest renewed after the Clojure session of last Wednesday.

Since I didn't spot anyone else interested in giving it a try, I decided to spend some time to do it on my own, but with some guided Lisp advice of Michel and the moral support of many other Devnologists. And moral 'support you need'; trying to build something in Clojure. Not only because the task at hand was a bit overambitious, but also because the tooling is far from mature (or deterministic, which is an aspect I find very important :) )

The target for me was to create a visual Game of Life implementation so it was actually a combination of multiple earlier devnology events.

The approach used was :

  • Think of a new function and documented it + rationale
  • Define the function in my clojure file,
  • Update the REPL,
  • Test it, and the test usually ended up as the body of the new method
  • ( I did not write unit-tests, but the REPL is really good for testing, after a REPL-session I should have saved them as tests for regression though)

    I think you could say it was somewhat inspired by literate programming (writing the logic down with their rationale) and TDD (all code in the clojure file started as test)

    As a result of this procedure; the following code is more or less the transcript of my coding session. Also almost all of the code is written in this chronological order. Top of the file being the oldest of course. Only the failed JavaFX part has been removed.

    (ns myLeinProject.gol)
    
    ; The first decision I made was to represent the field as a single list, although i wanted my algorithms
    ; to mimic a matrix, I didn't like having that complexity in my first application and mimicking a matrix on
    ; a single list is not that hard. Also i decided this would be easier than a sparse list of only live cells.
    ;
    ; later on i realized it might have been easier (or at least less code) to just write the neighbors
    ; algorithm in terms of a single list. Since the current approach has bidirectional mapping from coord to
    ; list-position and back
    ;
    ; we use > 1 values for living cells, 0 for dead ones. The number represents the number of alive iterations...
    ; (could resist the gold plating for keeping the 'age' )
    
    
    (def fieldTest
      " field with certain test patterns (formatted as a matrix but really just a list, therefor we need
        to define the height, width.
          contains: block, beehive, blinker, toad see http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life "
      (list
        0 0 0 0 0 0 0 0 1 0
        0 0 0 0 0 0 1 0 0 1
        0 0 1 1 0 0 1 0 0 1
        0 0 1 1 0 0 0 1 0 0
        0 0 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0 0
        0 0 1 0 0 0 1 1 0 0
        0 0 1 0 0 1 0 0 1 0
        0 0 1 0 0 0 1 1 0 0
        0 0 0 0 0 0 0 0 0 0
        ))
    
    ; needs to be in line with the field dimensions, alternatively i could have just limited to square fields and us the root of the list-length instead of manually saving dimensions in globals
    (def getFieldWidth 10)
    (def getFieldHeigth 10)
    
    (defn printField [field]
      " helper method to print the list as matrix to the console"
      (doseq [line (partition getFieldWidth field)]
        (println line)
      )
      (println "")
    )
    
    (defn getPos [x,y]
      "calculates the list-position for the coordinate"
      (+ x (* y getFieldWidth ))
    )
    
    (defn getVal [ x, y, field]
     " we assume that all cells next to the grid are dead-cells, alternatively we could wrap around... "
      ( cond
        (< x 0) 0 ; left of the field
        (>= x getFieldWidth) 0 ; right of the field
        (< y 0) 0 ; above the field
        (>= y getFieldHeigth) 0 ; below the field
        :else (nth field (getPos x y))
      )
    )
    
    
    (defn getStatusVal[ x, y, field]
      " since we store the age in the list we use this method to just get a 1 for all living cells
        making it just a bit easier to calc neighbors (just sum the numbers)"
      ( if (> (getVal x y field) 0)
            1
            0
        )
    )
    
    
    (defn getNeighbourCells [x y field]
      " returns the surround cell-status for x,y. but excluding x,y itself"
      (list
            (getStatusVal (- x 1) (- y 1) field)
            (getStatusVal x (- y 1) field)
            (getStatusVal (+ x 1) (- y 1) field)
    
            (getStatusVal (- x 1) y field)
            ; (getMinimalVal x y field) self
            (getStatusVal (+ x 1) y field)
    
            (getStatusVal (- x 1) (+ y 1) field)
            (getStatusVal x (+ y 1) field)
            (getStatusVal (+ x 1) (+ y 1) field)
       )
    )
    
    (defn countNeighbours [ x, y, field]
      "counting the neighbours is just summing up the values (0,1) of them"
      (reduce + (getNeighbourCells x y field) )
    )
    
    ;Any live cell with fewer than two live neighbours dies, as if caused by under-population.
    ;Any live cell with two or three live neighbours lives on to the next generation.
    ;Any live cell with more than three live neighbours dies, as if by overcrowding.
    (defn shouldLive [ x, y, field]
       (and
             (> (getVal x y field) 0) ; is Alive ?
             (> (countNeighbours x, y, field) 1) ; under population
             (< (countNeighbours x, y, field) 4) ; over population
          )
    
    )
    
    ;Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
    (defn shouldComeAlive [ x, y, field]
      (= (countNeighbours x, y, field) 3)
    )
    
    (defn nextStatus [x, y, field]
        (cond
          ( shouldLive x, y, field ) (+ (getVal x y field) 1) ; raise its age
          ( shouldComeAlive x, y, field ) 1 ; resurrect
          :else 0 ; remain dead or die
         )
    )
    
    ;since I wanted to map over the list I needed something to translate the list position back to x,y
    (defn getX[x]
      ( mod x getFieldWidth )
    )
    
    (defn getY[x]
      ( quot x getFieldWidth )
    )
    
    (defn progress [field]
      "create a range with all list indexes of the field and then map them (with the old field) to new field values into a new field list"
      ( map #(nextStatus (getX %) (getY %) field) (range 0 (* getFieldWidth getFieldHeigth)) )
    )
    
    ; since using JavaFX2 didn;t work out, i decided to write a html file with a table to visualize the field
    ; letting the browser rendering my field-status
    ; html is really awful but works on my machine (which is enough for the proof of concept)
    
    ; shamelessly copied from a website how to write a file
    (import '(java.io BufferedWriter FileWriter))
    (defn write-lines [file-name lines]
      (with-open [wtr (BufferedWriter. (FileWriter. file-name))]
        (doseq [line lines] (.write wtr line))))
    
    
    
    (defn html [x field]
      "turn the cell into a html tag"
      (let [cellVal (getVal (getX x) (getY x) field)]
      (cond
        (> cellVal 5) ""; really old cells become blue
        (> cellVal 0) ""; living cells are green
        :else "" ;dead cells are grey
      )
      )
    )
    
    (defn htmlLine [x field]
      "adds a html row tag when needed"
      (if (= (getX x) 0) ; start of line
         (str "" ( html x field))
         ( html x field)
      )
    )
    
    (defn tohtml [field]
      "maps the field to html"
      (map #(htmlLine % field) (range 0 (* getFieldWidth getFieldHeigth)))
    )
    
    (defn transformAndWriteToHtmlFile [field]
      (write-lines "d:/gol.html" (concat (list "") (tohtml field) (list "
    "))) ) (defn play [round max field] "the master method, call with (play 0 fieldTest " (printField field) ; console output (transformAndWriteToHtmlFile field) ; file output (. Thread (sleep 5000)) ; wait (when (< round max) ; progress when needed (play (+ 1 round) max (progress field)) ) )

    Lessons learned:

    Mind bending language?

    Although Lisp is known for its (){}[] just adding them 'to be safe' is not a good choice :-) An extra pair of () just means something different, so they should be carefully placed. It's not like in Java math/logic expressions where you just can do either 3 * 4 * 2 or ((3 *4) *2) or (3 * ((4) *2)).
    It took me about an hour to adjust to automatically / subconsciously write expressions the clojure style (* 3 2) instead of (3 * 2), so although most people find the syntax & semantics weird (i.e. not C style like) it actually doesn't take that much time to get used to. But that does not make you a Clojure programmer just yet, or so I have learned :)

    Tools are not good enough for noobs like me

    Eclipse Juno and CounterClockwise are not really mature. I had lots of encounters with problems that could be solved by either re-reloading the source file to REPL. Or by just completely restarting Eclipse. This seriously complicates development in a unfamiliar language, you want deterministic behaviour to be sure you're doing it wrong, or right; but at least be able to draw a conclusion from the actions and results. Now, after carefully reading error messages, you just have to decide 'could this error really be from this code' and then if not, restart the environment, which in almost all situations, magically fixed it.
    And I'm not going to talk bad about the error messages themselves, but to put it mildly, they could use some improvement (especially since the type errors are only caught at runtime in a language like this).
    Also I missed tool support for extracting functions/constants.Instead, I used comments for somethings that I'd rather have replaced with a named-const or function.
    Another thing that surprised me is that function ordering seemed to matter, you may not call a function that is declared below the calling location. I'm not sure what the exact rules are but this did strike me as odd. I rather have the (manually) extracted one-line methods below the place they got extracted from (example: getX)

    Java integration can be hard

    Clojure and JavaFX don't really mix. I lost quite some time trying to integrate JavaFX 2.2 into my clojure app for visualizing the game. As a sort of knowledgeable JavaFX user, this should have been a piece of cake. Though it was not, the class structure and the use of static initializer magic of the framework was not conquerable with my limited clojure experience. Also it seems there isn't much help online either (and I didn't bring my 'JavaFX 2 in Action' book to look the details up). I know there are special clojure bindings but I was unable to find them and writing my own interop in Java didn't work out to well either. Hence I ended up with the formerly discussed HTML visualization.



    All things considered, I'm pretty happy with the results and doing this exercise did give me a much better view of what the language is really about.