Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Digital Writes: Feature Proposal #181

Open
dtex opened this issue Oct 20, 2017 · 4 comments
Open

Multiple Digital Writes: Feature Proposal #181

dtex opened this issue Oct 20, 2017 · 4 comments

Comments

@dtex
Copy link
Contributor

dtex commented Oct 20, 2017

On digitalWrites I would like to be able to call writeToTransport once instead of once for each pin.

My plan was to either overload digitalWrite with arrays or create a new method (i.e. digitalWriteMulti).

For example:

// digitalWriteMulti(pins, values);

digitalWriteMulti([1,2,3,4], [1,0,1,0]);
// Results in one writeToTransport on nextTick

- or -

digitalWriteMulti([1,2,9,11], [1,0,1,0]);
// Results in two writeToTransports on nextTick. One for each port

I want this because I believe that I can get a reasonable speed on stepper motors with whole or half steps using just standardFirmata.

Perhaps there is already a way to do this?

@soundanalogous
Copy link
Member

One way to do this would be to add a writeDigitalPort(portNumber, portValue) method. You can set up to 8 pins at once this way, each pin is a bit. You'd just have to make sure that the motor is wired to pins in the same port. In firmata ports are allocated per 8 digital pins in order counting up from 0 so port0 is pins D0-D7, port1 is pins D8-D15, etc.

@dtex
Copy link
Contributor Author

dtex commented Oct 21, 2017

I thought about that, but the 8-pins per port is unique to firmata and I need to create something that will work for all the different IO plugins. writeDigitalPort doesn't make sense on other platforms. That's the reason I wanted to handle the pin to port stuff in firmata.js

@dtex
Copy link
Contributor Author

dtex commented May 6, 2018

What about an enqueueDigitalWrite(pin, value) method that builds a list of write commands and updates the ports on next tick? That way we would only have to write once during each pass through the event loop. Client libraries would not have to manage ports/port states, they could just check for the existence of enqueueDigitalWrite and if it exists use it instead of digitalWrite.

// psuedocoding

let digitalWriteQueue = [];

Board.prototype.enqueueDigitalWrite = function(pin, value) {
  if (!digitalWriteQueue.length) {
    process.nextTick(processDIgitalWriteQueue);
  }
  digitalWriteQueue.push([pin, value]);
};

function processDigitalWriteQueue() {
   let portsToWrite = [];
   digitalWriteQueue.forEach(command => {
     let port = command[0] >> 3;
     portsToWrite.push(port);
     let bit = 1 << (command[0] & 0x07);

     this.pins[pin].value = value;

     if (value) {
       this.ports[port] |= bit;
     } else {
       this.ports[port] &= ~bit;
     }
  });
  portsToWrite.forEach(port => writeDigitalPort);
});

function digitalWritePort(port) {
  writeToTransport(this, [
    DIGITAL_MESSAGE | port,
    this.ports[port] & 0x7F,
    (this.ports[port] >> 7) & 0x7F
  ]);
}

@dtex
Copy link
Contributor Author

dtex commented May 20, 2018

I've finally got the new stepper class in J5 far enough along that I was able to test this with a full J5 stack and it doubled the speed that I could move a stepper using standardFirmata. Gonna submit a PR soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants