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.

MSP430FR2676: Backchannel UART for 8x8 mutual capacitance array

Part Number: MSP430FR2676
Other Parts Discussed in Thread: MSP430G2553, ENERGIA

I have been working with the MSP430FR2676 using the programmer and debug modules and have a design of a typical diamond pattern 8x8 mutual capacitance array. I am wanting to figure out how to get the filtered count of every sensor of this array and constantly stream that information through the UART. I have been directed towards the MSP430FR2676 backchannel UART demo that's found inside the captivate design studio. I have opened this project and loaded it onto my board and I have the terminal open in CCS hoping to see the information being sent out but have not been able to get this work. From what I have gathered this particular example is only suppose to output information when a button is pressed and only outputs that one specific buttons filtered count to the terminal (although haven't seen this working yet). I have been using this http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430Ware/3_70_00_05/exports/MSP430Ware_3_70_00_05/captivate/docs/api_guide/FR2633/html/group__CAPT__Buttons.html as a reference and I see the three functions listed under CAPT_Buttons seem to only have support for finding the dominant button that's being pressed, not allowing for me to access all the buttons filtered count? Is there any example code out there for further examples of this type of thing, or any resources that might help? From my current understanding I create my project in the Captivate Design Studio and tune my sensors then generate source code for CCS and then add the code regarding the UART communication into this and upload it to the board. I have attached some images of my current project in the captivate design studio (I have been able to successfully tune my sensor).  My only experience with working with "embedded systems" was programming MSP430G2553's using Energia which I don't believe is supported for captivate devices, CCS is fairly abstract to me. These are the current resources that I have been utilizing thus far:

https://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/CapTIvate_Design_Center/latest/exports/docs/users_guide/html/CapTIvate_Technology_Guide_html/markdown/ch_workshop.html

http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430Ware/3_70_00_05/exports/MSP430Ware_3_70_00_05/captivate/docs/api_guide/FR2633/html/group__CAPT__Buttons.html#gaa50fcc71045648e6eaf5e31549d044b5

https://www.ti.com/lit/ug/slau445i/slau445i.pdf

Here is the example code Texas Instruments provides in the demo (the part im focused on): 

//#############################################################################
//
//! \file Backchannel_UART_demo.c
//
// Group: MSP
// Target Devices: MSP430FR2633
//
// (C) Copyright 2018, Texas Instruments, Inc.
//#############################################################################
// TI Release: 1.83.00.05
// Release Date: May 15, 2020
//#############################################################################

//*****************************************************************************
// Includes
//*****************************************************************************

#include "demo.h"

//*****************************************************************************
// Definitions
//*****************************************************************************

//*****************************************************************************
// Global Variables
//*****************************************************************************

//*****************************************************************************
// Function Prototypes
//*****************************************************************************

//*****************************************************************************
// Function Implementations
//*****************************************************************************

//callback function for keypad buttons
void keypad_callback(tSensor* pSensor){

//trigger once when the button is touched
if(((pSensor->bSensorTouch)) && (!(pSensor->bSensorPrevTouch))){

//decode the dominant button number
uint8_t myButtonNumber = CAPT_getDominantButton(pSensor);
uint8_t loopCounter = 0;
uint8_t cycleCounter = 0;
uint8_t elementCounter = 0;
uint8_t myCycle;
uint8_t myElement;

//go through each cycle pointer, and within it each element pointer to find element that corresponds to the dominant button
for(cycleCounter = 0; cycleCounter < pSensor->ui8NrOfCycles; ++cycleCounter){
for(elementCounter = 0; elementCounter < pSensor->pCycle[cycleCounter]->ui8NrOfElements; ++elementCounter){
//get the cycle and element numbers from the dominant button
if(loopCounter == myButtonNumber){
myCycle = cycleCounter;
myElement = elementCounter;
}
loopCounter++;
}

}

//placeholder for output data, must be static to ensure that it is available & unchanged across function calls
static uint8_t str[100];

//access the element's raw count
//CAPT_getDominantButton() returns 0x00 for button #1, 0x01 for button #2... etc
uint16_t rawCount = pSensor->pCycle[myCycle]->pElements[myElement]->pRawCount[0];

//extract the filtered count, NOTE this truncates to the nearest natural number
uint16_t filteredCount = pSensor->pCycle[myCycle]->pElements[myElement]->filterCount.ui16Natural ;

//get the length of the output string, insert int data into output string
uint8_t str_length = sprintf((char*)str, "Button Pressed: %d\tRaw Count: %d\tFiltered Count: %d\n\r", myButtonNumber + 1, rawCount, filteredCount);

//transmit data
UART_transmitBuffer(str, str_length);
}
}


