Main Site Documentation

Reflashing a malfunctioned bluetooth module


#1

Hello,
I have two GHI Bluetooth modules, one is working the other was observed spitting bad chars on the serial interface. the module is connected properly to the right port (2 or 6).

I excluded the chances that this is a cable error and reached to the conclusion that the module is bad. the module itself powers up and had the blue LED blinking (the red LED one isn’t) and is to some extent “talks” gibbrish to the mainboard.

if i didn’t had another Bluetooth module it wasn’t that easy but i know it’s bad.

my question is: is there an option to reflash the firmware on that bluetooth module? (how?)what other options do i have before i declare it “broken” ?

thanks!


#2

Welcome to the forum, mvalenci !!

Apparently the BT modules will remember a change in baud rate, so you should try to connect to it via baud rates you’ve used in the past. Garbled characters is exactly what you get at incorrect baud rates.

Good luck - I’d say it’s far from dead and you’ll have no problem resurrecting it !


#3

@ Brett - thanks for the response, you seem to be right.
the device was shipped with the speed of 460800 and I had to reconfigure it to it’s default which is 38400.

the only way to get out of this sttuation was to modify and recompile Bluetooth.cs source from:
https://gadgeteer.svn.codeplex.com/svn/Main/Modules/GHIElectronics/Bluetooth/Software/Bluetooth/Bluetooth_42/

It seems like there is a bug in the code:
the default constructor always starts with the speed of 38400 and the constructor that gets the baud setting does not pass the setting to the GTI.Serial class.
this would mean that if the speed of the module was changed, you are locked out and cannot even call SetDeviceBaud() because the device might never be in synch.

it seems that a fix would needs to go to the constructor that gets the baud, and pass it to the to take the speed as is.

how does this code being maintained? (i have other proposed fixes)

thanks


#4

As the person who contributed the code for the variable baud rate, I’m all ears !


            // Poundy added:
            Thread.Sleep(5);
            this.SetDeviceBaud(baud);
            this.serialPort.Flush();
            this.serialPort.Close();
            this.serialPort.BaudRate = (int)baud;
            this.serialPort.Open();
            // Poundy 

As you can see, it DOES change the serial port’s baud rate to the provided rate, but it opens the port earlier at the ORIGINAL speed of 38400. The testing I did on one module alone seemed to be fine for this approach - but this is now the 2nd or 3rd report where this hasn’t stayed the same. I wonder if my testing was bogus or whether the module firmware now remembers it’s baud rate change?


#5

[ul]it looks like the module remembers the speed settings as you mentioned.
please note that while the constructor calls SetDeviceBaud() the device may not get the command if it is waken up in a diffrent speed setting.
should the SetDeviceBaud() be changed and modify the Serial object settings?

some code fixes proposed:
a cosmetic fix to SetDeviceBaud() below:
an improvement to the code that peeks for a command from the serial. the code breaks the input by ‘\n’ and allows better parsing of commands that might be broken in the old code due to underrun.
[/ul]


public void SetDeviceBaud(long baud)
{
    switch (baud)
    {
        case 9600:
        case 19200:
        case 38400:
        case 57600:
        case 115200:
        case 230400:
        case 460800:
            break;
        default:
            return;
    }

    this.serialPort.Write("\r\n+STBD=" + baud + "\r\n");
    //todo: check it is working?! Probably should check the return code and do something about it. in the meantime,
    //todo: need to change serial speed?
    Thread.Sleep(500);
}

private String readData()
{
    String response = "";
    int timeout = 0;

    while (true)
    {
        while (serialPort.BytesToRead > 0)
        {
            char c = (char)serialPort.ReadByte();
            response = response + c;
            if (c == '\n')
                return response;
        }

        if (response.Length > 0)
        {
            timeout++;
            if (timeout > 100) // timeout for the command to arrive
                break;
        }
        Thread.Sleep(1);
    }

    return response;
}



private void runReaderThread()
{
    Debug.Print("Reader Thread");

    while (true)
    {
        try
        {
            String response = readData();
            if (response.Length > 0)
            {
                bool isCommand = parseCommand(response);
                if (!isCommand)
                {
                    OnDataReceived(this, response);
                }
            }
        }
        catch (Exception e)
        {
            Debug.Print("Exception: " + e.Message);
            Debug.Print("Stack: " + e.StackTrace);
        }
    }
} 


#6

Hi,
which Mainboard do you use?
Regards
Roland


#7

The speed setting does not seem to be related to my board (FEZ Cerderus) - because one BT mudule worked in a certain speed, and the other BT module worked in abother speed.

one more thing…
i’d recommend adding to the init code a function that auto detects the module speed.


#8

@ mvalenci -
Hi,
you are right, the speed setting has nothing to do with the type of the board. You are also quite right with your analysis in your post #2.
I have made a modification of the constructor that automatically switches to the baudrate selected at the call of the constructor.
https://www.ghielectronics.com/community/forum/topic?id=12192&page=2
This modification only works on the spider mainboard and not on Cerbuino Bee (and Cerberus I think) since on the cerbuino Bee the messages (BTSTATE) from the BT-module arrive in chunks from the serial port (are splitted) and the module driver, as it is now, does not consider this fact while parsing the arriving data for BT-STATE messages.
Regards
Roland


