How to carry out functions in a sequential manner

Posted on
  • Hi
    I'm new to Javascript/Espruino and trying to get a 4D Systems oled gmd-128 Display (serial connection) to work.
    After each command is sent the display responds with an ack(0x06) if successful and next command should not be sent until ack is received.

    I have managed to get the display working by using the setTimeout('func',td);
    but this is not the most efficient way.

    I would appreciate any info has to how to "force" sequential operation ie
    Send command 1
    wait for ack
    Send command 2
    wait for ack
    etc

    regards
    Gerry

    ps hope this makes sense !

  • Hi Gerry,

    Yes - no problem! It's probably most efficient to think of it like:

    • Send command 1
    • When ack received, send command 2
    • When ack received ....

    So you might want something like this:

    var ser = Serial1;
    var commands = [];
    var allSent = true;
    
    function sendCommand(cmd) {
     if (allSent) { 
       // if everything was sent, start again
       Serial.write(cmd);
       allSent = false;
     } else {
      // otherwise we're sending - just push the new command onto the end
      commands.push(cmd);
     } 
    }
    
    ser.on('data', function(d) {
      for (var i in d)
        if (d[i]=="\x06") {
          if (commands.length) { 
            // send command off the start of the list
            Serial.write(commands.shift());
          } else {
            // signal we're done
            allSent = true;
          }
        }
    });
    

    Then you just call sendCommand with each command, and they get queued up.

    I guess you might want some kind of timeout in there as well though?

  • Is the ack something you receive serially / over RX from the module?

    If so, use serial.onData(callback) with callback function receiving the ack and triggering the next command...

    For use in application logic, this is of course a bit cumbersome... Therefore, you may use a FIFO with some triggering methods inbetween your app and the display which takes care of feeding the display module with the comands in a timely correct manner/sequence, where as the application just pushes to the FIFO without having to be time aware.

    The FIFO is of course a buffer and could over-grow if you have a run-away in your application.

    Some code 'in the rough':

    var dsp =
    { cmds: [] // fifo
    , idling: false
    , serial: null
    , exec: function(cmd) { // cmd to send to display
        this.cmds.push(cmd);
        if (this.idling) { 
          this.idling = false;
          this._tx();
        }
      }
    , _tx: function() {
        this.serial.write(this.cmds.splice(0,1))­;
      }
    , _rx: function(data) {
        if (this.cmds.length > 0) { 
          this._tx(); 
        } else { 
          this.idling = true;
        }
      }
    , connect: funcrtion(serial) {
        this.serial = serial;
        this._rx.bind(this);
        this.serial.on('data',this._rx);
        this.idling = true;
        this.exec(""); // may be some initializations...
      }
    }
    
    Serial1.setup(9600); // setup Serial1
    dsp.connect(Serial1);
    dsp.exec("....."); // 1st cmd
    dsp.exec("....."); // 2nd cmd
    dsp.exec("....."); // 3rd cmd
    

    This code has no error handling (over flow, out of synch, etc.) in place. For examples:

    • .exec() needs overflow handling (some reasonable limit to the fifo size check)
      - ._rx() needs check ack data received and accdingly acted on
      - some state / timout has to be put in place in case communication gets 'out of sync'

      A first enhancement is to leave the command in the fifo (using this.serial.write(this.cmds[0]);) until 'good' ack is received and then removed (this.cmds.splice(0,1);). If 'bad' acc is received (or timout hits), re-send/re-print or drop - with or without error logging - has to be considered.

      The .connect() is currently minimal. You may extend it with additional parameter(s) - string (or array of strings) that include some display module initialization that has to be done anyway.

      Can you share the code how you got your display initially working?
  • @Gordon, what is the reason to go for a loop in the callback, since it is serialized anyway (at best one ack for every cmd and only ack can/should trigger the next cmd)?

  • Hi
    Thank you both for your prompt replies.

    regards

    Gerry

  • @allObjects true - I could just check with indexOf. I was assuming that there might be other characers sent - but if not, you could just use the occurrence of more data to trigger sending the next command.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

How to carry out functions in a sequential manner

Posted by Avatar for GKeely @GKeely

Actions