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

Extend to support C.H.I.P. #49

Closed
roccomuso opened this issue May 27, 2016 · 15 comments
Closed

Extend to support C.H.I.P. #49

roccomuso opened this issue May 27, 2016 · 15 comments

Comments

@roccomuso
Copy link

Couldn't be possible to extend it to support also the C.H.I.P board?

The package doing it (chip-gpio) is actually inspired by onoff :) https://github.com/jeremyscalpello/chip-gpio

@fivdi
Copy link
Owner

fivdi commented May 27, 2016

Yeah, I saw the chip-gpio package and spoke with the author. We discussed an issue related to reading the value of an input pin using onoff. The discussion is at jeremyscalpello/chip-gpio#1 but it stopped before figuring out what the problem is.

Perhaps we can figure out what the problem is together as I don't have a CHIP board. The PIN labels on the CHIP board are different to the Linux GPIO numbers. For example, XIO-P0 corresponds to gpio408, so 408 is the number to use with onoff. The table below shows the PIN labels and the corresponding gpio numbers to use with onoff.

PIN label gpio gpio number used by onoff
XIO-P0 gpio408 408
XIO-P1 gpio409 409
XIO-P2 gpio410 410
XIO-P3 gpio411 411
XIO-P4 gpio412 412
XIO-P5 gpio413 413
XIO-P6 gpio414 414
XIO-P7 gpio415 415

Can you try some outputs and inputs and let me know if there are issues? If there are, we can try to resolve them together.

@roccomuso
Copy link
Author

@fivdi Yeah of course we can try to debug everything together, but I'm still wait to get mine. I should have a couple of them on june. :')

@fivdi
Copy link
Owner

fivdi commented May 27, 2016

Ok, let me know how things go and we can take it from there :)

@fivdi fivdi changed the title Extend to support more platforms Extend to support C.H.I.P. May 29, 2016
@roccomuso
Copy link
Author

I got them ;) Let me know how could we debug everything.

@fivdi
Copy link
Owner

fivdi commented Jul 10, 2016

@roccomuso Excellent, thanks for the feedback.

Let's start by checking to see what parts of onoff work on the CHIP.

Below is a test program that can be run on the CHIP. It assumes that XIO-P6 (gpio414) is connected to XIO-P7 (gpio415). To be on the safe side, XIO-P6 should be connected to XIO-P7 via a 1K current limiting resistor.

The test program configures XIO-P6 (gpio414) as an input and XIO-P7 (gpio415) as an output. It then sets the output to 0/1 using the onoff writeSync/write methods and reads the input (which is connected to the output) to see if has the same value. The test program also test interrupts.

"use strict";

var Gpio = require('onoff').Gpio,
  input = new Gpio(414, 'in', 'both'),
  output = new Gpio(415, 'out');

// Set output to 0 synchronously and check if input is also set to 0
output.writeSync(0);
if (input.readSync() === 0) {
  console.log('success: writeSync set output to 0');
} else {
  console.log('error: writeSync did not set output to 0');
}

// Set output to 1 synchronously and check if input is also set to 1
output.writeSync(1);
if (input.readSync() === 1) {
  console.log('success: writeSync set output to 1');
} else {
  console.log('error: writeSync did not set output to 1');
}

// Set output to 0 asynchronously ...
output.write(0, function (err) {
  if (err) {
    throw err;
  }

  // ... and check if input is also set to 0
  input.read(function (err, value) {
    if (err) {
      throw err;
    }

    if (value === 0) {
      console.log('success: write set output to 0');
    } else {
      console.log('error: write did not set output to 0');
    }

    // Set output to 1 asynchronously ...
    output.write(1, function (err) {
      if (err) {
        throw err;
      }

      // ... and check if input is also set to 1
      input.read(function (err, value) {
        if (err) {
           throw err;
        }

        if (value === 1) {
          console.log('success: write set output to 1');
        } else {
          console.log('error: write did not set output to 1');
        }
      });
    });
  });
});

function interrupt(err, value) {
  if (err) {
    throw err;
  }

  if (value === 1) {
    console.log('success: rising edge interrupt detected');
  } else if (value === 0) {
    console.log('success: falling edge interrupt detected');
  } else {
    console.log('error: unknown interrupt type detected');
  }
}

setTimeout(function () {
  // Set output (and input) to 0
  output.writeSync(0);

  // Start interrupt detection
  input.watch(interrupt);

  // Trigger a rising edge interrupt by setting output (and input) to 1
  output.write(1);

  setTimeout(function () {
    // Trigger a falling edge interrupt by setting output (and input) to 0
    output.write(0);

    setTimeout(function () {
      input.unexport();
      output.unexport();
    }, 1000);
  }, 1000);
}, 1000);

Please give the test program a try and post your findings. If everything functions as expected, the following should be displayed on the console:

success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1
success: rising edge interrupt detected
success: falling edge interrupt detected

@shy21grams
Copy link

@fivdi - I connected GPIO6 and GPIO7 using a 1k resistor and ran the test code above on a CHIP. It returned:
success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1

