Earlier in this article series I showed how to install NodeJS -- it was pretty simple with an install script. However, I thought I better show how I actually worked with NodeJS to create my little 1b1 driver code.
Again, simple, I used others hard work. Specifically, Michael Hord with Sparkfun's MiniMoto library.
Really, all I did was tweak the code a little bit to fit JavaScript syntax.
The result
'use strict';
var i2c = require('i2c-bus');
var sleep = require('sleep');
// Commands
const FAULT_CMD = 0x01;
// Fault constants
const CLEAR_FAULT = 0x80;
const FAULT = 0x01;
const ILIMIT = 0x10;
const OTS = 0x08;
const UVLO = 0x04;
const OCP = 0x02;
// Direction bits
const FORWARD = 0b00000010;
const REVERSE = 0b00000001;
const HI_Z = 0b00000000;
const BRAKE = 0b00000011;
module.exports = class Motor {
/** 1. Add "inverse" motor option
* 2. Add option to clear fault on each motor call.
*
*/
constructor(address, i2cbus, options = undefined) {
this.address = address
this.i2cbus = i2cbus
this.options = options
}
getFault() {
var fault = {
message: '',
code: 0
}
var faultCode;
try {
this.i2cbus.readByteSync(this.address, FAULT_CMD);
} catch (e) {
console.log(`Read fault failed: ${e}`)
}
fault.code = faultCode;
if (faultCode !== undefined) {
console.log(faultCode);
fault.message = 'Unknown fault.';
switch (faultCode){
case FAULT:
fault.message = 'Unknown fault.'
break;
case ILIMIT:
fault.message = 'Extended current limit event'
break;
case OTS:
fault.message = 'Over temperature.'
break;
case UVLO:
fault.message = 'Undervoltage lockout.'
break;
case OCP:
fault.message = 'Overcurrent lockout.'
break;
default:
fault.message = 'Unknown fault.'
break;
}
return fault;
} else {
fault.message = 'No fault';
return fault;
}
}
clearFault() {
var fault = this.getFault(this.address);
if (fault.code) {
try {
var success = this.i2cbus.writeByteSync(this.address, FAULT_CMD, CLEAR_FAULT);
if (success) { return true; }
} catch (e) {
console.log(`Failed to clear faults: ${e}`)
}
}
return false;
}
drive(speed = 0, direction = undefined, checkFault = false) {
// The speed should be 0-63.
if (checkFault) { this.clearFault();}
if (direction === undefined) {
direction = speed < 0;
speed = Math.abs(speed);
if (speed > 63) { speed = 63; }
speed = speed << 2 ;
if (direction) { speed |= FORWARD; }
else { speed |= REVERSE; }
} else {
speed = speed << 2 ;
speed |= direction;
}
try {
this.i2cbus.writeByteSync(this.address, 0x00, speed);
} catch (e){
console.log('Drive command failed.')
}
}
brake() {
try {
this.drive(0, HI_Z);
} catch (e) {
console.log('Brake command failed.')
}
}
stop() {
try {
this.drive(0, BRAKE);
} catch (e) {
console.log('Brake command failed.')
}
}
}
There's a lot left to do, but it works.
Todo List:
- Have the constructor accept an
options
object - Add
read()
to get the current speed which a motor is set. - Refactor option to clear faults on write to be determined during construction
- Add acceleration and deceleration algorithms add functions.
- Create an async polling of fault codes.
But! For now it works.
Also, or those who are like, "You stole code, dewd! Not cool." Mhord's code has a beerware license. I sent this email to Sparkfun in regards to the license and how I might pay Sparkfun back for their work.
Hey Mr. Hord,
I'm in the process of porting your DRV8830 library to Node--I wanted to make sure I give appropriate credit.
Also, was going to ship some beer to Sparkfun--in respect of the beerware license. Just let me know what kind.
Lastly, I wanted to make sure Sparkfun benefits. It looks like the DRV8830 TinyMoto board has been discontinued. > Should I recommend people roll their own...or gasp get something off a slow ship from China?
---Thomas
aka, Ladvien
But I didn't hear back. C'est la vie
Top comments (0)