20170708

Plugging TLS into your Go Backend - for free!

I don't think I need sell anyone on the concept that securing client-server traffic is a good idea. These days we can even do it for free through Let's Encrypt.

In my example of how to implement it, I'll assume running an Ubuntu server. First order of business is getting Let's Encrypts' Certificate Generator up and running on your system, cutely named Certbot. This will create your TLS certificate, and later update it.

The one downside of using Let's Encrypt is that the certificates only last 3 months before needing to be re-issued. If you're clever, you'll have your backend do it automatically by either generating new ones on each deploy (assuming reasonably high frequency of updates) and/or during daily Cron jobs, check the timestamp of the certificate files, and renew if getting close to the expiration date.

Another gotcha is that Let's Encrypt won't issue certificates to typical AWS domain names like <ec2-12-123-12-123.eu-central-1.compute.amazonaws.com> as these servers can easily be used for various nefarious purposes. So you're going to need a proper address to plug into your certificate. Any DNS service will let you point to your AWS EC2 instance, so it's no biggie. If you already got one, say for a website, just set up a subdomain there that points to your AWS IP.

I'll not go into those topics in any detail here though. So moving on, the very first thing on the agenda, is installing Certbot and generating the certificates.

Once you've SSH'ed into your server, this will get you the bot:

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install certbot


Next, since we're not running some external webserver or anything like that, but let the goodness of Go do it for us, we'll need a 'standalone webserver' certificate that we can use.

$ sudo certbot certonly --standalone -d katzrule.com -d www.katzrule.com

This will create the two files you need import into your Go app. You'll find them under '/etc/letsencrypt/live/katzrule.com/' and they should be named 'fullchain.pem' and 'privkey.pem'.

How you import them into Go is a matter of preference. I'm a bit lazy, so I didn't want to comment in and out the loading of the certs for when developing (just testing using localhost) and when deploying (running live on AWS). So I set up a little type to hold the location of the certs, made a function to test for if I am on live server or not, import the certificate location into the previous made type if on the server, and then finally in the API function, serve up over https or http depending on if certificates are found or not.

So the implementation itself.

In package structs:

type TLS_t struct {
    Fullchain string
    PrivKey   string
}


In package fileIO:

func GetTLSExists() (structs.TLS_t, bool) {

    var fullchain = "/etc/letsencrypt/live/katzrule.com/fullchain.pem"
    var privKey = "/etc/letsencrypt/live/katzrule.com/privkey.pem"

    var TLS structs.TLS_t
    var exists bool

    if _, err := os.Stat("./conf/app.ini"); err != nil {
        exists = false
    } else {
        exists = true
        TLS.Fullchain = fullchain
        TLS.PrivKey = privKey
    }
    return TLS, exists
}


The file I check for - './conf/app.ini' only exist on my server. You can check for any file you wish that you know only exist on the server - or have an initialization file you load on startup, with one field (assuming JSON or XML encoding) saying if on live or dev. Anyway, this little hack works for me.

Finally in my API package:

func Initialize() {

    router := mux.NewRouter()

    ip, err := fileIO.GetPrivateIP()
    if err != nil {
        fmt.Println("Error loading IP config - exiting")
        postgres.Close()
        os.Exit(0)
    }

    server := &http.Server{
        Handler:      router,
        Addr:         ip,
        WriteTimeout: 10 * time.Second,
        ReadTimeout:  10 * time.Second,
    }

    router.HandleFunc("/noDogParkPetition", noDogPark)

    TLS, live := fileIO.GetTSLExists()
    if live {
        fmt.Println("TLS Certs loaded - running over https")
        log.Fatal(server.ListenAndServeTLS(TLS.Fullchain, TLS.PrivKey))
    } else {
        fmt.Println("No TLS Certs - running over http")
        log.Fatal(server.ListenAndServe())
    }
}