Edge detection works using CHIP_IO with GPIO2 and CSID0 connected using a 1k resistor.

So I updated your test code to reflect GPIO02 and CSIDO info. That test code was successful detecting the rising and falling edge with the with GPIO2 and CSID0 connected using a 1k resistor.
input = new Gpio(410, 'in', 'both'),
output = new Gpio(132, 'out');

I'm not sure why edge detection didn't work with GPIO6 and GPIO7 connected. Please let me know if I can help with other information. Thanks!

@fivdi
Copy link
Owner

fivdi commented Jul 19, 2016

So the onoff read, readSync, write, and writeSync methods appear to function as expected.

For some reason edge detection doesn't appear to function on XIO-P6 (gpio414). Edge detection does however appear to function on XIO-P2 (gpio410), when connected to CSID0 (gpio132).

Does edge detection function on XIO-P2 (gpio410) when XIO-P2 is wired to XIO-P7 (gpio415) via a 1K resistor? i.e., what's the output of the following test program?

"use strict";

var Gpio = require('onoff').Gpio,
  input = new Gpio(410, 'in', 'both'),
  output = new Gpio(415, 'out');

// Set output to 0 synchronously and check if input is also set to 0
output.writeSync(0);
if (input.readSync() === 0) {
  console.log('success: writeSync set output to 0');
} else {
  console.log('error: writeSync did not set output to 0');
}

// Set output to 1 synchronously and check if input is also set to 1
output.writeSync(1);
if (input.readSync() === 1) {
  console.log('success: writeSync set output to 1');
} else {
  console.log('error: writeSync did not set output to 1');
}

// Set output to 0 asynchronously ...
output.write(0, function (err) {
  if (err) {
    throw err;
  }

  // ... and check if input is also set to 0
  input.read(function (err, value) {
    if (err) {
      throw err;
    }

    if (value === 0) {
      console.log('success: write set output to 0');
    } else {
      console.log('error: write did not set output to 0');
    }

    // Set output to 1 asynchronously ...
    output.write(1, function (err) {
      if (err) {
        throw err;
      }

      // ... and check if input is also set to 1
      input.read(function (err, value) {
        if (err) {
           throw err;
        }

        if (value === 1) {
          console.log('success: write set output to 1');
        } else {
          console.log('error: write did not set output to 1');
        }
      });
    });
  });
});

function interrupt(err, value) {
  if (err) {
    throw err;
  }

  if (value === 1) {
    console.log('success: rising edge interrupt detected');
  } else if (value === 0) {
    console.log('success: falling edge interrupt detected');
  } else {
    console.log('error: unknown interrupt type detected');
  }
}

setTimeout(function () {
  // Set output (and input) to 0
  output.writeSync(0);

  // Start interrupt detection
  input.watch(interrupt);

  // Trigger a rising edge interrupt by setting output (and input) to 1
  output.write(1);

  setTimeout(function () {
    // Trigger a falling edge interrupt by setting output (and input) to 0
    output.write(0);

    setTimeout(function () {
      input.unexport();
      output.unexport();
    }, 1000);
  }, 1000);
}, 1000);

@shy21grams
Copy link

shy21grams commented Jul 22, 2016

success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1

That is the output after P2 and P7 were connected.

@fivdi
Copy link
Owner

fivdi commented Jul 22, 2016

@shy21grams: I'm not sure what's going on here.

If I understand you correctly, if XIO-P2 (gpio410) is connected to CSID0 (gpio132):

input = new Gpio(410, 'in', 'both'),
output = new Gpio(132, 'out');

Then the output of the test program is:

success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1
success: rising edge interrupt detected
success: falling edge interrupt detected

But if XIO-P2 (gpio410) is connected to XIO-P7 (gpio415):

input = new Gpio(410, 'in', 'both'),
output = new Gpio(415, 'out');

Then the output of the test program is:

success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1

Is this correct?

@nkolban
Copy link

nkolban commented Jul 29, 2016

I think we need to also be cognizant of what version of the Kernel is being used. There are two distributed by CHIP. One is at 4.3 and the other is at 4.4. They have distinct base addresses for GPIO usage.

@nkolban
Copy link

nkolban commented Aug 7, 2016

I have a couple of CHIPs and feel pretty handy in JavaScript and C. Is there anything I can offer up to assist in adding support for CHIP?

@fivdi
Copy link
Owner

fivdi commented Aug 7, 2016

To the best of my knowledge, interrupt detection should work on AP-EINT1, AP-EINT3, and XIO-P0 through XIO-P7. From the reports above, onoff appears to be able to detect interrupts in some cases and not in others. I don't understand why this is the case.

The first thing to do is to find out which GPIOs onoff can detect interrupts on. If it can detect interrupts, then all is ok. If it can't, the question is why.

The gpio numbers to use with onoff depends on the Linux kernel version.

