rwaldron / galileo-io

Intel Galileo & Intel Edison IO Plugin for Johnny-Five
http://johnny-five.io
MIT License
101 stars 26 forks source link

Digital write not working on PWM pins, Gen 2 #16

Closed ryoshu closed 9 years ago

ryoshu commented 9 years ago
var Galileo = require("galileo-io");
var board = new Galileo();
var pin = 11; //use any PWM pin

board.on("ready", function() {
  var byte = 0;
  this.pinMode(pin, this.MODES.OUTPUT);

  setInterval(function() {
    board.digitalWrite(pin, (byte ^= 1));
  }, 500);
});

Expected behavior: Digital write should send HIGH on all digital pins.

rwaldron commented 9 years ago

Is this also on the latest IoT kit image? Can you provide the version? Really sorry all of these errors are getting in your way and I'll work on addressing them ASAP

ryoshu commented 9 years ago

It's the latest version: http://software.intel.com/iot. Let me know if you need anything else. Thanks!

rwaldron commented 9 years ago

I just updated the mraa bindings used by Galileo-IO to the latest release and tested digital pins 2 through 13 to confirm digital writes and all pins worked correctly. Please run the following and post back the output, thanks!

node -e 'console.log(require("mraa").getVersion());'
michaesc commented 9 years ago

I've hit this problem as well on both Galileo generations. Not sure how to debug this, but:

GALILEO GEN1 FW 1.0.3

This is while using a fresh install of the current IoT Devkit image 1.1 [1].

[1] http://iotdk.intel.com/images/1.1/iot-devkit-201409031152-mmcblkp0.direct.bz2

$ node -e 'console.log(require("mraa").getVersion());' v0.5.0-12-g3898182

opkg info libmraa0

Package: libmraa0 Version: 0.5.0.12 Provides: libmraa-dev, libmraa-dbg, libmraa-doc, libmaa-dev, libmaa-dbg, libmaa-doc, libmaa0 Replaces: libmraa-dev, libmraa-dbg, libmraa-doc, libmaa-dev, libmaa-dbg, libmaa-doc, libmaa0 Conflicts: libmraa-dev, libmraa-dbg, libmraa-doc, libmaa-dev, libmaa-dbg, libmaa-doc, libmaa0 Status: install user installed Section: libs Architecture: i586 Maintainer: Intel IoT-Devkit MD5Sum: 473e2b3092bf293045acbebf640286dc Size: 189072 Filename: libmraa0_0.5.0.12_i586.ipk Source: https://github.com/intel-iot-devkit/mraa Description: mraa built using CMake Installed-Time: 1411900482

GALILEO GEN2 FW 1.0.2 (Not current!)

I'm not sure about the version of the IoT Devkit image version on this board, but judging by the libmraa(3) version I assume it's 1.0:

$ node -e 'console.log(require("mraa").getVersion());' v0.4.4

opkg info libmraa0

Package: libmraa0 Version: 0.4.4-r0 Depends: libgcc1 (>= 4.8.2), python-core, libpython2.7-1.0 (>= 2.7.3), libstdc++6 (>= 4.8.2), libc6 (>= 2.19) Status: install user installed Architecture: i586 Installed-Time: 1408097108

...didn't need to sanitize any of that, it's the exact output of command line.

michaesc commented 9 years ago

An important clue is that while using the Intel XDK [1](latest version with IoT components) to upload and run a blink example similar to ryoshu's code, it actually works (the light blinks) on the Gen2 board with 1.0.2 firmware (the identical configuration as indicated in the previous comment [2].) Since the XDK uploads NodeJS projects to the Galileo, this clue could be useful in narrowing the problem scope.

[1] http://xdk-software.intel.com/ [2] https://github.com/rwaldron/galileo-io/issues/16#issuecomment-57081965

rwaldron commented 9 years ago

Sorry, but I've never used the XDK. When working directly on Galileo-IO or using it as an IO Plugin for Johnny-Five in projects, I just SSH to the board and use rsub to open files from the board for editting in Sublime Text.

rwaldron commented 9 years ago

Despite the obviously negative tone of this deleted part of your comment, there were some valid questions:

If you're feeling generous, then please share how you fix these things so that we can learn and do it ourself,

  1. SSH to board
  2. touch test.js
  3. rsub test.js
  4. Write out the code in test.js that will hopefully produce the error. In best cases, the code has been provided in the bug report.
  5. In terminal: node test.js
  6. Make best possible assertion about observed behavior.

I have a script for files in galileo-io/lib/* that will scp the files to the board when changes are made locally.

If problems can be reproduced, write tests in test/* and work towards making them pass as well as observing the correct behavior of the original test case program.

Are most problems resembling this one in the bindings of libmraa(3)? Source file?

I'm not sure how to answer this since I haven't been able to reproduced the bug. It's still unclear to me how this bug was encountered—no one has provided an actual "steps to reproduce".

rwaldron commented 9 years ago

As I mentioned in my email response, the following must be confirmed before a Galileo-IO version is published to npm

  1. Blink an led on pins 2-13
  2. Log a button's state on pins 2-13
  3. Fade an led through 2hz phases (0-255, 255-0, 500ms each) on all PWM pins
  4. Sweep a servo from 0-180, 180-0 on all PWM pins
  5. Log sensor readings on all analog pins
ryoshu commented 9 years ago

root@quark016d09:~/projects/coral-test# cat /etc/version 201409031130

root@quark016d09:~/projects/coral-test# node -e 'console.log(require("mraa").getVersion());' && node -v v0.4.5 v0.10.28

Sorry about the delay!

rwaldron commented 9 years ago

@ryoshu thanks! Can you update the libmraa0 bindings to the latest version (will be easier for us to coordinate)

echo "src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf
opkg update
opkg install libmraa0
michaesc commented 9 years ago

'# opkg upgrade' Upgrading libmraa0 on root from 0.4.4-r0 to 0.5.0.12... Downloading http://iotdk.intel.com/repos/1.1/intelgalactic/libmraa0_0.5.0.12_i586.ipk. Upgrading upm on root from 0.1.6-r0 to 0.1.8.28... Downloading http://iotdk.intel.com/repos/1.1/intelgalactic/upm_0.1.8.28_i586.ipk.

When I tried upgrading on Gen2 it didn't help.

And possibly related, setting GPIO pins manually seems to be defective:

Note: On Gen2, GPIO7 == Pin13

echo -n "7" >/sys/class/gpio/export

-sh: echo: write error: Device or resource busy

echo -n "out" >/sys/class/gpio/gpio7/direction

echo -n "1" >/sys/class/gpio/gpio7/value

echo -n "0" >/sys/class/gpio/gpio7/value

Note: Last two commands do not blink pin 13

Maybe the problem we're seeing is not even in user space?

rwaldron commented 9 years ago

That looks like a pretty serious issue. As a software engineer, I've spent 15 years assuming that the code I wrote was the source of the bug and so I sometimes forget when dealing with hardware that this is not always the case.

ryoshu commented 9 years ago

root@quark016d09:~/projects/coral-test# echo "src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf root@quark016d09:~/projects/coral-test# opkg update Downloading http://iotdk.intel.com/repos/1.1/iotdk/Packages. Updated list of available packages in /var/lib/opkg/iotdk. Downloading http://iotdk.intel.com/repos/1.1/intelgalactic/Packages. Updated list of available packages in /var/lib/opkg/mraa-upm. root@quark016d09:~/projects/coral-test# opkg install libmraa0 Upgrading libmraa0 on root from 0.4.5-r0 to 0.5.0.12... Downloading http://iotdk.intel.com/repos/1.1/intelgalactic/libmraa0_0.5.0.12_i586.ipk. Removing package libmraa-dev from root... Removing package libmraa-doc from root... Removing obsolete file /usr/lib/libmraa.so.0.4.5. Configuring libmraa0. root@quark016d09:~/projects/coral-test# node -e 'console.log(require("mraa").getVersion());' v0.5.0-12-g3898182

Same issue. PWM pins don't blink, but non-PWM pins do.

Let me reimage some another SD card with the default Yocto image, rather than the IoT Devkit. That could help isolate where the issue is.

rwaldron commented 9 years ago

Side note: I've never been able to blink the on-board led by writing to pin 13's gpio via sysfs (on gen 1). I have a thread on the intel community forums that was never answered in any helpful way: pin 13 is not actually connected to the onboard led, so how does the gen 1 galileo know to control the onboard led when a user uploads the blink.ino program via the IDE (which uses pin 13)?

(Note, this is unrelated to our current issue)

rwaldron commented 9 years ago

By any chance, do you have a sketch running?

ryoshu commented 9 years ago

Not currently. I've had a sketch running before, but now I remove it and reboot, just in case there's some pin exporting strangeness (I've also killed the process before, but I haven't checked to see if that causes pin exporting weirdness).

rwaldron commented 9 years ago

Let me reimage some another SD card with the default Yocto image

Just a heads up, this doesn't ship with the libmraa0 bindings and apparently cannot be installed either: https://github.com/intel-iot-devkit/mraa/issues/2#issuecomment-54199201, which means this bug can't actually exist there. Galileo-io will fall back to filesystem gpio/sysfs when libmraa0 isn't present, so your code will be in an entirely different path.

ryoshu commented 9 years ago

Hrm. Thanks for the heads up. What OS/version are you using? I've tried a few Gen 2 boards now and two fresh installs of the latest IoT devkit.

rwaldron commented 9 years ago

iot-devkit (Intel IoT Development Kit) 1.1

201409031130

ryoshu commented 9 years ago

Very strange! I'll do a step-by-step unboxing tomorrow and post the steps + results using a brand new board and brand new download.

sethismyfriend commented 9 years ago

I'm having similar issues with the PWM pins (digital works well). Using the latest IOTDK image and having updated with opkg

root@quark0171ae:~# node -e 'console.log(require("mraa").getVersion());'
v0.5.0-12-g3898182

I ran servo-write.js with a servo motor on pin 3 (power on 5v, and ground pin on ground) and then analog-write.js with an LED just to be sure.

It flickers for a second and then there is no output. I'm going to look at running the python examples that come with MRAA to help narrow down what the issue is next.

sethismyfriend commented 9 years ago

I pulled the MRAA repo and went into the examples/python folder.

Both the cycle-pwm.py and blink-io8 examples are working well for me.

There are four javascript examples in the directory as well:

AioA0.js  Blink-IO.js  GPIO_DigitalRead.js  GPIO_DigitalWrite.js

I tested all four with my build and they work. Analog read from A0 and writing out to pin 5 which is a PWM pin - but there is no PWM examples included with MRAA - or servo examples as far as I can tell.

rwaldron commented 9 years ago

@sethismyfriend thanks for doing this research, super helpful :) I'll focus my attention on PWM for Servo controlling

ryoshu commented 9 years ago

Step-by-step from this morning - https://gist.github.com/ryoshu/b3a59142c46e5081704f

sethismyfriend commented 9 years ago

@ryoshu - can you try running some of the examples in MRAA to confirm if they work?

rwaldron commented 9 years ago

@sethismyfriend I have a big changeset coming, will ping when ready

ryoshu commented 9 years ago

@sethismyfriend Blink on pin 9 and analog read on pin A0 confirmed in the MRAA examples.

rwaldron commented 9 years ago

About to push this release, just waiting for new tests to run through travis

rwaldron commented 9 years ago

@ryoshu @sethismyfriend v0.3.2 is now on npm

This is the most relevant commit: https://github.com/rwaldron/galileo-io/commit/389c91e806ab935b79274060c419ea79601993a7

rwaldron commented 9 years ago

Actually... v0.3.3

sethismyfriend commented 9 years ago

sweet - will try this before the end of the day

sethismyfriend commented 9 years ago

Servo example confirmed to work on my build!

ryoshu commented 9 years ago

Digital write on PWM pins still not working for me. Confirmed digital write works through Arduino IDE. Confirmed still working using MRAA.

rwaldron commented 9 years ago

Can you paste the JS code?

ryoshu commented 9 years ago
var board = new Galileo();
var pin = 9;
board.on("ready", function() {
  console.log("ready");
  var byte = 0;
  this.pinMode(pin, this.MODES.OUTPUT);

  setInterval(function() {
    board.digitalWrite(pin, (byte ^= 1));
  }, 500);
});
rwaldron commented 9 years ago

I'm going to assume that includes: var Galileo = require("galileo-io");?

I'm wondering how you are running this code? Specifically, do you ssh to the board, then type something like node file.js? Or is this controlled by some other means?

What is the output of the program run?

You mentioned trying sketches again, are you certain those sketches are properly removed after testing them?

What is the current installed version of Galileo-IO?

ryoshu commented 9 years ago

The require is in there. Sorry about that!

I've used iTerm with screen, ssh from Terminal and Putty on Win 8.1. I use vi to create and edit the files while logged into the board.

The output of the program is "ready".

re: sketch, "kill -14 {pid}" of the sketch and rm'd it from /sketch. I've also rebooted after removing the sketch. kill left the pin high, so I used node and MRAA to turn it low.

I've tried running some examples in /eg. Still no luck. Version is 0.3.3 according to package.json.

I'll retest all pins on digital write (PWM and regular) as I only tested pin 9 and 13 this time. I'll also hook up another Gen 2 and go through the tests again. And I've got some Gen 1s lying around so I'll try one of those and let you know if any of them work.

rwaldron commented 9 years ago

Are you in Brooklyn today?

ryoshu commented 9 years ago

Alas, no. Sent you an email.

rwaldron commented 9 years ago

I feel completely insane right now... I've using existing code that was "basically the same" as your examples, but operating on pin 3 (also PWM) and everything works correctly—I just tried your code exactly as is—on pin 9—and reproduced the issue. Hold off on testing until I ping back.

rwaldron commented 9 years ago

Also, I created a scoping mistake when I introduced IS_TEST_MODE that was causing the fallback path to be taken.

rwaldron commented 9 years ago

Here's what I think happened...

  1. Hopefully I had fixed whatever issues existed previously.
  2. I wrote some tests and added what I thought would be an innocuous global flag
  3. The flag turned out to be throwing an exception inside of a try/catch that exists explicitly to do the mraa feature detection.
rwaldron commented 9 years ago

@ryoshu can you try v0.3.4

sethismyfriend commented 9 years ago

I had an issue where if I had another instance of node running somewhere else the servo example was not working.

BTW - @rwaldron the servo is humming that I am using, a HiTec HS-425BB. That means that the frequency calculation for the motor might not be right. I'll play around with the code a bit to see if I can reduce the humming.

sethismyfriend commented 9 years ago

analog_write.js is working well.

I tried running analog_read and encountered this error on my board:

root@clanton:~/galileo-io/eg# node analog-read.js
READY

/home/root/galileo-io/lib/galileo.js:84
        processRead(board, report, board.pins[report.index].read());
                                                            ^
TypeError: Object #<Pin> has no method 'read'
    at /home/root/galileo-io/lib/galileo.js:84:61
    at Array.forEach (native)
    at Object.read [as _onImmediate] (/home/root/galileo-io/lib/galileo.js:82:15)
    at processImmediate [as _immediateCallback] (timers.js:336:15)
rwaldron commented 9 years ago

I had an issue where if I had another instance of node running somewhere else the servo example was not working.

Are they both controlling pins? That's probably an issue with the mraa bindings—presumably the pin state management expects only one process to be controlling at a time. I'll look into this a little more, but I'd consider refactoring my system to run in one process...

BTW - @rwaldron the servo is humming that I am using, a HiTec HS-425BB. That means that the frequency calculation for the motor might not be right

Did you mean pulse width? There is no code changing the frequency. What kind of hum are you hearing? Light hum? Gear grind? Can you record the sound? The HS-425BB is a pretty low end servo (bottom of the barrel for Hi-Tec). I always experience a bit of hum with these:

Additionally, the HS-425BB is a 90° stock rotation, but can support a 180° modified rotation; since Firmata based systems default to the Servo.cpp's default of 0-180° degrees (mapped to 544-2400μs pulses), then external code is responsible for setting sub-180° ranges—which is why this is built in to Johnny-Five's Servo class:

// initialize a servo that has a physical limit of 90° (centered)
var servo = new five.Servo({ pin: 9, range: [ 45, 135 ] }); 

For Galileo-IO, I found that 544-2400μs range would result in the servo arm over extending past 0° to ~-5°, 90° to somewhere between 80-87° and 180° falling short at about 160° (measured with http://www.servocity.com/html/servo_protractor.html#.VC9HuyldVZM or plain protractor for models that don't fit). For continuous servos, the result was a stopping point that wasn't 90°.

For each μs range I worked through, the following was tested:

Standard Servos

Models

Continuous Servos

Models

In the end, the most consistently accurate range was 600-2600μs. This was a lot of work ;)

If using analogWrite on it's own is resulting in gear grinding at the ends, then I suggest using Johnny-Five with Galileo-IO to have at least software-level control over the servo range. I never intended Galileo-IO to be used a stand-alone library—but only because that would make for a crummy programming experience. I strongly encourage the use of Johnny-Five, coupled with Galileo-IO (this is how I use it in my own projects).

rwaldron commented 9 years ago

I tried running analog_read and encountered this error on my board:

This is a duplicate of #17

I just pushed a patch that should address this error, but if there is no read method there, then something is wrong with mraa bindings.

ryoshu commented 9 years ago

Apparently the Intel XDK runs a node process on boot, so I killed that per @sethismyfriend. Now I get a different behavior after upgrading to v0.3.5.

I run blink.js sketch on pin 3 and it goes high, then never goes back to low. I retested all digital pins using the same script from above. Other than 3 going high and staying high, no other PWM pins blink. All non-PWM pins blink.

Running the Blink-IO.js example in MRAA works fine on pin 3.

MRAA Version: v0.5.0-12-g3898182

rwaldron commented 9 years ago

Apparently the Intel XDK runs a node process on boot, so I killed that per @sethismyfriend.

  • What is the node process?
  • What does it do?
  • Where is the source?
  • Is this process only run when working from the XDK?

I have never used the XDK, which means that Galileo-IO has ever been tested under those circumstances. I'm concerned that it won't matter what I do, there is no way to account for this other node process in Galileo-IO (because there is now way to safely know about other processes).

I run blink.js sketch on pin 3 and it goes high, then never goes back to low.

Here are some demonstrations of the correct behavior, along with the code used to produce them...

Blink, all pins, Galileo-IO

https://www.youtube.com/watch?v=mihxl7DNJOY

var Galileo = require("galileo-io");
var board = new Galileo();

board.on("ready", function() {
  console.log("ready");
  var start = Date.now();
  var byte = 0;
  var pins = Array.from({ length: 12 }, function(_, i) {
    return i + 2;
  });
  var toOutput = function(pin) {
    this.pinMode(pin, this.MODES.OUTPUT);
  };
  var highOrLow = function(pin) {
    this.digitalWrite(pin, byte);
  };

  pins.forEach(toOutput, this);
  setInterval(function() {
    byte ^= 1;
    pins.forEach(highOrLow, this);
  }.bind(this), 500);
});

https://www.youtube.com/watch?v=Kn9dfdAJ9QM

var temporal = require("temporal");
var five = require("johnny-five");
var Galileo = require("galileo-io");
var board = new five.Board({
  io: new Galileo()
});

board.on("ready", function() {
  var leds = new five.Leds([ 3, 5, 6 ]);

  function fader() {
    temporal.queue([
      {
        wait: 1000,
        task: function() {
          leds.fadeIn(500);
        },
      },
      {
        wait: 1000,
        task: function() {
          leds.fadeOut(500);
        }
      },
      {
        wait: 1000,
        task: function() {
          fader();
        }
      }
    ]);
  }

  fader();
});

Fade in/out, all PWM pins, Johnny-Five + Galileo-IO:

https://www.youtube.com/watch?v=SdQr7RKZDow

var temporal = require("temporal");
var five = require("johnny-five");
var Galileo = require("galileo-io");
var board = new five.Board({
  io: new Galileo()
});

board.on("ready", function() {
  var leds = new five.Leds([ 3, 5, 6, 9, 10, 11 ]);

  function fader() {
    temporal.queue([
      {
        wait: 1000,
        task: function() {
          leds.fadeIn(500);
        },
      },
      {
        wait: 1000,
        task: function() {
          leds.fadeOut(500);
        }
      },
      {
        wait: 1000,
        task: function() {
          fader();
        }
      }
    ]);
  }

  fader();
});

Same: v0.5.0-12-g3898182

ryoshu commented 9 years ago

root@quark016df6:~# ps | grep node 157 root 34656 S /usr/bin/node /opt/xdk-daemon/main.js 181 root 78244 S /usr/bin/node /opt/xdk-daemon/current/appDaemon.js 192 root 2488 S grep node

That's on the Gen 2 Galileo running the IoTDK latest. It loads on startup. Do you not have those processes running on your Galileo with the IoTDK build?