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

Proposed addition to stepper #1218

Open
dtex opened this issue Sep 6, 2016 · 56 comments
Open

Proposed addition to stepper #1218

dtex opened this issue Sep 6, 2016 · 56 comments

Comments

@dtex
Copy link
Collaborator

dtex commented Sep 6, 2016

I'm working on a project that requires getting down into stepper and I have a proposed addition. I want to be able to control the enable pin of a motor controller to shut off a stepper so it's not consuming power when it is not needed (and getting super hot).

I could do this independently of the stepper class by controlling an independent digital pin, or I could integrate it as a parameter on stepper. For example:

Four-Wire

five.Stepper({
  type: five.Stepper.TYPE.FOUR_WIRE
  stepsPerRev: number,
  pins: {
    motor1: number,
    motor2: number,
    motor3: number,
    motor4: number,
    enable: number
  }
});

// or

five.Stepper({
  type: five.Stepper.TYPE.FOUR_WIRE
  stepsPerRev: number,
  pins: [ motor1, motor2, motor3, motor4, enable ]
});

or Two Wire

five.Stepper({
  type: five.Stepper.TYPE.TWO_WIRE
  stepsPerRev: number,
  pins: {
    motor1: number,
    motor2: number,
    enable: number
  }
 });

// or 

five.Stepper({
  type: five.Stepper.TYPE.TWO_WIRE
  stepsPerRev: number,
  pins: [ motor1, motor2, enable ]
}); 

Alternately enable could be a separate param:

five.Stepper({
  type: five.Stepper.TYPE.TWO_WIRE
  stepsPerRev: number,
  pins: {
    motor1: number,
    motor2: number
  },
  enable: number
 });
@rwaldron
Copy link
Owner

rwaldron commented Sep 6, 2016

Seems like a good addition to me, but I'd like to see Stepper re-written to match the design of Motor and Servo before any new additions are made. WDYT?

@dtex
Copy link
Collaborator Author

dtex commented Sep 6, 2016

I'd say wait a bit on the rewrite. @soundanalgous is looking to replace FirmataStepper with AccelStepper which could give us lots of new features. I'm auditing AccelStepper features to see what makes sense in a new protocol for stepper commands in firmata.

AccelStepper includes support for enable pins so the feature will remain... and it would only take a couple of hours... and I need it by Saturday :-P

@rwaldron
Copy link
Owner

rwaldron commented Sep 6, 2016

Ok, go for it

@dtex
Copy link
Collaborator Author

dtex commented Sep 20, 2016

Okay, #1225 had this feature added (as long as you instantiated your stepper with an opts object and not an array), but I've closed because that branch was good enough for my purposes and stepper really needs that refactor.

First step is to update Firmata. I've proposed a new firmata protocol for stepper here:

firmata/protocol#42

@dtex
Copy link
Collaborator Author

dtex commented Sep 23, 2016

edited 9/30:

  • Added units property to options which allows user to choose wether to work in revolutions, radians, deci-radians, degrees or steps. Underlying functions will all work in steps for efficiency, but getters, setters and API methods will all use the specified units
  • Added default controller which uses firmata or firmataPlus to control pins directly instead of relying on configurableFirmata+stepperFirmata. I think that will work for low step speeds... I guess we'll find out :-P
  • Added microstepping type for the default controller

edited 10/3:

  • Removed proposed ratio param. Anything that happens after the output gear is not really part of the stepper. Besides, people can just use fmap()

edited 10/13

  • Added autoEnable feature that will automatically toggle the enable pin when a stepper starts or ends a movement

edited 7/24

  • Added millrads

Stepper API Proposal

  • Adds support for three wire, half three wire, half four wire and micro-stepping four wire stepper motors.
  • firmata controller depends on the next version of FirmataStepper which wraps accelStepper
  • Adds initialization parameters for maxSpeed, speed and position
  • Adds support for enable pins (steppers consume a lot of energy when they are just sitting still)
  • Users can pass in speed or rpm in an instantiation object. If they pass in both, speed will be used.
  • Adds method to(position) that allows user to pass in an integer for desired step position
  • Adds method stop(). When the motor is stopped mid-move, we report back on the position
  • Adds method enable()
  • Adds method disable()
  • Adds a multiStepper class. This is different than a Steppers collection in that to() commands can accept multiple values in a single firmata message and linear tweening will be handled entirely by firmata. Note that a multiStepper groups must all be on the same microcontroller. Stepper collections can be spread out across multiple Boards. I need to work on clarifying this distinction

Breaking changes

  • accel and decel are now passed as units/second2 instead of the number of steps over which to accelerate
  • Default unit for speed() is based on opts.units which defaults to steps instead of centi-radians

