Rock-Paper-Scissors with Netduino and Arduino


Been constantly persuaded by my 6 years old daughter to play Rock-Paper-Scissors I decided that we can make it a bit more interesting, so I’ve put following schematics on the prototyping shield:

Rock-Paper-Scissors

Netduino and Arduino are pin compatible, but the output voltages are different: 3.3V for Netduino and 5V for Arduiono. For current limiting, I’ve selected 150Ohm resistor to avoid changing the elements, when change the platform. The 10K pull-down resistors assure false state on the digital inputs until button is pressed.

I’ve tested it with Netduino Plus, Arduino Uno and Shrimpuino (homebrewed Arduino Uno analog).

Netduino:

using System.Threading;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace RockPaperScissors
{
	public class Program
	{
		private static OutputPort redLed = new OutputPort(Pins.GPIO_PIN_D11, false);
		private static OutputPort greenLed = new OutputPort(Pins.GPIO_PIN_D12, false);
		private static OutputPort blueLed = new OutputPort(Pins.GPIO_PIN_D13, false);

		private static InputPort rockButton = new InputPort(Pins.GPIO_PIN_D10, true, ResistorModes.Disabled);
		private static InputPort paperButton = new InputPort(Pins.GPIO_PIN_D6, true, ResistorModes.Disabled);
		private static InputPort scissorsButton = new InputPort(Pins.GPIO_PIN_D2, true, ResistorModes.Disabled);

		private static InputPort stopButton = new InputPort(Pins.ONBOARD_SW1, true, Port.ResistorMode.Disabled);

		private enum Choice
		{
			None,
			Rock,
			Paper,
			Scissors
		}

		private enum Player
		{
			None,
			First,
			Second
		}

		public static void Main()
		{
			while (stopButton.Read())
			{
				AllLedsOff();
				IntroForPlayer(Player.First);
				Choice firstPlayer = GetChoice();

				AllLedsOff();
				IntroForPlayer(Player.Second);
				Choice secondPlayer = GetChoice();

				AllLedsOff();
				EvaluateAndShowResult(firstPlayer, secondPlayer);

				Thread.Sleep(2000);
			}
		}

		private static void IntroForPlayer(Player player)
		{
			switch (player)
			{
				case Player.First:
					greenLed.Write(true);
					break;
				case Player.Second:
					redLed.Write(true);
					break;
			}
		}

		private static Choice GetChoice()
		{
			var choice = Choice.None;
			while (choice == Choice.None)
			{
				if (rockButton.Read())
				{
					choice = Choice.Rock;
				}

				if (paperButton.Read())
				{
					choice = Choice.Paper;
				}

				if (scissorsButton.Read())
				{
					choice = Choice.Scissors;
				}
			}

			Thread.Sleep(500);
			return choice;
		}

		private static void EvaluateAndShowResult(Choice firstPlayerChoice, Choice secondPlayerChoice)
		{
			if (firstPlayerChoice == secondPlayerChoice)
			{
				ShowWinner(Player.None);
				return;
			}

			if ((firstPlayerChoice == Choice.Rock) && (secondPlayerChoice == Choice.Scissors) ||
				(firstPlayerChoice == Choice.Paper) && (secondPlayerChoice == Choice.Rock) ||
				(firstPlayerChoice == Choice.Scissors) && (secondPlayerChoice == Choice.Paper))
			{
				ShowWinner(Player.First);
			}
			else
			{
				ShowWinner(Player.Second);
			}
		}

		private static void ShowWinner(Player player)
		{
			for (var i = 0; i < 8; i++)
			{
				if (player == Player.None)
				{
					blueLed.Write(true);
				}
				else
				{
					IntroForPlayer(player);
				}

				Thread.Sleep(200);
				AllLedsOff();
				Thread.Sleep(100);
			}
		}

		private static void AllLedsOff()
		{
			redLed.Write(false);
			greenLed.Write(false);
			blueLed.Write(false);
		}
	}
}

Arduino:

int redLed = 11;
int greenLed = 12;
int blueLed = 13;

int rockButton = 10;
int paperButton = 6;
int scissorsButton = 2;

int choiceNone = 0;
int choiceRock = 1;
int choicePaper = 2;
int choiceScissors = 3;

int playerNone = 0;
int playerFirst = 1;
int playerSecond = 2;

void AllLedsOff() {
	digitalWrite(redLed, false);
	digitalWrite(greenLed, false);
	digitalWrite(blueLed, false);
}

