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.

MSP432E401Y: Reduce sleep time for thread

Part Number: MSP432E401Y
Other Parts Discussed in Thread: MSP-EXP432E401Y,

Hello community,

I am using the MSP-EXP432E401Y (TI-RTOS). I am developing a script to identify a system. The system consists of a DC motor (with H-Bridge) and an encoder. For the system identification I set a PWM and measure the current position and velocity via the encoder API.

The program consists of two threads. The first thread executes a driving routine that lets the DC motor drive a defined profile. The second thread reads the current measured variables (PWM, position and velocity) and writes them to a vector. This is output at the end of the program via the console.

The basic program works very well. However, the query of the measured variables is not possible in a smaller time interval than 100 milliseconds.
A sampling of 10ms is however indispensable for the system identification.

If I choose the cycle time smaller than 100ms, the thread which converts the driving profile is not called often enough and the driven profile does not correspond any more to the desired profile.

Is it possible to call the second thread in a cycle of 10 ms? Or is that not possible for the MSP432E401Y? Because it is too computationally intensive or similar?

(This question e2e.ti.com/.../msp432e401y-maximum-adc-sample-frequency shows that it is possible in principle, the question would be, why does it lead with me to these problems).

In the following the relevant code:

void generateSysIdentificationVec()
{
    u[iter] = (GPIO_read(CONFIG_GPIO_L298N_IN2)-GPIO_read(CONFIG_GPIO_L298N_IN1))*duty*120;
    y1[iter] = QEIPositionGet(QEI0_BASE);
    y2[iter] = (long)(QEIDirectionGet(QEI0_BASE)*QEIVelocityGet(QEI0_BASE));
    iter = iter +1;
}

/*
 *  ======== sysIdentificationThread ========
 */
void *systemIdentificationThread(void *arg0)
{
    ...

    /* System Identification */
    do
    {
        generateSysIdentificationVec();
        // 100ms - best possible
        usleep(100000);
    }
    while (sysIdentificationRoutineRunning);
    
    ...

    return 0;
}

/*
 *  ======== stopMotor ========
 *  Stop Motor
 */
void stopMotor()
{
    /* Spinning Direction Forward
     *
     * Input1: High(1)
     * Input2: High(1)
    */

    /* Set L298N Input1 */
    GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_ON);
    GPIO_write(CONFIG_GPIO_L298N_IN1, 1);

    /* Set L298N Input2 */
    GPIO_write(CONFIG_GPIO_LED_2, CONFIG_GPIO_LED_ON);
    GPIO_write(CONFIG_GPIO_L298N_IN2, 1);
}

/*
 *  ======== setSpinningDirectionForward ========
 *  Set motor direction: Forward
 */
void setSpinningDirectionForward()
{
    /* Spinning Direction Forward
     *
     * Input1: Low(0)
     * Input2: High(1)
    */

    /* Set L298N Input1 */
    GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_OFF);
    GPIO_write(CONFIG_GPIO_L298N_IN1, 0);

    /* Set L298N Input2 */
    GPIO_write(CONFIG_GPIO_LED_2, CONFIG_GPIO_LED_ON);
    GPIO_write(CONFIG_GPIO_L298N_IN2, 1);
}

/*
 *  ======== setSpinningDirectionBackward ========
 *  Set motor direction: Backward
 */
void setSpinningDirectionBackward()
{
    /* Spinning Direction Backward
     *
     * Input1: High(1)
     * Input2: Low(0)
    */

    /* Set L298N Input1 */
    GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_ON);
    GPIO_write(CONFIG_GPIO_L298N_IN1, 1);

    /* Set L298N Input2 */
    GPIO_write(CONFIG_GPIO_LED_2, CONFIG_GPIO_LED_OFF);
    GPIO_write(CONFIG_GPIO_L298N_IN2, 0);
}

/*
 *  Drive Test route
 */
void driveRoutine()
{
    sysIdentificationRoutineRunning = true;
    usleep(100000);

    Display_printf(display, 1, 0, "Backward");
    duty = 70;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 70) / 100)));
    setSpinningDirectionBackward();
    //usleep(400000);
    ThreadAPI_Sleep(400);
    stopMotor();

    Display_printf(display, 1, 0, "Forward");
    duty = 100;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 100) / 100)));
    setSpinningDirectionForward();
    //usleep(600000);
    ThreadAPI_Sleep(600);
    stopMotor();

    Display_printf(display, 1, 0, "Backward");
    duty = 90;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 90) / 100)));
    setSpinningDirectionBackward();
    //usleep(300000);
    ThreadAPI_Sleep(300);
    stopMotor();

    Display_printf(display, 1, 0, "Forward");
    duty = 75;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 75) / 100)));
    setSpinningDirectionForward();
    //usleep(500000);
    ThreadAPI_Sleep(500);
    stopMotor();

    Display_printf(display, 1, 0, "Backward");
    duty = 40;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 40) / 100)));
    setSpinningDirectionBackward();
    //usleep(700000);
    ThreadAPI_Sleep(700);
    stopMotor();

    Display_printf(display, 1, 0, "Forward");
    duty = 40;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 40) / 100)));
    setSpinningDirectionForward();
    //usleep(700000);
    ThreadAPI_Sleep(700);
    stopMotor();

    Display_printf(display, 1, 0, "Stop");
    //usleep(500000);
    ThreadAPI_Sleep(500);

    Display_printf(display, 1, 0, "Backward");
    duty = 100;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 100) / 100)));
    setSpinningDirectionBackward();
    //usleep(800000);
    ThreadAPI_Sleep(800);
    stopMotor();

    Display_printf(display, 1, 0, "Forward");
    duty = 20;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 20) / 100)));
    setSpinningDirectionForward();
    //usleep(300000);
    ThreadAPI_Sleep(300);
    duty = 30;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 30) / 100)));
    //usleep(300000);
    ThreadAPI_Sleep(300);
    duty = 40;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 40) / 100)));
    //usleep(300000);
    ThreadAPI_Sleep(300);
    duty = 50;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 50) / 100)));
    //usleep(300000);
    ThreadAPI_Sleep(300);
    duty = 60;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 60) / 100)));
    //usleep(300000);
    ThreadAPI_Sleep(300);
    duty = 70;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 70) / 100)));
    //usleep(300000);
    ThreadAPI_Sleep(300);
    stopMotor();

    Display_printf(display, 1, 0, "Backward");
    duty = 40;
    PWM_setDuty(pwm, ((uint32_t) (((uint64_t) PWM_DUTY_FRACTION_MAX * 40) / 100)));
    setSpinningDirectionBackward();
    //sleep(2);
    ThreadAPI_Sleep(2000);
    stopMotor();

    sysIdentificationRoutineRunning = false;
}

/*
 *  ======== sysIdentificationThread ========
 */
void *driveProfileThread(void *arg0)
{
    ...
    
    /* Drive Profile */
    driveRoutine();
    
    ...

    return 0;
}

I hope the community can help me with this.

With kind regards
Patrick

  • Hi Patrick,

    It looks like you're trying to use polling rather than interrupts to synchronize the threads in your code. With TI-RTOS, the scheduler should be able to prioritize various threads, whether those are tasks or interrupts. You can use the System Analyzer in CCS to see execution times for various threads and time spent at idle.

    Also, I'm not quite sure how the ADC thread you linked above relates to what you're trying to do here. That thread is mainly talking about interleaving two separate ADC modules to double the effective ADC sampling rate. The actual maximum sampling rate per ADC module does not change.

    Anyway, I hope others from the community can chime in and help you.