Parameters

options An object of property parameters

Property Type Value/Description Default Required
pins Object * See table. An object containing the names pin addresses for the 6 supported types yes1
pins Array * See Table. An array containing the pin addresses for the 6 supported types yes1
controller constant five.Stepper.CONTROLLER.DEFAULT,
five.Stepper.CONTROLLER.FIRMATASTEPPER
DEFAULT yes
device constant five.Stepper.TYPE.DRIVER,
five.Stepper.TYPE.TWO_WIRE,
five.Stepper.TYPE.THREE_WIRE,
five.Stepper.TYPE.FOUR_WIRE,
five.Stepper.TYPE.MICRO_FOUR_WIRE,
five.Stepper.TYPE.HALF_THREE_WIRE,
five.Stepper.TYPE.HALF_FOUR_WIRE
yes
type Number Alias for device no
controller constant Chooses where stepping is managed
five.Stepper.CONTROLLER.DEFAULT
five.Stepper.CONTROLLER.FIRMATASTEPPER
DEFAULT no
stepsPerRev Number Steps per revolution. This will differ by motor, refer to motor specs for value yes
units constant five.Stepper.UNITS.REVS
five.Stepper.UNITS.RADS
five.Stepper.UNITS.DRADS
five.Stepper.UNITS.DEGREES
five.Stepper.UNITS.STEPS
STEPS no
maxSpeed Number Maximum speed in units per second 30 steps per second no
speed Number Units per second 60 RPM no
acceleration Number Maximum steps per second 1.0 no
deceleration Number Maximum steps per second 1.0 no
position Number Starting position 0 no
direction constant five.Stepper.DIRECTION.CW,
five.Stepper.DIRECTION.CCW
no2
autoEnable Boolean Automatically toggle enable pin when movement begins or ends no

Pins

Config As Object As Array
DRIVER { step, dir [, enable] } [ step, dir [, enable] ]
TWO_WIRE { m1, m2 [, enable] } [ m1, m2 [, enable] ]
THREE_WIRE { m1, m2, m3 [, enable] } [ m1, m2, m3 [, enable] ]
FOUR_WIRE { m1, m2, m3, m4 [, enable] } [ m1, m2, m3, m4 [, enable] ]
HALF_THREE_WIRE { m1, m2, m3 [, enable] } [ m1, m2, m3 [, enable] ]
HALF_FOUR_WIRE { m1, m2, m3, m4 [, enable] } [ m1, m2, m3, m4 [, enable] ]
MICRO_FOUR_WIRE { m1, m2, m3, m4 [, enable] } [ m1, m2, m3, m4 [, enable] ]
  1. The pins property is required, but can be EITHER an object or an array.
  2. The direction property is not required, but if it is undefined then Stepper.step() will do nothing.

Shape

{
  id: A user definable id value. Defaults to a generated uid
  pins: Object containing the pin addresses for the Stepper
  units: Units to be used by class
  maxSpeed: Maximum speed in units/second
  direction:
  speed: Current set speed in units/second
  position: Current step position
  accel: Units per second^2
  decel: Units per second^2
}

API

step(unitsOrOpts, callback) Move a stepper motor.

// unitsOrOpts
{
  units: Distance to move in this.units
  steps: explicit number of steps to move
  speed: speed in units/second
  direction: 1, 0 (CCW, CW)
  duration: ms to complete movement
  accel: Units per second^2
  decel: Units per second^2
}

//
//   - 10 full revolutions
//   - Clockwise
//   -
//   -
//

stepper.step({ step: 2000, direction: 1, accel: 1600, decel: 1600 }, function() {
  console.log("Done stepping!");
});

to(positionOrOpts, callback) Move a stepper motor to a specific position.

// positionOrOpts
{
  position: Position in chosen units (this.units)
  speed: speed in units/second
  duration: ms to complete movement
  accel: Steps per second^2
  decel: Steps per second^2
}

//
//   - Move to step 228 in 1 second
//   - Accel over the first 1600 steps
//   - Decel over the last 1600 steps
//

stepper.step({ position: 228, duration: 1000, accel: 1600, decel: 1600 }, function() {
  console.log("Done stepping!");
});

stop(callback) Stop a stepper motor. Optional callback receives the current position.

stepper.stop(function(pos) {
  console.log("Stepper position: " + pos);
});

disable() Disable a stepper by setting all pins low. If there is an enable pin it will also be set low.

stepper.disable();

enable() Enable a stepper by restoring pin state. If there is an enable pin it will also be set high.

stepper.enable();

rpm() Get the rpm.

