This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Microcontroller and sensor communication

Other Parts Discussed in Thread: MAX232

Hi all,

Can anybody provide me tips for communicating Microcontroller and Laser Sensor.???

Thanks,

Ishika.

  • The interface seems to be a plain RS232 interface , whcih can be addressed by teh 1611 with a simple chargepump level shifter like the MAX232 and its brothers.
    I had stable serial connections with the 1611 at any baudrate up to 115kBaud (using an 8MHz crystal quartz as timebase, clocking the UART with 1MHz), so the hardware side is no problem.

    How to program thesensor is a different thing and should be explained in the "detailed information on the simple serial protocol used to manipulate the readings, turn on/off the laser, and interact with this rich sensor" which comes with the sensor, at least accordign to the Acroname Robotics product page.

    I don't know, however, whether the sensor data is available at the serial port at all. The sensor produces 6666 readings per second (240° range, 0.36° resolution, 10Hz), which would be above 115kBd for 16bit values. (but could be packed 12 bit values, as the range is up to 4000mm). But then, I don't say teh 1611 won't do more than 115kBd, I just never tested more as my PCs serial port doesn't support more :)

  • Hi Jens-Michael,

    Thanks for the reply. You are right about 1611 and surely there is no problem on the microcontroller side. I am more concerned about sensor programming. I found lot of documentation on web but all are for Windows, Linux or Mac. I just wanted to know is there anything different while programming it for microcontroller?

    Information regarding the sensor readings is quite useful and I will keep it in mind. Thanks for a valuable information.

    Ishika

  • Well, how to program the sensor itself, I cannot tell. I must admit, I didn't search further after getting the first few hits about the sensor itself.
    The protocol on the serial (and far more the USB side) is unknown to me.

    Generally I can say that it won't be possible to access the sensor through USB with an MSP. The only USB profiles that exist for the MSP are client profiles, so no direct connection between MSP and any other client is possible, even if adding the necessary hardware or using an MSP with internal USB controller.

    What you can do over the serial connection may be equivalent to USB or limited. The documentation will tell. Anyway, the MSP with its few kb of Flash and RAM space is surely not suited to do what the typical windows applications will do (e.g. collecting 3D images of the sensors surroundings etc.). I might, however, be good enough for some simpler applications, such as collision detection (including collision angle and speed), calculation of size, position and speed of obstacles etc.

    In any case I don't recommend starting new projects with the 1611. There are cheaper MSPs with more features and better performance available. The 1611, while not being discontinued for the next future, is not recommended for new designs by TI. And unless you need its combination of features ofr have optimized code libraries for it, you can do better with other devices. For example the 5418 is cheaper, faster, has more ram and flash, requires less power (well, the laser consumes so much that this won't count) and has more hardware features. It is better in every aspect except that it is missing the dual analog outputs the 1611 has.

    But to sum it up to answer your last question: indeed there is some difference between interfacing the sensor from a PC or a microcontroller. Or better between doing something on a PC and doing it on a Microcontroller in general:
    On a microcontroller you should know what you're doing, and you need to do it simple and efficient by using the hardware where possible. And this means not writing beautiful, structurized code but slim, fast and efficient code, have to carefully decide what data you need to gather and/or keep and what code to write and what to dismiss or to avoid. This for example includes heavily object-oriented programming or the use of floating point variables. Both are possible but require a LOT processing power and memory and the use should be limited to where it is necessary, if at all. The rule of thumb with Microcontrollers is: do what you need and only what you really need, and do it as simple and fast as you can. Imagination is as important as programming skills, if not more.

  • Hi Jens-Michael,

    Thanks for your useful suggestion regarding microcontroller programming. Being a beginner, I really need to know this.

    Regarding my previous question of interfacing sensor-microcontroller-PC, I have a question(it may sound weird). My interface is RS232, and want to transfer the data from sensor to PC via microcontroller. For this, I am planning to use USART1 for  sensor-microcontroller communication and USART0 for MSP430-PC communication.  Do I need to communicate both the USARTs? If yes, then how can this be established?

    This is my first time and I am highly confused. Kindly give some suggestions.

    Ishika

  • Ishika Sharma said:
    My interface is RS232, and want to transfer the data from sensor to PC via microcontroller.

    Well, it only makes sense if you need to either buffer or interpret the data or have to translate it (baudrate change, whatever). Else just use a direct connection :)

    I guess what you want is to get commands form the PC, control the sensor accordingly and forward the output back to the PC.

    There are several possible setups. You can do two separate comm chains. Taliking with the PC on one side and with the sensor on the other. It's the most generic setup and of course requires you to listen on both serial connections all teh time and talking to both.

    A bit easier is if you want to get commands from the PC, send instructions to the sensor, get answers from teh sensor but don't have to respond to the PC.

    Then you only have to handle talk to sensor and listen to PC and ca directly link the sensor output to the PC (you can even sniff what the sensor sends to the PC). Then you cannot answer the PC, But the PC must be able to understand and handle all responses of the sensor. If you don't need any response from the sensor to the MSP, then it reduces you to just two channels: incoming from PC and outgoing to sensor.

    Depending on the exact task you have for the MSP, there are many different devices available. The 5438 with its 4 USART modules, can handle 4 simultaneous bi-directional serial connections with 115200Bd. (If all four are active at the same time, it is a bit tight for additional functionality, but works). At lower baudrates it's not a problem at all.
    Some MSPs, however, have only one UART module. There oyu can write a software solution or (in the second scenario) you split the hardware, as long as both sides have the same baudrate.

    it depends on what exactly you want to do.

  • Hi Jens-Michael,

    I want to do some processing thats why I am using MSP430. But, for now I am just trying to establish communication between the devices. And for this I am using  both the UARTs. But, I am facing few problems.

    As for a start, I tried to communicate between Uart0 and Pc and was successful.

    I tried to communicate UART1 and UART0 of MSP430F16xx. I wanted to

    Transmit "Hello" using UART1 and suppose I receive "Hi". then I want to Transmit this Hi to another device using UART0.

    I tried the following:

    void main(){

    -------------

    ------------

      while(string1[i] != '\0')  {

       while(!(IFG2 & UTXIFG1));

        U1TXBUF = string1[i];

         i++;}

     

    }

    #pragma vector=UART1RX_VECTOR

    __interrupt void usart1_rx (void)

    {

      string1[j++] = RXBUF1;

      if (j > sizeof (string1)-1)

      {

        j = 0;

        TXBUF0 = string1[j++];

      }

     

    }


    Could you point out the loop-holes in this?

    Also, I tried just to transmit "Hello" to the hyper-terminal using Uart0 with the following code,

    void main(){

    -----------

    ------------

    while(string1[i] != '\0')  {

       while(!(IFG1 & UTXIFG0));

        U0TXBUF = string1[i];

         i++;}

    }

     

    It worked properly. But, when I tried same thing for UART1, it didn't.

     

    Kindly suggest.

     

    Regards,

    Ishika

  • The first thing that pops into view is that you sometime suse U0TXBUF and then TXBUF0/RXBUF1. While both notations should be the same, it is at least confusing.

    Next is the usart init code. You didn't post it. Maybe it's there. where the problem lies. Improperly set enable flags (both usarts use different SFRs for their enable bits), USART1 is enabled in ME2, USART0 in ME1. same for the IE bits and IFGs.

    Using the 1611 myself, I know that both usarts are working (one project uses 2 uarts,115200+38400Bd+2MHz SPI at the same time, another one makes an 38400<->115200 bridge with content translation/command interpretation)

  • I am sorry for that.

    Here is my initialization. I am using baut rate 115200 for both.

     

      P3SEL  |= BIT4 + BIT5 + BIT6 + BIT7;

      

     

      U0CTL   |= BIT0 + BIT4 ;        

      U0TCTL  |= BIT5;                

      U0RCTL  |= BIT3;              

     

      U0MCTL  = 0xb5;

      U0BR0   = 0x34;              

     

      U0BR1   = 0x00;

      ME1     |= BIT7 + BIT6;       

      U0CTL   &= ~BIT0;              

      IE1     |= URXIE0; 

     

     

     

      U1CTL   = BIT0 + BIT4;       

      U1TCTL  |= BIT5;                

      U1RCTL  |= BIT3;               

      U1MCTL  = 0xb5;

      U1BR0   = 0x34;                

      U1BR1   = 0x00;

      ME2     |= BIT5 + BIT4;        

      U1CTL   &= ~BIT0;              

      IE2     |= URXIE1; 

     

     

  • Well, the init looks okay. The only difference between the two is the first line (U0CTL|= / UCTL1=) but it makes no difference.
    I just wonder why you enabled interrupts for erroneous characters. Your code doesn't check for the error bits. But it won't make any difference, as the 1611 USART does handle them liek normal received characters too

    Also, you should use the qualified bit defines rather than the general ones (these are only useful for port registers, where each bit matches a port pin).

    Using the qualified defines such as
    U1CTL |=SWRST|CHAR;
    It's way more telling and allows you to detect wrongly assigned bits on first glance rather than requiring a look into the docs. You'll still have to ensure that you're assigning the right bits to the right register.

    For the clock selection in UxTCTL (or other multi-bit fields anywhere) there is usually an additional constant set available such as SSEL_SMCLK or SSEL_ACLK, along with the usual SSEL_0 to SSEL_3 for selection option 0..3 (not to be confused with SSEL0 and SSEL1 which directly have the bit value ot the first and second bit inside the SSELx area.)

    Still I don't see why it doesn't work.

    Dumb question: when switching from UART0 to UART1, did you also switch the physical port pins you use? Are these connected to the PC the same way as the UART0? Maybe you have a 'cold solder point'? Or accidentally twisted the TX and RX lines? Sometimes it just in't the software :)

  • Hi,

    You were right. My transmission line was twisted and after soldering its working fine.

    Thanks,

    Ishika

  • Hi,

    I am trying to receive string whose length is undefined. I am trying following function for it:

    char get_string(){

    while(1){
        while(!(IFG1 & URXIFG0));

      *s = U0RXBUF; // get a char

        while(!(IFG1 & UTXIFG0));

         U0TXBUF = *s;

       if(*s == '\n') {
           U0TXBUF = '\n';
           *s = 0;
         }
          else
            s++;

    }

    }

    I am breaking the string when "\n" is received. But, its not working. Is it the correct way to receive string in receive buffer or I should use some different approach.

    Kindly suggest.

    Regards,

    Ishika.

  • basically, there's nothing wrong with your code loop itself.

    Just that the end condition is a no-op. What happens if a return is received? Well, you set the current position in the string to 0, terminating the string. Fine. But then? The next char received will overwrite the termination and the string continues to grow until your RAM explodes.
    You never exit your endless while(1) loop. or, more specific, after teh *s=0 you should add a break; so teh function exits.

    Anways, your function never inits s* nor does it reserve space for the storage. It also does not check whetehr the string may be too long for the available buffer space.

    The calling function should provide 's' initialized to the beginning of the buffer, and also the maximum length of the reserved buffer space. Each time a char is stored, this length should be reduced and the strigng terminated when it reaches zero, whether there was a return char or not.

  • Hi Jens-Michael,

    As suggested by you, I did the changes in my function. Now, the problem is I am able to transmit the  string via UART0 and Receive on UART0. But, while transmtting the received string via UART1 I am missing the first character. After that, I am not able to transmitting anything else(not even from UART0). It simply gets stucked in

      while(!(IFG1 & URXIFG0));.

     

    Following is my function:

     

     

    #define UART0_RX_BUFFERSIZE 64

     

    char uart0_rx_buffer[UART0_RX_BUFFERSIZE];

     

    Funtion for receiving string:

     

    char UART0_getstring(void) {

      unsigned int n = UART0_RX_BUFFERSIZE;

      unsigned int len=0;

      char *tmp;

      *tmp = uart0_rx_buffer[0];

     

      while(n--){

        *tmp = UART0_getchar(); // get a char

          UART1_putchar(*tmp); // echo

        if(*tmp == '\n') {

          UART1_putchar('\n');

          *tmp = 0;

           break;

        }

        else {

          len++;

          tmp++;

        }

       

       }

     

    }

     

    char UART0_getchar(void) //Receives single character on UART0

    {

      char c;

      while(!(IFG1 & URXIFG0));

      c = U0RXBUF;

       return c;

    }

     

    //Transmits single character from UART1

    char UART1_putchar(char c) {

     while(!(IFG2 & UTXIFG1)); // wait for tx buf empty

     U1TXBUF = c;

    }

     

    UART0 Receive interrupt serive routine:

    #pragma vector = UART0RX_VECTOR

    __interrupt void usart0_rx(void)

    {

        UART0_getstring();

    }

     

    Kindly suggest.

     

    Regards,

    Ishika.

  • Ishika Sharma said:
    After that, I am not able to transmitting anything else

    Hmm, if I interpret this right, you're saying that when you start to send the string using UART1_putchar, the first byte won't be sent and the program stalls. Does it ever return from the first call of UART1_putchar?
    It sonds to me that even the first call to UART1_putchar hangs. Probably in the while loop.

    Kepp in mind that TXIFG is set the moment TXBUF is empty, but it does not stay set if you manually reset it without writing something to TXBUF. It is not a TXBUF state flag, it is a state change flag.

    If you remove this while loop, you should at least see the first and last byte of teh message (or maybe some in between, depending on execution speed) appearing on the output.

     

  • Well, I am able to send the response of Uart0 to PC via UART1 where UART1 was able to transfer the string without the first character. After that it gets stucked in UART0_getchar().  I have enabled UART0 Receive interrupt only (If that is the problem)

    Regards,

    Ishika

  • I guess i found the problem:

    char *tmp;

    This creates a pointer to a char. Yet this pointer point to nowhere (not initialized). When you then do your

    *tmp = uart0_rx_buffer[0];

    Which move sthe first element of the rx_buffer to the location tmp points to. Which is virtually anywhere from flash (where the write would be ignored) through ram (where you'd overwrite stack, variables, whatver) to the most likely location, 0, the SFRs. So this assignment with a certain probability writes something the the SFRs, clearing the IE or IFG flags.

    If you want tmp to point to the rx_buffer, you have to remove the [0] as well as the * from the assignment, so you're assigning the address of the array to the pointer and not the first element of the array to the destination of the pointer.

**Attention** This is a public forum