2021 PROJECTS

In this post, I will cover some projects I have worked on over the last few months and some projects I have planned for the future.

Bipedal Robot


I am currently busy building a bipedal robot based on this Instructables post by K.Biagini. I used his design as a foundation and added additional components and functionality (such as arms and a Piezo for sound).

I had to modify his 3D models to achieve what I wanted. Here are links to download my modified 3d Models:
– Body Extension (to fit in the extra components) – Link
– Modified Head – Link
– Arms – Link

Here is a list of all the electronic components used:
– 1x Arduino Nano
– 6x micro servos
– 2 x push buttons
– 1x mini toggle switch
– 1x 9v Battery
– 1x ultrasonic sensor (HC-SR04)
– 1x RGB LED
– 1x Piezo

These components are connected as follows:

Pinout configuration of Arduino Nano:

Pin NumberConnected Hardware
2Ultrasonic Sensor Echo Pin
3RGB LED Red Pin
4Push Button 1
5RGB LED Green Pin
6RGB LED Blue Pin
7Push Button 2
8Servo Signal Pin (Right Hip)
9Servo Signal Pin (Right Ankle)
10Servo Signal Pin (Left Hip)
11Piezo
12Servo Signal Pin (Left Ankle)
13Ultrasonic Sensor Trigger Pin
14 (A0)Servo Signal Pin (Left Arm)
15 (A1)Servo Signal Pin (Right Arm)

This is still an in-progress project and is not done, Especially from a coding perspective on the Arduino, but once I have completed this project, I will create a post containing the complete source code.

Rotary Control

I needed a rotary control for another project discussed below, so I decided to build one as per this Post on the Prusa Printers blog. It is based on an Arduino Pro Micro and uses Rotary Encoder Module.

I modified the code available on the Prusa blog to mimic keyboard WASD inputs. Turning the dial left and right will input A and D, respectively. Pressing in the dial control push button will switch to up and down inputs, thus turning the dial left and right will input W and S.
Here is the modified code (Based on Prusa Printers blog post code):

#include <ClickEncoder.h>
#include <TimerOne.h>
#include <HID-Project.h>

#define ENCODER_CLK A0 
#define ENCODER_DT A1
#define ENCODER_SW A2

ClickEncoder *encoder; // variable representing the rotary encoder
int16_t last, value; // variables for current and last rotation value
bool upDown = false;
void timerIsr() {
  encoder->service();
}

void setup() {
  Serial.begin(9600); // Opens the serial connection
  Keyboard.begin();
  encoder = new ClickEncoder(ENCODER_DT, ENCODER_CLK, ENCODER_SW); 

  Timer1.initialize(1000); // Initializes the timer
  Timer1.attachInterrupt(timerIsr); 
  last = -1;
} 

void loop() {  
  value += encoder->getValue();

  if (value != last) { 
    if (upDown)
    {
    if(last<value) // Detecting the direction of rotation
        Keyboard.write('s');
      else
        Keyboard.write('w');
    }
    else
    {
      if(last<value) // Detecting the direction of rotation
        Keyboard.write('d');
      else
        Keyboard.write('a');
    }
    last = value; 
    Serial.print("Encoder Value: "); 
    Serial.println(value);
  }

  // This next part handles the rotary encoder BUTTON
  ClickEncoder::Button b = encoder->getButton(); 
  if (b != ClickEncoder::Open) {
    switch (b) {
      case ClickEncoder::Clicked: 
        upDown = !upDown;
      break;      
      
      case ClickEncoder::DoubleClicked: 
        
      break;      
    }
  }

  delay(10); 
}

I use the rotary control with a Raspberry Pi to control a camera pan-tilt mechanism. Here is a video showing it in action:

I will cover the purpose of the camera as well as the configuration and coding related to the pan-tilt mechanism later in this post.

Raspberry Pi Projects

Raspberry Pi and TensorFlow lite

TensorFlow is a deep learning library developed by Google that allows for the easy creation and implementation of Machine Learning models. There are many articles available online on how to do this, so I will not focus on how to do this.