rpm(value) Set the rpm.

stepper.rpm(180).step(2000, function() {
  console.log("Done stepping!");
});

speed() Get the speed.

speed(value) Set the speed in units/second.

// 50 steps per second
stepper.speed(50).step(200, function() {
  console.log("Done stepping in four seconds!");
});

direction() Get the direction.

direction(value) Set the direction.

stepper.direction(1).step(2000, function() {
  console.log("Done stepping!");
});

stepper.direction(0).step(2000, function() {
  console.log("Done stepping!");
});

Or...

stepper.direction(five.Stepper.DIRECTION.CW).step(2000, function() {
  console.log("Done stepping!");
});

stepper.direction(five.Stepper.DIRECTION.CCW).step(2000, function() {
  console.log("Done stepping!");
});

accel() Get the acceleration in steps per second2.

accel(value) Set the acceleration in steps per second2.

stepper.accel(1600).step(2000, function() {
  console.log("Done stepping!");
});

decel() Get the deceleration in steps per second2.

decel(value) Set the deceleration in steps per second2.

stepper.decel(1600).step(2000, function() {
  console.log("Done stepping!");
});

maxSpeed() Get the maximum speed in steps per second.

maxSpeed(value) Set the maximum speed in steps per second.

stepper.maxSpeed(100).step(2000, function() {
  console.log("Welcome to 20 seconds later!");
});

position() Get the current position. This is only updated when a movement has completed

position(value) Set the current position. This cannot be called while a stepper is moving.

stepper.position(100);

cw() Set the Stepper to move Clockwise.

stepper.cw().step(2000);

ccw() Set the Stepper to move Counter-Clockwise.

stepper.ccw().step(2000);

MultiStepper API

Parameters

options An object of property parameters

Property Type Value/Description Default Required
Steppers Steppers collection A Steppers collection whose movements should be coordinated by firmata running on a single stepper yes

API

to(positionsArray, callback) Move a multiStepper group of motors to an array of desired positions. The positions will be passed in a single firmata message and firmata will handle linear tweening so that all steppers arrive at the desired position simultaneously.

multiStepper.to([140, 210], function() {
  console.log("Done stepping!");
});

stop(callback) Stop a multiStepper group. Optional callback receives an array of the current positions.

multiStepper.stop(function(positions) {
  positions.each(function(pos, index) {
    console.log("Stepper " + index + " position: " + pos);
  });
});

Constants

Units

Unit Value Constant
STEPS 0 Stepper.UNITS.STEPS
REVS 1 Stepper.UNITS.REVS
RADS 2 Stepper.UNITS.RADS
DRADS 3 Stepper.UNITS.DRADS
CRADS 4 Stepper.UNITS.CRADS
MRADS 4 Stepper.UNITS.MRADS
DEGREES 5 Stepper.UNITS.DEGREES

Run States

State Value Constant
STOP 0 Stepper.RUNSTATE.STOP
DRIVE 1 Stepper.RUNSTATE.ACCEL
DRIVE 2 Stepper.RUNSTATE.DECEL
DRIVE 3 Stepper.RUNSTATE.RUN

Directions

Direction Value Constant
CCW 0 Stepper.DIRECTION.CCW
CW 1 Stepper.DIRECTION.CW

@rwaldron
Copy link
Owner

Wow.

This will take me a bit to get through, please be patient <3

@dtex
Copy link
Collaborator Author

dtex commented Oct 19, 2016

Submitted a PR to firmata/protocol#66

@dtex
Copy link
Collaborator Author

dtex commented Nov 6, 2016

That PR to protocol has landed. Next steps, updating configurableFirmata, firmata.js, and then finally Johnny-Five

@dtex
Copy link
Collaborator Author

dtex commented Jan 18, 2017

The new protocol (AKA Stepper 2) had some minor revisions to how we pass certain values. Those changes are here firmata/protocol#81

Also note that we are now using a new command value so client libraries can continue to use the old stepper interface.

@MiaoDX
Copy link

MiaoDX commented Mar 7, 2017

@dtex Come from Add enable pin for stepper #1225, and see updates to stepper 2.0 proposal based on comments, it seems that you(and many other people) have spend so much time on the improvements of Stepper, THANKS A LOT! And the community is pretty nice!

However, it says:

Example files:
Version 2.0 of the stepper protocol has not yet been implemented.

in stepper-2.0.md, and I really wonder when shall we have the luck to use the Stepper-2?

It will be great help for us(me especially) to make code cleaner and concentrate more on the really logical stuff, though it may seems a little push for you guys, I am really looking forward to it!

@dtex
Copy link
Collaborator Author