And that is about it. Those with keen eyes may notice my call to fileIO.GetPrivateIP() - this is merely a call to load the IP address. For the same reason as mentioned earlier. By loading the IP from file rather than hardcode it, I can move the app freely between dev and live by just uploading the updated binary. On dev, the file just tells the app to serve on localhost, on live it loads up my AWS outward pointing IP and port.

Makes deployment super easy. SSH in, close down the app (and do the usual linux/Ubuntu update/upgrade since this is a very good time to do so), use Filezilla to FTP over SSH the new binary, then start it up all good to Go - if you pardon the pun.

Happy - and secure - coding! :)

20170621

Bounce buttons in Array

This post is derivative of the one I did in this reddit thread. There though the focus was more on how the OP could restructure his code to not only make it work, but also get rid of multiple repetitions of basically the same code.

Anyhow, making the little example to get him on the right track, I stumbled upon another little challenge. Anyone who's been doing any Arduino projects for a while most likely have gotten to use the <Bounce2.h> library.

For those who have not, the short of it is that it relieves you of the task of debouncing buttons manually in code - or for that matter in electronics by routing the input through a schmitt-trigger chip.

Just attach buttons in software to the Bounce object, and you're good to go. Which is fine when you got one to three buttons all assigned their own unique ID. Any more, and it soon looks both tedious and newbish to declare a ton of buttons like so:

Bounce buttonA = Bounce();
Bounce buttonB = Bounce();
Bounce buttonC = Bounce();


Which also bring on the issue of each little 'is a button pressed?' routine need be in triplicate - one for each unique button. Surely stuffing all that stuff into an array is much better?!

Which I set out to do in my little example of 'clean & structured' code. A little research and trial and error later, this is what I came up with:

#include <Bounce2.h>

const byte ledPin[2] = {10, 11};
const byte butPin[2] = {2, 3};

Bounce button[2] = {
  Bounce(butPin[0], 2),
  Bounce(butPin[1], 2)
};

bool ledState[2] = {false, false};

void setup(){
  for(byte i = 0; i < 2; i++){
    pinMode(ledPin[i], OUTPUT);
    pinMode(butPin[i], INPUT_PULLUP);
    button[i].attach(butPin[i]);
  }
}

void loop(){
  for(byte i = 0; i < 2; i++){
    if(getButton(i)){
      flipLED(i);
    }
  }
}

bool getButton(byte b){ 
  if(button[b].update() && button[b].read() == LOW){   
    return true;
  } else {
    return false;
  }
}

void flipLED(byte b){
  ledState[b] = !ledState[b];
  digitalWrite(ledPin[b], ledState[b]);
}


The only surprise, and what had me scratching my head a bit, is that each declaration of a Bounce object, need have the max number of objects at the end - after the pin assignment of it.

Another little thing to note that beginners may not realize, is that 0 = false = LOW, and conversely 1 = true = HIGH. So rather than turn the LED on and off through your typical if(this){do that} routine one can save oneself a bit of work and CPU cycles by making the led state variable a bool - essentially a bit - that you can flip easily with the not '!' operator.

Doing proper bitwise operations would be more efficient - but this example was to help a beginner. No need to confuse more than strictly speaking necessary :)

20170521

rPi 3 vs Parallella benchmark

Been knee deep in C# lately, so updates have been rather sparse. Well, non existent really. Anyhow - got the desire to have a little fun with my Pi3 and another favourite of mine, Go.

Basic premise; see how faster a bit of Go routines would make a simple program. Copy - Paste from the reddit thread I made for this project:

---

First, I do not have a Parallella - so I'm using the numbers from this talk:

Parallella Demonstration

The gist of it is, it got 2 ARM cores and 16 custom RISC cores - and testing it they run a program written in C to test performance running in serial (on one ARM CPU core) and then in parallel (on all 16 risc cores). Both times finding the prime numbers between 0 and 16 million.
Results are:
  • Serial: ~4min
  • Parallel: ~18sec
So decided to do the same on the Pi, though using Go rather than C as it is easier to spin up multiple threads in that language. Go is not quite as efficient as C, so some performance is 'lost in translatation' as it were. But the difference should be minimal.

