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-CC1350: 130us continuous sampling

Part Number: LAUNCHXL-CC1350


Tool/software: TI-RTOS

Hello there,

I'm trying to make a non-blocking adc sampling in 3 channels. My signals are sine waves with 60Hz frequency, and I want to have 128 samples per cycle, so I need to sample these 3 channels every 130us. To achieve this, I'm using a Clock task with periodic calls of 130us. The problem is that it is taking longer than the 130us for me to make the samples,which hinders the execution of the rest of the code. I decided to only open the adc handles once (and never close them) which made the code run faster, but now my adc readings are wrong. Is there a way to set up 3 adcs with 7680Hz sampling frequency that still gives me freedom to operate UARTs, radio, etc?


Here is my code:

main.c

/*
 * main.c
 *
 *  Created on: 7 de apr de 2019
 *      Author: pedro.henrique
 */

#include "main.h"

/* variáveis de relógios e tarefas */
Clock_Params clkParamsADC,clkParams;
Clock_Handle clkHandleADC,clkHandle;
Clock_Struct clkStructADC,clkStruct;

Task_Struct task0Struct;
Task_Params taskParams;
Char task0Stack[TASKSTACKSIZE];

Semaphore_Struct semUartStruct;
Semaphore_Handle semUartHandle;
Semaphore_Params semUartParams;

/* Variáveis ADC */
ADC_Handle adc0,adc1,adc2,adc3;
ADC_Params adcParamsTensao;

/* Variáveis  */
UART_Handle uart;
UART_Params uartParams;

/* pinos e LEDs */
static PIN_State ledPinState;
PIN_Handle ledPinHandle;

