Main Site Documentation

(SOLVED) Code runs while debugging but not standalone


#1

Hi Guys,

I have a strange problem. While I’m waiting for some parts to arrive to start building a remote controlled / autonomous feeder boat I thought I’d start writing up some code for the GPS. After sorting out a couple of problems with the buffer and serialport I have the gps spitting out the data and an xbee sending it over remotely to my computer (xbee hooked to an ardiuno). Everything works great when I’m debugging it in visual studio. However, when I unplug the board and hook it up to a battery it doesn’t do anything.

Anyone have an idea why?

Runinng on a FEZ Domino:

Program:


using System;
using System.IO.Ports;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Text;
using System.Threading;

namespace GPS_Data
{
    public class Program
    {
        public static SerialPort xbee = new SerialPort("COM1", 115200);

        public static void Main()
        {
            Debug.EnableGCMessages(false);
            Logger.OnLog += new Logger.LogCallback(Logger_OnLog);

            GPS gps = new GPS("COM2", 4800);
            gps.Open();
            Thread.Sleep(1000);
            xbee.Open();
            Thread.Sleep(1000);

            while (true)
            {
                Thread.Sleep(1000);
            }

            //gps.Close();
        }

        static void Logger_OnLog(string Data)
        {
            if (xbee.IsOpen)
            {
                //Debug.Print(Data);
                byte[] helloBytes = Encoding.UTF8.GetBytes(Data);
                xbee.Write(helloBytes, 0, helloBytes.Length);
            }
        }
    }
}

GPS Class:


using System;
using System.IO.Ports;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Text;

namespace GPS_Data
{
    public class GPS
    {
        SerialPort serialPort = null;
        SerialBuffer serialBuffer = new SerialBuffer(70);

        public GPS(string Port, int BaudRate)
        {
            serialPort = new SerialPort(Port, BaudRate);
            serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
            serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
        }

        public void Open()
        {
            if (serialPort != null)
                serialPort.Open();
        }

        public void Close()
        {
            if (serialPort != null)
                if(serialPort.IsOpen)
                    serialPort.Close() ;
        }

        byte[] buffer = new byte[10];
        void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            serialBuffer.LoadSerial(serialPort);
            string dataLine;
            for (int i = 0; i < 100; i++)
            {
                while ((dataLine = serialBuffer.ReadLine()) != null)
                {
                    Logger.Log(dataLine);
                }
            }
        }

        void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            Logger.Log(e.EventType.ToString());
        }
    }
}

Logger Class:


using System;
using System.Text;

namespace GPS_Data
{
    /// <summary>
    /// This is a event based logger
    /// and is available through out the whole project
    /// </summary>
    public static class Logger
    {
        public delegate void LogCallback(string Data);
        public static event LogCallback OnLog;

        public static void Log(string data)
        {
            if (OnLog != null)
            {
                OnLog(data);
            }
        }
    }
}

SerialBuffer:


using System;
using System.IO.Ports;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Text;

namespace GPS_Data
{
    public class SerialBuffer
    {
        private System.Text.Decoder decoder = System.Text.UTF8Encoding.UTF8.GetDecoder();
        private byte[] buffer;
        private int startIndex = 0;
        private int endIndex = 0;
        private char[] charBuffer;

        public SerialBuffer(int initialSize)
        {
            buffer = new byte[initialSize];
            charBuffer = new char[256];
        }

        public void LoadSerial(SerialPort port)
        {
            int bytesToRead = port.BytesToRead;
            if (buffer.Length < endIndex + bytesToRead) // do we have enough buffer to hold this read?
            {
                // if not, look and see if we have enough free space at the front
                if (buffer.Length - DataSize >= bytesToRead)
                {
                    ShiftBuffer();
                }
                else
                {
                    // not enough room, we'll have to make a bigger buffer
                    ExpandBuffer(DataSize + bytesToRead);
                }
            }
            //Debug.Print("serial buffer load " + bytesToRead + " bytes read, " + DataSize + " buffer bytes before read");
            port.Read(buffer, endIndex, bytesToRead);
            endIndex += bytesToRead;

        }


        private void ShiftBuffer()
        {
            // move the data to the left, reclaiming space from the data already read out
            Array.Copy(buffer, startIndex, buffer, 0, DataSize);
            endIndex = DataSize;
            startIndex = 0;
        }

        private void ExpandBuffer(int newSize)
        {
            byte[] newBuffer = new byte[newSize];
            Array.Copy(buffer, startIndex, newBuffer, 0, DataSize);
            buffer = newBuffer;
            endIndex = DataSize;
            startIndex = 0;
        }

        public byte[] Buffer
        {
            get
            {
                return buffer;
            }
        }

        public int DataSize
        {
            get
            {
                return endIndex - startIndex;
            }
        }