dtex commented Mar 7, 2017

It's good to hear other people are looking forward to it and it certainly hasn't fallen off my radar. Hopefully I'll have a first commit in the next couple of weeks.

@joepuzzo
Copy link

Hey guys, any updates on this? This new proposed interface looks great. Is there code written for this that I could look at? Also I have a question about the to(position) function. What would happen if i said go to(228) and then one second later say to(228) would it go further than expected. Similar to now if i say step(1000) and then after 500 steps say step(1000) again the stepper will go 1500 steps.

@dtex
Copy link
Collaborator Author

dtex commented Mar 15, 2018

Hi @joepuzzo

Progress has been made, but this has been taking a back seat to another J5 change I'm working on. Here's where we stand:

  • Firmata protocol - My PR has landed
  • Configurable Firmata - My PR has landed
  • Firmata.js - My PR has landed
  • J5 - I'm about halfway done preparing my PR. It has been backburnered while I do some other stuff.

The upcoming changes in J5 will allow users to take advantage of all the new firmata stuff, or control steppers with standardFirmata, and control steppers on other platforms besides Arduino (like Raspi-io). For now the only way to control a stepper on a Raspberry Pi with Johnny-Five is to connect an Arduino to it.

There are two ways to control steppers connected to an Arduino when running Johnny-Five. If you build configurableFirmata with firmataStepper you can use Johnny-Five's stepper class. If you build configurableFirmata with firmataAccelStepper you can use firmata.js's stepper methods. You can still use Johnny-Five for other devices on the same Uno along side the firmata.js stepper instance. firmataAccelStepper gives much more functionality than firmataStepper so I recommend that path. The firmata.js API for stepper is much more "J5-like" than other firmata methods so it shouldn't feel to weird.

What would happen if i said go to(228) and then one second later say to(228) would it go further than expected.

firmataStepper - n/a. There is no "to"
firmataAccelStepper - It will go to 228. Calling a second "to" would immediately halt the first, but firmataAccelStepper keeps track of the position so we only trigger the number of steps remaining. Keep in mind that we know how many steps we have requested at any point in time, but some physical obstruction may have stopped the motor from completing a step so our real world position would be off.

if i say step(1000) and then after 500 steps say step(1000) again the stepper will go 1500 steps

firmataStepper - I don't remember. I'd have to dig into firmataStepper, or run some tests.
firmataAccelStepper - Yes, the stepper will go 1500 steps. The second call will stop the first.

Sorry this is taking so long to land. The other changes I'm working on for J5 span several repos and I'm slow even in the best of circumstances.

@joepuzzo
Copy link

joepuzzo commented Mar 15, 2018

Thanks thats fine! I am already using J5 with a teensy LC connected to ras pi to control a stepper motor and its working great! To do this I flashed the teensy with AdvancedFirmata as specified in the J5 docs. It sounds like if i wanted the more advanced features now i would have to push firmataAccelStepper and use firmata.js instead of johnny five. ( I could not use them both at the same time correct? ).

@dtex
Copy link
Collaborator Author

dtex commented Mar 15, 2018

You wil need a custom build of configurable firmata from http://firmatabuilder.com/ I usually include the first five options and accelStepperFirmata.

The docs for firmata's new stepper API are here

You can absolutiely use Johnny-Five and firmata's stepper API at the same time. Something like this:

var Five = require("johnny-five");

var board = new Five.Board();

board.on("ready", function() {

    // Here's a J5 class isntance
    let led = new Five.Led(9);
    led.blink();

    // The firmata.js instance for this board is at this.io
    this.io.accelStepperConfig({
      deviceNum: 0,
      type: this.io.STEPPER.TYPE.FOUR_WIRE,
      motorPin1: 4,
      motorPin2: 5,
      motorPin3: 6,
      motorPin4: 7,
      stepSize: this.io.STEPPER.STEP_SIZE.WHOLE
    });

    this.io.accelStepperSpeed(0, 300);
    this.io.accelStepperAcceleration(0, 100);
    this.io.accelStepperStep(0, 2000, function(position) {
      console.log("Current position: " + position);
    });
  });
});

The Johnny-Five class will of course make everything a little easier (like working with an instance of stepper instead of having to pass the deviceNum with every call) and will add some helpers, but you can do most everything you will need to do with just firmata.

@joepuzzo
Copy link

Wow dude this is so cool i had no clue you could do this! But wait you never required firmata.js in your example above? is that returired to have those methods on io?

@dtex
Copy link
Collaborator Author

dtex commented Mar 15, 2018