void ShowWinner(int player) {
	for (int i = 0; i < 8; i++) {
		if (player == playerNone) {
			digitalWrite(blueLed, true);
		} else {
			IntroForPlayer(player);
		}
		delay(200);
		AllLedsOff();
		delay(100);
	}
}

int GetChoice() {
	int choice = choiceNone;
	while (choice == choiceNone) {
		if (digitalRead(rockButton) == HIGH) {
			choice = choiceRock;
		}
		if (digitalRead(paperButton) == HIGH) {
			choice = choicePaper;
		}
		if (digitalRead(scissorsButton) == HIGH) {
			choice = choiceScissors;
		}
		delay(10);
	}
	delay(500);
	return choice;
}

void IntroForPlayer(int player) {
	if (player == playerFirst) {
		digitalWrite(greenLed, true);
	} else if (player == playerSecond) {
		digitalWrite(redLed, true);
	}
}

void EvaluateAndShowResult(int firstPlayerChoice, int secondPlayerChoice) {
	if (firstPlayerChoice == secondPlayerChoice) {
		ShowWinner(playerNone);
		return;
	}
	if ((firstPlayerChoice == choiceRock) && (secondPlayerChoice == choiceScissors) ||
	    (firstPlayerChoice == choicePaper) && (secondPlayerChoice == choiceRock) ||
	    (firstPlayerChoice == choiceScissors) && (secondPlayerChoice == choicePaper)) {
		ShowWinner(playerFirst);
	} else {
		ShowWinner(playerSecond);
	}
}

void setup() {
	pinMode(redLed, OUTPUT);
	pinMode(greenLed, OUTPUT);
	pinMode(blueLed, OUTPUT);

	pinMode(rockButton, INPUT);
	pinMode(paperButton, INPUT);
	pinMode(scissorsButton, INPUT);
}

void loop() {
	while(true){
		AllLedsOff();
		IntroForPlayer(playerFirst);
		int firstPlayer = GetChoice();

		AllLedsOff();
		IntroForPlayer(playerSecond);
		int secondPlayer = GetChoice();

		AllLedsOff();
		EvaluateAndShowResult(firstPlayer, secondPlayer);

		delay(2000);
	}
}

What the code is doing and how to play:
After MCU initialise, RGB LED becomes steady GREEN thus indicating first player’s move. In secret from the other player, press the chosen button (from left to right in order: ROCK, PAPER, SCISSORS). RGB LED becomes steady RED and now this is the second player’s turn (at that stage of the game, the player may not press the button in secret any more). After the second player’s choice, the RGB LED will flash with the winners colour: GREEN (first player), RED (second player) and BLUE for TIE. Few seconds later, game restarts and you can play again.

Enjoy.

Read Netduino for beginners tutorial online on this blog


Hi guys,

You can now read the tutorial directly here! Just visit/navigate to this page.

Improving slowly but surely 🙂

Cheers

Netduino for beginners tutorial release v1.11


Hi guys,

I’ve done it again! New version of the tutorial (v1.11) is here and can be downloaded from Box section on the right, Netduino’s wiki page or read it online here.

Enjoy!

Netduino for beginners tutorial release v1.10


Hi guys!

My Christmas present for you – v1.10 of the Netduino for beginners tutorial. You can download it from the “Box” section on the right column of this page.

Enjoy!

Merry Christmas!

PS It appears Internet explorer users experience some problems with downloads from Box, so you can use Netduino’s wiki page to download the tutorial files. If you need just the tutorial without the code files then you can use this link or read it directly from Scribd.

 

Using NAND logic gate to solve problem with Netduino’s pin output on boot or restart


Well, many people complain about this problem. There are many suggestions about using pull-down resistors to solve the problem but reality act is you have to experiment rather to calculate correct pull-down resistor value on each different occasion.

In my beginners tutorial (code files, forum, wiki) I am showing few different ways to solve this problem in way that is more predictable. Up to now, we have seen how to use Relay with PNP transistor switch and interesting SCR thyristor approach. There will be few more on the way. This may not be very intriguing for advance audience but for beginners is a perfect way to learn. Following schematics are teaser for what is coming into next version of the tutorial: using a NAND logic gate.

LED, NAND, 5V power

LED, NAND, 5V power, 3.3V compare

LED, NAND, 3.3V power, 3.3V compare

LED, NAND, 5V power,  Second pin