        public string ReadLine()
        {
            lock (buffer)
            {
                int lineEndPos = Array.IndexOf(buffer, '\n', startIndex, DataSize);  // HACK: not looking for \r, just assuming that they'll come together        
                if (lineEndPos > 0)
                {
                    int lineLength = lineEndPos - startIndex;
                    if (charBuffer.Length < lineLength)  // do we have enough space in our char buffer?
                    {
                        charBuffer = new char[lineLength];
                    }
                    int bytesUsed, charsUsed;
                    bool completed;
                    decoder.Convert(buffer, startIndex, lineLength, charBuffer, 0, lineLength, true, out bytesUsed, out charsUsed, out completed);
                    string line = new string(charBuffer, 0, lineLength);
                    startIndex = lineEndPos + 1;
                    //Debug.Print("found string length " + lineLength + "; new buffer = " + startIndex + " to " + endIndex);
                    return line;
                }
                else
                {
                    return null;
                }
            }
        }
    }
}


#2

It sounds like the battery is not supplying enough power to drive your board, GPS and Xbee. What type of battery are you using? You might try a power adapter 7-12V and see if that works.


#3

I’m actually using a powermonkey explorer to power the board through the usb port. That might be the problem. Will try with a power adapter tonight. I’ll let you know what happens.


#4

You must open the port before subscribing to events
see this http://www.fezzer.com/project/47/gps-extension/

static public void Initialize()
            {
                _port = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
                _port.ReadTimeout = 0;
                _port.ErrorReceived += new SerialErrorReceivedEventHandler(_port_ErrorReceived);
                _port.Open();// If you open the port after you set the event you will endup with problems
                _port.DataReceived += new SerialDataReceivedEventHandler(_port_DataReceived);
            }

#5

Thanks Gus.

Changed the code and it works like a charm.

Cheers

Changed the GPS Class:

using System;
using System.IO.Ports;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Text;

namespace GPS_Data
{
    public class GPS
    {
        SerialPort serialPort = null;
        SerialBuffer serialBuffer = new SerialBuffer(70);

        public GPS(string Port, int BaudRate)
        {
            serialPort = new SerialPort(Port, BaudRate);
        }

        public void Initialize()
        {
            serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
            Open();
            serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
        }

        private void Open()
        {
            if (serialPort != null)
                serialPort.Open();
        }

        public void Close()
        {
            if (serialPort != null)
                if(serialPort.IsOpen)
                    serialPort.Close() ;
        }

        byte[] buffer = new byte[10];
        void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            serialBuffer.LoadSerial(serialPort);
            string dataLine;
            for (int i = 0; i < 100; i++)
            {
                while ((dataLine = serialBuffer.ReadLine()) != null)
                {
                    Logger.Log(dataLine);
                }
            }
        }

        void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            Logger.Log(e.EventType.ToString());
        }
    }
}

Now gives me this as output on the pc:

$GPGSA,A,3,04,20,23,32,07.6,04.8,05.905
$GPGSV,3,1,12,02,07,312,00,04,37,301,43,10,07,271,00,11,18,159,27
7B
$GPGSV,3,2,12,12,01,327,00,13,42,205,30,17,28,236,25,20,60,090,457F
$GPGSV,3,3,12,23,72,169,45,24,08,140,26,25,04,002,00,31,25,047,34
7E
$GPRMC,180555,A,5241.2485,N,00513.7431,E,000.0,000.0,021210,A*73
$GPGGA,180556,5241.2484,N,00513.7430,E,1,04,04.8,-00015.2,M,046.6,M,*65


#6

If you need GPS, see my libs. Already done and you don’t have to deal with the huge mess that is NMEA.

http://files.chrisseto.com/1tK

See Drivers/ChrisSeto/GeoInfoSystems


#7

Bakkie:

I noticed the different between the Open() method in GPS Class.
The revised one is

        
private void Open()
{
   if (serialPort != null)
        serialPort.Open();
  }

is this supposed to be

public void Open() 

???


#8

“You must open the port before subscribing to events”

If you open port before you subscribe, is not possible to miss the first event?


#9

I might be slow, but can someone explain to me why the original program worked in debug mode and failed when powered by a battery?
This would be good to know.


#10

I doubt anyone knows the cause :slight_smile: Since this has a simple work around, I do not think the guys here did look into it in details


#11

@ Sam:

My idea was that it would automaticaly open the port when initialized. But you’re right you might as well make it public so you can open it again after you close it.

@ Gier:

We we’re just starting to programm for the fez. I have no idea why it would work when in debug mode. As far as we can see it should work. Though it would be interesting to know the reason behind this we’re just gonna use the workaround.


#12

@ Chris: Thanks for the link to the code. Will look through the code in more detail later. (Kinda late right now) What are you using it for?


#13

@ Bakkie, I am using it for an autopilot.