How to Use UART multitasking ?

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello community

 

i have made a programme that reads GPS data from a gps module and then send it to my server via GPRS using a GSM module (a car tracking system) which can be pretty simple

 

the tracking is done by sending data frames every X second (this variable can be modified)

 

the thing is that i wanted to send commands from the server to my system so i can change some stuf remotly (like X second mentioned previosly)

 

and it worked fine but whene i put the two modes togather (the tracking mode + the waiting for commands mode) there was some bugs which are logical because of the interference of the two modes

 

PS : i am not using any delay function, i used the millis() function which is better then delay when multitasking but still the interference didn't go away

 

the reason is that sometimes whene i am sending commands from the server, at that same time my system is in the sending process which requires to read the gsm buffer to confirme that it is connected and the sending is good and with this informations comes the command that i sended so automaticly it is droped away to finish sending

 

here is a demonstration on how my system is working

 

 

so i am asking if it is possible to read the GSM buffer (UART) in a parallel way one for tracking and one for reading commands

 

thank you

Hello World!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you using two different UARTS (one for GPS and one for GPRS) or is it one UART that you are somehow sharing between the two channels?

 

It does sound like the general problem of sharing resources between multiple tasks. You have two tasks and both want to be able to communicate with the GPRS, right? So there are two options. One is to implement a mechanism to make sure that at any time only one task can access the UART (you typically use a "mutex" for this). The other option is to have one and only one task that accesses the GPRS, and let that task handle the multiplexing of the two different GPRS communication tasks (perhaps with some kind of queue).

/Jakob Selbing

Last Edited: Sun. Jan 14, 2018 - 12:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The "neat" / "professional" way is to make all your uart routine's interrupt controlled.

Interrupts are a very cool thing and they can do stuff independent from the main program.

For example the main program would prepare a string to be send (in an array) and then start the interrupt controlled sending of that data.

Another interrupt can collect incoming data and put it in a buffer (array)  (circular buffer) and set a flag if a complete packet of data is received.

 

--------

Because your communication is probably quite slow (9600 baud or so ?) there are also alternatives.

You can chop you program into little pieces.

Instead of sending / receiving whole packets, you can modify your code to send/receive separate bytes.

main( ) {
    for(;;) {
        // Get data from Uart.
        if( uart_has_data()) {
            read_uart_data();
            if( uart_message_complete()) {
                ...
            }
        }

        // Send data to uart.
        if( data_to_send()) {
            send_next_byte();
        }
    
        // Do something else...
    }
}

Or you can hide the internals a little bit further:

main( ) {
    
    for(;;) {
        uart_incoming_statemachine();
        uart_outgoing_statemachine();
    }
}

State machines are a very cool thing. Check them out.

They remember  the "state" in which they are and which is dependendt on past events.

A small pseudocode example for a state machine for receiving some bytes below.

I've ommited quite some things to make it easy to read.

uart_incoming_statemachine() {
    
    static enum { wait, receive, finished } State;
    static char array [20];
    
    switch ( State) {
    case wait:
        if( data_received()){
            bytes = 0;
            State = receive;
        }
        break;

    case receive:
        if( data_received()) {
            array[bytes] = data_read();
            ++bytes;
            if( bytes >=12) {
                State = finished;
            }
        }
        break;
        
    case finished;
        // Do something with your received data.
        State = wait;
        break;
    }

One of the tricks in statemachines is to run the statemachine again if the internal state changed.

You can do that by wrapping your state machine in a do- while loop.

    State oldstate = state;
    
    do {
        oldstate = state;
        switch() {
        case A:
            break;
        case B:
            break;
        case C:
            break;
        }
    }while (oldstate != state)

 

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
The "neat" / "professional" way is to make all your uart routine's interrupt controlled ... circular buffer

Absolutely!

 

And note that's Circular Buffers (aka Ring Buffers or FIFOs) for both transmit and receive - something like this:

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The reference to millis() suggests Arudino. Thus the uarts should have circular buffers already.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

One more tip, if this arduino, be sure your using hardware that can support more then one serial port in hardware, i.e not an uno or m328 based arduino.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

And note that's Circular Buffers

They look rectangular to me......

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

laugh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

    If your GPRS module UART interface happens to have hardware control lines like RTS and CTS, you could get away with only one UART interface on your microcontroller.