PIN_Config ledPinTable[] = {
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_DIO12| PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

/* Comandos AT */

uint8_t count=0,buffer[12];
uint16_t adcRaw,eventos,tensaoUcap;
uint16_t amostraTensao[128],amostraCorrente[128],amostraUcap[128];
uint32_t tik,tok;
int contadorMedidas;

medida tensao,corrente;
threshold limites;
SIGFOX sigfoxserial;

void montaBuffer(void){

    int i;
    uint8_t bufEventos[2],bufTensao[4],bufCorrente[4],bufCurto[4];

    eventos = 0x00;
    corrente.rms = 0x0000;
    corrente.dt16 = 0x0000;

    bufEventos[0] = (0x0F & eventos);
    bufEventos[1] = (0xF0 & eventos) >> 4;
    bufTensao[0] = (0x000F & tensao.rms);
    bufTensao[1] = (0x00F0 & tensao.rms) >> 4;
    bufTensao[2] = (0x0F00 & tensao.rms) >> 8;
    bufTensao[3] = (0xF000 & tensao.rms) >> 12;
    bufCorrente[0] = (0x000F & corrente.rms);
    bufCorrente[1] = (0x00F0 & corrente.rms) >> 4;
    bufCorrente[2] = (0x0F00 & corrente.rms) >> 8;
    bufCorrente[3] = (0xF000 & corrente.rms) >> 12;
    bufCurto[0] = (0x000F & corrente.dt16);
    bufCurto[1] = (0x00F0 & corrente.dt16) >> 4;
    bufCurto[2] = (0x0F00 & corrente.dt16) >> 8;
    bufCurto[3] = (0xF000 & corrente.dt16) >> 12;

    for(i=0;i<sizeof(bufTensao);i++){

        if(bufCurto[i] < 0x0A)
            bufCurto[i] = bufCurto[i] + 0x30;
        else
            bufCurto[i] = bufCurto[i] + 0x37;

        if(bufTensao[i] < 0x0A)
            bufTensao[i] = bufTensao[i] + 0x30;
        else
            bufTensao[i] = bufTensao[i] + 0x37;

        if(bufEventos[i] < 0x0A && i < 2)
            bufEventos[i] = bufEventos[i] + 0x30;
        else
            bufEventos[i] = bufEventos[i] + 0x37;

        if(bufCorrente[i] < 0x0A)
            bufCorrente[i] = bufCorrente[i] + 0x30;
        else
            bufCorrente[i] = bufCorrente[i] + 0x37;
    }

    memcpy(&sigfoxserial.send.buffer[7],&bufEventos,2);
    memcpy(&sigfoxserial.send.buffer[9],&bufTensao,4);
    memcpy(&sigfoxserial.send.buffer[13],&bufCorrente,4);
    memcpy(&sigfoxserial.send.buffer[17],&bufCurto,4);
    sigfoxserial.send.buffer[30] = '\r';
    sigfoxserial.send.buffer[31] = '\n';

}
Void eventFxn(UArg arg2, UArg arg3){

    while (1) {
        Semaphore_pend(semUartHandle,BIOS_WAIT_FOREVER);
        tensao.antrms = tensao.rms;
        corrente.antrms = corrente.rms;
        corrente.acc = corrente.acc/ADC_SAMPLES;
        corrente.rms = sqrt(pow(corrente.max,2)/2+pow(corrente.acc,2)/2);
        tensao.rms = sqrt(pow(tensao.max,2)/2+pow(tensao.acc,2)/2);
        corrente.rms = (corrente.max*100)/(100*sqrt(2));
        corrente.dt32 = (corrente.rms - corrente.antrms)*1000/(26*100);
        corrente.dt16 = corrente.dt32;
        tensao.aux = tensao.rms;
        corrente.aux = corrente.rms;
        eventos = 0x00;
        if(tensao.rms < limites.tensao && tensao.antrms > limites.zerotensao)
            eventos |= T_DESLIGAMENTO;
        if(tensao.rms > limites.tensao && tensao.antrms < limites.zerotensao)
            eventos |= T_RELIGAMENTO;
        if(corrente.rms < limites.corrente && corrente.antrms > limites.zerocorrente)
            eventos |= C_DESLIGAMENTO;
        if(corrente.rms > limites.corrente && corrente.antrms < limites.zerocorrente)
            eventos |= C_RELIGAMENTO;
        if(corrente.dt16 > limites.didt)
            eventos |= C_SURTO;

        montaBuffer();
        sendUART(ENVIABUFFER);
        System_printf("\nCorrente: %u\nTensao: %u\nCurto: %u",corrente.rms,tensao.rms,corrente.dt16);
        System_flush();

       // PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
    }
}

Void medeADC(UArg arg0, UArg arg1){
    //PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
    if(contadorMedidas == 0){
        tensao.acc = 0;
        tensao.min = 10000;
        tensao.max = 0;
        corrente.acc = 0;
        corrente.min = 10000;
        corrente.max = 0;
    }
    tik = Clock_getTicks();
    adcTensao();
    adcCorrente();
    adcCorrenteX10();

    if(amostraTensao[contadorMedidas] >= tensao.max){
        tensao.max = amostraTensao[contadorMedidas];
    }
    if(amostraTensao[contadorMedidas] <= tensao.min){
        tensao.min = amostraTensao[contadorMedidas];
    }
    tensao.acc = tensao.acc + amostraTensao[contadorMedidas];

    if(amostraCorrente[contadorMedidas] >= corrente.max){
        corrente.max = amostraCorrente[contadorMedidas];
    }
    if(amostraCorrente[contadorMedidas] <= corrente.min){
        corrente.min = amostraCorrente[contadorMedidas];
    }
    corrente.acc = corrente.acc + amostraCorrente[contadorMedidas];

    contadorMedidas++;
    tok = Clock_getTicks();
    //System_printf("\n%u",tok-tik);
    //System_flush();


    if(contadorMedidas == ADC_SAMPLES){
        adcUcap();
        contadorMedidas = 0;
        count++;
        PIN_setOutputValue(ledPinHandle, Board_LED2, !PIN_getOutputValue(Board_LED2));
        if(count == 60){
            count = 0;
            PIN_setOutputValue(ledPinHandle, Board_LED1, !PIN_getOutputValue(Board_LED1));
            Semaphore_post(semUartHandle);
        }
    }
}

void sendUART(const int tipo){

    uint8_t uartbuf4[6],uartbuf3[5];
    int i = 0;
    if(tipo == ENVIABUFFER){
        uart = UART_open(Board_UART0, &uartParams);
        UART_write(uart, &sigfoxserial.send.buffer, sizeof(sigfoxserial.send.buffer));
        UART_close(uart);
    }
}


void adcUcap(void){
   // adc = ADC_open( ADC_IO26, &adcParamsTensao);
    ADC_convert(adc0, &adcRaw);
    tensaoUcap = ADC_convertRawToMicroVolts(adc0,adcRaw)/1000;
   // ADC_close(adc);
}
void adcTensao(void){
   // adc1 = ADC_open( ADC_IO24, &adcParamsTensao);
    ADC_convert(adc1, &adcRaw);
    amostraTensao[contadorMedidas] = ADC_convertRawToMicroVolts(adc1,adcRaw)/1000;
   // ADC_close(adc);
}
void adcCorrente(void){
   // adc = ADC_open( ADC_IO25, &adcParamsTensao);
    ADC_convert(adc2, &adcRaw);
    amostraCorrente[contadorMedidas] = ADC_convertRawToMicroVolts(adc2,adcRaw)/1000;
   // ADC_close(adc);
}
void adcCorrenteX10(void){
   // adc = ADC_open( ADC_IO27, &adcParamsTensao);
    ADC_convert(adc3, &adcRaw);
    amostraCorrente[contadorMedidas] = ADC_convertRawToMicroVolts(adc3,adcRaw)/1000;
   // ADC_close(adc);

}
/*
 *  ======== main ========
 */
int main(void)
{
    /* funçoes de inicialização de periféricos */
    Board_initGeneral();
    Board_initUART();
    Board_initADC();
    /* inicialização de objetos de software */
    initThings();

    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, ledPinTable);
    if(!ledPinHandle) {
        System_abort("Error initializing board LED pins\n");
    }

    PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
    //PIN_setOutputValue(ledPinHandle, Board_DIO12, 1);
    BIOS_start();
    return (0);
}

