Skip to content
This repository has been archived by the owner on Aug 5, 2022. It is now read-only.

Commit

Permalink
[pwm] Require PWM period/pulseWidth to be set at the same time (#928)
Browse files Browse the repository at this point in the history
This is a wise API choice because you can go through invalid states
by setting the wrong one first, where the pulse width is bigger than
the period. I convinced Zephyr itself to make this change, but we
hadn't gotten around to reflecting this in our own API.

Fixes #359.

Signed-off-by: Geoff Gustafson <geoff@linux.intel.com>
  • Loading branch information
grgustaf authored and Jimmy Huang committed Mar 30, 2017
1 parent 85b6000 commit d56bac2
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 233 deletions.
62 changes: 18 additions & 44 deletions docs/pwm.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,8 @@ dictionary PWMInit {

[NoInterfaceObject]
interface PWMPin {
void setPeriod(double ms);
void setPeriodCycles(unsigned long cycles);
void setPulseWidth(double ms);
void setPulseWidthCycles(unsigned long cycles);
void setCycles(unsigned long period, unsigned long pulseWidth);
void setMilliseconds(double period, double pulseWidth);
};
```

Expand Down Expand Up @@ -89,63 +87,39 @@ the period. *NOTE: This doesn't seem to work currently on Arduino 101.*
The function returns a PWMPin object that can be used to change the period and
pulse width later.

### PWMPin.setPeriod
### PWMPin.setCycles

`void setPeriod(double ms);`
`void setCycles(unsigned long period, unsigned long pulseWidth);`

Sets the repeat period for the pulse signal. It is given in milliseconds, so
these can be fractional to provide microsecond timings, etc. The actual
resolution available will depend on the hardware, so the value you provide may
get rounded.
*TODO: We could probably have the period attribute show the actual setting for
the device when it is read back.*

This version of the API is useful when the timing of the pulse matters (e.g.
the 'servo' model of PWM control described in the
[Introduction](#introduction)).

### PWMPin.setPeriodCycles

`void setPeriodCycles(unsigned long cycles);`
Sets the repeat period and pulse width for the signal, in terms of hardware
cycles. One hardware cycle is the minimum amount of time the hardware supports
having the pulse signal on (high).

Sets the repeat period for the pulse signal, in terms of hardware cycles. One
hardware cycle is the minimum amount of time the hardware supports having the
pulse signal on (high).
Throws an error if pulseWidth is greater than period.

This version of the API is useful when the duty cycle is what matters (e.g.
using the 'analog' model of PWM control described in the
[Introduction](#introduction)). For example, a period of 2 with a pulse width of
1 will make an LED at 50% brightness, with no flicker because the changes occur
far faster than visible to the human eye.

### PWMPin.setPulseWidth
### PWMPin.setMilliseconds

`void setPulseWidth(double ms);`
`void setMilliseconds(double periodMS, double pulseWidthMS);`

Sets the repeat period and pulse width for the signal. It is given in
milliseconds, so these can be fractional to provide microsecond timings, etc.
The actual resolution available will depend on the hardware, so the value you
provide may get rounded.
*TODO: We could probably have the period attribute show the actual setting for
the device when it is read back.*

Sets the pulse width for the signal. It is given in milliseconds, so these can
be fractional to provide microsecond timings, etc. The actual resolution
available will depend on the hardware, so the value you provide may get rounded.
*TODO: We could probably have the pulseWidth attribute show the actual
setting for the device when it is read back.*
Throws an error if pulseWidth is greater than period.

This version of the API is useful when the timing of the pulse matters (e.g.
the 'servo' model of PWM control described in the
[Introduction](#introduction)).

### PWMPin.setPulseWidthCycles

`void setPulseWidthCycles(unsigned long cycles);`

Sets the pulse width for the signal, in terms of hardware cycles. One hardware
cycle is the minimum amount of time the hardware supports having the pulse
signal on (high).

This version of the API is useful when the duty cycle is what matters (e.g.
using the 'analog' model of PWM control described in the
[Introduction](#introduction)). For example, a period of 2 with a pulse width of
1 will make an LED at 50% brightness, with no flicker because the changes occur
far faster than visible to the human eye.

Sample Apps
-----------
* [PWM sample](../samples/PWM.js)
Expand Down
12 changes: 4 additions & 8 deletions samples/PWM.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016, Intel Corporation.
// Copyright (c) 2016-2017, Intel Corporation.

// Test code for Arduino 101 that uses the PWM on IO3 to set an LED's blink
// pattern to on for 1s, then off 1/2s, indefinitely. Another PWM on IO5 sets
Expand All @@ -14,8 +14,7 @@ var pins = require("arduino101_pins");
var led0 = pwm.open({channel: pins.IO3});

// set timings in milliseconds
led0.setPeriod(1500);
led0.setPulseWidth(1000);
led0.setMilliseconds(1500, 1000);

// set brightness to 33% using hw cycle-based values
var led1 = pwm.open({channel: pins.IO5, period: 3, pulseWidth: 1});
Expand All @@ -29,8 +28,7 @@ var period = maxPeriod;
var dir = 0;

// set initial state
led2.setPeriod(period);
led2.setPulseWidth(period / 2);
led2.setMilliseconds(period, period / 2);

setInterval(function () {
if (dir) {
Expand All @@ -50,7 +48,5 @@ setInterval(function () {
}
}

led2.setPeriod(period);
led2.setPulseWidth(period / 2);

led2.setMilliseconds(period, period / 2);
}, 4000);
10 changes: 5 additions & 5 deletions samples/WebBluetoothDemo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016, Intel Corporation.
// Copyright (c) 2016-2017, Intel Corporation.

// Test code for Arduino 101 that replicates the WebBluetooth demo
// using BLE to advertise temperature changes and allow LED color changes
Expand Down Expand Up @@ -100,7 +100,7 @@ ColorCharacteristic._value.writeUInt8(0, 1);
ColorCharacteristic._value.writeUInt8(0, 2);

ColorCharacteristic.ledR = pwm.open({
channel: pins.IO3, period: 0.256, pulseWidth: 255 / 1000
channel: pins.IO3, period: 0.256, pulseWidth: 0.255
});
ColorCharacteristic.ledG = pwm.open({
channel: pins.IO5, period: 0.256, pulseWidth: 0
Expand Down Expand Up @@ -129,9 +129,9 @@ ColorCharacteristic.onWriteRequest = function(data, offset, withoutResponse,
return;
}

this.ledR.setPulseWidth(this._value.readUInt8(0) / 1000);
this.ledG.setPulseWidth(this._value.readUInt8(1) / 1000);
this.ledB.setPulseWidth(this._value.readUInt8(2) / 1000);
this.ledR.setCycles(256, this._value.readUInt8(0));
this.ledG.setCycles(256, this._value.readUInt8(1));
this.ledB.setCycles(256, this._value.readUInt8(2));
// TODO: probably only supposed to call this if withoutResponse is false?
callback(this.RESULT_SUCCESS);
};
Expand Down
8 changes: 3 additions & 5 deletions samples/arduino/basics/Fade.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016, Intel Corporation.
// Copyright (c) 2016-2017, Intel Corporation.

// Reimplementation of Arduino - Basics - Fade example
// - Fades LEDs in and out using PWM
Expand Down Expand Up @@ -31,18 +31,16 @@ var pins = require("arduino101_pins");
var led1 = pwm.open({
channel: pins.IO3
});
led1.setPeriodCycles(256);

var led2 = pwm.open({
channel: pins.IO5,
polarity: "reverse"
});
led2.setPeriodCycles(256);

// update the brightness every 30ms
setInterval(function () {
led1.setPulseWidthCycles(brightness);
led2.setPulseWidthCycles(brightness);
led1.setCycles(256, brightness);
led2.setCycles(256, brightness);

// adjust the brightness for next time
brightness += fadeAmount;
Expand Down
13 changes: 4 additions & 9 deletions samples/arduino/starterkit/ColorMixingLamp.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016, Intel Corporation.
// Copyright (c) 2016-2017, Intel Corporation.

// Reimplementation of Arduino Starter Kit's ColorMixingLamp example
// - Lights up an RGB LED based on the ambient light color detected by three
Expand Down Expand Up @@ -43,11 +43,6 @@ var blueSensor = aio.open({
pin: pins.A2
});

// initialize the period of the PWMs to 256 hardware cycles
redLED.setPeriodCycles(256);
greenLED.setPeriodCycles(256);
blueLED.setPeriodCycles(256);

setInterval(function () {
var redValue = redSensor.read();
var greenValue = greenSensor.read();
Expand All @@ -70,9 +65,9 @@ setInterval(function () {
"\tGreen: " + greenValue +
"\tBlue: " + blueValue);

redLED.setPulseWidthCycles(redValue);
greenLED.setPulseWidthCycles(greenValue);
blueLED.setPulseWidthCycles(blueValue);
redLED.setCycles(256, redValue);
greenLED.setCycles(256, greenValue);
blueLED.setCycles(256, blueValue);

// FIXME: Currently, ZJS only reads analog pins once per second, so there's
// no point in checking more often. This should be fixed soon.
Expand Down
2 changes: 1 addition & 1 deletion src/zjs_modules.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ module_t zjs_modules_array[] = {
{ "grove_lcd", zjs_grove_lcd_init, zjs_grove_lcd_cleanup },
#endif
#ifdef BUILD_MODULE_PWM
{ "pwm", zjs_pwm_init },
{ "pwm", zjs_pwm_init, zjs_pwm_cleanup },
#endif
#ifdef BUILD_MODULE_I2C
{ "i2c", zjs_i2c_init },
Expand Down
Loading

0 comments on commit d56bac2

Please sign in to comment.