At a high level, I created a basic object identification model created on my windows PC and then converted the model to a TensorFlow lite model that can be run on a Raspberry pi 4. When the TensorFlow lite model is run on the Raspberry Pi, a video feed is shown of the attached Raspberry Pi camera, with green blocks around items that the model has identified with a text label of what the model believes the object is, as well as a numerical percentage which indicates the level of confidence the model has in the object identification.

I have attached a 3inch LCD screen (in a 3D printed housing) to the Raspberry Pi to show the video feed and object identification in real-time.

The Raspberry Pi Camera is mounted on a pan-tilt bracket which is controlled via two micro servos. As mentioned earlier, the pan-tilt mechanism is controlled via the dial control discussed earlier. The pan-tilt mechanism servos are driven by an Arduino Uno R3 connected to the Raspberry Pi 4 via USB. I initially connected servos straight to Raspberry Pi GPIO pins. However, this resulted in servo jitter. After numerous modifications and attempted fixes, I was not happy with the results, so I decided to use an Arduino Uno R3 to drive the servos instead and connect it to the Raspberry Pi Via USB. I have always found hardware interfacing significantly easier with Arduino and also the result more consistent.

Here is a diagram of how the servos are connected to the Arduino Uno R3:

Below is the Arduino source code I wrote to control the servos. Instructions are sent to the Arduino through serial communication via USB, and the servos are adjusted accordingly.

#include <Servo.h>
#define SERVO1_PIN A2
#define SERVO2_PIN A3

Servo servo1;
Servo servo2;
String direction;
String key;
int servo1Pos = 0;
int servo2Pos = 0;

void setup()
{
  servo1Pos = 90;
  servo2Pos = 90;
  Serial.begin(9600);
  servo1.attach(SERVO1_PIN);
  servo2.attach(SERVO2_PIN);

  servo1.write(30);
  delay(500);
  servo1.write(180);
  delay(500);
  servo1.write(servo1Pos);
  delay(500);
  servo2.write(30);
  delay(500);
  servo2.write(150);
  delay(500);
  servo2.write(servo2Pos);
  delay(500);
  Serial.println("Started");
  servo1.detach();
  servo2.detach();
}

String readSerialPort()
{
  String msg = "";
  if (Serial.available()) {
    delay(10);
    msg = Serial.read();
    Serial.flush();
    msg.trim();
    Serial.println(msg);
  }
  return msg;
}

void loop()
{
  direction = "";
  direction = readSerialPort();
  //Serial.print("direction : " + direction);
  key = "";

  if (direction != "")
  {
    direction.trim();
    key = direction;

    servo1.attach(SERVO1_PIN);
    servo2.attach(SERVO2_PIN);

    if (key == "97")
    {
      if (servo2Pos > 30)
      {
        servo2Pos -= 10;
      }
      servo2.write(servo2Pos);
      delay(500);
      Serial.print("A");
    }

    else if (key == "115")
    {
      if (servo1Pos < 180)
      {
        servo1Pos += 10;
      }
      servo1.write(servo1Pos);
      delay(500);
      Serial.print("S");
    }

    else if (key == "119")
    {
      if (servo1Pos > 30)
      {
        servo1Pos -= 10;
      }
      servo1.write(servo1Pos);
      delay(500);
      Serial.print("W");
    }

    else if (key == "100")
    {
      if (servo2Pos < 150)
      {
        servo2Pos += 10;
      }
      servo2.write(servo2Pos);
      delay(500);
      Serial.print("D");
    }

    delay(100);
    servo1.detach();
    servo2.detach();
  }

}

On the Raspberry Pi, the following Python script is used to transfer the rotary control input via serial communication to the Arduino:

# Import libraries
import serial
import time
import keyboard
import pygame

pygame.init()
screen = pygame.display.set_mode((1, 1))

with serial.Serial("/dev/ttyACM0", 9600, timeout=1) as arduino:
    time.sleep(0.1)
if arduino.isOpen():
    done = False
while not done:
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
    arduino.write('s'.encode())

if event.key == pygame.K_w:
    arduino.write('w'.encode())

if event.key == pygame.K_a:
    arduino.write('a'.encode())

if event.key == pygame.K_d:
    arduino.write('d'.encode())
time.sleep(0.5)

arduino.Close();
print ("Goodbye")

The next thing I want to implement on this project is face tracking using TensorFlow lite with automated camera movement.

Raspberry Pi Zero W Mini PC

