Author Topic: Sleep-receive state machine with timeouts  (Read 140 times)

Offline Raffaele

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
Sleep-receive state machine with timeouts
« on: September 13, 2020, 05:53:13 PM »
Hi,
I'm trying to implement a state machine but I am having issues with the task.
I simply have two states: SLEEP and RX and I want to do

1) stay in SLEEP for T1 sec
2) after T1 sec go to RX
3) stay in RX for T2 sec (if something is received, aka interrupt on a pin, process data)

All these things work independently in my code. But I don't know how to properly activate the task


Code: [Select]
int const SLEEP = 1;
int const RX = 2;

extern void stateMachineTask(TTASKTABLE *ptrTaskTable){
switch (iState) {

case 0 :
steupIinterruptHandler();

iState = 1;
uTaskerMonoTimer('C', (DELAY_LIMIT) (0.5 * SEC), UTASKER_ACTIVATE);
break;

case SLEEP :

deactivate_data_processing();

// do sleep operations here

iState = RX;
uTaskerMonoTimer('C', (DELAY_LIMIT) (T1 * SEC), UTASKER_ACTIVATE);
break;

case RX :
activate_data_processing();

//if received interrupt, process data

iState = SLEEP;
uTaskerMonoTimer('C', (DELAY_LIMIT) (T2 * SEC), UTASKER_ACTIVATE);
break;
}
}

My major problem is that the interrupt is not triggered (it normally works). If I can suspend/resume the whole task that's fine too, but I don't know how to do it
« Last Edit: September 13, 2020, 05:56:00 PM by Raffaele »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3079
    • View Profile
    • uTasker
Re: Sleep-receive state machine with timeouts
« Reply #1 on: September 13, 2020, 11:46:20 PM »
Hi

I would use states and events to better control a state machine.

Could you try something like this?

Code: [Select]
// States
#define START_DELAY 1
#define SLEEP       1
#define RX          2

// Events
#define GO_TO_SLEEP 1
#define GO_TO_RX    2

#define MY_TASK     'C'

extern void stateMachineTask(TTASKTABLE *ptrTaskTable) {
    static int iState = 0;
    QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input
    unsigned char       ucInputMessage[HEADER_LENGTH];                   // reserve space for receiving messages
    int iEvent = 0;

    if (fnRead(PortIDInternal, ucInputMessage, HEADER_LENGTH) == 0) { // check task input queue
        iEvent = ucInputMessage[MSG_TIMER_EVENT];
    }

    switch (iState) {
    case 0:
        uTaskerMonoTimer(MY_TASK, (DELAY_LIMIT)(0.5 * SEC), GO_TO_RX);
        iState = START_DELAY;
        break;

    case START_DELAY:
        steupIinterruptHandler();
        // Fall-though intentionally
        //
    case SLEEP:
        if (iEvent == GO_TO_RX) {
            activate_data_processing();
            iState = RX;
            uTaskerMonoTimer(MY_TASK, (DELAY_LIMIT)(T2 * SEC), GO_TO_SLEEP);
            uTaskerStateChange(MY_TASK, UTASKER_ACTIVATE);
            break;
        }
        // do sleep operations here
        break;

    case RX:
        if (iEvent == GO_TO_SLEEP) {
            deactivate_data_processing();
            iState = SLEEP;
            uTaskerMonoTimer(MY_TASK, (DELAY_LIMIT)(T1 * SEC), GO_TO_RX);
            uTaskerStateChange(MY_TASK, UTASKER_ACTIVATE);
            break;
        }
        // if received interrupt, process data
        break;
    }
}

Regards

Mark