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.

RTOS/LAUNCHXL-CC1310: Sending the received data from the collector to another device using SPI interface

Part Number: LAUNCHXL-CC1310

Tool/software: TI-RTOS

I have just started exploring the 802.15.4 stack implementation for CC13x0. So far I can successfully compile and run both Sensor and Collector project, receive the temperature of the sensor node in collector, and print using UART interface. 

I am looking forward to transmit these received data, from collector to a another device (NXP FRDM board) over SPI interface. I tried a basic approach, but it did not work. Here is what I did: 

In collector.c, I called a function for transmitting over SPI (transmitSPI) inside processSensorData(ApiMac_mcpsDataInd_t *pDataInd). The function transmitSPI() is described in the csf.c, just below the Csf_deviceSensorDataUpdate() function. I am tried calling the SPI using both blocking and callback mode, but it is not working. Basically what happens, the collector does not even show the joined node. I am suspecting the nodes are not even joining. The code is probably stuck somewhere before the joining part. I made sure that the PermitJoin is enabled in the collector. 

I would really appreciate if someone could help me understanding the right approach to implement this solution. Please let me know if you have any question. 

Thanks! 

  • Are you setting up the SPI driver correctly? There is example code on how to do this inside the cc13x0 SDK documentation - take a look at the SPI.h and SPICC26XXDMA.h references (simplelink_cc13x0_sdk_1_30_00_06/docs/tidrivers/doxygen/html/_s_p_i_c_c26_x_x_d_m_a_8h.html and _s_p_i_8h.html)

    Skyler
  • Hi Skyler,

    Thanks for responding! 

    I should have attached my SPI code. I used this code with rfWsnconcentrator example, and it was working. 

    This is what I have done. I called the SPI transfer function inside static void processSensorData(ApiMac_mcpsDataInd_t *pDataInd) in collector.c file. Code snippet looks like: 

        /* Report the sensor data */
        Csf_deviceSensorDataUpdate(&pDataInd->srcAddr, pDataInd->rssi,
                                   &sensorData);
    
        /*Sending the data over SPI interface*/
        Csf_sendSensorDataOverSPI(&pDataInd->srcAddr, pDataInd->rssi,
                                  &sensorData);
    
        processDataRetry(&(pDataInd->srcAddr));

    The function is defined in the csf.c: 

    /*!
     The application calls this function to transfer the sensor
     data to NXP FRDM board over SPI interface.
    
     Public function defined in csf.h
     */
    
    void Csf_sendSensorDataOverSPI(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
                                   Smsgs_sensorMsg_t *pMsg){
        SPI_Handle spi;
        SPI_Params spiParams;
        SPI_Transaction spiTrans;
        char buffer[128] = "\fSPI Sample:\r\n";
        SPI_Params_init(&spiParams);
        spiParams.bitRate = 1000000;
        spiParams.frameFormat = SPI_POL0_PHA0;
        spiParams.dataSize = 16;
        memset(&spiTrans, 0, sizeof(SPI_Transaction));
        spiParams.mode = SPI_MASTER;
        spiParams.transferMode = SPI_MODE_BLOCKING;
        //spiParams.transferCallbackFxn = packetReceivedCallback;
        spiParams.transferTimeout = 1000;
        spi = SPI_open(Board_SPI0, &spiParams);
        if (!spi) {
            System_printf("SPI did not open\n");
            System_flush();
        }
        strcpy(buffer, "SPI open with Master mode\n");
        System_printf(buffer);
        System_flush();
        //struct AdcSensorNode* nodePointer = knownSensorNodes;
    
        int16_t dataSPI [16];
        dataSPI[0] = (int16_t)pSrcAddr->addr.shortAddr;
        dataSPI[1] = pMsg->tempSensor.objectTemp;
        dataSPI[2] = (int16_t)rssi;
        dataSPI[3] = '\0';
    
        spiTrans.count = 4;
        spiTrans.txBuf = dataSPI;
        spiTrans.rxBuf = "TESTDATAFORSPI";
    
        int ret = SPI_transfer(spi, &spiTrans);
        if (ret) {
            System_printf("%d and Successful\n", &spiTrans.txBuf);
            System_flush();
        }
        else
        {
            System_printf("Unuccessful master SPI Transfer\n");
            System_flush();
        }
    
        System_printf ("Test: Does it really close? \n");
        System_flush();
        SPI_close(spi);
        System_printf ("Test: Looks like SPI closes! \n");
        System_flush();
    
    }

    I do understand that the SPI should be called using callback mode, not blocking, in order to have a continuous operation. However, I also think, it should work at least one time. Rather what I am seeing is, the sensor node stays in State 3 for a while, but not transmitting the data or showing the temperature (since I changed the LCD print command to print the temperature over UART). Then it just goes to State 5, which I believe, is the orphan mode. 

    Would you please let me know, in general what should be the right way to do this? Should I: 

    1) Use SPI callback mode? 

    2) In that case what the callback function is supposed to do? 

    3) Or shall I use an event to trigger the SPI communication? 

    Thankk you very much again for your response. Please let me know if you have any question. Thank you! 

     

  • I have a few questions/suggestions:
    1. Did you call SPI_init() somewhere in the program before using the SPI driver?
    2. If you're only transmitting data over SPI, you should set spiTrans.rxBuf = NULL.
    3. The callback mode is used when receiving over SPI, which I don't believe you need.
    4. If you're still having issues, it might be best to create a separate task for SPI with a higher priority, and pend on a semaphore (or event as you mentioned). With the SPI driver in a separate task and blocking mode, the other tasks in the stack will continue to run.

    Let me know if this is unclear or you have further questions.

    Skyler

  • Thanks!

    I copied and pasted the SPI code from another project of mine, and I forgot to call SPI_Init(). After adding this, it seems like the SPI module is working. I still have few questions:

    I notice that the project is very "sensitive". Everytime I make a change in the collector code, I need to re-build and debug the Sensor code as well. If I do not do that, the sensor node jumps to state 4, and it does not join the collector, even after enabling the perminJoin option. Restarting the sensor does not help either. Could you please tell me, which part of the (senor/collector) code results in such behavior? I was trying to figure out, but so far no luck. 

    I was also wondering- what is the most efficient way to handle the txBuffer. For example, in this case we have three different data types to store. Currently I am using typecasting, but not sure whether this is the right thing to do.

    To answer rest of your questions: 

    Although I am just sending at this point of time, but eventually I am expecting to receive over SPI as well. My target is to receive the reporting/polling interval from the other node, and enforce that parameter in collector/sensor node. Please let me know if you have any thoughts on it. 

    Thanks again for your support. 

  • I'm looking into your issue with the sensor state.

    The messages in TI Stack are configured as structs by default. You can put your three data types into a struct and the typecasting will be automatic. You just need to make sure the message length represents the full length of your struct.

    If you're going to be receiving, I would suggest using the callback mode; then you can set your intervals inside the callback. If you use blocking mode to receive, you'll have to create another task just for SPI.
  • Thanks! 

    I apologize for my late response. Last week I was sick, and could not check your answer. 

    Your suggestion seems quite rational to me. I will definitely try this approach. Meanwhile, while browsing the collector code, I could not find the part where "sending the ACK" part is configured. 

    Could you please let me know which function in the collector project is actually sending the ACK back to the sensor? I am planning to piggyback the user defined reporting interval using this ACK message. 

    Have a good day! 

  • Are you essentially trying to change the reporting interval dynamically?
  • Yes, that is correct. 

    I want to receive this interval from the other node (which is connected to the collector over SPI). The collector is supposed to disseminate this interval to all the sensor nodes. I was thinking about piggybacking the ACK message. I don't know why, but I cannot identify the part of the code which takes of the ACK from collector to sensor. Could you please help me with that? Also if you have a better suggestion, please let me know. 

    Thank you for your support. 

  • I'm not sure about sending it inside the ACK, but what you can do is create a new message type to send from the collector to the sensor.

    In the collector, add a message type (Smsgs_cmdIds_t) in smsgs.h, and you can create a function to send the appropriate message - look at Collector_sendToggleLedRequest() in collector.c and use that as a base to create your message.

    On the sensor side, add a new case to dataIndCB() in sensor.c, and set configSettings.reportingInterval - this is a (static) global that is read whenever the sensor collects new data.

    Skyler
  • Hey,

    The sensor device stores network information after joining a network. When reset it then loads this information and tries to rejoin the network. To clear previous network information, hold BTN-2 and press reset.

    state 1 - Joining (device has never joined a netowork)
    state 2 - rejoining (device reads network info from NV)
    state 3 - joined (follows state 1 once the device joins a network)
    state 4 - rejoined (follows state 2 once network info is read from NV).
    state 5 - Orphan sensor device can no longer communicate with the collector.

    ~Brocklobsta