void bufferFlush(uint8_t *buffer,size_t tam){
    int i;
    for(i=0;i<tam;i++){
        buffer[i] = 0;
    }
}

void initThings(void){

    /* Construção de tarefas e relógios */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    Task_construct(&task0Struct, (Task_FuncPtr)eventFxn, &taskParams, NULL);

    Clock_Params_init(&clkParamsADC);
    clkParamsADC.period = (UInt32)ADC_TRIGGER;  //useg
    clkParamsADC.startFlag = TRUE;
    Clock_construct(&clkStructADC, (Clock_FuncPtr)medeADC, 10, &clkParamsADC);
    clkHandleADC = Clock_handle(&clkStructADC);

    /* Semáforos */
    Semaphore_Params_init(&semUartParams);
    Semaphore_construct(&semUartStruct, 0, &semUartParams);
    semUartHandle = Semaphore_handle(&semUartStruct);

    /* UART */
    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = 9600;

    /* ADC */
    ADC_Params_init(&adcParamsTensao);

    adc0 = ADC_open( ADC_IO24, &adcParamsTensao);
    adc1 = ADC_open( ADC_IO25, &adcParamsTensao);
    adc2 = ADC_open( ADC_IO26, &adcParamsTensao);
    adc3 = ADC_open( ADC_IO27, &adcParamsTensao);

    /* Variáveis */
    limites.tensao = 3000;
    limites.corrente = 2000;
    limites.zerotensao = 100;
    limites.zerocorrente = 100;
    limites.didt = 100;

    bufferFlush(sigfoxserial.send.buffer,sizeof(sigfoxserial.send.buffer));
    memcpy(&sigfoxserial.send.devID,"AT$I=10\r",sizeof(sigfoxserial.send.devID));
    memcpy(&sigfoxserial.send.macrochannel,"AT$GI?\r",sizeof(sigfoxserial.send.macrochannel));
    memcpy(&sigfoxserial.send.macrochannelReset,"AT$RC\r",sizeof(sigfoxserial.send.macrochannelReset));
    memcpy(&sigfoxserial.send.buffer,"AT$SF=",sizeof("AT&SF="));
    sigfoxserial.send.buffer[6] = 0x03 + '0';

}

and the main.h

/*
 * main.h
 *
 *  Created on: 7 de apr de 2019
 *      Author: pedro.henrique
 */

#ifndef MAIN_H_
#define MAIN_H_

/* Bibliotecas C */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <time.h>

/* Headers do XDCtools (bootloader) */

#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

/* Headers da BIOS */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Clock.h>

/* Headers do TI-RTOS */
#include <ti/drivers/PIN.h>
#include <ti/drivers/ADC.h>
#include <ti/drivers/ADCBuf.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/I2C.h>

/* Headers específicos */
#include "Board.h"

/* Constantes */

#define ADC_TRIGGER               26
#define CLK_TRIGGER          1000000
#define ADC_SAMPLES               64
#define TASKSTACKSIZE            768
#define UART_TASK_PRIORITY         1

#define C_DESLIGAMENTO          0x01
#define C_RELIGAMENTO           0x02
#define T_DESLIGAMENTO          0x04
#define T_RELIGAMENTO           0x08
#define C_SURTO                 0x10
#define FALTA_TEMPORARIA        0x20
#define FALTA_PERMANENTE        0x40
#define T_UCAP_BAIXA            0x80

#define TENSAO                  1
#define CORRENTE                2
#define ENVIABUFFER             3

/* Variáveis */

typedef struct {
    uint16_t rms;
    uint16_t max;
    uint16_t min;
    uint16_t acc;
    uint16_t aux;
    uint16_t antrms;
    uint32_t dt32;
    uint16_t dt16;
}medida;

typedef struct {
    uint16_t tensao;
    uint16_t corrente;
    uint16_t zerocorrente;
    uint16_t zerotensao;
    uint16_t didt;
}threshold;

typedef struct {
    char devID[10];
    char macrochannel[7];
    char macrochannelReset[6];
    uint8_t buffer[32];
}SEND;

typedef struct {
    uint8_t ID[10];
    uint8_t ans[20];
}RECV;

typedef struct {
    SEND send;
    RECV recv;
}SIGFOX;


/* Funções */

void initThings(void);
void adcTensao(void);
void adcCorrente(void);
void adcCorrenteX10(void);
void adcUcap(void);
void esperaciclos(void);
void sendUART(const int tipo);
void montaBuffer(void);
int delay_ms(uint32_t tempo);
void bufferFlush(uint8_t *buffer,size_t tam);

#endif /* MAIN_H_ */