#9

please note that the code I posted - especially readData() would wait 100 mili for a command to arrive (or break as soon as it arrived).
should this code be more appropriate for all the platforms?

also, please note the try-catch phrase around the code that parses the commands from the module. i could find cases where the thread contained bugs in the parsing and committed suicide …
parsing is difficult, so always wrap it with try-catch and don’t let the user who uses this class scratch their heads in trying to understand “why does this thing dies on me…”


#10

Hi,
I didn´t read your code thoroughly yet. Interesting approach. I used another approach, namely to write the incoming data in a circular buffer, from where I read them if a complete message ending with 0x0A has arrived. But I am still struggling with the bugs.


#11

no need to use cyclic buffer, this might make some other parsing issues.
here are some code snippets that could help you:

some keypoints to note:

[ul]
always use try-catch to surround your parser so the thread won’t die (the parser isn’t that good)
break the commands by ‘\n’ to allow simpler parsing
add a read timeout to handle lagging
[/ul]


        /// <summary>
        /// Thread that continuously reads incoming messages from the module,
        /// parses them and triggers the corresponding events.
        /// </summary>
        private int readData(char []buffer, int offset, int length)
        {
            int timeout = 0;
            int count = 0;

            while(true)
            {
                while (serialPort.BytesToRead > 0)
                {
                    char c = (char)serialPort.ReadByte();
                    buffer[offset + count] = c;
                    count++;
                    if (c == '\n' || count == length)
                        return count;
                    timeout = 0;
                }

                if (count > 0)
                {
                    timeout++;
                    if (timeout > 100)
                        break;
                }
                Thread.Sleep(1);
            }

            return count;
        }

        /// <summary>
        /// Tries to parse a command (returns false if the parsing fails)
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        bool parseCommand(String response)
        {
            //Debug.Print(response);

            //Check Bluetooth State Changed
            if (response.IndexOf("+BTSTATE:") > -1)
            {
                string atCommand = "+BTSTATE:";

                //String parsing  
                // Return format: +COPS:<mode>[,<format>,<oper>]
                int first = response.IndexOf(atCommand) + atCommand.Length;
                int last = response.IndexOf("\n", first);
                int state = int.Parse(((response.Substring(first, last - first)).Trim()));

                OnBluetoothStateChanged(this, (BluetoothState)state);

                return true;
            }
            //Check Pin Requested
            if (response.IndexOf("+INPIN") > -1)
            {
                // EDUARDO : Needs testing
                OnPinRequested(this);
                return true;
            }
            if (response.IndexOf("+RTINQ") > -1)
            {
                //EDUARDO: Needs testing

                string atCommand = "+RTINQ=";
                //String parsing  
                int first = response.IndexOf(atCommand) + atCommand.Length;
                int mid = response.IndexOf(";", first);

                int last = response.IndexOf("\r", first);

                // Keep reading until the end of the message
                while (last < 0)
                {
                    while (serialPort.BytesToRead > 0)
                    {
                        response = response + (char)serialPort.ReadByte();
                    }
                    last = response.IndexOf("\r", first);
                }

                string address = ((response.Substring(first, mid - first)).Trim());

                string name = (response.Substring(mid + 1, last - mid));

                OnDeviceInquired(this, address, name);
                //Debug.Print("Add: " + address + ", Name: " + name );

                return true;
            }

            return false;
        }



        /// <summary>
        /// converts a char array to string (is there a native way in .net micro ?)
        /// </summary>
        /// <param name="buffer">buffer</param>
        /// <param name="offset">start offset</param>
        /// <param name="length">length</param>
        /// <returns></returns>
        static private String buf2String(char[] buffer, int offset, int length)
        {
            String response = "";
            for (int i = 0; i < length; i++)
                response += buffer[offset + i];
            return response;
        }

        /// <summary>
        /// Thread that continuously reads incoming messages from the module,
        /// parses them and triggers the corresponding events.
        /// </summary>
        private void runReaderThread()
        {
            Debug.Print("Reader Thread");

            char[] inputBuffer = new char[128];

            while (true)
            {
                try
                {
                    int rxBytes = readData(inputBuffer, 0, inputBuffer.Length);
                    if (rxBytes > 0) {
                        String response = buf2String(inputBuffer, 0, rxBytes);
                        bool isCommand = parseCommand(response);
                        if (!isCommand) {
                            OnDataReceived(this, response);
                        }
                    }
                }
                catch (Exception e) {
                    Debug.Print("Exception: " + e.Message);
                    Debug.Print("Stack: " + e.StackTrace);
                }
            }
        }



#12

Thanks, that looks promising. Did you write this code at the moment or did you already use it earlier in other applications?
I’ll try your code as soon as i get time.
Regards Roland