BluetoothWrite - locking up NXT
Posted: 20 Feb 2012, 23:57
As a continuation of a previous discussion, I just did some testing and here is what I am experiencing;
ignore all but the bottom right black window - that is a 'terminal' connected via bluetooth to the NXT. It uses the following code (in C#);
When I execute
in NXT-G and call the GetMail function, messages arrive depending on timing (some get lost).
Now when I execute this NXC program
I receive 6 bytes of data and the NXT get unresponsive. By that I mean I can not run the program again and see any data. And even turning the NXT off delays several minutes before it actually disconnects from USB. Menus still work, but that is about it.
So seeing how the PC code runs fine for one program, and the NXC code snippet is tiny and cause brick failure, I am at a loss.
Any help would be appreciated.
Mike
PS - did update the 'length' in the send buffer to 6 - that was an earlier screen shot in the first pic and wasn't the code that was running anyhow.
ignore all but the bottom right black window - that is a 'terminal' connected via bluetooth to the NXT. It uses the following code (in C#);
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
using System.ComponentModel;
using System.Threading;
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Handles and displays remotes messages
/// </summary>
public class RConsole
{
SerialPort BtConn;
Brush DefaultColor = Brushes.LightGreen;
Thread ReceiveThread;
ListBox listBox;
Dictionary<byte, string> StatusCodeMap;
byte[] receiveBuff = new byte[1024];
bool isNxtMail { get { return ((receiveBuff[2] == 0x02) && (receiveBuff[3] == 0x13)); } }
public RConsole(string Port, ListBox _ListBox)
{
BtConn = new SerialPort();
listBox = _ListBox;
BtConn.ReadTimeout = 1000;
BtConn.WriteTimeout = 1000;
BtConn.PortName = Port;
}
public void GetMail()
{
if (!BtConn.IsOpen)
{
ConsolePrintLine(DefaultColor, "##connection not open, get mail ignored");
return;
}
byte[] request = { 0x0, 0x0, 0x00, 0x13, 0x0A, 0x00, 0x01 }; // read slave mailbox 1 (1+9 = 0x0a), delete message ([5]=1)
request[0] = (byte)(request.Length - 2);
try
{
BtConn.Write(request, 0, request.Length);
}
catch (TimeoutException)
{
ConsolePrintLine(DefaultColor, "##write timeout");
}
}
public void OpenConnection()
{
try
{
BtConn.Open();
}
catch (Exception ex)
{
ConsolePrintLine(Brushes.Red, "##Connection open exception");
ConsolePrintLine(Brushes.Gray, ex.Message);
}
if (BtConn.IsOpen)
{
ConsolePrintLine(DefaultColor, "##Got connection");
BeginReceive();
}
else
ConsolePrintLine(Brushes.Red, "##Connection failed");
}
public void BeginReceive()
{
if (!BtConn.IsOpen)
{
ConsolePrintLine(DefaultColor, "##No connection, BeginReceive ignored");
return;
}
ReceiveThread = new Thread(new ThreadStart(ReceiveWorker));
ReceiveThread.Start();
ConsolePrintLine(DefaultColor, "##Receive thread started");
}
void ReceiveWorker()
{
try
{
while (true)
{
if (!BtConn.IsOpen)
{
ConsolePrintLine(Brushes.Yellow, "##Lost connection");
return;
}
if (BtConn.BytesToRead > 0)
{
Receive();
}
System.Threading.Thread.Sleep(100); // throttle
}
}
catch (ThreadAbortException)
{
}
}
void Receive()
{
StringBuilder t = new StringBuilder();
int bytesRead = BtConn.Read(receiveBuff, 0, receiveBuff.Length);
int msgLen = receiveBuff[0] + (receiveBuff[1] * 256); // just FYI
if (isNxtMail)
{
// mailboxes empty ?
if (receiveBuff[4] == 0) // status ok
DoGetMail();
else
if (receiveBuff[4] == 0xEC || receiveBuff[4] == 0x40)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
MainWindow.MessageText = StatusCodeToString(receiveBuff[4]);
}));
return; // no active program or no mail
}
else
{
InvokedPrintLine(DefaultColor, string.Format("##unexpected status from in NxtMail: {0}", StatusCodeToString(receiveBuff[4])));
DisplayBytes(receiveBuff, bytesRead);
return;
}
}
else
{
DisplayBytes(receiveBuff, bytesRead); // +++ for now, dump the line
//while (receiveBuff[i] != 0x0)
// t.Append((char)receiveBuff[i++]); // not mail, print it as a string
//InvokedPrintLine(Brushes.Gray, t.ToString());
}
}
public void Closing()
{
if (BtConn.IsOpen)
BtConn.Close();
if (ReceiveThread != null)
ReceiveThread.Abort();
}
string StatusCodeToString(byte c)
{
if (StatusCodeMap == null)
StatusCodeMapInit();
if (StatusCodeMap.ContainsKey(c))
return StatusCodeMap[c];
else
return string.Format("invalid status code {02X}", c);
}
void StatusCodeMapInit()
{
StatusCodeMap = new Dictionary<byte, string>();
StatusCodeMap.Add(0x20, "Pending communication transaction in progress");
StatusCodeMap.Add(0x40, "Specified mailbox queue is empty");
StatusCodeMap.Add(0xBD, "Request failed (i.e. specified file not found)");
StatusCodeMap.Add(0xBE, "Unknown command opcode");
StatusCodeMap.Add(0xC0, "Data contains out-of-range values");
StatusCodeMap.Add(0xDD, "Communication bus error ");
StatusCodeMap.Add(0xDE, "No free memory in communication buffer");
StatusCodeMap.Add(0xDF, "Specified channel/connection is not valid");
StatusCodeMap.Add(0xE0, "Specified channel/connection not configured or busy");
StatusCodeMap.Add(0xEC, "No active program");
StatusCodeMap.Add(0xED, "Illegal size specified");
StatusCodeMap.Add(0xEE, "Illegal mailbox queue ID specified");
StatusCodeMap.Add(0xEF, "Attempted to access invalid field of a structure");
StatusCodeMap.Add(0xF0, "Bad input or output specified");
StatusCodeMap.Add(0xFB, "Insufficient memory available");
StatusCodeMap.Add(0xFF, "Bad arguments");
}
private void DisplayBytes(byte[] Buff, int Length)
{
StringBuilder displayLines = new StringBuilder();
for (int i = 0; i < Length; i++)
{
if ((i) % 24 == 0)
displayLines.Append('\n');
else if ((i) % 4 == 0)
displayLines.Append(' ');
displayLines.Append(Buff[i].ToString("X2"));
}
if ((Length + 1) % 24 != 0)
displayLines.Append('\n');
string[] lines = displayLines.ToString().Split('\n');
foreach (string line in lines)
InvokedPrintLine(Brushes.Gray, line);
}
void DoGetMail()
{
string t;
Brush color = Brushes.Gray;
int textLength = receiveBuff[6] - 1; //cause it includes terminating 0x00
StringBuilder s = new StringBuilder(textLength);
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
MainWindow.MessageText = string.Format("you got NXTG mail length({0}):", textLength);
}));
for (int i = 0; i < textLength; i++)
s.Append((char)receiveBuff[7 + i]);
t = s.ToString();
if (t.Substring(0, 1) == "]")
{
Console.Clear();
return;
}
// if the second character is a ':' assume the first is a msg level
if (t.Substring(1, 1) == ":")
{
switch (t.Substring(0, 1))
{
case "W":
color = Brushes.Yellow;
break;
case "I":
color = Brushes.Cyan;
break;
case "E":
color = Brushes.Red;
break;
}
}
InvokedPrintLine(color, t);
}
public void ConsolePrintLine(Brush Color, string T)
{
ScrollViewer sv;
TextBlock t = new TextBlock();
t.Text = T;
t.Foreground = Color;
int i = listBox.Items.Add(t);
sv = FindVisualChild<ScrollViewer>(listBox);
if (sv != null)
sv.ScrollToBottom();
}
void InvokedPrintLine(Brush color, string t) // run on the GUI thread
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
ConsolePrintLine(color, t);
}));
}
// helps to find if scrollbar in a listbox
childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
{
return (childItem)child;
}
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
}
}
in NXT-G and call the GetMail function, messages arrive depending on timing (some get lost).
Now when I execute this NXC program
I receive 6 bytes of data and the NXT get unresponsive. By that I mean I can not run the program again and see any data. And even turning the NXT off delays several minutes before it actually disconnects from USB. Menus still work, but that is about it.
So seeing how the PC code runs fine for one program, and the NXC code snippet is tiny and cause brick failure, I am at a loss.
Any help would be appreciated.
Mike
PS - did update the 'length' in the send buffer to 6 - that was an earlier screen shot in the first pic and wasn't the code that was running anyhow.