суббота, 26 сентября 2009 г.

Freeduino Motor Shield



Наконец дошли руки до Motor Shield.
Решил осуществить управление машинкой игровым геймпадом через компьютер.
Реализовал в двух вариантах: через COM порт и через сеть Ethernet.

Вот скетч управления моторчиками машинки через COM порт:



#include
int incomingByte = 0;
int dirbpinB = 7; // up&down Direction pin for motor B is Digital 12
int speedbpinB = 6; // up&down Speed pin for motor B is Digital 9 (PWM)
int dirbpinA =4; //left&right Direction pin for motor A is Digital 13
int speedbpinA = 5; //left&right Speed pin for motor A is Digital 10 (PWM)
int speedB = 255; //Speed up&down
int speedA = 255; //Speed left&right
int up = 0; //up
int dw = 1; //dw
int lf = 0; //left
int rg = 1; //right

void setup()
{
pinMode(dirbpinA, OUTPUT);
pinMode(dirbpinB, OUTPUT);
Serial.begin(9600);
}

void loop()
{
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();

switch (incomingByte) {
case '1': // up
digitalWrite(dirbpinB, up);
analogWrite(speedbpinB, speedB);
delay(100);
break;
case '2': //down
digitalWrite(dirbpinB, dw);
analogWrite(speedbpinB, speedB);
delay(100);
break;
case '3': //left
digitalWrite(dirbpinA, lf);
analogWrite(speedbpinA, speedA);
delay(100);
break;
case '4': //right
digitalWrite(dirbpinA, rg);
analogWrite(speedbpinA, speedA);
delay(100);
break;

}

}
else{
analogWrite(speedbpinA, 0);
analogWrite(speedbpinB, 0);
}

}



Поясню. Ввиду того что я собирался подключать к Arduino еще и NKC Ethernet Shield for Arduino.
Я отвел для мотор шилда 4, 5, 6 и 7 цифровые контакты. Хотя следовал конечно использовать 13, 12 , 10 и 9. Но Ethernet Shield тоже использует 13 и 10 контакты.
Т.е. 4, 5, 6, 7 и контакты Arduino я подсоединил к 13, 10, 9, 12 контактам мотор шилда соответственно.

Для того что бы задействовать, для управления машинкой, геймпад я написал программу на C#. Т.е. нашел хороший пример на codeproject и чуть его переделал.
По сути я там исправил всего один файл frmMain.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace JoystickSample
{
public partial class frmMain : Form
{
private JoystickInterface.Joystick jst;
private SerialPort sp = new SerialPort();

public frmMain()
{
InitializeComponent();
}

private void frmMain_Load(object sender, EventArgs e)
{
// grab the joystick
jst = new JoystickInterface.Joystick(this.Handle);
string[] sticks = jst.FindJoysticks();
jst.AcquireJoystick(sticks[0]);

// add the axis controls to the axis container
for (int i = 0; i < jst.AxisCount; i++)
{
Axis ax = new Axis();
ax.AxisId = i + 1;
flpAxes.Controls.Add(ax);
}

// add the button controls to the button container
for (int i = 0; i < jst.Buttons.Length; i++)
{
JoystickSample.Button btn = new Button();
btn.ButtonId = i + 1;
btn.ButtonStatus = jst.Buttons[i];
flpButtons.Controls.Add(btn);
}

// start updating positions
tmrUpdateStick.Enabled = true;

if (!sp.IsOpen)
{
sp.PortName = "COM12";
sp.BaudRate = 9600;

try
{
sp.Open();
}
catch
{

}

}
}

private void tmrUpdateStick_Tick(object sender, EventArgs e)
{
// get status
jst.UpdateStatus();

// update the axes positions
foreach (Control ax in flpAxes.Controls)
{
if (ax is Axis)
{
switch (((Axis)ax).AxisId)
{
case 1:
((Axis)ax).AxisPos = jst.AxisA;
break;
case 2:
((Axis)ax).AxisPos = jst.AxisB;
break;
case 3:
((Axis)ax).AxisPos = jst.AxisC;
if (jst.AxisC == 65535)
{ sp.Write("4"); }
if (jst.AxisC == 0)
{ sp.Write("3"); }
break;
case 4:
((Axis)ax).AxisPos = jst.AxisD;
if (jst.AxisD == 65535)
{ sp.Write("1"); }
if (jst.AxisD == 0)
{ sp.Write("2"); }
break;
case 5:
((Axis)ax).AxisPos = jst.AxisE;
break;
case 6:
((Axis)ax).AxisPos = jst.AxisF;
break;
}
}
}

// update each button status
foreach (Control btn in flpButtons.Controls)
{
if (btn is JoystickSample.Button)
{
((JoystickSample.Button)btn).ButtonStatus =
jst.Buttons[((JoystickSample.Button)btn).ButtonId - 1];
}
}
}
}
}


С управленим через COM все.
Тепер осуществление управления через Ethernet.
Для этого подключим к Arduino помимо мотор шилда еще и Ethernet Shield.
Скетч:



#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 7 };
byte gateway[] = { 192, 168, 0, 1 };
byte subnet[] = { 255, 255, 255, 0 };
Server server(23);
int incomingByte = 0;
int dirbpinB = 7; // up&down Direction pin for motor B is Digital 12
int speedbpinB = 6; // up&down Speed pin for motor B is Digital 9 (PWM)
int dirbpinA = 4; //left&right Direction pin for motor A is Digital 13
int speedbpinA = 5; //left&right Speed pin for motor A is Digital 10 (PWM)
int speedB = 255; //Speed up&down
int speedA = 255; //Speed left&right
int up = 0; //up
int dw = 1; //dw
int lf = 0; //left
int rg = 1; //right

void setup()
{
pinMode(dirbpinA, OUTPUT);
pinMode(dirbpinB, OUTPUT);
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
}

void loop()
{
Client client = server.available();
if (client) {
// read the incoming byte:
incomingByte = client.read();

switch (incomingByte) {
case '1': //up
digitalWrite(dirbpinB, up);
analogWrite(speedbpinB, speedB);
delay(200);
break;
case '2': //dw
digitalWrite(dirbpinB, dw);
analogWrite(speedbpinB, speedB);
delay(200);
break;
case '3': //left
digitalWrite(dirbpinA, lf);
analogWrite(speedbpinA, speedA);
delay(200);
break;
case '4': //right
digitalWrite(dirbpinA, rg);
analogWrite(speedbpinA, speedA);
delay(200);
break;


}
else{
analogWrite(speedbpinA, 0);
analogWrite(speedbpinB, 0);
}

}



И подправленный файл frmMain.cs из проекта:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Net.Sockets;
using System.Net;

namespace JoystickSample
{
public partial class frmMain : Form
{
private JoystickInterface.Joystick jst;
static string hostName;
static int port;
Socket socket;
public frmMain()
{
InitializeComponent();
}

private void frmMain_Load(object sender, EventArgs e)
{
// grab the joystick
jst = new JoystickInterface.Joystick(this.Handle);
string[] sticks = jst.FindJoysticks();
jst.AcquireJoystick(sticks[0]);

// add the axis controls to the axis container
for (int i = 0; i < jst.AxisCount; i++)
{
Axis ax = new Axis();
ax.AxisId = i + 1;
flpAxes.Controls.Add(ax);
}

// add the button controls to the button container
for (int i = 0; i < jst.Buttons.Length; i++)
{
JoystickSample.Button btn = new Button();
btn.ButtonId = i + 1;
btn.ButtonStatus = jst.Buttons[i];
flpButtons.Controls.Add(btn);
}

// start updating positions
tmrUpdateStick.Enabled = true;

port = 23;
hostName = Dns.GetHostName();

try
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
string IPserv = "192.168.0.7";
IPHostEntry host = Dns.GetHostEntry(hostName);
IPEndPoint point = new IPEndPoint(IPAddress.Parse(IPserv), port);// Задайте 2 параметра (IPAdress и порт)
socket.Connect(point); // Подключите разъем к точке point

// Console.WriteLine("Connected to {0}\n", socket.RemoteEndPoint.ToString());


}
catch //(Exception ex)
{
//Console.WriteLine(ex.Message);
}
//Console.ReadKey(true);

}

private void tmrUpdateStick_Tick(object sender, EventArgs e)
{
// get status
jst.UpdateStatus();

// update the axes positions
foreach (Control ax in flpAxes.Controls)
{
if (ax is Axis && socket.Connected)
{
switch (((Axis)ax).AxisId)
{
case 1:
((Axis)ax).AxisPos = jst.AxisA;
break;
case 2:
((Axis)ax).AxisPos = jst.AxisB;
break;
case 3:
((Axis)ax).AxisPos = jst.AxisC;
if (jst.AxisC == 65535)
{
byte[] msg = Encoding.ASCII.GetBytes("4");
socket.Send(msg);
}

if (jst.AxisC == 0)
{
byte[] msg = Encoding.ASCII.GetBytes("3");
socket.Send(msg);
}
break;
case 4:
((Axis)ax).AxisPos = jst.AxisD;
if (jst.AxisD == 65535)
{
byte[] msg = Encoding.ASCII.GetBytes("1");
socket.Send(msg);
}
if (jst.AxisD == 0)
{
byte[] msg = Encoding.ASCII.GetBytes("2");
socket.Send(msg);
}
break;
case 5:
((Axis)ax).AxisPos = jst.AxisE;
break;
case 6:
((Axis)ax).AxisPos = jst.AxisF;
break;
}
}
}

// update each button status
foreach (Control btn in flpButtons.Controls)
{
if (btn is JoystickSample.Button)
{
((JoystickSample.Button)btn).ButtonStatus =
jst.Buttons[((JoystickSample.Button)btn).ButtonId - 1];
}
}
}
}
}

В таком виде все прекрасно работет.
Хотя в данном случае стоит релиазовать подключение через Ethernet не по TCP, а по UDP