Also a shoutout to /u/siritinga who helped me getting it working as intended and as efficiently as possible.

Full source (and a native ARM rPi binary if not wanting to compile yourself) on github

Final on Raspberry Pi 3 result was:
  • Serial: ~2min19sec
  • Parallel: ~58sec
Not bad! The Pi 3 is much faster in single thread - but not surprisingly slower in parallel. Taking about 3 times as long with 1/4 (4 vs 16) of the cores compared to the Parallella :)

edit: Upping the number of Go Routines to 16 reduced the result down to 53 seconds - shaving 5 seconds or nearly 10% off from when only running 4 Go Routines.

Will look into actual optimizations rather than just throwing more threads at the problem...

20170306

Mastermind Game #4: Input flow done

ARDUINO: Contrary to originally planned, the random assignment of the solution and the routines to check the players guess towards it have been pushed to the next update. Before that get put in, it made sense to finish up the general flow of input and storing the history of guesses in a game.

And it was quite the little brain-teaser. I totally overthought the problem. Juggling an array-slice around for the editing part, and then push that to the history array. Which caused problems when browsing the history and deciding to go back to edit.

A little rethink later, and keeping with the adage that simpler is better, I decided to do the edits directly on the last entry of the main history array. A little fiddling about later, it was all working as intended. Mind you, all in all a good few hours went the way of the dodo before I got that far.

Github repo for this stage.

At this point I may as well go a bit into depth on how it is all controlled. Inside the state_t struct, you'll find there is a variable named mode which is defined earlier as an enum. This to make the later main gameLoop switch more intuitive. I could have just used a number from 0 to 2 to jump between modes, but having named values makes it so much more readable.

Out of the state_t struct I make an instance of which inside the loop() namespace called state for passing along to where it is needed. This to avoid using globals. Globals are by and large evil. Passing data by value or reference is much safer. That way, one can control which functions can only make local changes - and which can manipulate the data so it also effects other functions.

Further on - each mode got their own little function, that will run as long as the variable switchMode in the state instance remains false. Once the user do the action to proceed to another mode, this is set to true, and the game jumps to whatever mode is then set in the mode variable in the state instance.

What mode to go to will vary a bit depending on both what mode one is in, if it is the first turn or if it is the last turn. In edit mode, one can only go to browse mode - unless in first turn. In which case it makes no sense to browse the history, so one is taken directly to the commit mode. This is handled by this ternary expression:

s.mode = (s.tries > 0) ? browse : commit;

Which do the same as the more verbose:

if(s.tries > 0){
  s.mode = browse;
} else {
  s.mode = commit;
}


Likewise, in the commit mode if one is at turn one and try to go back to browse, it is denied since there is no history to browse. Come to think of it, I should add an else there (or do another ternary) to throw the player back to edit of the first turn. Though shouldn't matter. The first turn will be a wild-ass guess at any rate, as there are no clues to go by.

When in browse mode, one can go back and forth in the history. If pressing the select button whilst not at the most recent entry, one is taken back to edit-mode and can make a change to ones current guess. If pressing the select button whilst at ones most recent guess, one is taken to the commit mode.

In commit mode, one can confirm the turn by pressing select - or go back to browsing by pressing the go right button. It may be a bit superfluous, but I like the added confirmation or go back option this mode provides.

And that is as far as I've gotten. Still not at the stage of being playable - even through Serial-monitor. But now all of the basic structure and setup is complete. So next time, the random colours selection will be put in, and the routines to compare the guess to the solution and store the result in the history instance of the ledOut_t struct.

Maybe even start to breadboard up a few LEDs and hook up the Shift-Register - but I'm not promising anything :)

20170226

Mastermind Game #3: Getting started with the code

ARDUINO: Allright, now that all is well planned out, it's time to flesh it out a bit by means of actual wiring up stuff, and write the code to run it. It'll all be done in steps adding one feature after the other in separate writeups so as to not get ahead of myself.

