Sarah Rosanna Busch
Engineering Technologist
C# Twentyfirst Century EtchSketch
This was my final project for my embedded C#/C++ course. I designed a game controller using a Netduino and external USB serial port for an Etch-A-Sketch type Windows application using Visual Studio. This project is a fun example of the unique nature of this Electronics and Computer Engineering Technlogy program, in that it incorportates circuit design, prototyping, and coding.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
/* Etch A Sketch type game that is controlled by a Netduino 3 Wifi
* through a USB module.
* Written by Sarah Busch, December 2015
* for ELEX231 final exam
* */
namespace etchSketch
{
public partial class etchSketchForm : Form
{
////////////////////////////
// Set up safe Threading //
////////////////////////////
//This delegate enables asynchronous calls for setting
//the text property on a TextBox control.
delegate void SetTextCallBack(string text);
//This thread is used to demonstrate both thread-safe and
//unsafe ways to call a Windows Forms control.
private Thread demoThread = null;
string packet;
private void ThreadProcSafe()
{
this.SetText(packet);
}
private void SetText(string text)
{
//InvokeRequired required compares the thread ID of the
//calling thread to the thread ID of the creating thread.
//If these threads are different, it returns true.
if (this.readPacket.InvokeRequired)
{
SetTextCallBack d = new SetTextCallBack(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.readPacket.Text = "";
this.readPacket.Text += text;
parsePacket();
}
}
////////////////////////////////////////////
// Establish communication with Netduino //
////////////////////////////////////////////
public etchSketchForm()
{
InitializeComponent();
String[] ports = SerialPort.GetPortNames(); //find available ports
commPort.Items.AddRange(ports); //and display them in dropdown menu
}
private void commPort_SelectedIndexChanged(object sender, EventArgs e)
{
serialPort1.PortName = commPort.Text; //default is COM4, drop down menu shows other available options
openButton.Enabled = true;
}
private void etchSketchForm_Load(object sender, EventArgs e)
{
openComm(); //opens communication with netduino on form load
}
private void openButton_Click(object sender, EventArgs e)
{
openComm(); //if comm is closed this button is activated so it can be reopened
}
private void openComm()
{
serialPort1.PortName = commPort.Text;
serialPort1.BaudRate = 115200; //matches firmware on netduino
serialPort1.Open();
openButton.Enabled = false;
closeButton.Enabled = true;
serialPort1.Write(sendPacket.Text);
}
private void closeButton_Click(object sender, EventArgs e)
{
serialPort1.Close();
openButton.Enabled = true;
closeButton.Enabled = false;
}
private void viewDebugPanelToolStripMenuItem_Click(object sender, EventArgs e)
{
debugPanel.Visible = true; //menu item makes debug panel visible
}
private void hideDebugPanelToolStripMenuItem_Click(object sender, EventArgs e)
{
debugPanel.Visible = false; //menu item hides debug panel
}
///////////////////////////////////
// Receive packet from Netduino //
///////////////////////////////////
//etchSketch variables
Point startPoint = new Point();
Point endPoint = new Point();
bool drawFlag = false;
string redLed;
string startStopBtn;
string greenLed;
string shakeBtn;
string colourBtn;
string R;
string G;
string B;
int penColour = 0;
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
packet = serialPort1.ReadLine();
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
private void parsePacket()
{
boxPacket.Text = packet.Substring(3, 3); //packet #
boxA0.Text = packet.Substring(6, 4); //left pot
boxA1.Text = packet.Substring(10, 4);
boxA2.Text = packet.Substring(14, 4);
boxA3.Text = packet.Substring(18, 4);
boxA4.Text = packet.Substring(22, 4);
boxA5.Text = packet.Substring(26, 4); //right pot
boxButton.Text = packet.Substring(30 ,1); //onboard button
boxD7.Text = packet.Substring(31, 1); //redLed
boxD6.Text = packet.Substring(32, 1); //startStopBtn
boxD5.Text = packet.Substring(33, 1); //greenLed
boxD4.Text = packet.Substring(34, 1); //shakeBtn
boxD3.Text = packet.Substring(35, 1); //colourBtn
boxD2.Text = packet.Substring(36, 1); //R
boxD1.Text = packet.Substring(37, 1); //G
boxD0.Text = packet.Substring(38, 1); //B
//assign parsed packet values to etchSketch variables
redLed = boxD7.Text;
startStopBtn = boxD6.Text;
greenLed = boxD5.Text;
shakeBtn = boxD4.Text;
colourBtn = boxD3.Text;
R = boxD2.Text;
G = boxD1.Text;
B = boxD0.Text;
}
////////////////////
// Game controls //
////////////////////
private void etchSketch() //creates graphics in response to controller
{
Graphics line = drawingPanel.CreateGraphics(); //drawing area is limited to the drawing panel
if (drawFlag == true)
{
endPoint = getPotValues();
if (penColour == 1)
{
Pen pen = new Pen(Brushes.Green);
pen.Width = 5;
line.DrawLine(pen, startPoint, endPoint);
}
else if (penColour == 2)
{
Pen pen = new Pen(Brushes.Blue);
pen.Width = 5;
line.DrawLine(pen, startPoint, endPoint);
}
else if (penColour == 3)
{
Pen pen = new Pen(Brushes.DarkViolet);
pen.Width = 5;
line.DrawLine(pen, startPoint, endPoint);
}
else
{
Pen pen = new Pen(Brushes.Red);
pen.Width = 5;
line.DrawLine(pen, startPoint, endPoint);
}
startPoint = endPoint;
}
}
private void boxD6_TextChanged(object sender, EventArgs e)
{
//drawBtn toggles start and stop drawing
parsePacket();
if (startStopBtn == "1") //buton pressed
{
if (redLed == "1") //drwing enabled
{
greenLed = "1";
redLed = "0";
drawFlag = true;
startPoint = getPotValues();
}
else //drawing disabled
{
greenLed = "0";
redLed = "1";
drawFlag = false;
}
txData(); //send data to netduino
}
}
private Point getPotValues() //pots control drawing coordinates
{
Point point = new Point(0,0);
point.X = Int32.Parse(boxA0.Text);
point.Y = Int32.Parse(boxA5.Text);
point.X /= 12; //to keep the lines in the drawingPanel
point.Y /= 12;
point.X += 10;
point.Y += 10;
pointBox.Text = point.ToString(); //display point in debug window
return point;
}
private void boxA0_TextChanged(object sender, EventArgs e)
{
etchSketch(); //when the pots are turned add to drawing
}
private void boxA5_TextChanged(object sender, EventArgs e)
{
etchSketch(); //when the pots are turned add to drawing
}
private void boxD4_TextChanged(object sender, EventArgs e)
{
//shakeBtn erases drawing
parsePacket();
if (shakeBtn == "1")
{
this.Refresh();
txData();
}
}
private void boxD3_TextChanged(object sender, EventArgs e)
{
//colourBtn toggle pen colours
if (colourBtn == "1")
{
switch(penColour)
{
case 0:
penColour = 1; //green
R = "1";
G = "0";
B = "1";
break;
case 1:
penColour = 2; //blue
R = "1";
G = "1";
B = "0";
break;
case 2:
penColour = 3; //purple
R = "0";
G = "1";
B = "0";
break;
case 3:
penColour = 0; //red
R = "0";
G = "1";
B = "1";
break;
default:
penColour = 0; //red
break;
}
txData();
}
}
private void txData() //send packet to netduino
{
int chkSum = 0;
string dataOut = "###" + redLed + startStopBtn + greenLed + shakeBtn + colourBtn + R + G + B;
//add bytes to checksum code
for (int i = 3; i < 11; i++) //does not include ###
{
chkSum += (int)dataOut[i];
}
dataOut += chkSum.ToString("d3"); //three chars
sendPacket.Text = dataOut;
serialPort1.Write(sendPacket.Text);
}
}
}