rwaldron / galileo-io

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

Trouble getting motor control to work with Pololu DRV8835 Arduino motor shield #34

Closed vrubiolo closed 9 years ago

vrubiolo commented 9 years ago

[Apologies if this is the wrong place to post, please redirect me if needed]

Hi,

I am trying to use the Pololu DRV8835 Arduino motor shield with the Edison Arduino breakout board. This configuration (code+shield) works fine when it runs on Arduino with Firmata but when plugged into the Arduino headers of the Edison breakout board, it misbehaves. Namely, instead of my motors staying idle until I send the direction order, one starts going full throttle and I cannot stop it.

I have checked my pinouts and they look OK. I would need help investigating the problem here.

Here is the control code:

var argv = require('minimist')(process.argv.slice(2));
var cmdline = {
    arduino: false,
    verbose : false
    };

if (argv.h || argv.help) {
    console.log ("-v|--verbose: dump debug data");
    console.log ("-a|--arduino: use Arduino Firmata instead of Edison");
    process.exit(0);
}

if (argv.v || argv.verbose) {
    console.log("Verbose mode enabled");
    cmdline.verbose = true;
    //process.stdout.write("arg array: "); console.dir(argv);
}

if (argv.a || argv.arduino) {
    console.log("Running against Arduino Firmata");
    cmdline.arduino = true;
}

var five = require("johnny-five");
if (cmdline.arduino == true) {
    var board = new five.Board();
} else { 
    var Edison = require("edison-io");
    var board = new five.Board({
      io: new Edison()
    });
}

function ready_mark ()
{
  console.log ("J5 ready.");
  var led = new five.Led(13);
  led.strobe();
}

function move (m1, m2, speed, secs, fwM1, fwM2)
{
    if (fwM1)
    {
        m1.fwd(speed);
    } else {
        m1.rev(speed);
    }

    if (fwM2)
    {
        m2.fwd(speed);
    } else {
        m2.rev(speed);
    }
}

function forward (m1, m2)
{
    console.log ("Moving forwards at " + speed);
    move (m1, m2, speed, 3, true, true);
}

function backward (m1, m2)
{
    console.log ("Moving backwards at " + speed);
    move (m1, m2, speed, 3, false, false);
}

function right_turn (m1, m2)
{
    console.log ("Turning right at " + speed);
    move (m1, m2, speed, 3, false, true);
}

function left_turn (m1, m2)
{
    console.log ("Turning left at " + speed);
    move (m1, m2, speed, 3, true, false);
}

function stop (m1, m2) {
    console.log ("Stop request");
    m1.stop();
    m2.stop();
}

var speed = 255;
board.on("ready", function() {
    // Pololu DRV8835, with PWM 9/10 -> 5/6
    var m1 = new five.Motor({
              pins: {
                pwm: 5,
                dir: 7
              }
            });

    var m2 = new five.Motor({
              pins: {
                pwm: 6,
                dir: 8
              }
            });

    this.repl.inject({
        f: function() {
          forward(m1, m2);
        },
        b: function() {
          backward(m1, m2);
        },
        r: function() {
          right_turn(m1, m2);
        },
        l: function() {
          left_turn(m1, m2);
        },
        s: function() {
          stop(m1, m2);
        },
        sp: function(spd) {
          speed = spd;
        },
        j: function () {
          j_dump(j);
        }
    });

    ready_mark();
});

One important point worth noting is that the shield uses PWM9 which mandates the use of the PWM swizzler but this is unsupported by libmraa (only works with the Arduino IDE). For that reason, I am using jumper wires to route PWM9&10 to PWM5&6. As I said, this works fine with Arduino on Firmata.

Version info (johnny-five and edison-io/galileo-io installed via npm): $ uname -a Linux VincentR 3.10.17-poky-edison+ #1 SMP PREEMPT Wed Apr 29 03:54:01 CEST 2015 i686 GNU/Linux

$ cat /etc/opkg/mraa-upm.conf src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic

$ opkg info libmraa0 Package: libmraa0 Version: 0.6.2 Provides: libmraa-dev, libmraa-dbg, libmraa-doc Replaces: libmraa-dev, libmraa-dbg, libmraa-doc Conflicts: libmraa-dev, libmraa-dbg, libmraa-doc Status: install user installed Section: libs Architecture: i586 Maintainer: Intel IoT-Devkit MD5Sum: 77c7285bd95f774b2b3b560a4480ad0f Size: 266598 Filename: libmraa0_0.6.2_i586.ipk Source: https://github.com/intel-iot-devkit/mraa Description: mraa built using CMake Installed-Time: 1433725304

$ node --version v0.10.35

$ npm list |grep johnny-five ├─┬ johnny-five@0.8.77

$ npm list |grep -- -io ├── edison-io@0.8.14 ├─┬ galileo-io@0.8.14 │ ├─┬ galileo-io@0.8.14

Note: I get the following when listing my npm packages, not sure if this is related : npm ERR! extraneous: mraa@0.6.1-36-gbe4312e /home/root/node_modules/galileo-io/node_modules/mraa npm ERR! not ok code 0