Today, the basic structure of the code and getting the buttons to work as intended. First off I believe the source code of this project to get rather big - in Arduino terms - so I've split it up into three files so as to be easier to navigate.

- mastermind.ino
The main file. Contains all the various definitions, setup and loop. Note here that I've structured it in such a way that loop() will never actually do just that. Inside it I got some initializations, and then an endless loop using a while(true){} loop to take care of business resetting values on new game and then get the game going. The game-loop itself is separated out into a separate function

- chores.ino
Contains various helper-functions to make it all work as intended. This is where most the logic work is done. Keeping up with and setting state, feed data to and from structs and arrays. You know, all the fun stuff.

- inOut.ino
The nuts and bolts level of the operation. Reading buttons, control the shift-register to change LED output and such. If there is something to be done with the actual hardware, this is where it'll be at.

Github repo for this stage.

Mind you, when using several files like this - it do not work quite as in other more 'professional' development environments. The extra files are not packages unto themselves that are fully enclosed bar the functionality and structures you make public for export. No, in the Arduino IDE it just means that at compile time, the IDE will collate all the files in the project, and treat them combined as one big file rather than several smaller.

So whilst you do not have to worry about transporting data around or import supporting files - you pay for it in lack of encapsulation and separate name-spaces.

In its' current state, it'll read the buttons, and allow navigation to change colours of the players guess and proceed to the next stage.

Breadboard wiring for this stage:



Using button left and right you traverse the LEDs. Hitting button select, you change color 0..5 by hitting button left and right. When happy with the choice, hitting button select will take you back to traversing the LEDs again. When traversing, one can also get to the 'next stage' option by being off the right 'edge' of LEDs.

Mind you, no LEDs are actually hooked up yet, so everything is 'emulated' by dumping the values of internal state to the Serial-monitor.

The next update will flesh out some more functionality. Probably the random assignment of colours to the game solution - and the routine to check the players guess up towards the generated solution, and display the result.

20170225

Mastermind Game #2: Failing to plan is planning to fail!

ARDUINO: Been having a bit of a rethink of the Mastermind game project. The rather prolonged inactivity on it have been unfortunate. Been busy in other areas, though I have mulled over this project to refine it before I get started proper.

First and foremost, I've ditched the idea of using a rotary encoder. I'll use three buttons instead. One for select, and then two for browsing. Not so much for coding considerations, but UX and saving some precious space in what I think will be a very cramped enclosure.

Secondly, my previous though of using three shift-registers to drive the LEDs was somewhat wasteful. I can get by with one as it happens. And four NPN transistors plus eight resistors.



As for the general layout of the project, I've landed on a 4x3 LED grid plus a single LED. Since two rows are made of RGB LEDs, electrically it is an 7x4 grid - and the lone LED making sure I use all 8 outputs from the shift-register. Finally the three button go on the bottom. Inside, it'll be a two-layer proto-board design. Lower layer for the ICs and glue hardware, upper layer for the LEDs. The buttons will be attached directly to the lid.

Basic 'display' as it were will be from top to bottom:

- A 4x row of Blue LEDs to count the tries. Binary FTW!
- A 4x row of RGB LEDs to signal result. Blue for a correct colour, Green for a correct color and placement, Red for neither.
- A 4x row of RGB LEDs for user selection of colour.
- A single Green LED to signal browse row or commit row mode.

How the UI will work:

- On the left there will be one button (1) to select and commit.
- On the right there will be two buttons (2 and 3) to browse.

Basic procedure:

00 - Power switch is turned on.
---
01 - Game starts, a little lights-show and then all LEDs turn off.
02 - User in edit mode, browse colours on a column - when happy commit colour with button 1. Current column will blink.
03 - User in edit mode, browse left-righ to select another column with button 1.
04 - Repeat from 2 until four colours are committed at which point user may:
05 - Browse off left or right column to get to mode select.
06 - If green LED is blinking, browse previous history by hitting button 2 (back) and 3 (forward) if available.
07 - If green LED is blinking and at current go to commit mode by hitting button 3.
08 - If green LED is blinking and at current go to edit mode by hitting button 1.
09 - If green LED is solid, commit turn by hitting button 3.
10 - If green LED is solid, go back to browse history mode by hitting button 1.
11 - Result is computed and displayed, if not solved, back to 2
12 - Result is computed and correct. A little lights-show, reset to 1 on hitting button 1
---
13 - Power switch is turned off.

To start off, it'll all have to be breadboarded up of course. And even-though the final product will run off a bare Atmega328, during the prototyping, programming and testing - I'll use an UNO. It's such a nice device for that purpose. Though it'll be quite the rats-nest of wires :)

Since I got no serious plans for the weekend, some actual hands on progress and write up of it all may even surface soon(tm)

20170220

Raspberry Pi 3 CPU Fan Control

PI / GOLANG: Finally got my Raspberry Pi 3 working the way I wanted. It's been on my list of todo-projects for a while. I got it about half a year ago or so - and it was my first foray into Linux. It did not go too well, so that install got to be a real mess.

Since then I've been using Ubuntu more or less daily on my laptops, so I got the urge the other week to try out Ubuntu MATE on the Pi. Got it up and running well enough - but it did not take to updates all that well. It froze dead twice during that process actually. So waited a bit until Ubuntu MATE 16.04.02 got released last week and tried that. This worked fine but for one major niggle - no matter what I did, my Norwegian keyboard layout would not stick between reboots.

So, back to Raspbian. And since last, it's been rebranded PIXEL. Fine. Gave it a go. Worked very well straight out of the box. Though, it would not recognize my WiFi card in the GUI. Some bash-magic fixed that, so got connected to my home network.

Plenty of updates, tweaks and twiddling about later, it is now working like a charm. It's a pretty decent little setup as it happens. Very pleased with it.



Even better, with a bit of investigation I found someone that had been so kind as to compile Visual Studio Code for the Pi. Tried doing this myself, but ran into all kinds of problems with out of date this, missing that and misconfigured other thing. So having it already compiled and available was quite the boon to my efforts.



Most other IDEs (on the Pi anyway) require all kinds of esoteric configurations and fiddling with settings to work flawlessly with my language of choice - Go. Not so with VS Code. Everything is in place after mere minutes, and by and large automagically. It's just wonderful.

With all things performing well and to my taste, I thought it a good idea to give it a proper spin. Do a little project to enhance my Pi. I got this enclosure for my Pi that included heatsinks and a CPU fan. Though I never used the fan after first testing it, as it makes for a rather noisy rattling annoyance when going full tilt. Which is all it would do, as it is a simple two-wire job with no speed control.

Though to protect from overheat having a fan available is always a good idea. The Pi will throttle down the CPU at I think 80'C. However running such temperatures may significantly reduce the lifespan of the CPU. I've even read about people measuring upwards of 100'C on a Pi 3. Obviously, that won't do.

A little fan-control circuitry and code was in order. The circuitry itself is simple enough. A S8050 NPN transistor, a 10 ohm resistor, a tiny bit of proto-typing board and some wires, headers and plugs.



Soldered it up and tested with +5V and +3.3V from a lab PSU - worked as intended.



Next I taped it up with some electrical-tape and crammed it into the Pi enclosure. It fit snuggly between the case and fan.



Hardware done, on with the software. I know plenty of others have done similar - if not identical - projects to this. Though from what I've seen, the software have been done in Python or even as a Bash-script.

That just rubs me the wrong way. Just the interpreter for JIT languages like Python gobbles up a ton of resources before you've even executed a single line of code. Then there is the compatibility issues, the distribution issues, the slowness of the execution. And so on and so forth.