NOTE: Appears the shown schematics mislead few people to think that those are “ultimate” solutions that I am proposing. This is not the case. These ones are just extracts from the tutorial text. There are not necessarily solutions of the global problem and they are far away from ultimate. They are partial and contextual ones that make sense only when you read the tutorial. Only then, they make sense as they are part where a digital logic gates are introduced to the beginner. And yes, there will be better ways to solve the problem at more global level than LED switch (in fact the tutorial already contains two methods shown) and they will show later, so please be patient, beginners need time to learn some stuff before jump into the advanced techniques 🙂

Multithreading with Netduino and .NET Microframework – part 4


(to part 1, part 2 or part 3)

In his post, I want to show you one more way to synchronise threads. It is more like “waiting” a thread to finish, before continues with execution of the code in the calling thread. I have seen people usually do this in following manner:

public class Program
{
     public static void Main()
     {
        Thread someThread = new Thread(SomeThreadMethod);

        // Start the thread execution
        someThread.Start();

        // Put main thread into infinite sleep
        Thread.Sleep(Timeout.Infinite);

        // Main thread never resumes!
     }

     private static void SomeThreadMethod()
     {
          // The thread's code
          ...
     }
}

Well it might look OK and it works OK but it is somehow “ugly” and you lose control over the main thread continuation. .NETMF provides nice way of doing this:

public class Program
{
     public static void Main()
     {
          Thread someThread = new Thread(SomeThreadMethod);

          // Start the thread execution
          someThread.Start();

          // Tell main tread to wait until someThread finish its execution
          someThread.Join();

          // Main thread code continues
          ...
     }

     private static void SomeThreadMethod()
     {
          // The thread's code
          ...
     }
}

Now that’s better! You still may block the app from exiting: just never return from SomeThreadMethod(). But anytime you decide to change algorithm you can do it easily. Another advantage of Join() method is that you do not have to do event synchronising thus saving yourself writing few more lines of code.

Here also one very quick way just to drop some thread to do something:

public class Program
{
     public static void Main()
     {
          new Thread(
              () =>
                  Debug.Print("Hello ...")
              ) { Priority = ThreadPriority.AboveNormal }
              .Start();

          new Thread(
              () =>
              {
                   Debug.Print("Line 1");
                   Debug.Print("Line 2");
              }) { Priority = ThreadPriority.Lowest }
              .Start();

          // Main thread code continues
          ...
     }

     private static void SomeThreadMethod()
     {
          // The thread's code
          ...
     }
}

(to part 1, part 2 or part 3)

Netduino for beginners tutorial release


A new release of the Netduino for beginners can be downloaded from here (code files) or from Netduino forum or wiki.

I am expecting your comments and suggestions.

Cheers

Switching ON/OFF SCR thyristor (video demonstration)


(visit  the first or second post in this series)

In previous post, I explained how the schematic works. To illustrate this in action, I have added a LED in series with 150Ω resistor as load and wrote a wee application that controls the thyristor.

For those of you that may wonder where this becomes practical: the goal of this project is to switch on or off the power of any schematic, attached and controlled by Netduino. One example is the problem when you power Netduino and a motor driving schema starts the motor just because Netduino pins are in a high state. You can list here as many other cases you want. The solution I am showing here, allows you to control the power (like electronic power switch) of any such schematic. Just consider SCR cathode as + end of a power supply. Of course, you can consume only what Netduino’s 5V pin can give you so check the specs.

Full explanation of how schematic works will be available soon inside the tutorial (code files) posted at Netduino forum and wiki.

Switching ON/OFF SCR thyristor


 

(visit  the first or third post in this series)

In previous post, I showed a schematic able to switch ON/OFF SCR. You may wonder how that is possible. Well here is the explanation.

The SCR I used is C106D, which is a sensitive gate thyristor. Those ones have ability to increase their holding current when their gate is negative biased like this:

SCR Negative bias

SCR holding current increases reciprocal to the resistance – smaller resistor increases holding current more than a bigger resistor. In proposed schema

SCR with NPN switch

There is no such resistor as discreet element, but still there is a tiny resistance of the transistor’s collector-emitter junction. Because this resistance is very low, we increase holding current quite significantly. This on other side means, that there will be no enough holding current to keep SCR open when we remove triggering signal from the gate.

We have to be very careful not to burn the transistor, as we will expose it (even this will be for very short period) to current that could be higher than one it can sustain. We can use small resistor attached between the SCR gate and transistor’s collector, to eliminate this danger, but we should not add very high value resistor, because this will lower the holding current and we may lose the switching OFF ability.

