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

Reading Digital Pin State #1371

Closed
MitchGaines opened this issue Aug 10, 2017 · 4 comments
Closed

Reading Digital Pin State #1371

MitchGaines opened this issue Aug 10, 2017 · 4 comments

Comments

@MitchGaines
Copy link

MitchGaines commented Aug 10, 2017

Hello there,

Right now I am rewriting an arduino library in order to be able to use it in johnny-five. I essentially have it rewritten except for the logic surrounding johnny-five's digitalRead function. My code is shown below...

Essentially what I am doing is reading a stream of bits from the sensor I am using. I cannot simply create a sensor object because I need both data and clock pins which, to my understanding, is not supported. The issue here lies in the fact that the handler function for board.digitalRead(...) does not run unless the pin state changes. Is there any way to simply just read the current state of a digital pin without major logic changes in the codebase I have?

var board = new five.Board();
var precise = new NanoTimer();
var clk_pin = 7;
var data_pin = 4;
var cycle = "25u";

function mcsReadBit(){
  board.digitalWrite(clk_pin, 0);
  precise.setTimeout(function(){
    board.digitalWrite(clk_pin, 1);

    var r = data_stream.value;
    precise.setTimeout(function() {
      console.log(r);
      return r;
    } , '', cycle);
  }, '', cycle);
}

function mcsReadByte(){
  var bits = 8;
  var val = 0x80;
  var b = 0;

  while(bits > 0) {
    if(mcsReadBit()){
      b |= val;
    }

    val = val >> 1;
    --bits;
  }

  board.pinMode(data_pin, board.io.MODES.INPUT);
  board.digitalWrite(data_pin, 0);
  return b;
}

EDIT: fixed sync vs async logic; still doesn't work

@kdorosh
Copy link

kdorosh commented Aug 10, 2017

ctk

@soundanalogous
Copy link

Related: firmata/firmata.js#167.

@rwaldron
Copy link
Owner

rwaldron commented Aug 10, 2017

Pin state reading aside, there are a number of issues with the code. Let try to make helpful points here.

The first issue I'm seeing is that there is no board.on("ready", ...), maybe that was just omitted?

There is no place where the mode is set for clk_pin

Next is an issue with return values:

function mcsReadBit(){
  board.digitalWrite(clk_pin, 0);
  precise.setTimeout(function(){
    board.digitalWrite(clk_pin, 1);

    var r = data_stream.value;
    precise.setTimeout(function() {
      console.log(r);
      return r;
    } , '', cycle);
  }, '', cycle);
}

Based on the call to mcsReadBit() further down in the code, I believe you expect this function to return r; (as shown in the code itself), but that's not what's actually happening. The return r; is returning for the callback function passed to the inner-most precise.setTimeout(...):

precise.setTimeout(function() {
  console.log(r);
  return r;
} , '', cycle);

Which actually means it's returned to nowhere since precise.setTimeout() doesn't capture the return value of the task callback. What is actually occurring is that your mcsReadBit() always returns undefined; which in turn means this condition is never met:

if(mcsReadBit()){
  b |= val;
}

Given the operations inside mcsReadBit(), the function could never be expected to return synchronously.

What is the source of data_stream.value;?

I put together a button circuit to try this out:

const five = require("johnny-five");
const NanoTimer = require("nanotimer");

const board = new five.Board();
const precise = new NanoTimer();

board.on("ready", function() {

  function readByte(callback) {
    const {INPUT, OUTPUT} = board.io.MODES;
    const clock = 7;
    const data = 4;
    const cycle = "25u";
    let bits = 8;
    let val = 0x80;
    let byte = 0;

    function read() {
      let bit = 0;
      board.digitalWrite(clock, 0);
      precise.setTimeout(() => {
        board.digitalWrite(clock, 1);
        bit = board.pins[data].value;
        // Remove this
        console.log(bit);
        precise.setTimeout(() => {
          if (bit) {
            byte |= val;
          }
          val = val >> 1;

          if (--bits) {
            read();
          } else {
            callback(byte);
          }
        } , '', cycle);
      }, '', cycle);
    }

    board.pinMode(clock, OUTPUT);
    board.pinMode(data, INPUT);
    board.digitalRead(data, _ => _);
    read();
  }

  readByte(byte => {
    console.log(byte);
  });

  board.repl.inject({
    byte() {
      readByte(byte => {
        console.log(byte);
      });
    }
  });
});

Type: byte() (<enter>) in the repl to read a byte. Since I'm just using a button and I have nothing attached to the clock pin, this is the output I see:

$ node eg/mcs-read.js
1502400429478 Available /dev/cu.usbmodem1411
1502400429486 Connected /dev/cu.usbmodem1411
1502400431169 Repl Initialized
>> 0
0
0
0
0
0
0
0
0

>> byte()
undefined
>> 0
0
0
0
0
0
0
0
0

>> byte()
undefined
>> 1
1
1
1
1
1
1
1
255
>> .exit
1502400444587 Board Closing.

You can see when I'm holding the button and when I'm not. I have no idea if this will work for you actual use case, but it will at least serve as an illustrative tutorial w/r to receiving async pin report data.

@MitchGaines
Copy link
Author

MitchGaines commented Aug 11, 2017

Ahhh, I see what you're saying there. I intentionally omitted the board.on("ready", ...) as it wasn't entirely in the scope of my issue. Lots of good points though.. going to go fix my code now and implement that logic throughout. If I get it functional, I'll post the results and close the issue; if not, I'll close it as you sufficiently answered my question. Thanks a ton!

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

4 participants