Native binaries for the win! If resources are at a premium, nothing beats C/C++. Well, assembler do, but who got time for that?! Luckily, a Pi3 got reasonable amounts of resources, so Go is a very viable option for writing native apps in. It will be a bit bigger and hungrier than C/C++ due to the inner workings of the concurrency model and garbage collector. But it'll be nearly as fast and lean in execution - and also got all the other advantages of a static native binary.

Anyhow, the full code and binary can be found on my github;

rDybing/PiFanControl

Just download, and move the binary to a location of your choosing. Then to have it start automatically at boot, edit your /etc/rc.local file to include the pifc binary. Remember to put an ampersand at the end to make it run on a thread of its own. My edit look like this:

/etc/fancontrol/pifc &

Pin connections are easy enough;

+5VCC   (red wire)
GND     (black wire)
GPIO-18 (green wire)

Another little note - my application relies on the command '$ vcgencmd measure_temp' not needing sudo. This won't be a problem if running the default user - but if logged in as another user, it may. The solution is to add your user account to root Video-group for some reason. Yeah, don't ask why - you just have to. Here is the command to do that:

>$ sudo usermod -a -G video yourUserNameHere

Nothing too complicated in the code. Fairly straight forward. Anyone who's been fiddling around with Arduino for instance, should be comfortable with both structure and syntax of how to operate the GPIO pins on the Pi using Go.

The one thing worth noting in the code is how the temperature limits are implemented. In most others code I've seen (yes, those dreaded Python and Bash scripts), it's a simple threshold. Above it, turn on, below it turn off.

Which sounds nice and dandy in theory. In practice though, you can get some heavy trashing between the two states as the temperature may fluctuate right on the threshold. So I got a 'deadzone' implemented.


---

func setFan(s *state_t) {
  if s.fanOn {
    if s.tempC < s.limitOff {
      // turn off fan
      s.fanOn = false
      embd.DigitalWrite(fanPin, embd.Low)
    }
  } else {
    if s.tempC > s.limitOn {
      // turn on fan
      s.fanOn = true
      embd.DigitalWrite(fanPin, embd.High)
    }
  }
}


---

As you can see, I use a flag to check if fan is on or off, and then check the limits. The limit for turning on is set to above 65'C and turning off is set to below 63'C.

I check the temperature every other second. In between the app sleeps. At first I tried using a timer rather than sleep - but all that resulted in was one core running at 100%. So even-though I am not a fan of sleep commands in code, here was one of those few times where it was warranted.

It works very well. During testing, running sysbench pushing all four cores to 100%, it will intermittently hit 70'C - but usually hovers around 68-69'C. During normal use, the fan is off naturally as it won't even be close to the threshold to trigger it. But now I got the added safety of having a fan kick in should it be needed.

Now I just need think up another project for my Pi. Probably something server/backend related for an Arduino project I am contemplating :)

20170213

Collating a list in Go

GOLANG: So I am working on an admin tool for a database-backend. One of the reports wanted is to extract from a table number of messages in a given network. Which sounds easier than it is. The database entry for a message got quite the few fields, but the only one I am interested in, is the network ID which is stamped into each message entry. So there is a lot of network IDs that repeat. I got to count them and collate them for the report.

In this case, it is finding what networks is near or at the limit for free use, which is to say between 40 and 50 messages in the network. And to do this without hitting the backend database any more than strictly speaking necessary. With well over 100k individual messages in the database spread out over some 5k networks, the obvious solution is to just fetch and cache the entire table column of network IDs. Each ID being 64 bits, that is a transfer of roughly 800kb which is not too bad.

Then sort through it all. It took a bit of head-scratching thinking through the problem. And a pot of coffee.

Eventually I came up with this:

---

type collate_t struct {
  id       int64
  count    int
  // whatever else you need
}

func collateList(entry []collate_t) []collate_t {
   
  var collected collate_t
  var collated []collate_t

  for i := range entry {
    collected.id = entry[i].id
    if i > 0 && getExist(collated, collected.id) {
      collected.count = 0
    } else {
      if i < len(entry) {
        for j := i + 1; j < len(entry); j++ {
          if collected.id == entry[j].id {
            collected.count++
          }
        }

        collated = append(collated, collected) 
      }
    }
  }
  return collated
}

func getExist(c []collate_t, id int64) bool {
  for i := range c {
    if id == c[i].id
    return true
  }
  return false
}


---

That is *NOT* the first version - it is however the *WORKING* version 😁

Oh, and I did not include the cutoff function to trim the fat to only network IDs with between 40 and 50 messages in them - as that is rather simple.

The code is presented here a bit more general than what I've used in the actual application - as that is mired in a function with some postgres SQL queries and a few other bits and bobs. Anyhow, I think the solution is quite efficient - eventhough it do not use any of Gos' concurrency-goodieness.

The short of it is to iterate over the incoming entry slice - transfer the ID to a temp struct. Check if the incoming slice is iterated over at least once and if that ID have been counted already and is registered in the collated list. If not, run through the entire range of the incoming slice and count the number of hits on that ID. Finally then append to the collated list the new collected ID and count.

Pretty pleased with it, and just had to reward myself a Guiness for the effort -  and to calm my little tummy after all the coffee it took to reach that solution!

20170212

Mastermind Game #1: Considerations and Limitations

ARDUINO: Pondering doing a fun little project for a while now, but not quite found the correct one until it hit me: A version of the classic Mastermind board game.


Though it won't be a 1:1 copy. That would require an unholy amount of LEDs and just the though of soldering all those RGB leds and accompanying resistors make me dizzy. So no, got to simplify things a bit.

I guess I could cheat, and just use a color display - but then I might as well do it on the Pi in Go or AGK. Nope, I want this to be 'hands-on' as it were. So LEDs, buttons and I'm also thinking a rotary encoder...

But first - the rules. In the original you get six colors, ten tries and the 'coder' can tell if a color is correct or if a color and position is correct. But not what position and/or color. But since the 'cracker' got the entire history available, the process of elimination is simple enough.

In the version I'm making, The history will not be directly visible as such. I'm thinking of using a rotary encoder to browse back and forth in the history. The same encoder will be used to select what LED to change and to what color.

Speaking of colors. Your typical RGB LED got plenty to choose from - but for simplicity I'll keep it to what can be achieved using binary on/off. So no gradients. If not counting fully off (black) or fully on (white) that leaves six colors. Which is just perfect.

Color - R - - G - - B -
red 1 0 0
green 0 1 0
blue 0 0 1
yellow 1 1 0
magenta 1 0 1
cyan 0 1 1

As for the 'coder' LEDs, I'll just use four yellow ones to signal correct color, and four green ones to signal correct color and position.

In addition I'll also need something to signal how many tries have been attempted. If counting LEDs needed to be controlled now, I get 5 x 4 = 20. I can control that using three Shift Registers and have four channels left over. So unless I want to throw in another Shift Register, a 7seg LED display is not going to happen. But with the four bits left over from the three Shift Registers, I can count to 16 - which is plenty. So I'll add four blue LEDs and use that as a digital counter. Counting in digital is cool anyways, and blue LEDs are the coolest, so double win!

In the next installment I'll go through some of the initial hardware design. Ultimately, I'm going to want this in a nice little box with a 9V battery for power. So it's all going to run off a bare Atmega328P in the end with all the necessary discrete components to have it all humming along nicely. Which will be fun to bodge up on perf-boards with a ton of wires hither and dither to connect it all 😄

20170209

About this blog

Here I'll gather my little personal projects, various tutorials and help I give others in their projects. Most content will probably cover various topics related to programming in Go (aka Golang), fun and games with Arduino and also App Game Kit.

Other topics may crop up - but in general I'll contain myself to the more technical side of technology. Whilst I do have many opinions on many a topic, this is not a political or philosophical blog :)

I may be Norwegian, but will write in English. I live in Bergen, which means it is probably wet outside so I got nothing better to do than be inside and tinker with toys anyway.