node-pantilt-hat
Version:
Pimoroni PanTilt servo and lighting HAT for node.js
107 lines (86 loc) • 2.89 kB
text/typescript
import * as i2c from 'i2c-bus';
const BUS_NUMBER = 0x01;
const ADDR = 0x15;
const CONFIG = 0x00;
const REG_PAN_SERVO = 0x01;
const REG_TILT_SERVO = 0x03;
export const SERVO_MIN = 575;
export const SERVO_MAX = 2325;
const IDLE_TIME = 2000; // ms
export class NodePanTilt {
private i2c: i2c.I2cBus;
private servoPanState: boolean;
private servoTiltState: boolean;
private timerPanServo: NodeJS.Timer;
private timerTiltServo: NodeJS.Timer;
constructor() {
this.i2c = i2c.openSync(BUS_NUMBER);
this.servoPanState = false;
this.servoTiltState = false;
}
public getPan() {
this.enablePanServo();
const pan = this.toDegrees(this.i2c.readWordSync(ADDR, REG_PAN_SERVO));
this.disablePanServo();
return pan;
}
public getTilt() {
this.enableTiltServo();
const tilt = this.toDegrees(this.i2c.readWordSync(ADDR, REG_TILT_SERVO));
this.disableTiltServo();
return tilt;
}
public setPan(angle: number) {
this.enablePanServo();
this.i2c.writeWord(ADDR, REG_PAN_SERVO, this.toServoDegrees(angle), () => this.disablePanServo());
}
public setTilt(angle: number) {
this.enableTiltServo();
this.i2c.writeWord(ADDR, REG_TILT_SERVO, this.toServoDegrees(angle), () => this.disableTiltServo());
}
private enablePanServo() {
if (!this.servoPanState) {
this.servoPanState = true;
this.putConfig();
}
}
private enableTiltServo() {
if (!this.servoTiltState) {
this.servoTiltState = true;
this.putConfig();
}
}
private disablePanServo() {
this.timerPanServo = this.clearTimer(this.timerPanServo);
this.timerPanServo = setTimeout(() => {
this.servoPanState = false;
this.putConfig();
}, IDLE_TIME);
}
private disableTiltServo() {
this.timerTiltServo = this.clearTimer(this.timerTiltServo);
this.timerTiltServo = setTimeout(() => {
this.servoTiltState = false;
this.putConfig();
}, IDLE_TIME);
}
private clearTimer(timer: NodeJS.Timer) {
if (timer) clearTimeout(timer);
return null
}
private putConfig(config = this.setUpConfig()) {
this.i2c.writeByteSync(ADDR, CONFIG, config);
}
private setUpConfig() {
let config = 0;
config = config | Number(this.servoPanState) << 0;
config = config | Number(this.servoTiltState) << 1;
return config;
}
toServoDegrees(degrees: number): number {
return SERVO_MIN + Math.ceil(((SERVO_MAX - SERVO_MIN) / 180) * (degrees + 90));
}
toDegrees(servoDegrees: number): number {
return Math.round(((servoDegrees - SERVO_MIN) / (SERVO_MAX - SERVO_MIN)) * 180.0) - 90;
}
}