If you don't pass a different IO plugin when you initialize your board, Johnny-Five will assume you want to use firmata, will initialize it for you then make it available on board.io. In other words, J5 handles the require.

@joepuzzo
Copy link

Thanks a lot! I got it all working and its awesome! Cant wait to see this become part of J5.

@a1xon
Copy link

a1xon commented Jul 31, 2018

Any idea when this becomes part of J5? Is there another workaround to stop a stepper?

@dtex
Copy link
Collaborator Author

dtex commented Jul 31, 2018

Hopefully soon. This PR is blocking. In the meantime you can use the firmata io object in the Johnny-Five board instance (assuming you are using an Arduino).

It requires the latest firmata.js and a custom build of firmata which includes accelStepper. You can get the custom build over at firmatabuilder.com. The firmata stepper API is documented here

For example:

// Note I just typed in this code and didn't test so 
// there may be (er, probably is) a typo or two

let Five = require("johnny-five");
let board = new Five.Board();

board.on("ready", function() {
    
  board.accelStepperConfig({
      deviceNum: 0,
      type: board.STEPPER.TYPE.FOUR_WIRE,
      motorPin1: 32,
      motorPin2: 34,
      motorPin3: 36,
      motorPin4: 38,
      enablePin: 30,
      stepType: board.STEPPER.STEPTYPE.HALF
  });
    
  this.io.accelStepperSpeed(0, 200);
  this.io.accelStepperAcceleration(0, 100);
  this.io.step(10000);
    
  // Stop after 2 seconds
  setTimeout(() = {
    this.io.stop(0);
  }, 2000 });

});

@dtex
Copy link
Collaborator Author

dtex commented Aug 1, 2018

Yep, typos and brain farts. Here's the corrected code

let Five = require("johnny-five");
let board = new Five.Board();

board.on("ready", function() {
    
  this.io.accelStepperConfig({
      deviceNum: 0,
      type: this.io.STEPPER.TYPE.FOUR_WIRE,
      motorPin1: 32,
      motorPin2: 34,
      motorPin3: 36,
      motorPin4: 38,
      enablePin: 30,
      stepType: this.io.STEPPER.STEPTYPE.HALF
  });
    
  this.io.accelStepperSpeed(0, 200);
  this.io.accelStepperAcceleration(0, 100);
  this.io.accelStepperStep(10000);
    
  // Stop after 2 seconds
  setTimeout(() = {
    this.io.accelStepperStop(0);
  }, 2000 });

});

@a1xon
Copy link

a1xon commented Aug 1, 2018

@dtex thanks very much! I'll try that. Do you know the reason why this wasn't in the initial commit for the stepper module? I mean are most users hardcode their bot-movements? Doesn't nearly every stepper need some kind of homeposition or haltpoints?

@dtex
Copy link
Collaborator Author

dtex commented Aug 1, 2018

Johnny-Five depends on firmata.js which is the host side interface to firmata (the client) which runs on the Arduino. The old Firmata stepper code was very basic and just didn’t have these features. Once this lands we will still have a ton of work to get the other platforms up to speed.

@rwaldron
Copy link
Owner

rwaldron commented Aug 6, 2018

Sorry about the delay... that patch is landed and temporal@0.7.0 is published.

@joepuzzo
Copy link

Any updates on this? The workaround i have been using for the past year has been great! No problems there. But it would be nice to see this as part of the core.

@panchalmanish2208
Copy link

Yes I am using Arduino board for driving multiple stepper motor(3 or 4) and arduino board gets instruction from Raspberry Pi. Pls provide some example or code for the same.

@panchalmanish2208
Copy link

Yes I am using Arduino board for driving multiple stepper motor(3 or 4) and arduino board gets instruction from Raspberry Pi. Pls provide some example or code for the same.

And on the arduino board ,I had uploaded Configurable Firmata.

@dtex
Copy link
Collaborator Author

dtex commented Apr 14, 2020

You can find documentation for using accelStepper directly with firmata.js here and here is an example of it playing nice with Johnny-Five.

All other devices (LED's, Sensor's, etc) can be used with the Johnny-Five API.

let Five = require("johnny-five");
let board = new Five.Board();