//Sets all the parameters for UART transmission
const tUARTPort UARTPort =
{
//does not receive messages, so no callback needed
.pbReceiveCallback = NULL,

//does not receive messages, so no callback needed
.pbErrorCallback = 0,

//choose clock source
.peripheralParameters.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK,

//clockPrescalar is UCBRx = int(N / 16), where N = clock_frequency / baud_rate
//int(N / 16) = int(2000000 / 9600 / 16) = int(13.02) = 13;
.peripheralParameters.clockPrescalar = SMCLK_FREQ_MHZ * 1000000 / 9600 / 16,

//controls UCBRF bits for oversampling mode
//UCBRF = int(((N/16) - int(N/16)) * 16) = int(((208.3333/16) - int(208.3333/16)) * 16) = int(0.3333) = 0
.peripheralParameters.firstModReg = 0,

//consult table 22-4 in the user's guide to find the register value corresponding to UCBRF number
//fraction portion of N = 0.3333
//in the table, 0.3333 <---> 0x49
.peripheralParameters.secondModReg = 0x49,

//controls parity bit - NOTE the eZ-FET does not support a parity bit
.peripheralParameters.parity = EUSCI_A_UART_NO_PARITY,

//least or most significant bit first
.peripheralParameters.msborLsbFirst = EUSCI_A_UART_LSB_FIRST,

//select either one or two stop bits
.peripheralParameters.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT,

//select whether to use multiprocessor/autobaud modes
.peripheralParameters.uartMode = EUSCI_A_UART_MODE,

//selects oversampling vs low-freq baud rate modes
.peripheralParameters.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION

};

  • Hi Alex,

    I edited your post a bit for clarity for others to follow this topic.

    Sounds like you are on the right track.

    Step #1 - The first thing you want to make sure you have set correctly in the CAPT_Userconfig.h, is the CAPT_INTERFACE is set to (__CAPT_NO_INTERFACE__), which it should be since you started with the MSP430FR2676_backchannel_uart_demo.

    This essentially disables the communications interface between the target and the GUI by telling the compiler not to include any of the communication drivers in the build and anywhere else in code where the captivate library wants to send data to the GUI.

    Step #2 - Next, you want to be able to re-use the UART driver function calls, so in this demo's project settings under compiler->predefined symbols you will see UART__ENABLE=true by default.

    NOTE: If you ever want to go back and communicate with the GUI (re-tune sensors or something), you will need to remove this symbol from the project settings and change the #define CAPT_INTERFACE  (__CAPT_NO_INTERFACE__) to #define CAPT_INTERFACE  (__CAPT_UART_INTERFACE__) or #define CAPT_INTERFACE  (__CAPT_BULKI2C_INTERFACE__), which ever interface you are using.

    Step #3 - You obviously don't want to run @250K baud, which is the default rate for communication with the GUI so instead, it is simple to create your own UART configuration and select a baud rate that works for with your PC terminal application.  Looks like you have done this as well.

    Step #4 -  In your callback you want to do something like the following. The code loops through all the cycles and all the elements within each cycle, grabs the filtered measurement count, converts to ASCII and sends to the pc.  You can optimize or do this however you wish.  Keep in mind you have 64 elements and sending all that data in the callback could potentially taking longer than the measurement scan period (33ms default).  So you may have choose a very high baud rate or increase you measurement period.

    void trackpad_callback(tSensor* pSensor)
    {
        uint8_t ui16BufferLength;
        uint8_t ui8Index = 0;
        uint8_t element;
        uint8_t cycle;
    
        for(cycle = 0; cycle < pSensor->ui8NrOfCycles; ++cycle)
        {
            for(element = 0; element < pSensor->pCycle[cycle]->ui8NrOfElements; ++element)
            {
                filteredCount[ui8Index] = pSensor->pCycle[cycle]->pElements[element]->filterCount.ui16Natural;
                ui16BufferLength = sprintf((char*) asciiBuffer, "%d\t%d\r\n\0", ui8Index, filteredCount[ui8Index] );
                UART_transmitBuffer(asciiBuffer,ui16BufferLength);
                ui8Index++;
            }
        }
    
    }

    Does this help?

  • Hi Alex,

    I wanted to add one more comment regarding speeding up the conversions, since you have 64 measure points.

    There is a bit in the sensor struct, .bLpmControl = false, that essentially puts the CapTIvate peripheral 1.5v LDO into a standby mode after each measurement cycle to save power.  On the next measurement cycle the LDO is set back to active mode, but delays about 350uS for the LDO to stabilize.  If you have a handful of buttons that takes 2 measurement cycles, there isn't much impact, plus you are not tracking finger motion so its really a don't care.  But since you have 16 measurements back to back you want to get through them quickly so it doesn't make sense to incur these delays.

    So I would suggest changing that bit in the sensor struct to .bLpmControl = true.

  • I have not been able to get it to work yet, I made the changes but now it's saying it can't open source file "demo.h" in my main.c although it had no issues with doing this in the demo I have been using for an outline. I have the folder demo in the project and based on the TI provided demo they don't include any extra paths either so I would assume that's not needed.

  • Hi Alex,

    Check that you have a demo path in the compiler include path options set in the project settings.

    else, in main try using #include "./demo/demo.h"

    Dennis

  • Solved that error, I also need "UART_ENABLE=true" in predefined symbols? Having many other errors now all related to undefined variables : tUARTPort, asciiBuffer, and filteredCount. tUARTPort is defined with " UART_openPort(&UARTPort);" in main.c right? and the others should be from the captivate API? 

  • Hi Alex,

    Yes, correct.

  • Hi Alex,


    It's been a while since we have heard from you, so I'm going to assume you were able to move forward with your project.
    I will mark this posting as RESOLVED, but if this isn’t the case, please click the "This did NOT resolve my issue" button and reply to this thread with more information.
    If this thread is locked, please click the "Ask a related question" button, and in the new thread describe the current status of your issue and any additional details you may have to assist us in helping to solve your issues.

  • Sorry for the late responses I've been trying to work through the problem myself, I still have not been able to solve some of the errors I am getting and I don't understand why. 

    Here is an image of the errors:

    I have been using the search feature to investigate why it's saying these are undefined, (strangely enough the demo uses the same and is not having this issues). I see tUARTPort is defined in CAPT_interface and used in UART.c and UART.h with no issues but when referenced in demo.c and demo.h it becomes a problem (just used same file name for simplicity but different project). asciiBuffer does not seem to be defined as apart of the captivate API? Fixed the unfilteredCount with filteredCount[ui8Index] = pSensor->pCycle[cycle]->pElements[element]->filterCount.ui16Natural;.

  • Hi Alex,

    This is partially my bad.  You need to define these variables.

    uint8_t     asciiBuffer[32];
    uint16_t    filteredCount[64];

    I only provided a portion of the demo code to illustrate how to iterate through the cycle and elements to retrieve the filtered count.

    Below is the entire code.

    #include "captivate.h"
    #include "CAPT_UserConfig.h"
    #include "CAPT_BSP.h"
    #include "UART.h"
    #include <stdio.h>
    
    //======================== DEFINES ========================================
    #define FIRST_SENSOR_TOUCH      (pSensor->bSensorTouch == true) && (pSensor->bSensorPrevTouch == false)
    #define SENSOR_TOUCH            (pSensor->bSensorTouch == true) && (pSensor->bSensorPrevTouch == true)
    #define EXIT_TOUCH              (pSensor->bSensorTouch == false) && (pSensor->bSensorPrevTouch == true)
    #define NO_TOUCH TOUCH          (pSensor->bSensorTouch == false) && (pSensor->bSensorPrevTouch == false)
    
    //======================= VARIABLES ========================================
    uint8_t     asciiBuffer[32];
    uint16_t    filteredCount[64];
    
    // Added this so when switching back to GUI interface, this code doesn't cause compiler warnings
    #if CAPT_INTERFACE ==  (__CAPT_NO_INTERFACE__)
    
    /*
     * CREATE A LOCAL INSTANCE OF UART PARAMETERS
     */
    static const tUARTPort UARTPort =
    {
        .pbReceiveCallback = NULL,
        .pbErrorCallback = 0,
        .peripheralParameters.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK,
        .peripheralParameters.clockPrescalar = UART__PRESCALER,
        .peripheralParameters.firstModReg = UART__FIRST_STAGE_MOD,
        .peripheralParameters.secondModReg = UART__SECOND_STAGE_MOD,
        .peripheralParameters.parity = EUSCI_A_UART_NO_PARITY,
        .peripheralParameters.msborLsbFirst = EUSCI_A_UART_LSB_FIRST,
        .peripheralParameters.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT,
        .peripheralParameters.uartMode = EUSCI_A_UART_MODE,
        .peripheralParameters.overSampling = UART__SAMPLING_MODE
    };
    #endif
    
    //=========================== CALLBACKS =======================================
    /*
     * TRACKPAD CALLBACK
     * AUTOMATICALLY CALLED AFTER SENSOR IS PROCESSED
     * ADD APPLICATION SPECIFIC CODE HERE
     */
    void trackpad_callback(tSensor* pSensor)
    {
        uint8_t ui16BufferLength;
        uint8_t ui8Index = 0;
        uint8_t element;
        uint8_t cycle;
    
        for(cycle = 0; cycle < pSensor->ui8NrOfCycles; ++cycle)
        {
            for(element = 0; element < pSensor->pCycle[cycle]->ui8NrOfElements; ++element)
            {
                filteredCount[ui8Index] = pSensor->pCycle[cycle]->pElements[element]->filterCount.ui16Natural;
                ui16BufferLength = sprintf((char*) asciiBuffer, "%d: %d\r\n", ui8Index, filteredCount[ui8Index] );
                UART_transmitBuffer(asciiBuffer,ui16BufferLength);
                ui8Index++;
            }
        }
    
    }

    Regarding the error about not finding 'tUARTPort', that is defined in the captivate library communication section in UART.h.  Are you sure you have 'UART__ENABLE = true' in the compiler pre-defined symbols?

    If still stuck, export your CCS project to a zip file and upload here to this thread.  I'll take a look.  To properly export the project in CCS select from the top menu, File>export>archive file.

**Attention** This is a public forum