I could not find trace of a similar issue which is why I am posting here. Would anyone have suggestions on how to debug the problem?

Many thanks for your help!

Vincent

rwaldron commented 9 years ago

Thanks for the report.

One important point worth noting is that the shield uses PWM9 which mandates the use of the PWM swizzler but this is unsupported by libmraa (only works with the Arduino IDE). For that reason, I am using jumper wires to route PWM9&10 to PWM5&6. As I said, this works fine with Arduino on Firmata.

That's incorrect, libmraa0 supports PWM on 3, 5, 6 and 9, but not 10 and 11.

vrubiolo commented 9 years ago

@rwaldron : thanks for the pointers. Indeed, the libmraa link I pointed seconds what you said. Let me double-check my wiring and get back to you ...

rwaldron commented 9 years ago

@vrubiolo cool, keep me posted :)

vrubiolo commented 9 years ago

@rwaldron OK, I redid the setup and since libmraa0 supports PWM9, I only switched PWM 10 to PWM5. Here is the updated part of the code:

    // Pololu DRV8835, with PWM 10 -> 5
    var m1 = new five.Motor({
              pins: {
                pwm: 9,
                dir: 7
              }
            });
    var m2 = new five.Motor({
              pins: {
                pwm: 5,
                dir: 8
              }
            });

Motor 1 (connected to PWM9 and digital pin 7) correctly behaves but motor 2 (connected to PWM5 and digital pin 8) continuously goes forward. Actually, what I see is that M2 appears to follow the direction orders, it's just that it never stops:

  1. When I start the program, M2 starts right away (instead of not moving, as does M1).
  2. When I do a forward (via f() on the repl), both will go forward.
  3. I then stop, but only M1 stops.
  4. I then go backwards, via b(), both will go backwards, M1 from a stop position, M2 from its previously running forward position.
  5. If I go forward again, then both will go forward, etc.

I will not be able to touch this for a few weeks but if you guys have hints on what I could check, that'd be great.

rwaldron commented 9 years ago

I will try to reproduce this from your explanations and report back!

vrubiolo commented 9 years ago

Hi there,

A little bit more investigation on the setup using an oscilloscope. For the working motor, I can correctly see the PWM and direction signals. The PWM correctly adapts to the motor speed.

For the non-working motor, the PWM signal (for pin 5) is constantly as if the speed was 255 (which maps to the behavior of the motor going full speed all the time). If I use it as a simple pin with the following code, I can see the correct PWM corresponding to the pin strobe:

var five = require("johnny-five");
var Edison = require("edison-io");
var board = new five.Board({
  io: new Edison()
});

board.on("ready", function() {
  console.log ("J5 ready.");
  var strobe = new five.Pin(5);
  var state = 0x00;

  this.loop(500, function() {
    strobe.write(state ^= 0x01);
  });
});

So it looks to me something might be wrong inbetween (maybe with the motor class init code?).

rwaldron commented 9 years ago

For the non-working motor, the PWM signal (for pin 5) is constantly as if the speed was 255 (which maps to the behavior of the motor going full speed all the time)

Can you share the exact code you're using, along with the a photo of the exact hardware setup? Thanks!!

vrubiolo commented 9 years ago

@rwaldron : thanks for your reply. Let me gather that data and get back to you with the info you request.

vrubiolo commented 9 years ago

Hello back,

I did some additional experimentations while gathering data to send you and actually found the source of the problem: the PWM swizzler. I had changed it during the Intel IoT roadshow to try to make the motor shield work on Arduino. I had left it in its current position since then. Once switched back to its default position, both motors worked fine.

For the record, here is how we proceeded for the investigation:

  1. Oscilloscope to measure the PWM signals and compare with the working ones. That identified the problematic pin and provided with a reference, working pin.
  2. Try to isolate the faulty code/trim down the testcase. This is where I used the strobe code which was working[1].
  3. Ran motor sample code that was working on a friend of mine Edison board. It was failing whereas we were running the same Yocto runtime (1.7).
  4. Inserted debug output in the J5 motor library on setPin and setPwm methods of the Motor class to print out which pin was set for each operation. That showed the init orders went down to the right pins and matched what was set in the code.
  5. At that point, we were thinking about something wrong with the breakout board itself. My friend indeed told me he had seen some Edison breakout boards with fried/dead PWMs. We proceeded to swap the breakout boards (i.e use my Edison compute module with his Edison Arduino breakout board).
  6. About to do the swap, I glanced at the swizzler, then remembered the issues I had during the roadshow and double checked with his. I then realized we had different jumper settings.

That's it. I am thus closing the thread. Let me know if you have questions or observations otherwise.

Thanks for all the useful help so far !

Vincent

[1] At this point, I don't know why it did so. Because the issue eventually turned out to be a HW/jumper problem, it should have failed in both cases (i.e motor code and strobe code). I suspect this was a test issue on my side.

rwaldron commented 9 years ago

Wow, thanks for the detailed follow-up :) Hopefully this will help somebody else in the future!