board.on("ready", () => {

  board.io.accelStepperConfig({
    deviceNum: 0,
    type: board.STEPPER.TYPE.FOUR_WIRE,
    motorPin1: 5,
    motorPin2: 6,
    motorPin3: 7,
    motorPin4: 8,
    stepSize: board.STEPPER.STEP_SIZE.WHOLE
  });

  board.io.accelStepperConfig({
    deviceNum: 1,
    type: board.STEPPER.TYPE.FOUR_WIRE,
    motorPin1: 9,
    motorPin2: 10,
    motorPin3: 11,
    motorPin4: 12,
    stepSize: board.STEPPER.STEP_SIZE.HALF
  });

  board.io.accelStepperSpeed(0, 400);
  board.io.accelStepperSpeed(1, 400);

  board.io.multiStepperConfig({
    groupNum: 0,
    devices: [0, 1]
  });

  board.io.multiStepperTo(0, [2000, 3000], () => {

    board.io.accelStepperReportPosition(0, value => {
      console.log(`Stepper 0 position: ${value}`);
    });

    board.io.accelStepperReportPosition(1, value => {
      console.log(`Stepper 1 position: ${value}`);
    });

  });

});

@panchalmanish2208
Copy link

panchalmanish2208 commented Apr 16, 2020

You can find documentation for using accelStepper directly with firmata.js here and here is an example of it playing nice with Johnny-Five.

All other devices (LED's, Sensor's, etc) can be used with the Johnny-Five API.

let Five = require("johnny-five");
let board = new Five.Board();

board.on("ready", () => {

  board.io.accelStepperConfig({
    deviceNum: 0,
    type: board.STEPPER.TYPE.FOUR_WIRE,
    motorPin1: 5,
    motorPin2: 6,
    motorPin3: 7,
    motorPin4: 8,
    stepSize: board.STEPPER.STEP_SIZE.WHOLE
  });

  board.io.accelStepperConfig({
    deviceNum: 1,
    type: board.STEPPER.TYPE.FOUR_WIRE,
    motorPin1: 9,
    motorPin2: 10,
    motorPin3: 11,
    motorPin4: 12,
    stepSize: board.STEPPER.STEP_SIZE.HALF
  });

  board.io.accelStepperSpeed(0, 400);
  board.io.accelStepperSpeed(1, 400);

  board.io.multiStepperConfig({
    groupNum: 0,
    devices: [0, 1]
  });

  board.io.multiStepperTo(0, [2000, 3000], () => {

    board.io.accelStepperReportPosition(0, value => {
      console.log(`Stepper 0 position: ${value}`);
    });

    board.io.accelStepperReportPosition(1, value => {
      console.log(`Stepper 1 position: ${value}`);
    });

  });

});

Can u pls tell in detail how to use johnny five and firmata.js simultaneously ? firmata.js for stepper motor and johnny-five for others sensor,led ,etc.
Thanks a lot.

@panchalmanish2208
Copy link

@dtex while running above code i got this error, can you please tell how to fix it?
Capture

@dtex
Copy link
Collaborator Author

dtex commented Apr 23, 2020

Ah, I see. the STEPPERobject is on board.io, not board.

The two lines that say

    type: board.STEPPER.TYPE.FOUR_WIRE,

should be

    type: board.io.STEPPER.TYPE.FOUR_WIRE,

You'll also need to fix the stepSize lines

@panchalmanish2208
Copy link

@dtex now i get this error
Capture_1

@dtex
Copy link
Collaborator Author

dtex commented Apr 23, 2020

What version of node are you using?

@panchalmanish2208
Copy link

What version of node are you using?

Capture_2

@dtex
Copy link
Collaborator Author

dtex commented Apr 23, 2020

The exponentiation operator was added in version 7. Johnny-Five requires version 8 or newer.

@panchalmanish2208
Copy link

Previously code was running but now it was showing only Connected, Available and Repl initialized (as in pic ) and there is no more execution further.
Capture _3
@dtex can u please tell what is happening here?

@dtex
Copy link
Collaborator Author

dtex commented Apr 26, 2020

@manish2208 We've strayed pretty far from the original topic. Can you open a new issue? If you're using the code from above, I suspect you do not have the proper version of firmata installed on the Uno. If there is anything different about your code, please post it in a new issue.

@stale
Copy link

stale bot commented Jul 21, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Jul 21, 2021
@TheLogan
Copy link

TheLogan commented Aug 1, 2021

Was this ever added :)

@stale stale bot removed the stale label Aug 1, 2021
@dtex
Copy link
Collaborator Author

dtex commented Aug 1, 2021

Sadly no. I got stuck on how to handle stepper collections and kinda forgot about it. I should revisit and see if it's any easier with the new codebase, or maybe I've gotten smarter in the past few years and it'll be easier to figure out. 🤞

@TheLogan
Copy link

TheLogan commented Aug 2, 2021

I'll be waiting with bated breath, but until then I'll try your suggestion from above ^_^

@joepuzzo
Copy link

@dtex

You can find documentation for using accelStepper directly with firmata.js here and here is an example of it playing nice with Johnny-Five.
All other devices (LED's, Sensor's, etc) can be used with the Johnny-Five API.