PIN label gpio number used by onoff
AP-EINT1 193
AP-EINT3 35
XIO-P0 408 (4.3) 1016 (4.4)
XIO-P1 409 (4.3) 1017 (4.4)
XIO-P2 410 (4.3) 1018 (4.4)
XIO-P3 411 (4.3) 1019 (4.4)
XIO-P4 412 (4.3) 1020 (4.4)
XIO-P5 413 (4.3) 1021 (4.4)
XIO-P6 414 (4.3) 1022 (4.4)
XIO-P7 415 (4.3) 1023 (4.4)

@rkagerer
Copy link

rkagerer commented Aug 12, 2016

Ran the Jul 9 code (slightly modified to change 414 --> 1022 and 415 --> 1023) on my CHIP running 4.4 with a 1K resistor connecting P6 to P7, and got identical output to @shy21grams; no rising/falling edges detected:

chip@Chip1:~/nodehello$ sudo node onofftest1.js
success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1

Did the same as him and changed input pin to P2 (1018) and output to CSID0 (132) and got the edges:

success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1
success: rising edge interrupt detected
success: falling edge interrupt detected

Then tried the Jul 19 code (also modified to work with 4.4) with P2 (1018) inputting from P7 (1023), again with the same results as shy21grams:

chip@Chip1:~/nodehello$ sudo node onofftest1.js
success: writeSync set output to 0
success: writeSync set output to 1
success: write set output to 0
success: write set output to 1

So I can confirm the answer to the Jul 20 question is "Yes, that's correct".

I also inspected the binary value by hand, per the Jan 10 instructions here:

sudo sh -c 'echo 1018 > /sys/class/gpio/export'
sudo sh -c 'echo both > /sys/class/gpio/gpio1018/edge' # was 'none' by default
od -cx /sys/class/gpio/gpio1018/value

Yeilds 0x30 when XIO-P2 is grounded, and 0x31 when it's tied to 3.3V (same results as jeremyscalpello).

To answer the unanswered Jan 11 questions in the other thread:

chip@Chip1:~/nodehello$ cat testONE.js
var ONE = new Buffer('1');
console.log(ONE[0].toString(16));

chip@Chip1:~/nodehello$ node testONE.js
31

And the second small example using input.watch seems to behave correctly (outputting 0 or 1 depending on whether P2 is grounded).

Side note: A more kernel-agnostic way to find the correct pin numbers is described here, with some further discussion here, and a sample python algorithm. Seeing as Howie at NextThingCo says they're anticipated to change yet again in upcoming kernel 4.7, it might be a good idea to prepare.

Also note, according to the docs:

CHIP’s most easily available IO pins are the “XIO” pins on header U14. This is the “GPIO eXpander” that uses an I2C bus to create eight (8) convenient pins for GPIO. These use address 0x38 on the TWI bus 2. Other pins are available for GPIO if more than eight are needed.

I'm not sure how the CSID pins are connected vs XIO, but is it possible the I2C expander on the latter is the reason edge interrupts aren't occurring? Perhaps the schematics will help.

I'm limited on time for any follow-up troubleshooting, but sent @fivdi an email offering to buy / lend him a $9 CHIP to facilitate his efforts. Would also love to see an improved debounce mechanism implemented.

Hope this helps!

@fivdi
Copy link
Owner

fivdi commented Aug 28, 2016

@rkagerer Thanks for all the feedback and yes, it helps. I've ordered a few CHIP computers that should ship in October. Hopefully I can figure things out when they arrive.

@fivdi
Copy link
Owner

fivdi commented Dec 23, 2016

I finally got a CHIP computer and was able to do some testing. It turns out that onoff actually works well on the CHIP. Input, output and interrupt detection all function as expected.

So why doesn't the test program listed above detect interrupts in all cases?

The hardware setup for the test program is two GPIOs connected to each other via a 1K current limiting resistor. One GPIO is configured as an input, the other as an output. If the state of the output is changed an interrupt is expected on the input. However, depending on the GPIOs chosen, interrupt detection may not work.

If the two GPIOs chosen are any of XIO-P0 through XIO-P7, interrupt detection doesn't work. However, if the input GPIO is any of XIO-P0 through XIO-P7 and the output is anything other than XIO-P0 through XIO-P7, for example, any of CSID0 through CSID7, interrupt detection does work.

The reason for interrupt detection not functioning correctly is related how the PFC8574 I/O expander works. XIO-P0 through XIO-P7 are pins from the PCF8574 I/O expander broken out to the CHIPs GPIO header. When the test program changes the state of the GPIO output, it writes information to the PCF8574 I/O expander using the I2C bus. The value written to the GPIO output also changes the state of the GPIO input as both GPIOs are connected together. However, a side effect of this write operation on the I2C bus to the PCF8574 I/O expander is that it clears the interrupt. The interrupt ends up getting lost.

Section 8.1 of the PFC8574 I/O expander datasheet explains how interrupts can be lost.

Interrupt detection is possible on any of XIO-P0 through XIO-P7, AP-EINT1 and AP-EINT3. Initial tests show that interrupt detection on AP-EINT1 and AP-EINT3 is approximately three times faster than on XIO-P0 through XIO-P7.

Have fun with onoff on your CHIP computer :)

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

5 participants