I built a tiny PC using a Raspberry Pi Zero W combined with a RII RT-MWK01 V3 wireless mini keyboard and a 5 inch LCD display for Raspberry Pi with a 3D printed screen stand.


It is possible to run Quake 1 on the Raspberry Pi Zero following the instructions in this GitHub, and it runs great.

Raspberry Pi Mini Server Rack

I have 3D printed a mini server rack and configured a four Raspberry Pi Cluster consisting of three raspberry Pi 3s and one Raspberry Pi 2. They are all networked via a basic five-port switch.

I am currently busy with a few different projects using the Pi cluster and will have some posts in the future going into some more details on these projects.

I developed a little Python application to monitor my different Raspberry Pis and show which ones are online (shown in green) and offline (shown in red).

The application pings each endpoint every 5 seconds, and it is also possible to click on an individual endpoint to ping it immediately. The list of endpoints is read from a CSV file, and it is easy to add additional endpoints. The UI is automatically updated on program startup with the endpoints listed in the CSV file.

Here is the Python source code of the application:

import PySimpleGUI as sg
import csv
import time
import os
from apscheduler.schedulers.background import BackgroundScheduler


def ping(address):
    response = os.system("ping -n 1 " + address)
    return response


def update_element(server):
    global window
    global layout
    response = ping(server.address)
    if response == 0:
        server.status = 1
        window.Element(server.name).Update(button_color=('white', 'green'))
        window.refresh()
    else:
        server.status = 0
        window.Element(server.name).Update(button_color=('white', 'red'))
        window.refresh()


def update_window():
    global serverList
    for server in serverlist:
        update_element(server)


class server:
    def __init__(self, name, address, status):
        self.name = name
        self.address = address
        self.status = status


serverlist = []

with open('servers.csv') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            line_count += 1
        else:
            serverlist.append(server(row[0], row[1], 0))
            line_count += 1

layout = [
    [sg.Text("Server List:")],
]

for server in serverlist:
    layout.append([sg.Button('%s' % server.name, 
                    button_color=('white', 'orange'), 
                    key='%s' % server.name)])

window = sg.Window(title="KillerRobotics Server Monitor", 
                    layout=layout, margins=(100, 30))
window.finalize()
scheduler = BackgroundScheduler()
scheduler.start()

scheduler.add_job(update_window, 'interval', seconds=5, id='server_check_job')

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        scheduler.remove_all_jobs()
        scheduler.shutdown()
        window.close()
        break
    elif event in [server.name for server in serverlist]:
        scheduler.pause()
        update_element([server for server in 
                         serverlist if server.name == event][0])
        scheduler.resume()

Raspberry Pi Pico

I ordered a few Raspberry Pi Picos on its release, and thus far, I am very impressed with this small and inexpensive microcontroller.

The Raspberry Pi Pico sells for $4 (USD) and has the following specifications:
– RP2040 microcontroller chip designed by Raspberry Pi
– Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz
– 264KB on-chip SRAM
– 2MB on-board QSPI Flash
– 26 multifunction GPIO pins, including 3 analogue inputs
– 2 × UART, 2 × SPI controllers, 2 × I2C controllers, 16 × PWM channels
– 1 × USB 1.1 controller and PHY, with host and device support
– 8 × Programmable I/O (PIO) state machines for custom peripheral support
– Low-power sleep and dormant modes
– Accurate on-chip clock
– Temperature sensor
– Accelerated integer and floating-point libraries on-chip

It is a versatile little microcontroller that nicely fills the gap between Arduino and similar microcontrollers and the more traditional Raspberry Pis or similar single board computers.
I have only scratched the surface of using the Pico on some really basic projects, but I have quite a few ideas of using it on some more interesting projects in the future.

3D Printing

I ran into some problems with my 3D printer (Wanhao i3 Mini) over the last few months. The First problem was that half of the printed LCD display died, which was an annoyance, but the printer was still usable. The next issue, which was significantly more severe, was that the printer was unable to heat up the hot end.

My first course of action was to replace both the heating cartridge and the thermistor to ensure that neither of those components were to blame, and unfortunately, they were not. After some diagnostics with a multimeter on the printer’s motherboard, I determined that no power was passing through to the heating cartridge connectors on the motherboard.

I ordered a replacement motherboard and installed it, and the 3D printer is working as good as new again. When I have some more time, I will try and diagnose the exact problem on the old motherboard and repair it.
Here are photos of the old motherboard I removed from the printer:

Below are some photos of a few things I have 3D printed the last few months:

2021 PROJECTS

LEARNING PYTHON AND DEVELOPING A GAME

Screen

As I mentioned in my Surviving Lockdown post, I started upskilling on Python, and when upskilling on a new programming language, I usually do a project to build on and enforce the things I am learning.

For my Python-based project, I decided to use PyGame to develop a small game. One piece of advice I can offer when developing a game is that it is better to develop a small and basic game that you finish than a large and ambitious game you never complete. I believe everyone who has tried some form of game development has at least one over-ambitious project they never completed, so it is better to start small.

The game I developed is called “Space Octopus Invasion” and here is a video of the game in action:

The tools and resources I used in the development process are as follows:

  • Trello
    I used Trello for task tracking and planning.
    trello
  • PyCharm
    PyCharm is my favorite Python IDE developed by JetBrains, and it offers a free community edition.
    pycharm
  • PyInstaller 
    A great utility to package a python application into an executable file.
  • InstallForge 
    A free installer maker that allows you to create a professional-looking setup wizard to install your game.
  • GameDevMarket.net
    I am not an artistically inclined person, and typically I use art, sound, and music assets when developing a game, I recommend GameDevMarket.net as they have a great selection of assets available.

The Installer for the game can be downloaded here: Installer.

And the source code can be downloaded here: Source Code.

LEARNING PYTHON AND DEVELOPING A GAME

The Dark Art of DevOps (and how Azure DevOps fits in)

Here is a Post n wrote for my Companies blog, originally posted here.

DevOps has become a hot topic in organisations over the past year or so. However, there seems to be a lot of confusion regarding what DevOps actually entails. So, what is DevOps?

If you asked a more sales-inclined individual, you may get a response along the lines of: DevOps digitally transforms an organisation’s development department by bridging the gap between development and operations, resulting in higher quality solutions, fewer bugs, quicker delivery times, shorter recovery times, and controlling scope creep.”

This sounds amazing! However, it does not answer the question as to what DevOps really is. So, I will be taking a different approach to delve into what DevOps entails.

DevOps is based on the principal of continuous improvements in the Software Development Lifecycle, and consists of principles, practices and tools that allow an organisation’s development department to deliver projects at a high velocity, while maintaining quality and continuously improving the process associated with delivery. This is where Azure DevOps comes in. Azure DevOps is a selection of tools that facilitate the implementation of DevOps within an organisation.

DevOps consists of five main pillars (which are supported by processes, practices and tools), namely:

1. Plan and Track

This involves planning what development work needs to be completed and tracking progress against that. The tool Azure DevOps offers here is Azure Boards.

2. Develop

This is where your software developers write code and store that code. In the Azure DevOps ecosystem, the tools that used here are Visual Studio, Visual Studio Code and Azure Repos as a source code repository.

3. Build and Test

Automated builds and testing are a very important part of DevOps, as this automation frees up valuable resource time to focus on more imperative tasks. Automated builds can be set up to trigger new builds (compiling source code into executable programs) based on certain criteria (for example, “once a day”), and automated tests can then be run to verify that everything is working as expected without the intervention of a person.  Azure Pipelines and Azure Test Plans are the tools utilized here.

4. Deploy

The next step is Automated Deploy – first to a UAT\Test environment and eventually to production. Doing deploys in this manner prevents unwanted changes being accidentally deployed from a developer’s machine and introduces additional controls to only deploy what is wanted and limiting the introduction of problems.  By automating the deployment of systems deployment times are also drastically reduced and thus system down time is reduced. Azure Release Management is the Azure DevOps tool used to automate deployments.

5. Monitor and Operate

After a system has been deployed, it needs to be monitored and operational activities need to be performed to ensure it is up and running and running optimally. Azure Monitor and Application Insights are the tools available in the Azure DevOps tool-belt for this.

With the tools provided by Microsoft Azure DevOps, as well as industry tried and tested principles, the above five pillars can dramatically improve the operations and output of a development department while driving down operational costs.