let Five = require("johnny-five");
let board = new Five.Board();

board.on("ready", () => {

  board.io.accelStepperConfig({
    deviceNum: 0,
    type: board.STEPPER.TYPE.FOUR_WIRE,
    motorPin1: 5,
    motorPin2: 6,
    motorPin3: 7,
    motorPin4: 8,
    stepSize: board.STEPPER.STEP_SIZE.WHOLE
  });

  board.io.accelStepperConfig({
    deviceNum: 1,
    type: board.STEPPER.TYPE.FOUR_WIRE,
    motorPin1: 9,
    motorPin2: 10,
    motorPin3: 11,
    motorPin4: 12,
    stepSize: board.STEPPER.STEP_SIZE.HALF
  });

  board.io.accelStepperSpeed(0, 400);
  board.io.accelStepperSpeed(1, 400);

  board.io.multiStepperConfig({
    groupNum: 0,
    devices: [0, 1]
  });

  board.io.multiStepperTo(0, [2000, 3000], () => {

    board.io.accelStepperReportPosition(0, value => {
      console.log(`Stepper 0 position: ${value}`);
    });

    board.io.accelStepperReportPosition(1, value => {
      console.log(`Stepper 1 position: ${value}`);
    });

  });

});

Can u pls tell in detail how to use johnny five and firmata.js simultaneously ? firmata.js for stepper motor and johnny-five for others sensor,led ,etc. Thanks a lot.

So Im trying this and its not working. When I tell a single motor to go to a position it works fine. but with same code here no movement. Any thoughts ?

@dtex
Copy link
Collaborator Author

dtex commented Aug 31, 2022

Hmmm, not sure. First I would see if replacing

board.io.multiStepperTo(0, [2000, 3000], () => {

    board.io.accelStepperReportPosition(0, value => {
      console.log(`Stepper 0 position: ${value}`);
    });

    board.io.accelStepperReportPosition(1, value => {
      console.log(`Stepper 1 position: ${value}`);
    });

  });

with

board.io.accelStepperTo(0, 2000);
board.io.accelStepperTo(1, 3000);

causes both motors to move. It might be a problem with the multiStepper class.

@joepuzzo
Copy link

The latter causes both to move but the former does not

@dtex
Copy link
Collaborator Author

dtex commented Aug 31, 2022

Well, that helps.

This could be a problem in firmata.js or the accelStepper addon to configurable firmata.

Are you able to make your project work with individual stepper control?

@joepuzzo
Copy link

joepuzzo commented Aug 31, 2022

Yes I can do it with individual stepper control. I just wrote my own

var five = require("johnny-five");
var board = new five.Board();

//var Board = require("firmata");
//var board = new Board();

const ENABLED = true;
const DISABLED = !ENABLED;

board.on("ready", function () {

  board.io.accelStepperConfig({
		deviceNum: 0,
		type: this.io.STEPPER.TYPE.DRIVER,
		stepPin: 0,
		directionPin: 1,
    enablePin: 33,
    invertPins: [33]
 	});

	board.io.accelStepperConfig({
		deviceNum: 1,
		type: this.io.STEPPER.TYPE.DRIVER,
		stepPin: 6,
		directionPin: 7,
    enablePin: 36,
 	});

	board.io.accelStepperSpeed(0, 1000);
	board.io.accelStepperSpeed(1, 1000);

  board.io.multiStepperConfig({
    groupNum: 0,
    devices: [0, 1]
  });

  board.io.accelStepperEnable(1, ENABLED)
  board.io.accelStepperEnable(0, ENABLED)

  const steppers = [0,0];

  this.repl.inject({
		to: (id, loc, speed = 1000) =>{
      this.io.accelStepperSpeed(id, speed);
      this.io.accelStepperTo(id,loc);
    },
    multi: (speed = 1000) =>{

			this.io.accelStepperSpeed(0, speed);
      this.io.accelStepperSpeed(1, speed);

  		board.io.multiStepperTo(0, [2000, 3000], () => {

        console.log("Moved Multi")

    		this.io.accelStepperReportPosition(0, value => {
      		console.log(`Stepper 0 position: ${value}`);
   			});

    		this.io.accelStepperReportPosition(1, value => {
      		console.log(`Stepper 1 position: ${value}`);
    		});

  		});

    },
    mine: (positions) =>{

      // First find the stepper that will take the longest time
      let longestTime = 0;

      for(let i = 0; i < 2; i++ ){
         const thisDistance = positions[i] - steppers[i];
         const thisTime = Math.abs(thisDistance) / 1000;

         if(thisTime > longestTime){
           longestTime = thisTime;
         }
      }

      console.log('Longest Time:', longestTime);

			// Set speed for each based on time
      for(let i = 0; i < 2; i++ ){
       	const thisDistance = positions[i] - steppers[i];
	    	const thisSpeed = thisDistance / longestTime;
      	this.io.accelStepperSpeed(i, thisSpeed);
      }

			// Now go!
			for(let i = 0; i < 2; i++ ){
      	this.io.accelStepperTo(i, positions[i], (pos) =>{
          // update pos for this stepper
          console.log('Update:', pos);
          steppers[i] = pos;
        });
      }
  
    },

    loc: (id) => {
      console.log( this.io.accelStepperReportPosition(id) );
    },
		enable: (id) => {
			this.io.accelStepperEnable(id, ENABLED)
    },
    disable: (id) => {
			this.io.accelStepperEnable(id, DISABLED)
    },
    zero: (id) => {
      this.io.accelStepperZero(id);
    }
  });

});

