rwaldron/galileo-io

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

vrubiolo opened this issue · 10 comments

[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

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.

@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 ...

@vrubiolo cool, keep me posted :)

@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.

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

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?).

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!!

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

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.

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