Now that we understand what DevOps is and how it works, what outcomes can we expect from mastering the 5 pillars?

  • Better quality solutions
  • Quicker delivery times
  • Fewer bugs
  • Shorter recovery times to resolve bugs
  • Prevents uncontrolled scope creep
  • Improved collaboration and agility in teams
  • Better cross-skilling in teams
  • More automation
The Dark Art of DevOps (and how Azure DevOps fits in)

BITE SIZE C# – LINQ

LINQ or Language Integrated Query is part of the Microsoft .NET Framework and it adds native data querying capabilities to .NET languages.

LINQ allows the user to query:

  • Objects in Memory (i.e. collections such as lists) using LINQ to Objects
  • Databases using LINQ to Entities
  • XML using LINQ to XML
  • ADO.Net Datasets using LINQ to Datasets

LINQ can either be implemented using predefined extension methods or alternatively using LINQ Query Operators.

Below are three examples utilising LINQ Extension methods:

In this example a list of Book objects is filtered to return only the Objects where the price is less than 10.

List<Book> cheapBooks = books.Where(b=>b.Price < 10);

 

In this example a list of Book objects is filtered to return only the Objects where the price is less than 10 and additionally the newly created list of Book objects is sorted alphabetically based on the Title field.

List<Book> cheapBooks = books.Where(b=>b.Price < 10).OrderBy(b.Title);

 

In this example the cheapBooks list is filtered to only return the Titles of the books therein and these Titles are then inserted into a new list of strings.

List<string> cheapBooksTitles = cheapBooks.Select(b=>b.Title);

 

Multiple extension methods can be combined to ascertain the desired results, for example:

List<string> cheapBooksTitles = books.Where(b=>b.Price).OrderBy(b.Title);
                                   .Select(b=>b.Title);

 

LINQ query operators tend to be slightly more verbose, and the above example can be implemented with query operators as follows:

List<string> cheapBooksTitles = from b in books
                         where b.Price < 10
                         orderby b.Title
                         select b.Title;

 

Some common extension methods are:

Single

var book = books.Single(b=>b.Title == ”Building Robots”);

Returns a single object that matches the defined criteria. However note that in the event that none or more than one book matches the criteria specified an exception will be thrown.

 

SingleOrDefault

var book = books.SingleOrDefault(b=>b.Title == ”Building Robots”);

Returns a single object that matches the defined criteria, if more than one book matches the criteria specified an exception will be thrown, however if no books match the criteria the default value defined will be returned.

 

First

Returns the first object that matches the criteria, however if no matches are found an exception is thrown.

 

FirstOrDefault

Returns the first object that matches the criteria and if no match is found the default value will be returned.

 

Last

Returns the last object that matches the criteria, however if no matches are found an exception is thrown.

 

LastOrDefault

Returns the last object that matches the criteria and if no match is found the default value will be returned.

 

Max

var maxValue = books.Max(b=>b.Price);

Max is used with numeric values and will return the highest value that is contained in the Price field in the Book objects.

 

Min

var minValue = books.Min(b=>b.Price);

Min is another operation used with numeric values and will return the smallest value that is contained in the Price field in the Book objects.

 

Sum

var totalPrice = books.Sum(b=>b.Price);

Sum is used to add up all the values in a numeric field.

 

There are many other methods available to filter and manipulate data in LINQ and the possibilities for the utilisation of LINQ are nearly endless, for example

var bookSelection = books.Skip(2).Take(3);

The above example will skip the first two books in the books list and take the next three placing them into the newly created bookSelection list.

The best option to gain a better insight of what is possible with LINQ is to give it a try.

BITE SIZE C# – LINQ

BITE SIZE C# – LAMBDA EXPRESSIONS

A lambda expression is a function definition with no name, no access modifier and no return statement. Lambda expressions are also known as Anonymous methods or functions.

The syntax for the definition of a lambda expressions is as follows:

(arguments) => expression

The below C# code does not use lambda expressions and is given as a comparative reference point:

static int SquareNumber(int number)
{
   return number*number;
}

static void Main(string[] args)
{
   Int y = SquareNumber(10);
   Console.WriteLine(y); // This will display 100
}

The above code can be refactored using a lambda expression as follows:

static void Main(string[] args)
{

   Func<int,int> square = number=>number*number;
   Console.WriteLine(square(10)); // This will display 100

}

The result of this refactor is fewer lines of code in order to achieve the same result.

Lambda expressions can also make use of Delegates as shows here:

delegate int squareDelegate (int number);

static void Main(string[] args)
{
   squareDelegate square = number=>number*number;
   Console.WriteLine(square(10)); // This will display 100
}

 

The syntax for a lambda expression that takes no arguments is as follows:

()=>expression

For one argument:

X=>expression

For more than one argument:

(x,y,z)=>expression

 

Lambda expressions can also be very effectively used with objects that implement the IEnumerable and IQueryable interfaces to filter or search based on defined criteria, for example:

var highPriceList = PriceList.FindAll(a=>a.Price>10);

This will return all items with a price larger than 10, and place these items in the highPriceList.

 

var nyCustomers = Customers.Where(a=>a.City==”New York”);

This will place all customers with the city property set to “New York” into the nyCustomers collections.

Lambda expressions are an extremely useful tool with many other uses.

BITE SIZE C# – LAMBDA EXPRESSIONS

Bite Size C# – Eventing\Observer Pattern

Let us have a look at the eventing or observer pattern. This pattern is based on the raising and handling of events. Events are a mechanism for the communication between object that allow us to build loosely coupled applications that can be easily extended.

At a high level this pattern functions as follows:
An object (known as the Publisher) defines a contract (delegate method) to which other objects (knows as Subscribers) must comply in order to be notified of a certain condition occurring in the Publisher object. This is achieved as follows, when a certain state is reached in the Publisher object an event will be raised, which will then trigger all the Subscriber objects to react by executing the method defined within the individual Subscriber objects that matches the delegate method as defined in the Publisher.

Now let us have a look at an example:

First let us create the Publisher, here we have to do three things:
1. Define a delegate which will act as the contract between the Publisher and Subscribers.
2. Define an event based on the delegate.
3. Raise the defined event.

public class KillerRobotPublisher
{
	public delegate void KillerRobotEventHandler(object source, EventArgs args);

	public event KillerRobotEventHandler KillerRobotAction;

	protected virtual void OnKillerRobotAction()
	 {
		if(KillerRobotAction!=null) //check if there are any subscribers
			{
				KillerRobotAction(this,EventArgs.Empty);
			}
	 }

	public void DoKillerRobotAction(string action)
	 {
		Console.WriteLine(“Killer Robot is doing “ +action);
		//add additional action logic here

		OnKillerRobotAction();
	}
}

Next let us create a Subscriber to subscribe to the KillerRobotAction event on the Publisher.

public class KillerRobotSubscriber
{
	public void OnKillerRobotAction(object source, EventArgs args)
     //this method conforms to the delegate defined in the Publisher
	 {
		Console.WriteLine(“The Killer Robot did something!”);
	 }
}

Now lastly let us create a basic application to instantiate the objects and to subscribe the Subscriber to the Publisher:

class Program
{
	static void Main(string[] args)
	{
		var killerRobotPub = new KillerRobotPublisher(); //Instantiate Publisher Object
		var killerRobotSub = new KillerRobotSubscriber(); //Instantiate Subscriber Object 

		killerRobotPub.KillerRobotAction += killerRobotSub.OnKillerRobotAction;
		//Subscribe the KillerRobotSubscriber to the KillerRobotAction event on the KillerRobotPublisher.

		killerRobotPub.DoKillerRobotAction(“A Dance”);
	}
}

The console output of this application will look like this:

console_Output

Bite Size C# – Eventing\Observer Pattern

Bite Size C# – Extension Methods

Extension methods allow us to add methods to existing classes without changing the class’ source code, nor by inheriting from the class. Extension methods are more relevant when wanting to add a method to a class from which one cannot inherit, such as sealed classes.
Just note, you cannot use extension methods with a static class as extension methods require an instance variable for an object in order to be utilised.
Let us look at an example, here we will add an extension method to the string class, which is a sealed class (i.e. you cannot inherit from this class).

class Program
{
	static void Main(string[] args)
	{
		string sentence=  “This is something a person would say.”;

		var robotSentence = sentence.ToRobot();
		Console.WriteLine(robotSentence);
	}
}