@joepuzzo
Copy link

multi does NOT work but mine does

@joepuzzo
Copy link

in other words calling mine([1000, 2000]) works but calling multi() does not

@joepuzzo
Copy link

joepuzzo commented Sep 1, 2022

Also while I have your attention @dtex do you know who I can contact to get this merged ? firmata/firmata.js#261 . I cant seem to get in touch with anyone that works on firmata js

@dtex
Copy link
Collaborator Author

dtex commented Sep 1, 2022

I think @rwaldron is the only one able to merge PRs on that repo.

@joepuzzo
Copy link

joepuzzo commented Sep 1, 2022

Ok thanks will try to get in touch with him. Also for anyone that attempts to use the methods described above with accelStepper and Johnny five with the latest stepper drivers make sure you check the pulse width settings inside of AccelStepper.cpp read the info about your stepper driver from its manual ( it should say minimum pulse width ). I needed to update mine to be 8.5. If you are using an arduino uno it defaults it to 5. For teensy boards it does not so you may be scratching your head for hours trying to figure out why your motors are not moving and its as simple as changing the pulse width.

@joepuzzo
Copy link

joepuzzo commented Sep 1, 2022

Also I would like to add for anyone using a teensy4.1 board you need to add the following code to the Boards.h in the firmatas src/utility directory

// Teensy 4.0 & 4.1
#elif defined(__IMXRT1062__)
#define TOTAL_ANALOG_PINS       NUM_ANALOG_INPUTS
#define TOTAL_PINS              NUM_DIGITAL_PINS
#define VERSION_BLINK_PIN       13
#define PIN_SERIAL1_RX          0
#define PIN_SERIAL1_TX          1
#define PIN_SERIAL2_RX          7
#define PIN_SERIAL2_TX          8
#define PIN_SERIAL3_RX          15
#define PIN_SERIAL3_TX          14
#define PIN_SERIAL4_RX          16
#define PIN_SERIAL4_TX          17
#define PIN_SERIAL5_RX          21
#define PIN_SERIAL5_TX          20
#define PIN_SERIAL6_RX          25
#define PIN_SERIAL6_TX          24
#define PIN_SERIAL7_RX          28
#define PIN_SERIAL7_TX          29
#define IS_PIN_DIGITAL(p)       ((p) >= 0 && (p) < NUM_DIGITAL_PINS)
#ifdef ARDUINO_TEENSY40
  #define IS_PIN_ANALOG(p)        ((p) >= 14 && (p) <= 27)
  #define PIN_TO_ANALOG(p)        ((p) - 14)
#endif
#ifdef ARDUINO_TEENSY41
  #define IS_PIN_ANALOG(p)        (((p) >= 14 && (p) <= 27) || ((p) >= 38 && (p) <= 41))
  #define PIN_TO_ANALOG(p)        (((p) <= 27) ? (p) - 14 : (p) - 24)
#endif
#define IS_PIN_PWM(p)           digitalPinHasPWM(p)
#define IS_PIN_SERVO(p)         ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p)           ((p) == PIN_WIRE_SDA || (p) == PIN_WIRE_SCL)
#define IS_PIN_SERIAL(p)        (((p) >= 0 && (p) <= 1) || ((p) >= 7 && (p) <= 8) || ((p) >= 14 && (p) <= 17) || ((p) >= 20 && (p) <= 21) || ((p) >= 24 && (p) <= 25) || ((p) >= 28 && (p) <= 29))
#define PIN_TO_DIGITAL(p)       (p)
#define PIN_TO_PWM(p)           (p)
#define PIN_TO_SERVO(p)         (p)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants