tessel/t2-firmware

pin.on 'change' event not working properly

Closed this issue · 7 comments

I am playing with the pin.pull right now and I am still experiencing some odd behavior. If I run a simple setInterval loop like the following it works fine... meaning I have the pin.pull('pulldown') set and when I push a button it sends 3.3V to that pin and will toggle back and forth between 0 and 1 as expected.

setInterval(function() {
    pin.read(function(err, val) {
        console.log('pull down val', val);
    });
 }, 500);

But, if I setup a change event on the pin it will only read the event the first time the button is pressed (it actually reads it twice for some reason) but it never returns to 0 an therefore the change event never fires again.

pin.on('change', function() {
    pin.read(function(err, val) {
        console.log('pull down val', val);
    });
});

@rwaldron I have tried to debug this on my own without luck yet... do you have any idea what might be causing this behavior?

All I have found so far is that the first time I push the button the "byte" value is 194 (for pin 2) and from that point on the "byte" value is only 130 or 131 depending on if it is high or low. So whatever causes the "byte" value to reflect the change event is only happing once?

var REPLY = {
  ACK: 0x80,
  NACK: 0x81,
  HIGH: 0x82, //=130
  LOW: 0x83, //=131
  DATA: 0x84,

  MIN_ASYNC: 0xA0,
  ASYNC_PIN_CHANGE_N: 0xC0, //=194 for pin 2
  ASYNC_UART_RX: 0xD0
};

Sorry, it seems I missed this when you first posted. Will try to repro now

Ok, I put together this circuit:

And ran this code:

[2, 5, 6, 7].forEach(index => {
  tessel.ports.A.pin[index].on('change', function() {
    console.log(index);
  });
});

And I'm able to observe change events for the life of the program. What I find problematic is that I don't know the state of the pin when that change event is fired. I'm going to attempt to co-opt bit 3 as a "value field", ie.

With a console.log(replyBuf); on line 173 of tessel-export.js.

Pin Byte Bits: As-is Proposed Bits: High
2 0xc2 0b11000010 0b11001010
5 0xc5 0b11000101 0b11001101
6 0xc6 0b11000110 0b11001110
7 0xc7 0b11000111 0b11001111

I wasn't using the resistor (as shown in your example) because I was using the built-in pulldown/pullup resistors running the code below. I just re-tested it based on what you sent and it seems to work fine without the .read() within the .on('change') event.

This doesn't work past the first time the event is fired...

var tessel = require('tessel'); // import tessel

var pin = tessel.port['B'].pin[2];
pin.pull('pulldown');

pin.on('change', function() {
    this.read(function(err, val) {
        console.log('val', val);
    });
});

This works every time the event is fired...

var tessel = require('tessel'); // import tessel

var pin = tessel.port['B'].pin[2];
pin.pull('pulldown');

pin.on('change', function() {
   console.log('change event');
});

I guess, if you use .on('rise') or .on('fall') you will effectively know the value without even having it available.

Cool. I also think it's important that you should never have to also ask for the value when you get a change event... so I implemented my idea above and it works exactly as I'd hoped. Bit 3 of the interrupt response byte was not in use, bits 0, 1 & 2 were used to indicate that a "change" occurred on a "pin". You could know what pin, but not what its state was... so I put the state in bit 3 and it works perfectly. Patch and tests to follow.

This will definitely work, but I still don't understand why the .read() within the .on('change') event would cause the problem I was seeing? I'm just curious as to what was happening I guess.

I played with this some more and discovered that it works fine with .rawRead() but .read() definitely doesn't work when called within the callback of the .on('change') event.

var tessel = require('tessel');
var tesselPort = 'B';

var changeCount = 0;

var pins = [2, 5, 6, 7];

// works with .rawRead() but not with .read()
pins.forEach(pinNum => {
    tessel.port[tesselPort].pin[pinNum].pull('pulldown');
    tessel.port[tesselPort].pin[pinNum].on('change', function() {
        changeCount++;
        console.log('pin:', pinNum, 'changeCount:', changeCount);

        // this works
        this.rawRead(function(err, val) {
            console.log('val:', val);
        });

        // this doesn't work
        /*
        this.read(function(err, val) {
            console.log('val:', val);
        });
        */

    });
});

setImmediate(function() {
    console.log('ready');
});