public static class StringExtensions
{
	public static string ToRobot(this string str)
	{
		if(String.IsNullOrEmpty(str)) return str;
		var words = str.Split(‘ ‘);
		var robotStr = String.Empty;

		foreach(var word in words)
		{
			if(word.Length > 4)
			{
				robotStr+=“BEEP “;
			} else {
				robotStr+=“BOOP ”;
			}
		}

		return robotStr.Trim();
	}
}

Also note that extension methods must be non-generic static methods defined in a static class.

Bite Size C# – Extension Methods

Bite Size C# – Delegates

A delegate is a form of a type-safe function pointer. More simply put, it is an object that knows how to call a method, i.e. a reference to a method. Delegates are useful as they assist us in writing flexible and extendable applications.

Delegates are useful when using the eventing design pattern also known as the observer pattern. The eventing or observer pattern consists of an object, called the subject or publisher, which maintains a list of dependent objects, called observers or subscribers, and notifies them automatically of a state change in the subject-object by raising an event and then calling a method on the observer objects by using a delegate. We will cover this pattern in more detail when I cover events in a separate post.

For now, let us simply focus on delegates.

So, let us look at an example:


public class KillerRobot
{
	public string Name { get; set; }
}

public class KillerRobotActuator
{
	public delegate void KillerRobotActionHandler(KillerRobot robot); 	//Declare delegate which will act as a
															//signature for methods that can be
															//referenced.

	public void DoAction(string robotName, KillerRobotActionHandler actionHandler)
	{
		var robot = new KillerRobot {Name = robotName	};
		actionHandler(robot);
	}
}

public class RobotActions
{
	public void RobotTalk(KillerRobot robot)
	{
		Console.WriteLine(“{0} is Talking.”, robot.Name);
	}

	public void RobotDance(KillerRobot robot)
	{
		Console.WriteLine(“{0} is Dancing.”, robot.Name);
	}
}

class Program
{
	static void Main(string[] args)
	{
		var robotActuator = new KillerRobotActuator();
		var robotActions = new RobotActions();
		KillerRobotActuator.KillerRobotActionHandler actionHandler = robotActions.RobotTalk;
		actionHandler += robotActions.RobotDance;
		actionHandler += RobotPowerOff;

		robotActuator.DoAction(“The Geek”,actionHandler);
	}

	static void RobotPowerOff(KillerRobot robot)
	{
		Console.WriteLine(“{0} has turned off.”, robot.Name);
	}
}

So, in this basic example we have a class KillerRobotActuator which declares a delegate:

public delegate void KillerRobotActionHandler(KillerRobot robot);

Any method that complies to this signature can then be added to this delegate and in the DoAction method where the following is executed:

actionHandler(robot);

All the methods that have been added to the actionHandler will then be executed.
We can see in the Main method of the Program class that a new KillerRobotActionHandler is declared and three method references are added to it as below:

KillerRobotActuator.KillerRobotActionHandler actionHandler = robotActions.RobotTalk;
actionHandler += robotActions.RobotDance;
actionHandler += RobotPowerOff;

And then finally the DoAction method on KillerRobotActuator is executed, passing in the above declared actionHandler containing references to the three methods:

robotActuator.DoAction(“The Geek”,actionHandler);

All three the methods that are referenced by the actionHandler comply to the signature defined in the delegate declaration in the KillerRobotActuator class. i.e. a void return type and an input parameter of type KillerRobot.
It is also worth mentioning that of the methods referenced, two are contained in a separate class RobotActions and the third is a static method declared in the Program class, so methods from multiple different class locations can be added as long as they comply to the signature of the delegate declares.

 

Bite Size C# – Delegates

Bite Size C# – Generics

Generics refer to the method of creating classes and methods in a way that defers the specification of the type or types associated with the class or method until it is declared and instantiated.

What this means in plain english is that you can define a single class or method that can be utilised with multiple types, thus resulting in less and tidier code.

So let us have a look at an example. Firstly let us look at some code that is not generic. Here we have a class which consist of a list of integers, it has a default constructor as well as two methods, one to add an integer to the list and the other to return the sum of all the integers in the list.

public class KillerRoboticsIntList
{
   public List<int> IntList { get; set; }