Now when we send 1 (true) to transistor switch, it will open and thus cause a reverse current to flow from cathode (at that moment it will be more positive than the gate), through the gate, then sinking to the ground. As the transistor’s resistance is so small, it will make SCR holding current to rise significantly. When the current flowing through the load is below this holding current, the result is that SCR switches OFF.

For now, I will leave you to try and figure out the calculations. I am writing down all that in much more detail including the calculations and will publish it very soon inside next version of my Netduino tutorial (code files) at the forum and wiki.

Last thing to mention is that I successfully tested the schematic with different sensitive gate SCR – MCR22-6.

(visit the first or third post in this series)

Multithreading with Netduino and .NET Microframework – part 3


(to part 1, part 2 or part 4)

In addition to the previously mentioned methods for synchronisation of threads, Microframework provided two classes to do this, using events: AutoResetEvent and ManualResetEvent. Both classes inherit WaitHandle and only differ by the fact that you have to manually reset status when using ManualResetEvent. Let’s see some examples of using those classes:

public class Program
{
     // Initialise auto reset event with not signalled (false) initial state
     private static AutoResetEvent autoResetEvent = new AutoResetEvent(false);

     static void Main()
     {
          Thread someThread = new Thread(SomeMethod);
          someThread.Start();
          ...
          // Waiting for thread's notification
          autoResetEvent.WaitOne();
          ...
          // This is auto reset event so no reset is required
          someThread.Start();
          autoResetEvent.WaitOne();
          ...
     }

     private static void SomeMethod()
     {
          ...
          // Send notification
          autoResetEvent.Set();
     }
}

or

public class Program
{
     // Initialise manual reset event with not signalled (false) initial state
     private static ManualResetEvent namualResetEvent = new ManualResetEvent(false);

     static void Main()
     {
          Thread someThread = new Thread(SomeMethod);
          someThread.Start();
          ...
          // Waiting for thread's notification
          namualResetEvent.WaitOne();
          ...
          // This is manual reset event so reset is required
          namualResetEvent.Reset();
          someThread.Start();
          namualResetEvent.WaitOne();
          ...
     }

     private static void SomeMethod()
     {
          ...
          // Send notification
          namualResetEvent.Set();
     }
}

WaitHandle class (thus both AutoResetEvent and ManualResetEvent classes too) have two more interesting and flexible methods – WaitAll() and WaitAny(). First waits for all the elements in the specified array to receive a signal and second waits for any of the elements to receive a signal. Note that they accept array of WaithHandles thus way you can create and work with many threads and synchronise between them. Both methods has overrides that allow specifying the number of milliseconds to wait and parameter to specify shall thread(s) to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it afterwards.

You can set the thread priority using ThreadPriority enumeration and check thread status using ThreadState enumeration. TheadState allows you to perform bitwise operations so you can check for multiple statuses:

if (someThread.ThreadState == (ThreadState.Suspended | ThreadState.Stopped))
{
     ...
}

Lastly, we must not leave Timer class without attention 🙂 This is very useful class that “Provides a mechanism for executing a method at specified intervals”. It is simple as it states. Timer’s constructor uses TimerCallback delegate for the method you want to execute and there are two handy overrides, which allow us to specify times intervals using int (in milliseconds) or TimeSpan. The second parameter is also useful in case you want to pass additional information to the executed method. Keep it null if no information is to be passed.

public class Program
{
     static void Main()
     {
          // Initial delay 5s, invoke every 1 second after that
          var someTimer = new Timer(new TimerCallback(SomeMethod), "Some data", 5000, 1000);
          // Or
          //var someTimer = new Timer(new TimerCallback(SomeMethod), "Some data", new TimeSpan(0, 0, 0, 5), new TimeSpan(0, 0, 0, 1));
          ...
          Console.ReadLine();
     }

     private static void SomeMethod(object data)
     {
          ...
          Console.WriteLine((string)data);
          ...
     }
}

One good thing about last version Microframework is that we can use lambda expressions:

public class Program
{
     static void Main()
     {
          var someTimer = new Timer(new TimerCallback(
               (object data) =>
               {
                    Console.WriteLine((string)data);
               }),
               "Some data", new TimeSpan(0, 0, 0, 5), new TimeSpan(0, 0, 0, 1));
          ...
          Console.ReadLine();
     }
}

Last note to take is that Microframework’s System.Threading namespace does not implement all the classes of the full .NET framework System.Threading.

(to part 1, part 2 or part 4)