├── .gitignore ├── .npmignore ├── .npmrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── declarations └── index.d.ts ├── dist ├── index.js └── index.js.map ├── package.json ├── script └── pigpio.sh ├── src └── index.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/ 26 | 27 | # Dependency directories 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history 35 | 36 | # Output of 'npm pack' 37 | *.tgz 38 | 39 | # IDE 40 | .vscode 41 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/ 26 | 27 | # Dependency directories 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history 35 | 36 | # Output of 'npm pack' 37 | *.tgz 38 | 39 | # IDE 40 | .vscode 41 | 42 | # package specific 43 | src/ 44 | test/ 45 | tsconfig.json 46 | tslint.json -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 6.0.1 (2021-10-11) 2 | 3 | - Deprecated this package in favor of [raspi-soft-pwm](https://github.com/nebrius/raspi-soft-pwm) 4 | 5 | ## 6.0.0 (2018-4-21) 6 | 7 | - Updated pigpio to v1 8 | - BREAKING CHANGE: dropped support for Node.js 4 9 | 10 | ## 5.0.0 (2017-9-12) 11 | 12 | - POTENTIALLY BREAKING CHANGE: renamed the following private properties to begin with an underscore because I just learned TypeScript doesn't do anything to hide private properties. Don't use these properties, changes may not be semver-major next time. 13 | - `PWM.frequencyValue` -> `PWM._frequencyValue` 14 | - `PWM.dutyCycleValue` -> `PWM._dutyCycleValue` 15 | - `PWM.pwmPort` -> `PWM._pwmPort` 16 | - `PWM.pwm` -> `PWM._pwm` 17 | - BREAKING CHANGE: dropped support for Node.js < 4.0.0, and now enforce it via package.json "engines" field. 18 | - SORT OF BREAKING-ISH CHANGE: dropped support for attempting to install on non-arm platforms via package.json's "cpu" field. 19 | - Attempting to install this on a non-Raspberry Pi platform before gave a bunch of obtuse errors, so this doesn't _actually_ change the ability to install raspi-pwm, but does make it fail earlier and harder. 20 | 21 | ## 4.0.2 (2017-4-25) 22 | 23 | - Fixed a bug in the TypeScript definitions that said `frequencey` was required when in reality it's not. 24 | 25 | ## 4.0.1 (2017-4-23) 26 | 27 | - Updated documentation 28 | 29 | ## 4.0.0 (2017-4-23) 30 | 31 | - Removed Wiring Pi and replaced it with pigpio. 32 | - BREAKING CHANGE: removed the `range` and `clockDivisor` constructor options and instance properties 33 | - Added `frequency` constructor option and instance property. Replace the use of `range` and `clockDivisor` with this property. 34 | - BREAKING CHANGE: `write` now takes a floating point number between 0 and 1, instead of an integer between 0 and 1024. 35 | 36 | ## 3.1.3 (2017-22-1) 37 | 38 | - Publishing a new version to update the README on npmjs.com. No other changes. 39 | 40 | ## 3.1.2 (2016-12-21) 41 | 42 | - Fixed a TypeScript API definition bug where the constructor config was not marked as optional 43 | - Note: this does not affect functionality unless you were using the TypeScript definition 44 | 45 | ## 3.1.1 (2016-12-3) 46 | 47 | - Converted the project to TypeScript and cleaned up a bunch of odds and ends 48 | - Note: there is no functionality change or bug fixes with this release 49 | 50 | ## 3.1.0 (2016-7-7) 51 | 52 | - Switched dependency ranges to ^ 53 | - Bumped dependencies to bring in support for a new Raspberry Pi Zero revision 54 | 55 | ## 3.0.0 (2016-3-20) 56 | 57 | - Dependency update to fix bug 58 | - POTENTIALLY BREAKING CHANGE: using the identifier `PWM1` now maps to Wiring Pi pin 23, not 24 59 | - New build system 60 | 61 | ## 2.3.1 (2016-3-7) 62 | 63 | - Dependency update to add missing Raspberry Pi 3 Model B revision 64 | 65 | ## 2.3.0 (2016-3-4) 66 | 67 | - Updated dependencies to add Raspberry Pi 3 Model B support 68 | 69 | ## 2.2.0 (2016-2-18) 70 | 71 | - Added `range` and `clockDivisor` accessors 72 | 73 | ## 2.1.0 (2015-12-8) 74 | 75 | - Updated dependencies to add Raspberry Pi Zero support 76 | 77 | ## 2.0.0 (2015-10-20) 78 | 79 | - Upgraded to NAN 2 80 | - POTENTIAL BREAKING CHANGE 81 | - The API has not changed, but the build requirements have 82 | - Make sure you are running Raspbian Jessie because this module no longer builds on stock Raspbian Wheezy 83 | - See https://github.com/fivdi/onoff/wiki/Node.js-v4-and-native-addons for more information 84 | 85 | ## 1.4.0 (2015-10-13) 86 | 87 | - Exposed clock and range properties 88 | - Dependency updates to fix bug with invalid pin aliases 89 | - Updated build dependencies 90 | 91 | ## 1.3.3 (2015-9-3) 92 | 93 | - Dependency updates to fix a bug with pin aliasing 94 | 95 | ## 1.3.2 (2015-7-16) 96 | 97 | - Updated dependencies 98 | - Updated the repository links to point to their new location 99 | - Added a contributing guide 100 | - Added code linter 101 | - Update code style to use newer best practices 102 | 103 | ## 1.3.1 (2015-3-17) 104 | 105 | - Dependency update to fix a bug with destroying peripherals 106 | 107 | ## 1.3.0 (2015-2-21) 108 | 109 | - Switched from traceur to babel for ES6->ES5 compilation 110 | 111 | ## 1.2.2 (2015-2-20) 112 | 113 | - Fixed a bug with mismatched versions of the traceur runtime 114 | - Skipped 1.2.1 because of a typo on my part when publishing (oops) 115 | 116 | ## 1.2.0 (2015-2-20) 117 | 118 | - Removed prebuilt binary support as there are now multiple targets (need to use node-pre-gyp) 119 | - Upgraded NAN to get support for Node.js 0.12 120 | - io.js support is theoretically there, but won't work until https://github.com/TooTallNate/node-gyp/pull/564 is landed 121 | 122 | ## 1.1.0 (2015-2-13) 123 | 124 | - Added support for multiple PWMs. Note: the API was extended, but is backwards compatible with 1.0.x releases 125 | 126 | ## 1.0.5 (2015-2-12) 127 | 128 | - README updates 129 | 130 | ## 1.0.4 (2015-1-21) 131 | 132 | - Locked down the NAN version for now since code breaks on 1.5 133 | 134 | ## 1.0.3 (2015-1-8) 135 | 136 | - Added pre-built lib so users don't have to compile on their own Raspberry Pis. 137 | 138 | ## 1.0.2 (2014-12-29) 139 | 140 | - Added docs 141 | - Switched to using the 'PWM0' pin nomenclature 142 | 143 | ## 1.0.1 (2014-12-6) 144 | 145 | - Critical bug fix (why did I even publish 1.0.0?) 146 | 147 | ## 1.0.0 (2014-11-28) 148 | 149 | - Initial implementation 150 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Bryan Hughes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Raspi PWM 2 | ========== 3 | 4 | **NOTICE: This package has been deprecated in favor of [raspi-soft-pwm](https://github.com/nebrius/raspi-soft-pwm)** 5 | 6 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nebrius/raspi-io?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 | 8 | Raspi PWM is part of the [Raspi.js suite](https://github.com/nebrius/raspi) that provides access to the hardware PWM. 9 | 10 | If you have a bug report, feature request, or wish to contribute code, please be sure to check out the [Raspi IO Contributing Guide](https://github.com/nebrius/raspi-io/blob/master/CONTRIBUTING.md). 11 | 12 | ## System Requirements 13 | 14 | - Raspberry Pi Model B Rev 1 or newer (sorry Model A users) 15 | - Raspbian Jessie or newer 16 | - [Node-RED](http://nodered.org/) works, but can be finicky and difficult to debug. 17 | - See https://github.com/nebrius/raspi-io/issues/24 for more info about support for other OSes 18 | - Node 6.4.0 or newer 19 | 20 | Detailed instructions for getting a Raspberry Pi ready for NodeBots, including how to install Node.js, can be found in the [wiki](https://github.com/nebrius/raspi-io/wiki/Getting-a-Raspberry-Pi-ready-for-NodeBots) 21 | 22 | ## Installation 23 | 24 | First, be sure that you have installed [raspi](https://github.com/nebrius/raspi). 25 | 26 | Install with npm: 27 | 28 | ```sh 29 | npm install raspi-pwm 30 | ``` 31 | 32 | **Note:** this project is written in [TypeScript](http://www.typescriptlang.org/) and includes type definitions in the package.json file. This means that if you want to use it from TypeScript, you don't need to install a separate @types module. 33 | 34 | ## Example Usage 35 | 36 | In TypeScript/ES6: 37 | 38 | ```TypeScript 39 | import { init } from 'raspi'; 40 | import { PWM } from 'raspi-pwm'; 41 | 42 | init(() => { 43 | const led = new PWM('P1-12'); 44 | led.write(0.5); // 50% Duty Cycle, half brightness 45 | }); 46 | ``` 47 | 48 | In JavaScript: 49 | 50 | ```JavaScript 51 | const raspi = require('raspi'); 52 | const pwm = require('raspi-pwm'); 53 | 54 | raspi.init(() => { 55 | const led = new pwm.PWM('P1-12'); 56 | led.write(0.5); // 50% Duty Cycle, aka half brightness 57 | }); 58 | ``` 59 | 60 | ## Pin Naming 61 | 62 | The pins on the Raspberry Pi are a little complicated. There are multiple headers on some Raspberry Pis with extra pins, and the pin numbers are not consistent between Raspberry Pi board versions. 63 | 64 | To help make it easier, you can specify pins in three ways. The first is to specify the pin by function, e.g. `'GPIO18'`. The second way is to specify by pin number, which is specified in the form "P[header]-[pin]", e.g. `'P1-7'`. The final way is specify the [Wiring Pi virtual pin number](http://wiringpi.com/pins/), e.g. `7`. If you specify a number instead of a string, it is assumed to be a Wiring Pi number. 65 | 66 | Be sure to read the [full list of pins](https://github.com/nebrius/raspi-io/wiki/Pin-Information) on the supported models of the Raspberry Pi. 67 | 68 | ## PWM ports 69 | 70 | Raspberry Pi Model B Rev 2 and older versions of the Raspberry Pi only expose one PWM port on pin `P1-12`, so be sure to always use that port (or leave it as the default). The Raspberry Pi Model B+ and newer exposes two PWM ports. 71 | 72 | On newer Raspberry Pi's, these two PWM ports can be accessed via four different pins. `PWM0` can be accessed on either pin `P1-12` _or_ `P1-32`, and `PWM1` can be accessed on either pin `P1-33` _or_ `P1-35`. Each PWM _cannot_ be accessed on both pins though. 73 | 74 | If you try to run the following code, which initializes both PWM0 ports, _you will get an exception_. 75 | 76 | ```JavaScript 77 | const raspi = require('raspi'); 78 | const pwm = require('raspi-pwm'); 79 | 80 | raspi.init(() => { 81 | const led1 = new pwm.PWM('P1-12'); 82 | const led2 = new pwm.PWM('P1-32'); 83 | }); 84 | ``` 85 | 86 | ## API 87 | 88 | ### new PWM(config) 89 | 90 | Instantiates a new PWM instance on the given pin. Note that PWM is limited to only 1 pin on the Model A/B and 2 pins on the A+/B+/2/Zero. On the A/B, the PWM pin is exposed on `GPIO18`. The A+/B+/2 is a little more complicated. The first PWM is exposed on two pins, `GPIO18` and `GPIO12`. This PWM can only be active on one of these pins at a time, however, so choose carefully. The second PWM pin on the A+/B+/2/Zero is exposed on `GPIO19`. Check the [wiring information wiki](https://github.com/nebrius/raspi-io/wiki) for more information. 91 | 92 | _Arguments_: 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 130 | 131 |
ArgumentTypeDescription
config (optional)Number | String | ObjectThe configuration for the PWM pin. If the config is a number or string, it is assumed to be the pin number for the peripheral. If it is an object, the following properties are supported:
110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 |
PropertyTypeDescription
pin (optional)Number | StringThe pin number or descriptor for the peripheral. Defaults to 1 (GPIO18, PWM0).
frequency (optional)NumberThe frequency, in Hz, of the PWM signal. Defaults to 50.
129 |
132 | 133 | ### Instance Properties 134 | 135 | #### frequency 136 | 137 | A number representing the frequency initialization value, in Hz. If a value for `frequency` was passed to the constructor, it is reflected back here. If no value for `frequency` was passed to the constructor, then this reflects the default frequency value of `50`. 138 | 139 | #### dutyCycle 140 | 141 | A number representing the last written dutyCycle. If this property is read before a value is written, `0` is returned. 142 | 143 | ### Instance Methods 144 | 145 | #### write(dutyCycle) 146 | 147 | Sets the duty cycle for the PWM output, a floating point value between 0 and 1. 148 | 149 | _Arguments_: 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 |
ArgumentTypeDescription
dutyCycleNumberThe duty cycle for the PWM to set, must be a floating point number between 0 and 1
165 | 166 | _Returns_: None 167 | 168 | **Note:** The PWM does not start outputting a signal until write is called for the first time. 169 | 170 | License 171 | ======= 172 | 173 | The MIT License (MIT) 174 | 175 | Copyright (c) 2014-2017 Bryan Hughes 176 | 177 | Permission is hereby granted, free of charge, to any person obtaining a copy 178 | of this software and associated documentation files (the "Software"), to deal 179 | in the Software without restriction, including without limitation the rights 180 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 181 | copies of the Software, and to permit persons to whom the Software is 182 | furnished to do so, subject to the following conditions: 183 | 184 | The above copyright notice and this permission notice shall be included in 185 | all copies or substantial portions of the Software. 186 | 187 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 188 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 189 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 190 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 192 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 193 | THE SOFTWARE. 194 | -------------------------------------------------------------------------------- /declarations/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Peripheral } from 'raspi-peripheral'; 2 | export interface IConfig { 3 | pin?: number | string; 4 | frequency?: number; 5 | } 6 | export declare class PWM extends Peripheral { 7 | private _frequencyValue; 8 | private _dutyCycleValue; 9 | private _pwmPort; 10 | private _pwm; 11 | readonly frequency: number; 12 | readonly dutyCycle: number; 13 | constructor(config?: number | string | IConfig); 14 | destroy(): void; 15 | write(dutyCycle: number): void; 16 | } 17 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2014-2017 Bryan Hughes 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | */ 25 | var __extends = (this && this.__extends) || (function () { 26 | var extendStatics = Object.setPrototypeOf || 27 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 28 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 29 | return function (d, b) { 30 | extendStatics(d, b); 31 | function __() { this.constructor = d; } 32 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 33 | }; 34 | })(); 35 | Object.defineProperty(exports, "__esModule", { value: true }); 36 | var raspi_peripheral_1 = require("raspi-peripheral"); 37 | var pigpio_1 = require("pigpio"); 38 | var DEFAULT_PIN = 1; 39 | var DEFAULT_FREQUENCY = 50; 40 | var MAX_DUTY_CYCLE = 1000000; 41 | var PWM0 = 'PWM0'; 42 | var PWM1 = 'PWM1'; 43 | // So there's a funky thing with PWM, where there are four PWM-capable pins, 44 | // but only two actual PWM ports. So the standard pin contention mechanism 45 | // doesn't _quite_ cover all cases. This object tracks which PWM peripherals are 46 | // in use at a given time, so we can do error checking on it. 47 | var pwmPeripheralsInUse = (_a = {}, 48 | _a[PWM0] = false, 49 | _a[PWM1] = false, 50 | _a); 51 | var PWM = /** @class */ (function (_super) { 52 | __extends(PWM, _super); 53 | function PWM(config) { 54 | var _this = this; 55 | var pin = DEFAULT_PIN; 56 | var frequency = DEFAULT_FREQUENCY; 57 | if (typeof config === 'number' || typeof config === 'string') { 58 | pin = config; 59 | } 60 | else if (typeof config === 'object') { 61 | if (typeof config.pin === 'number' || typeof config.pin === 'string') { 62 | pin = config.pin; 63 | } 64 | if (typeof config.frequency === 'number') { 65 | frequency = config.frequency; 66 | } 67 | } 68 | _this = _super.call(this, pin) || this; 69 | // Pin details from http://elinux.org/RPi_BCM2835_GPIOs 70 | var gpioPin; 71 | var mode; 72 | switch (_this.pins[0]) { 73 | case 26:// GPIO12 PWM0 ALT0 74 | gpioPin = 12; 75 | mode = pigpio_1.Gpio.ALT0; 76 | _this._pwmPort = PWM0; 77 | break; 78 | case 1:// GPIO18 PWM0 ALT5 79 | gpioPin = 18; 80 | mode = pigpio_1.Gpio.ALT5; 81 | _this._pwmPort = PWM0; 82 | break; 83 | case 23:// GPIO13 PWM1 ALT0 84 | gpioPin = 13; 85 | mode = pigpio_1.Gpio.ALT0; 86 | _this._pwmPort = PWM1; 87 | break; 88 | case 24:// GPIO19 PWM1 ALT5 89 | gpioPin = 19; 90 | mode = pigpio_1.Gpio.ALT5; 91 | _this._pwmPort = PWM1; 92 | break; 93 | default: 94 | throw new Error("Pin " + pin + " does not support hardware PWM"); 95 | } 96 | if (pwmPeripheralsInUse[_this._pwmPort]) { 97 | throw new Error(_this._pwmPort + " is already in use and cannot be used again"); 98 | } 99 | pwmPeripheralsInUse[_this._pwmPort] = true; 100 | _this._frequencyValue = frequency; 101 | _this._dutyCycleValue = 0; 102 | _this._pwm = new pigpio_1.Gpio(gpioPin, { mode: mode }); 103 | return _this; 104 | } 105 | Object.defineProperty(PWM.prototype, "frequency", { 106 | get: function () { 107 | return this._frequencyValue; 108 | }, 109 | enumerable: true, 110 | configurable: true 111 | }); 112 | Object.defineProperty(PWM.prototype, "dutyCycle", { 113 | get: function () { 114 | return this._dutyCycleValue; 115 | }, 116 | enumerable: true, 117 | configurable: true 118 | }); 119 | PWM.prototype.destroy = function () { 120 | pwmPeripheralsInUse[this._pwmPort] = false; 121 | _super.prototype.destroy.call(this); 122 | }; 123 | PWM.prototype.write = function (dutyCycle) { 124 | if (!this.alive) { 125 | throw new Error('Attempted to write to a destroyed peripheral'); 126 | } 127 | if (typeof dutyCycle !== 'number' || dutyCycle < 0 || dutyCycle > 1) { 128 | throw new Error("Invalid PWM duty cycle " + dutyCycle); 129 | } 130 | this._dutyCycleValue = dutyCycle; 131 | this._pwm.hardwarePwmWrite(this._frequencyValue, Math.round(this._dutyCycleValue * MAX_DUTY_CYCLE)); 132 | this.emit('change', this._dutyCycleValue); 133 | }; 134 | return PWM; 135 | }(raspi_peripheral_1.Peripheral)); 136 | exports.PWM = PWM; 137 | var _a; 138 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "raspi-pwm", 3 | "version": "6.0.1", 4 | "description": "Provides access to PWM on the Raspberry Pi as part of the Raspi.js library suite", 5 | "main": "dist/index.js", 6 | "types": "./declarations/index.d.ts", 7 | "dependencies": { 8 | "raspi-peripheral": "^3.0.4", 9 | "pigpio": "^1.0.0" 10 | }, 11 | "devDependencies": { 12 | "@types/node": "^9.3.0", 13 | "@types/pigpio": "^0.4.1", 14 | "@types/raspi-peripheral": "^2.0.0", 15 | "tslint": "^5.7.0", 16 | "typescript": "^2.5.2" 17 | }, 18 | "engines": { 19 | "node": ">= 6.4.0" 20 | }, 21 | "cpu": [ 22 | "arm" 23 | ], 24 | "scripts": { 25 | "prebuild": "tslint 'src/**/*.ts'", 26 | "build": "tsc", 27 | "preinstall": "sh ./script/pigpio.sh", 28 | "test": "echo \"Error: no test specified\" && exit 1" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/nebrius/raspi-pwm.git" 33 | }, 34 | "keywords": [ 35 | "nodebots", 36 | "robotics", 37 | "raspberry pi" 38 | ], 39 | "author": "Bryan Hughes ", 40 | "license": "MIT", 41 | "bugs": { 42 | "url": "https://github.com/nebrius/raspi-pwm/issues" 43 | }, 44 | "homepage": "https://github.com/nebrius/raspi-pwm" 45 | } 46 | -------------------------------------------------------------------------------- /script/pigpio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2014-2017 Bryan Hughes 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | # Quick and dirty check to see if we're on a Raspberry Pi or not 25 | if ! [ -f /proc/cpuinfo ]; then 26 | echo "not on a Raspberry Pi, skipping installation" 27 | exit 0 28 | fi 29 | 30 | if command -v pigpiod -v >/dev/null 2>&1 31 | then 32 | echo "pigpio is already installed, skipping installation" 33 | exit 0 34 | fi 35 | 36 | echo "pigpio doesn't appear to be installed, installing now. You may be asked for your password." 37 | sudo apt-get install pigpio 38 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014-2017 Bryan Hughes 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | import { Peripheral } from 'raspi-peripheral'; 26 | import { Gpio } from 'pigpio'; 27 | 28 | export interface IConfig { 29 | pin?: number | string; 30 | frequency?: number; 31 | } 32 | 33 | const DEFAULT_PIN = 1; 34 | const DEFAULT_FREQUENCY = 50; 35 | const MAX_DUTY_CYCLE = 1000000; 36 | 37 | const PWM0 = 'PWM0'; 38 | const PWM1 = 'PWM1'; 39 | 40 | // So there's a funky thing with PWM, where there are four PWM-capable pins, 41 | // but only two actual PWM ports. So the standard pin contention mechanism 42 | // doesn't _quite_ cover all cases. This object tracks which PWM peripherals are 43 | // in use at a given time, so we can do error checking on it. 44 | const pwmPeripheralsInUse: { [ port: string ]: boolean } = { 45 | [PWM0]: false, 46 | [PWM1]: false 47 | }; 48 | 49 | export class PWM extends Peripheral { 50 | 51 | private _frequencyValue: number; 52 | private _dutyCycleValue: number; 53 | private _pwmPort: string; 54 | 55 | private _pwm: Gpio; 56 | 57 | public get frequency() { 58 | return this._frequencyValue; 59 | } 60 | 61 | public get dutyCycle() { 62 | return this._dutyCycleValue; 63 | } 64 | 65 | constructor(config?: number | string | IConfig) { 66 | let pin: number | string = DEFAULT_PIN; 67 | let frequency = DEFAULT_FREQUENCY; 68 | if (typeof config === 'number' || typeof config === 'string') { 69 | pin = config; 70 | } else if (typeof config === 'object') { 71 | if (typeof config.pin === 'number' || typeof config.pin === 'string') { 72 | pin = config.pin; 73 | } 74 | if (typeof config.frequency === 'number') { 75 | frequency = config.frequency; 76 | } 77 | } 78 | super(pin); 79 | 80 | // Pin details from http://elinux.org/RPi_BCM2835_GPIOs 81 | let gpioPin: number; 82 | let mode: number; 83 | switch (this.pins[0]) { 84 | case 26: // GPIO12 PWM0 ALT0 85 | gpioPin = 12; 86 | mode = Gpio.ALT0; 87 | this._pwmPort = PWM0; 88 | break; 89 | case 1: // GPIO18 PWM0 ALT5 90 | gpioPin = 18; 91 | mode = Gpio.ALT5; 92 | this._pwmPort = PWM0; 93 | break; 94 | case 23: // GPIO13 PWM1 ALT0 95 | gpioPin = 13; 96 | mode = Gpio.ALT0; 97 | this._pwmPort = PWM1; 98 | break; 99 | case 24: // GPIO19 PWM1 ALT5 100 | gpioPin = 19; 101 | mode = Gpio.ALT5; 102 | this._pwmPort = PWM1; 103 | break; 104 | default: 105 | throw new Error(`Pin ${pin} does not support hardware PWM`); 106 | } 107 | 108 | if (pwmPeripheralsInUse[this._pwmPort]) { 109 | throw new Error(`${this._pwmPort} is already in use and cannot be used again`); 110 | } 111 | pwmPeripheralsInUse[this._pwmPort] = true; 112 | 113 | this._frequencyValue = frequency; 114 | this._dutyCycleValue = 0; 115 | this._pwm = new Gpio(gpioPin, { mode }); 116 | } 117 | 118 | public destroy() { 119 | pwmPeripheralsInUse[this._pwmPort] = false; 120 | super.destroy(); 121 | } 122 | 123 | public write(dutyCycle: number) { 124 | if (!this.alive) { 125 | throw new Error('Attempted to write to a destroyed peripheral'); 126 | } 127 | if (typeof dutyCycle !== 'number' || dutyCycle < 0 || dutyCycle > 1) { 128 | throw new Error(`Invalid PWM duty cycle ${dutyCycle}`); 129 | } 130 | this._dutyCycleValue = dutyCycle; 131 | this._pwm.hardwarePwmWrite(this._frequencyValue, Math.round(this._dutyCycleValue * MAX_DUTY_CYCLE)); 132 | this.emit('change', this._dutyCycleValue); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "outDir": "dist", 8 | "declaration": true, 9 | "declarationDir": "declarations", 10 | "strictNullChecks": true, 11 | "noUnusedParameters": true, 12 | "noUnusedLocals": true 13 | }, 14 | "include": [ 15 | "src/**/*.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "indent": [ true, "spaces", 2 ], 9 | "no-console": false, 10 | "quotemark": [ true, "single" ], 11 | "semicolon": [ true, "always" ], 12 | "trailing-comma": false, 13 | "ordered-imports": false, 14 | "object-literal-sort-keys": false, 15 | "variable-name": [ true, "allow-leading-underscore", "allow-pascal-case" ], 16 | "max-classes-per-file": false 17 | }, 18 | "rulesDirectory": [] 19 | } 20 | --------------------------------------------------------------------------------