    public KillerRoboticsIntList()
    {
        IntList = new List<int>();
    }

    public void Add(int item)
    {
        IntList.Add(item);
    }

    public int Sum()
   {
	int sum;
	foreach(int i in IntList)
	{
	 sum += i;
	}
	return sum;
   }

}

This is a very basic example and can be utilised as follows:

class Program
        {
            public static void Main()
            {
                KillerRoboticsIntList iList = new KillerRoboticsIntList();
		        iList.Add(1);
		        iList.Add(2);
		        iList.Add(3);
		        iList.Add(4);
		        int sum = iList.Sum();
                Console.WriteLine(“Sum = {0}.", sum);

            }
        }

This is very straight forward, however if I would like to use this class with a data type other than int (for example a float or a double) I would need to define a new class for each data type. This can be overcome by utilising Generics. Below is an example of how this can be implemented:

public class KillerRoboticsGenericList<T>
{
   public List GenList<T> { get; set; }

    public KillerRoboticsGenericList()
    {
        GenList = new List<T>();
    }

    public void Add(T item)
    {
        GenList.Add(item);
    }

    public T Sum()
   {
	T sum;
	foreach(T i in GenList)
	{
	 sum += i;
	}
	return sum;
   }

}

The above class can now be defined for various types as seen below:

class Program
        {
            public static void Main()
            {
              KillerRoboticsIntList<int> intList = new KillerRoboticsIntList<int>();
		        intList.Add(1);
		        intList.Add(2);
		        intList.Add(3);
		        intList.Add(4);
		        int sum = intList.Sum();
                Console.WriteLine(“Int Sum = {0}.", sum);

		        KillerRoboticsIntList<double> = new KillerRoboticsIntList<double>();
		        doubleList.Add(0.1);
		        doubleList.Add(2.2);
		        doubleList.Add(3.0);
		        doubleList.Add(1.4);
		        double dSum = doubleList.Sum();
                Console.WriteLine(“Double Sum = {0}.", dSum);

            }
        }

In some cases you might want to put a restriction on the types that can be utilised to implement a generic class of method, this can be achieved by utilising constraints. For example the class we defined above can be restricted to types that implement the IComparable interface by simple changing the first line as follows:

public class KillerRoboticsGenericList<T> where T : IComparable

Some additional examples of constraints are:

where T : Product

This restricts the type of T to an implementation of the class Product or any of its child classes.

where T : struct

This restricts the type of T to the value type struct.

where T : new()

This restricts the type of T to an object with a default constructor.

Multiple Constraints can also be appled at the same time, for example:

 
public class KillerRoboticsGenericList<T> where T : IComparable, new() 

A Generic class can be defined to utilise multiple types, for example:

 
public class KillerRoboticsGenericList<T,U,V>  

It is also worth mentioning that the default c# List class used in the above examples also utilises generics, along with all the other predefined c# collections contained in System.Collections.Generic.

I hope this post has been useful and I will be posting on some additional C# topics, such as Delegates, Lamda Expressions, LINQ, Extension Methods, etc. over the next few months.

Bite Size C# – Generics

A Story About A Game

15 Years ago I wrote a small game called Hellspawn and I rediscovered it again when I was going through some old backup discs. It is a top down shooter and was developed in Borland C++ Builder (I think version 6). It was a very basic game (especially looking back now) from when I was still a very inexperienced developer, still studying to get a degree.

So if anyone is interested here it is: HellSpawn

To get it working on windows 10:

Use Hellspawn.exe to start the game, but first in file properties:

  • Set executable to run in compatibility mode  – Windows 98 / Windows ME
  • Reduced Color mode – 16-bit
  • Override DPI Scaling Behavior, Scaling performed by – Application
  • Can also set to run in 640 x 480, however is best to change screen resolution in windows to 1024 x 768 for best experience.

compatibility

The controls are as follows:

  • Arrow keys to move
  • Left ctrl keys to fire weapon

Simply kill all the enemies to proceed to the next level.

On another note I have some Steam game keys to give away!

For a chance to win one simply email killerrobotics.me@gmail.com with the subject line ‘Killer Robotics Steam Giveaway’ and for the message content just be creative.

Winners will be randomly selected and announced via twitter.

A Story About A Game