embeddedmsp430code-composerhm-10

Why HM-10 doesn't send an OK if i send AT from an MSP430 Launchpad?


I'm trying to set up an UART communication with a HM-10 chip on a Texas Instruments MSP430 Launchpad, but I ran into a very elementary problem.

What I want to achieve is to send an "AT" through UART to HM-10, and receive an answer for that. By the way this is a code I found here and I slightly modified for my purposes.

#include "msp430g2553.h"

const char string[] = { "AT" };
unsigned int i;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop the Watch dog

  //------------------- Configure the Clocks -------------------//

  if (CALBC1_1MHZ==0xFF)   // If calibration constant erased
     {
        while(1);          // do not load, trap CPU!!
     }

   DCOCTL  = 0;             // Select lowest DCOx and MODx settings
   BCSCTL1 = CALBC1_1MHZ;   // Set range
   DCOCTL  = CALDCO_1MHZ;   // Set DCO step + modulation

  //---------------- Configuring the LED's ----------------------//

   P1DIR  |=  BIT0 + BIT6;  // P1.0 and P1.6 output
   P1OUT  &= ~BIT0 + BIT6;  // P1.0 and P1.6 = 0

  //--------- Setting the UART function for P1.1 & P1.2 --------//

   P1SEL  |=  BIT1 + BIT2;  // P1.1 UCA0RXD input
   P1SEL2 |=  BIT1 + BIT2;  // P1.2 UCA0TXD output

  //------------ Configuring the UART(USCI_A0) ----------------//

   UCA0CTL1 |=  UCSSEL_2 + UCSWRST;  // USCI Clock = SMCLK,USCI_A0 disabled
   UCA0BR0   =  104;                 // 104 From datasheet table-
   UCA0BR1   =  0;                   // -selects baudrate =9600,clk = SMCLK
   UCA0MCTL  =  UCBRS_1;             // Modulation value = 1 from datasheet
   //UCA0STAT |=  UCLISTEN;            // loop back mode enabled
   UCA0CTL1 &= ~UCSWRST;             // Clear UCSWRST to enable USCI_A0

  //---------------- Enabling the interrupts ------------------//

   IE2 |= UCA0TXIE;                  // Enable the Transmit interrupt
   IE2 |= UCA0RXIE;                  // Enable the Receive  interrupt
   _BIS_SR(GIE);                     // Enable the global interrupt

   i = 0;
   UCA0TXBUF = string[i];                  // Transmit a byte

   _BIS_SR(LPM0_bits + GIE);         // Going to LPM0
}

  //-----------------------------------------------------------------------//
  //                Transmit and Receive interrupts                        //
  //-----------------------------------------------------------------------//

  #pragma vector = USCIAB0TX_VECTOR
  __interrupt void TransmitInterrupt(void)
  {
    P1OUT  ^= BIT0;//light up P1.0 Led on Tx
    if (i == sizeof string - 1)
    {
    UC0IE &= ~UCA0TXIE;
    }
    UCA0TXBUF = string[i++];
  }

  #pragma vector = USCIAB0RX_VECTOR
  __interrupt void ReceiveInterrupt(void)
  {
    // light up P1.6 LED on RX
    if (UCA0RXBUF == 'O')
    {
        P1OUT  ^= BIT6;
    }
    IFG2 &= ~UCA0RXIFG; // Clear RX flag
  }

According to the datasheet I should receive an OK answer for this command.

If there was an 'O' in the RX buffer, I would expect the LED to light up on my board, but that doesn't happen.

Using Code Composer, I also verified with adding a breakpoint to the RX interrupt that there is indeed no RX answer.

I believe this is entirely a software question, that's why I put it here. I'm using the correct rotation of jumpers(http://xanthium.in/Serial-Communication-MSP430-UART-USCI_A) and RX is wired to TX and vica versa.

I would appreciate if you could point out if I was doing anything conceptionally wrong or if I just made a mistake. Thank you!


Solution

  • I think for everyone who is working with HM-10 devices in the future I want to answer this question, because it has I think its own sort of mini-literature, which was first frustrating, but then I kind of liked the challenges it posed to me.

    Some of the problems are hardware related, so this post might need to be moved to an embedded engineering section. (Great consequence - you cannot be 100% sure before checking it with a scope)

    Know your hardware - HM-10 has tons of versions, and it turned our one needed an extra potential divider because it has a 3.3V logic level high instead of 5V. This website is a fantastic place to start. Though, ours turned out to be an MLT-BT05 which is a clone of a clone. It doesn't have iBeacon capability on its firmware, so if you don't want to power cycling, then you should probably avoid this one.

    About the coding bit the most important thing is to check with \n, \r and \n\r, as linuxfan briefly mentioned its importance above, because some of the devices need it. The best place to start is AT and if it works, then use AT+HELP and find the version, usually AT+VERSION command so you can identify with 100% certainty which chip you have.

    Currenetly it is prototyped on an Arduino, but I will include working code as soon as its finished on MSP430.

    The Arduino code:

    #include <SoftwareSerial.h>
    SoftwareSerial bluetooth(9, 10); // RX, TX
      char commandbuffer[50];
          int j = 0;
    void setup()
    {
    
      memset(commandbuffer, 0, sizeof(commandbuffer));
      analogWrite(12, 255);
      analogWrite(11, 0);
      // Start the hardware serial port
      Serial.begin(19200);
      bluetooth.begin(9600);
      // un REM this to set up a Master and connect to a Slave
    
      Serial.println("BLE CC41A Bluetooth");
      Serial.println("----------------------------------");
      Serial.println("");
      Serial.println("Trying to connect to Slave Bluetooth");
      delay(1000);
      bluetooth.println("AT"); // just a check
      delay(2000);
    
    
      bluetooth.println("AT+NAMEHIST");
      delay(2000);
      bluetooth.println("AT+ROLE0");
      delay(2000);
        bluetooth.println("AT+INQ"); // look for nearby Slave
        delay(5000);
        bluetooth.println("AT+CONN1"); // connect to it */
    }
    void loop()
    {
      bluetooth.listen();
      // while there is data coming in, read it
      // and send to the hardware serial port:
      while (bluetooth.available() > 0) {
        char inByte = bluetooth.read();
        Serial.write(inByte);
      }
      // Read user input if available.
      if (Serial.available()) {
        delay(10); // The DELAY!
        char temp = Serial.read();
        if (temp == '\n')
        {
          bluetooth.println(commandbuffer);
          Serial.println(commandbuffer);
          memset(commandbuffer, 0, sizeof(commandbuffer));
          j = 0; // Reset
        }
        else
        {
          commandbuffer[j++] = temp;
        }
        delay(500);
      }