commit
72b91af24a
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
// HomeSpan Addressable RGB LED Examples. Demonstrates use of:
|
||||||
|
//
|
||||||
|
// * HomeSpan Pixel Class that provides for control of single-wire addressable RGB and RGBW LEDs, such as the WS2812 and SK6812
|
||||||
|
// * HomeSpan Dot Class that provides for control of two-wire addressable RGB LEDs, such as the APA102 and SK9822
|
||||||
|
//
|
||||||
|
// IMPORTANT: YOU LIKELY WILL NEED TO CHANGE THE PIN NUMBERS BELOW TO MATCH YOUR SPECIFIC ESP32/S2/C3 BOARD
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||||
|
|
||||||
|
#define NEOPIXEL_RGB_PIN 26
|
||||||
|
#define NEOPIXEL_RGBW_PIN 32
|
||||||
|
#define DOTSTAR_DATA_PIN 33
|
||||||
|
#define DOTSTAR_CLOCK_PIN 27
|
||||||
|
#define DEVICE_SUFFIX ""
|
||||||
|
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
|
#define NEOPIXEL_RGB_PIN 17
|
||||||
|
#define NEOPIXEL_RGBW_PIN 38
|
||||||
|
#define DOTSTAR_DATA_PIN 3
|
||||||
|
#define DOTSTAR_CLOCK_PIN 7
|
||||||
|
#define DEVICE_SUFFIX "-S2"
|
||||||
|
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
|
||||||
|
#define NEOPIXEL_RGB_PIN 8
|
||||||
|
#define NEOPIXEL_RGBW_PIN 2
|
||||||
|
#define DOTSTAR_DATA_PIN 0
|
||||||
|
#define DOTSTAR_CLOCK_PIN 1
|
||||||
|
#define DEVICE_SUFFIX "-C3"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "HomeSpan.h"
|
||||||
|
#include "extras/Pixel.h" // include the HomeSpan Pixel class
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
struct NeoPixel_RGB : Service::LightBulb { // Addressable single-wire RGB LED Strand (e.g. NeoPixel)
|
||||||
|
|
||||||
|
Characteristic::On power{0,true};
|
||||||
|
Characteristic::Hue H{0,true};
|
||||||
|
Characteristic::Saturation S{0,true};
|
||||||
|
Characteristic::Brightness V{100,true};
|
||||||
|
Pixel *pixel;
|
||||||
|
uint8_t nPixels;
|
||||||
|
|
||||||
|
NeoPixel_RGB(uint8_t pin, uint8_t nPixels) : Service::LightBulb(){
|
||||||
|
|
||||||
|
V.setRange(5,100,1); // sets the range of the Brightness to be from a min of 5%, to a max of 100%, in steps of 1%
|
||||||
|
pixel=new Pixel(pin); // creates Pixel LED on specified pin
|
||||||
|
this->nPixels=nPixels; // save number of Pixels in this LED Strand
|
||||||
|
update(); // manually call update() to set pixel with restored initial values
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean update() override {
|
||||||
|
|
||||||
|
int p=power.getNewVal();
|
||||||
|
|
||||||
|
float h=H.getNewVal<float>(); // range = [0,360]
|
||||||
|
float s=S.getNewVal<float>(); // range = [0,100]
|
||||||
|
float v=V.getNewVal<float>(); // range = [0,100]
|
||||||
|
|
||||||
|
Pixel::Color color;
|
||||||
|
|
||||||
|
pixel->set(color.HSV(h*p, s*p, v*p),nPixels); // sets all nPixels to the same HSV color
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
struct NeoPixel_RGBW : Service::LightBulb { // Addressable single-wire RGBW LED Strand (e.g. NeoPixel)
|
||||||
|
|
||||||
|
Characteristic::On power{0,true};
|
||||||
|
Characteristic::Brightness V{100,true};
|
||||||
|
Characteristic::ColorTemperature T{140,true};
|
||||||
|
Pixel *pixel;
|
||||||
|
uint8_t nPixels;
|
||||||
|
|
||||||
|
NeoPixel_RGBW(uint8_t pin, uint8_t nPixels) : Service::LightBulb(){
|
||||||
|
|
||||||
|
V.setRange(5,100,1); // sets the range of the Brightness to be from a min of 5%, to a max of 100%, in steps of 1%
|
||||||
|
pixel=new Pixel(pin,true); // creates Pixel RGBW LED (second parameter set to true for RGBW) on specified pin
|
||||||
|
this->nPixels=nPixels; // save number of Pixels in this LED Strand
|
||||||
|
update(); // manually call update() to set pixel with restored initial values
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean update() override {
|
||||||
|
|
||||||
|
int p=power.getNewVal();
|
||||||
|
|
||||||
|
float v=V.getNewVal<float>(); // range = [0,100]
|
||||||
|
float t=T.getNewVal<float>(); // range = [140,500] (140=coldest, 500=warmest)
|
||||||
|
|
||||||
|
float hue=240-(t-140)/3; // add in a splash of color between blue and green to simulated change of color temperature
|
||||||
|
|
||||||
|
// Pixel::Color color; // if static HSV method is used (below), there is no need to first create a Color object
|
||||||
|
|
||||||
|
pixel->set(pixel->HSV(hue, 100, v*p, v*p),nPixels); // sets all nPixels to the same HSV color (note use of static method pixel->HSV, instead of defining and setting Pixel::Color)
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
struct DotStar_RGB : Service::LightBulb { // Addressable two-wire RGB LED Strand (e.g. DotStar)
|
||||||
|
|
||||||
|
Characteristic::On power{0,true};
|
||||||
|
Characteristic::Hue H{0,true};
|
||||||
|
Characteristic::Saturation S{0,true};
|
||||||
|
Characteristic::Brightness V{100,true};
|
||||||
|
Dot *pixel;
|
||||||
|
uint8_t nPixels;
|
||||||
|
|
||||||
|
DotStar_RGB(uint8_t dataPin, uint8_t clockPin, uint8_t nPixels) : Service::LightBulb(){
|
||||||
|
|
||||||
|
V.setRange(5,100,1); // sets the range of the Brightness to be from a min of 5%, to a max of 100%, in steps of 1%
|
||||||
|
pixel=new Dot(dataPin,clockPin); // creates Dot LED on specified pins
|
||||||
|
this->nPixels=nPixels; // save number of Pixels in this LED Strand
|
||||||
|
update(); // manually call update() to set pixel with restored initial values
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean update() override {
|
||||||
|
|
||||||
|
int p=power.getNewVal();
|
||||||
|
|
||||||
|
float h=H.getNewVal<float>(); // range = [0,360]
|
||||||
|
float s=S.getNewVal<float>(); // range = [0,100]
|
||||||
|
float v=V.getNewVal<float>(); // range = [0,100]
|
||||||
|
|
||||||
|
Dot::Color color[nPixels]; // create an arrary of Colors
|
||||||
|
|
||||||
|
float hueStep=360.0/nPixels; // step size for change in hue from one pixel to the next
|
||||||
|
|
||||||
|
for(int i=0;i<nPixels;i++)
|
||||||
|
color[i].HSV(h+i*hueStep*p,s*p,100,v*p); // create spectrum of all hues starting with specified Hue; use current-limiting parameter (4th argument) to control overall brightness, instead of PWM
|
||||||
|
|
||||||
|
pixel->set(color,nPixels); // set the colors according to the array
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
homeSpan.begin(Category::Lighting,"Pixel LEDS" DEVICE_SUFFIX);
|
||||||
|
|
||||||
|
new SpanAccessory(); // create Bridge
|
||||||
|
new Service::AccessoryInformation();
|
||||||
|
new Characteristic::Name("Pixel LEDS" DEVICE_SUFFIX);
|
||||||
|
new Characteristic::Manufacturer("HomeSpan");
|
||||||
|
new Characteristic::SerialNumber("123-ABC");
|
||||||
|
new Characteristic::Model("Neo/Dot Pixels");
|
||||||
|
new Characteristic::FirmwareRevision("1.0");
|
||||||
|
new Characteristic::Identify();
|
||||||
|
|
||||||
|
new Service::HAPProtocolInformation();
|
||||||
|
new Characteristic::Version("1.1.0");
|
||||||
|
|
||||||
|
/////////
|
||||||
|
|
||||||
|
new SpanAccessory();
|
||||||
|
new Service::AccessoryInformation();
|
||||||
|
new Characteristic::Name("Neo RGB");
|
||||||
|
new Characteristic::Manufacturer("HomeSpan");
|
||||||
|
new Characteristic::SerialNumber("123-ABC");
|
||||||
|
new Characteristic::Model("8-LED Strand");
|
||||||
|
new Characteristic::FirmwareRevision("1.0");
|
||||||
|
new Characteristic::Identify();
|
||||||
|
|
||||||
|
new NeoPixel_RGB(NEOPIXEL_RGB_PIN,8); // create 8-LED NeoPixel RGB Strand with full color control
|
||||||
|
|
||||||
|
/////////
|
||||||
|
|
||||||
|
new SpanAccessory();
|
||||||
|
new Service::AccessoryInformation();
|
||||||
|
new Characteristic::Name("Neo RGBW");
|
||||||
|
new Characteristic::Manufacturer("HomeSpan");
|
||||||
|
new Characteristic::SerialNumber("123-ABC");
|
||||||
|
new Characteristic::Model("60-LED Strand");
|
||||||
|
new Characteristic::FirmwareRevision("1.0");
|
||||||
|
new Characteristic::Identify();
|
||||||
|
|
||||||
|
new NeoPixel_RGBW(NEOPIXEL_RGBW_PIN,60); // create 60-LED NeoPixel RGBW Strand with simulated color temperature control
|
||||||
|
|
||||||
|
/////////
|
||||||
|
|
||||||
|
new SpanAccessory();
|
||||||
|
new Service::AccessoryInformation();
|
||||||
|
new Characteristic::Name("Dot RGB");
|
||||||
|
new Characteristic::Manufacturer("HomeSpan");
|
||||||
|
new Characteristic::SerialNumber("123-ABC");
|
||||||
|
new Characteristic::Model("30-LED Strand");
|
||||||
|
new Characteristic::FirmwareRevision("1.0");
|
||||||
|
new Characteristic::Identify();
|
||||||
|
|
||||||
|
new DotStar_RGB(DOTSTAR_DATA_PIN,DOTSTAR_CLOCK_PIN,30); // create 30-LED DotStar RGB Strand displaying a spectrum of colors and using the current-limiting feature of DotStars to create flicker-free dimming
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
homeSpan.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
@ -8,6 +8,14 @@
|
||||||
|
|
||||||
* Instead, HomeSpan stores your WiFi Credentials in a dedicated non-volatile storage (NVS) partition of the ESP32. There are two ways of entering this information. If you are developing a sketch within the Arduino IDE, simply use the HomeSpan Command Line Interface and type 'W' into the Serial Monitor. HomeSpan will prompt you to input your WiFi SSID and Password (see [CLI](CLI.md) for details). As an alternative, if your HomeSpan device is not connected to a computer, you can launch HomeSpan's Temporary WiFi Setup Network and input your WiFi Credentials directly into the web forms served by your device (see the [User Guide](UserGuide.md#setting-homespans-wifi-credentials-and-setup-code) for details).
|
* Instead, HomeSpan stores your WiFi Credentials in a dedicated non-volatile storage (NVS) partition of the ESP32. There are two ways of entering this information. If you are developing a sketch within the Arduino IDE, simply use the HomeSpan Command Line Interface and type 'W' into the Serial Monitor. HomeSpan will prompt you to input your WiFi SSID and Password (see [CLI](CLI.md) for details). As an alternative, if your HomeSpan device is not connected to a computer, you can launch HomeSpan's Temporary WiFi Setup Network and input your WiFi Credentials directly into the web forms served by your device (see the [User Guide](UserGuide.md#setting-homespans-wifi-credentials-and-setup-code) for details).
|
||||||
|
|
||||||
|
#### What is the Setup Code used for pairing a HomeSpan device to HomeKit?
|
||||||
|
|
||||||
|
* The HomeSpan default Setup Code is 466-37-726. You can (and should) use the HomeSpan Command Line Interface to change this default to a secret code unique for each of your devices. Simply type 'S \<code\>' into the Serial Monitor, or specify your desired Setup Code at the outset when configuring your WiFi Credentials using HomeSpan's Temporary WiFi Setup Network.
|
||||||
|
|
||||||
|
#### Can you use more than one HomeSpan device on the same HomeKit network?
|
||||||
|
|
||||||
|
* Yes, multiple ESP32's, each running a separate copy of HomeSpan, can be used on the same HomeKit network, provided that each device has a unique *Device ID*, a unique *Host Name*, and a unique *Display Name*. Normally, the *Device ID* is randomly-generated by HomeSpan at start-up and will therefore automatically be unique across multiple devices. Also, unless you override the suffix of the default *Host Name*, it will also be unique across multiple devices since HomeSpan uses the *Device ID* as the suffix of the *Host Name*. The only thing you need to ensure is that you assign a different *Display Name* to each of your devices. See the [HomeSpan API Reference](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Reference.md) for details on how to do this.
|
||||||
|
|
||||||
#### Does HomeSpan support video and audio streams?
|
#### Does HomeSpan support video and audio streams?
|
||||||
|
|
||||||
* No, HomeSpan does not support streaming services, such as Audio Stream Management, Data Stream Transport Management, or Camera RTP Management. See [HomeSpan Services and Characteristics](ServiceList.md) for a complete list of all Services supported by HomeSpan.
|
* No, HomeSpan does not support streaming services, such as Audio Stream Management, Data Stream Transport Management, or Camera RTP Management. See [HomeSpan Services and Characteristics](ServiceList.md) for a complete list of all Services supported by HomeSpan.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ The Arduino IDE comes with built-in compilers and support for a variety of Ardui
|
||||||
|
|
||||||
HomeSpan is packaged as a standard Arduino library and can be installed either automatically from the Arduino IDE, or manually via GitHub.
|
HomeSpan is packaged as a standard Arduino library and can be installed either automatically from the Arduino IDE, or manually via GitHub.
|
||||||
|
|
||||||
* To install automatically, open the Arduino Library Manager from wihtin the Arduino IDE by selecting *Sketch → Include Library → Manage Libraries...* from the Arduino menu bar. Then, type *HomeSpan* into the search box, choose the latest version from the drop-down box, and click the `Install` button. The Arduino Library Manager will automatically download and install the version you selected. HomeSpan and all of the tutorial example sketches are now ready for use.
|
* To install automatically, open the Arduino Library Manager from within the Arduino IDE by selecting *Sketch → Include Library → Manage Libraries...* from the Arduino menu bar. Then, type *HomeSpan* into the search box, choose the latest version from the drop-down box, and click the `Install` button. The Arduino Library Manager will automatically download and install the version you selected. HomeSpan and all of the tutorial example sketches are now ready for use.
|
||||||
|
|
||||||
* To install manually, first download the [latest version](https://github.com/HomeSpan/HomeSpan/releases/latest) of *Source Code (zip)* to your desktop. It does not matter if your operating system keeps the package in zip form, or automatically unzips it when saving to you desktop. Next, from the top menu bar within the Arduino IDE, select *Sketch → Include Library → Add .ZIP Library...* and navigtate to the Desktop folder where you should see the HomeSpan package you just downloaded (either as a zip file, or a folder). Select the package (don't open it) and click `Choose`. This directs the Arduino IDE to copy the HomeSpan package into its library sub-folder. HomeSpan is now ready for use as a standard Arduino library (you may delete the HomeSpan package from your desktop as it is no longer needed).
|
* To install manually, first download the [latest version](https://github.com/HomeSpan/HomeSpan/releases/latest) of *Source Code (zip)* to your desktop. It does not matter if your operating system keeps the package in zip form, or automatically unzips it when saving to you desktop. Next, from the top menu bar within the Arduino IDE, select *Sketch → Include Library → Add .ZIP Library...* and navigtate to the Desktop folder where you should see the HomeSpan package you just downloaded (either as a zip file, or a folder). Select the package (don't open it) and click `Choose`. This directs the Arduino IDE to copy the HomeSpan package into its library sub-folder. HomeSpan is now ready for use as a standard Arduino library (you may delete the HomeSpan package from your desktop as it is no longer needed).
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ Ready to start creating your own HomeSpan sketches? Check out the [HomeSpan Ser
|
||||||
|
|
||||||
While developing your sketch remember to utilize the Arduino Serial Monitor. HomeSpan produces extensive diagnostics that will help you debug your sketches as well as monitor all aspects of the HomeSpan device. You'll also be able to control various aspects of HomeSpan from the Serial Monitor using the [HomeSpan Command-Line Interface (CLI)](CLI.md), including configuring the device's WiFi Credentials and HomeKit Setup Code.
|
While developing your sketch remember to utilize the Arduino Serial Monitor. HomeSpan produces extensive diagnostics that will help you debug your sketches as well as monitor all aspects of the HomeSpan device. You'll also be able to control various aspects of HomeSpan from the Serial Monitor using the [HomeSpan Command-Line Interface (CLI)](CLI.md), including configuring the device's WiFi Credentials and HomeKit Setup Code.
|
||||||
|
|
||||||
For access to even more advanced features, check out the [HomeSpan Extras](Extras.md) page for details on how to use HomeSpan's integrated PWM and Remote Control libraries.
|
For access to even more advanced features, check out the [HomeSpan PWM](https://github.com/HomeSpan/HomeSpan/blob/master/docs/PWM.md), [HomeSpan RFControl](https://github.com/HomeSpan/HomeSpan/blob/master/docs/RMT.md), and [HomeSpan Pixels](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Pixels.md) pages for tutorials and details on how HomeSpan can be used to control LEDs, lights, and Servo Motors with PWM signals; generate RF and IR Remote Control codes to operate appliances and TVs; and even control multicolor RGB LED strips.
|
||||||
|
|
||||||
Finally, disconnect your HomeSpan device from the computer and power it directly from a wall adapter. After all, HomeSpan devices are designed to run on a standalone basis connected to real-world applicances like lights, fans, door locks, and window shades. See the [HomeSpan User Guide](UserGuide.md) for end-user instructions on how to operate and configure a standlone HomeSpan device's WiFi Credentials and HomeKit Setup Code *without the need to connect the device to a computer*.
|
Finally, disconnect your HomeSpan device from the computer and power it directly from a wall adapter. After all, HomeSpan devices are designed to run on a standalone basis connected to real-world applicances like lights, fans, door locks, and window shades. See the [HomeSpan User Guide](UserGuide.md) for end-user instructions on how to operate and configure a standlone HomeSpan device's WiFi Credentials and HomeKit Setup Code *without the need to connect the device to a computer*.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Pulse Width Modulation (PWM)
|
||||||
|
|
||||||
|
The ESP32 has up to 16 PWM channels that can be used to drive a variety of devices. HomeSpan includes an integrated PWM library with dedicated classes designed for controlling **Dimmable LEDs** as well as **Servo Motors**. Both classes are provided in a standalone header file that is accessed by placing the following near the top of your sketch:
|
||||||
|
|
||||||
|
`#include "extras/PwmPin.h"`
|
||||||
|
|
||||||
|
## *LedPin(uint8_t pin [,float level [,uint16_t frequency]])*
|
||||||
|
|
||||||
|
Creating an instance of this **class** configures the specified *pin* to output a PWM signal suitable for a controlling dimmable LED. Arguments, along with their defaults if left unspecified, are as follows:
|
||||||
|
|
||||||
|
* *pin* - the pin on which the PWM control signal will be output
|
||||||
|
* *level* - sets the initial %duty-cycle of the PWM from from 0 (LED completely off) to 100 (LED fully on). Default=0 (LED initially off)
|
||||||
|
* *frequency* - sets the PWM frequency, in Hz, from 1-65535 (ESP32 only) or 5-65535 (ESP32-S2 and ESP32-C3). Defaults to 5000 Hz if unspecified, or if set to 0
|
||||||
|
|
||||||
|
The following methods are supported:
|
||||||
|
|
||||||
|
* `void set(float level)`
|
||||||
|
|
||||||
|
* sets the PWM %duty-cycle to *level*, where *level* ranges from 0 (LED completely off) to 100 (LED fully on)
|
||||||
|
|
||||||
|
* `int getPin()`
|
||||||
|
|
||||||
|
* returns the pin number (or -1 if LedPin was not successfully initialized)
|
||||||
|
|
||||||
|
LedPin also includes a static class function that converts Hue/Saturation/Brightness values (typically used by HomeKit) to Red/Green/Blue values (typically used to control multi-color LEDS).
|
||||||
|
|
||||||
|
* `static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b)`
|
||||||
|
|
||||||
|
* *h* - input Hue value, range 0-360
|
||||||
|
* *s* - input Saturation value, range 0-1
|
||||||
|
* *v* - input Brightness value, range 0-1
|
||||||
|
* *r* - output Red value, range 0-1
|
||||||
|
* *g* - output Green value, range 0-1
|
||||||
|
* *b* - output Blue value, range 0-1
|
||||||
|
|
||||||
|
See tutorial sketch [#10 (RGB_LED)](../examples/10-RGB_LED) for an example of using LedPin to control an RGB LED.
|
||||||
|
|
||||||
|
## *ServoPin(uint8_t pin [,double initDegrees [,uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees]])*
|
||||||
|
|
||||||
|
Creating an instance of this **class** configures the specified *pin* to output a 50 Hz PWM signal, which is suitable for controlling most Servo Motors. There are three forms of the constructor: one with just a single argument; one with two arguments; and one with all six arguments. Arguments, along with their defaults if left unspecified, are as follows:
|
||||||
|
|
||||||
|
* *pin* - the pin on which the PWM control signal will be output. The control wire of a Servo Motor should be connected this pin
|
||||||
|
* *initDegrees* - the initial position (in degrees) to which the Servo Motor should be set (default=0°)
|
||||||
|
* *minMicros* - the pulse width (in microseconds) that moves the Servo Motor to its "minimium" position of *minDegrees* (default=1000𝛍s)
|
||||||
|
* *maxMicros* - the pulse width (in microseconds) that moves the Servo Motor to its "maximum" position of *maxDegrees* (default=2000𝛍s)
|
||||||
|
* *minDegrees* - the position (in degrees) to which the Servo Motor moves when receiving a pulse width of *minMicros* (default=-90°)
|
||||||
|
* *maxDegrees* - the position (in degrees) to which the Servo Motor moves when receiving a pulse width of *maxMicros* (default=90°)
|
||||||
|
|
||||||
|
The *minMicros* parameter must be less than the *maxMicros* parameter, but setting *minDegrees* to a value greater than *maxDegrees* is allowed and can be used to reverse the minimum and maximum positions of the Servo Motor. The following methods are supported:
|
||||||
|
|
||||||
|
* `void set(double position)`
|
||||||
|
|
||||||
|
* sets the position of the Servo Motor to *position* (in degrees). In order to protect the Servo Motor, values of *position* less than *minDegrees* are automatically reset to *minDegrees*, and values greater than *maxDegrees* are automatically reset to *maxDegrees*.
|
||||||
|
|
||||||
|
* `int getPin()`
|
||||||
|
|
||||||
|
* returns the pin number (or -1 if ServoPin was not successfully initialized)
|
||||||
|
|
||||||
|
A worked example showing how ServoPin can be used to control the Horizontal Tilt of a motorized Window Shade can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → ServoControl*](../Other%20Examples/ServoControl).
|
||||||
|
|
||||||
|
### PWM Resource Allocation and Limitations
|
||||||
|
|
||||||
|
The following PWM resources are available:
|
||||||
|
|
||||||
|
* ESP32: 16 Channels / 8 Timers (arranged in two distinct sets of 8 Channels and 4 Timers)
|
||||||
|
* ESP32-S2: 8 Channels / 4 Timers
|
||||||
|
* ESP32-C3: 6 Channels / 4 Timers
|
||||||
|
|
||||||
|
HomeSpan *automatically* allocates Channels and Timers to LedPin and ServoPin objects as they are instantiated. Every pin assigned consumes a single Channel; every *unique* frequency specified among all channels (within the same set, for the ESP32) consumes a single Timer. HomeSpan will conserve resources by re-using the same Timer for all Channels operating at the same frequency. *HomeSpan also automatically configures each Timer to support the maximum duty-resolution possible for the frequency specified.*
|
||||||
|
|
||||||
|
HomeSpan will report a non-fatal error message to the Arduino Serial Monitor when insufficient Channel or Timer resources prevent the creation of a new LedPin or ServoPin object. Calls to the `set()` method for objects that failed to be properly created are silently ignored.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[↩️](README.md) Back to the Welcome page
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
# Addressable RGB LEDs
|
||||||
|
|
||||||
|
HomeSpan includes two dedicated classes that provide for easy control of "addressable" RGB LEDs. The **Pixel()** class is used for RGB and RGBW LEDs that require only a single "data" control wire, such as this 8-pixel [NeoPixel RGB Stick](https://www.adafruit.com/product/1426) or this single-pixel [NeoPixel RGBW LED](https://www.adafruit.com/product/2759). The **Dot()** class is used for RGB LEDs that require two control wires ("data" and "clock"), such as this 144-pixel [DotStar RGB Strip](https://www.adafruit.com/product/2241) or this 60-pixel [RGB LED Strip](https://www.sparkfun.com/products/14015).
|
||||||
|
|
||||||
|
Both classes allow you to individually set each of the "pixels" in a multi-pixel LED strip to a different 24-bit RGB color (or 32-bit color, if using RGBW LEDs). Alternatively, the classes allow you to simply specify a single 24-bit (or 32-bit) color to duplicate across all pixels.
|
||||||
|
|
||||||
|
The methods for both classes are nearly identical, which allows you to readily interchange code written for single-wire devices to use with two-wire devices (and vice-versa) with only minor modifications.
|
||||||
|
|
||||||
|
Both classes are provided in a standalone header file that is accessed by placing the following near the top of your sketch:
|
||||||
|
|
||||||
|
`#include "extras/Pixel.h"`
|
||||||
|
|
||||||
|
## *Pixel(uint8_t pin, [boolean isRGBW])*
|
||||||
|
|
||||||
|
Creating an instance of this **class** configures the specified *pin* to output a waveform signal suitable for controlling a single-wire, addressable RGB or RGBW LED device with an arbitrary number of pixels. Such devices typically contain SK6812 or WS2812 LEDs. Arguments, along with their defaults if left unspecified, are as follows:
|
||||||
|
|
||||||
|
* *pin* - the pin on which the RGB control signal will be output; normally connected to the "data" input of the addressable LED device
|
||||||
|
* *isRGBW* - set to *true* for RGBW devices that contain 4-color (red/green/blue/white) LEDs; set to *false* for the more typical 3-color RGB devices. Defaults to *false* if unspecified. Note you must set the *isRGBW* flag to *true* if you are using an RGBW device, even if you do not intend on utilizing the white LED
|
||||||
|
|
||||||
|
The two main methods to set pixel colors are:
|
||||||
|
|
||||||
|
* `void set(Color color, int nPixels=1)`
|
||||||
|
|
||||||
|
* sets the color of a pixel in a single-pixel device, or equivalently, the color of the first *nPixels* in a multi-pixel device, to *color*, where *color* is an object of type **Color** defined below. If unspecified, *nPixels* defaults to 1 (i.e. a single pixel). It is not a problem if the value specified for *nPixels* does not match the total number of actual RGB (or RGBW) pixels in your device; if *nPixels* is less than the total number of device pixels, only the first *nPixels* will be set to *color*; if *nPixels* is greater than the total number of device pixels, the device will simply ignore the additional input
|
||||||
|
|
||||||
|
* `void set(Color *color, int nPixels)`
|
||||||
|
|
||||||
|
* individually sets the color of each pixel in a multi-pixel device to the color values specified in the **Color** array *\*color*, of *nPixels* size, where the first pixel of the device is set to the value in *color\[0\]*, the second pixel is set to the value in *color\[1\]* ... and the last pixel is set to the value in *color\[nPixels-1\]*. Similar to above, it is not a problem if the value specified for *nPixels* does not match the total number of actual RGB (or RGBW) pixels in your device
|
||||||
|
|
||||||
|
In both of the methods above, colors are stored in a 32-bit **Color** object configured to hold four 8-bit RGBW values. **Color** objects can be instantiated as single variables (e.g. `Pixel::Color myColor;`) or as arrays (e.g. `Pixel::Color myColors\[8\];`). Note that the **Color** object used by the **Pixel** class is scoped to the **Pixel** class itself, so you need to use the fully-qualified class name "Pixel::Color". Once a **Color** object is created, the color it stores can be set using one of the two following methods:
|
||||||
|
|
||||||
|
* `Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0)`
|
||||||
|
|
||||||
|
* where *r*, *g*, and *b*, represent 8-bit red, green, and blue values over the range 0-255, and *w* represents an 8-bit value [0-255] for the white LED. The white value may be left unspecified, in which case it defaults to 0. Also, the white value will be ignored by *set()* unless the *isRGBW* flag was specified as *true* in the constructor
|
||||||
|
* example: `myColor.RGB(255,255,0)` sets myColor to bright yellow
|
||||||
|
|
||||||
|
* `Color HSV(float h, float s, float v, double w=0)`
|
||||||
|
|
||||||
|
* where *h*=Hue, over the range 0-360; *s*=Saturation percentage from 0-100; and *v*=Brightness percentage from 0-100. These values are converted to equivalent 8-bit RGB values (0-255) for storage in the *Color* object. Note the *w* value is treated separately and represents a percentage of brightness for the white LED (from 0-100) that is also converted into an 8-bit value from 0-255 for storage in the **Color** object. Similar to above, the white value may be left unspecified, in which case it defaults to 0
|
||||||
|
* example: `myColor.HSV(120,100,50)` sets myColor to fully-saturated green with 50% brightness
|
||||||
|
|
||||||
|
Note both methods above return the completed **Color** object itself and can thus be used wherever a **Color** object is required: For example: `Pixel p(5); Pixel::Color myColor; p.set(myColor.RGB(255,215,0))` sets the color of a single pixel device attached to pin 5 to bright gold.
|
||||||
|
|
||||||
|
The **Pixel** class also supports the following class-level methods as a convenient alternative to creating colors:
|
||||||
|
|
||||||
|
* `static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0)`
|
||||||
|
* equivalent to `return(Color().RGB(r,g,b,w));`
|
||||||
|
* example: `Pixel p(8); p.set(Pixel::RGB(0,0,255),8);` sets the color of each pixel in an 8-pixel device to blue
|
||||||
|
|
||||||
|
* `static Color HSV(float h, float s, float v, double w=0)`
|
||||||
|
* equivalent to `return(Color().HSV(h,s,v,w));`
|
||||||
|
* example: `Pixel::Color c[]={Pixel::HSV(120,100,100),Pixel::HSV(60,100,100),Pixel::HSV(0,100,100)};` to create a red-yellow-green traffic light pattern
|
||||||
|
|
||||||
|
Finally, the **Pixel** class supports these two additional, but rarely-needed, methods:
|
||||||
|
|
||||||
|
* `int getPin()`
|
||||||
|
|
||||||
|
* returns the pin number, or -1 if the instantiation failed due to lack of resources
|
||||||
|
|
||||||
|
* `void setTiming(float high0, float low0, float high1, float low1, uint32_t lowReset)`
|
||||||
|
|
||||||
|
* the default timing parameters used by the **Pixel** class to generate the "data" signal needed to set the colors of an RGB LED device should work with most commercial products based on SK6812 or WS2812 driver chips. Use this method **ONLY** if you need to override the class defaults and replace them with your own timing parameters, where
|
||||||
|
* *high0* and *low0* specify the duration (in microseconds) of the high phase and low phase for a pulse encoding a zero-bit;
|
||||||
|
* *high1* and *low1* specify the duration (in microseconds) of the high phase and low phase for a pulse encoding a one-bit; and
|
||||||
|
* *lowReset* specifies the delay (in microseconds) representing the end of a pulse stream
|
||||||
|
* for reference, the **Pixel** class uses the following defaults: *high0=0.32𝛍s, low0=0.88𝛍s, high1=0.64𝛍s, low1=0.56𝛍s, lowReset=80.0𝛍s*
|
||||||
|
|
||||||
|
### Resource Usage and Resource Conflicts
|
||||||
|
|
||||||
|
The **Pixel** class relies on the ESP32's RMT peripheral to create the precise pulse trains required to control single-wire addressable RGB LEDs. Since each instantiation of **Pixel** consumes an RMT channel, the number of **Pixel** objects you can instantiate (each controlling a separate multi-pixel RGB LED device attached to a specific pin) is limited to the number of RMT available as follows: ESP32 - 8 instances; ESP32-S2 - 4 instances; ESP32-C3 - 2 instances.
|
||||||
|
|
||||||
|
Also, the **Pixel** class is optimized to handle arbitrarily-long LED strips containing hundreds of RGB or RGBW pixels. To accomplish this efficiently, the **Pixel** class implements its own RMT driver, which conflicts with the default RMT driver used by HomeSpan's **RFControl** library. Unfortunately this means you cannot use both the **Pixel** class library and **RFControl** class library in the same HomeSpan sketch.
|
||||||
|
|
||||||
|
## *Dot(uint8_t dataPin, uint8_t clockPin)*
|
||||||
|
|
||||||
|
Creating an instance of this **class** configures the specified pins to output waveform signals suitable for controlling a two-wire, addressable RGB LED device with an arbitrary number of pixels. Such devices typically contain SK9822 or APA102 LEDs, or an embedded WS2801 driver chip. Arguments, along with their defaults if left unspecified, are as follows:
|
||||||
|
|
||||||
|
* *dataPin* - the pin on which the RGB data signal will be output; normally connected to the "data" input of the addressable LED device
|
||||||
|
* *clockPin* - the pin on which the RGB clock signal will be output; normally connected to the "clock" input of the addressable LED device
|
||||||
|
|
||||||
|
The two main methods to set pixel colors are:
|
||||||
|
|
||||||
|
* `void set(Color color, int nPixels=1)`
|
||||||
|
|
||||||
|
* sets the color of a pixel in a single-pixel device, or equivalently, the color of the first *nPixels* in a multi-pixel device, to *color*, where *color* is an object of type **Color** defined below. If unspecified, *nPixels* defaults to 1 (i.e. a single pixel). It is not a problem if the value specified for *nPixels* does not match the total number of actual RGB pixels in your device; if *nPixels* is less than the total number of device pixels, only the first *nPixels* will be set to *color*; if *nPixels* is greater than the total number of device pixels, the device will simply ignore the additional input
|
||||||
|
|
||||||
|
* `void set(Color *color, int nPixels)`
|
||||||
|
|
||||||
|
* individually sets the color of each pixel in a multi-pixel device to the color values specified in the **Color** array *\*color*, of *nPixels* size, where the first pixel of the device is set to the value in *color\[0\]*, the second pixel is set to the value in *color\[1\]* ... and the last pixel is set to the value in *color\[nPixels-1\]*. Similar to above, it is not a problem if the value specified for *nPixels* does not match the total number of actual RGB pixels in your device
|
||||||
|
|
||||||
|
In both of the methods above, colors are stored in a 32-bit **Color** object configured to hold three 8-bit RGB values plus a 5-bit value that can be used to limit the LED current. **Color** objects can be instantiated as single variables (e.g. `Dot::Color myColor;`) or as arrays (e.g. `Dot::Color myColors\[8\];`). Note that the **Color** object used by the **Dot** class is scoped to the **Dot** class itself, so you need to use the fully-qualified class name "Dot::Color". Once a **Color** object is created, the color it stores can be set using one of the two following methods:
|
||||||
|
|
||||||
|
* `Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31)`
|
||||||
|
|
||||||
|
* where *r*, *g*, and *b*, represent 8-bit red, green, and blue values over the range 0-255, and *driveLevel* represents an 5-bit value [0-31] used to limit the LED current from 0 (no current) to 31 (max current, which is the default). Limiting the LED current by setting the *driveLevel* to a value of less than 31 provides a flicker-free way of controlling the brightness of the RGB LEDs for each pixel.
|
||||||
|
* example: `myColor.RGB(128,128,0)` sets myColor to yellow at half-brightness using a 50% duty cycle for the red and green LEDs (i.e. 128/256)
|
||||||
|
* example: `myColor.RGB(255,255,0,16)` sets myColor to yellow at half-brightness by limiting the LED current for the pixel to 50% of its max value (i.e. 16/32)
|
||||||
|
|
||||||
|
* `Color HSV(float h, float s, float v, double drivePercent=100)`
|
||||||
|
|
||||||
|
* where *h*=Hue, over the range 0-360; *s*=Saturation percentage from 0-100; and *v*=Brightness percentage from 0-100. These values are converted to equivalent 8-bit RGB values (0-255) for storage in the *Color* object. The *drivePercent* parameter controls the current in the same fashion as *driveLevel* above, except that instead of being specified as an absolute value from 0-31, it is specified as a percentage from 0 to 100 (the default)
|
||||||
|
* example: `myColor.HSV(120,100,50)` sets myColor to fully-saturated green at half-brightness using a 50% duty cycle
|
||||||
|
* example: `myColor.HSV(120,100,100,50)` sets myColor to fully-saturated green at half-brightness by limiting the LED current for the pixel to 50% of its max value
|
||||||
|
|
||||||
|
Note both methods above return the completed **Color** object itself and can thus be used wherever a **Color** object is required: For example: `Dot p(5,6); Dot::Color myColor; p.set(myColor.RGB(255,215,0))` sets the color of a single pixel device attached to pins 5 and 6 to bright gold.
|
||||||
|
|
||||||
|
The **Pixel** class also supports the following class-level methods as a convenient alternative to creating colors:
|
||||||
|
|
||||||
|
* `static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31)`
|
||||||
|
* equivalent to `return(Color().RGB(r,g,b,driveLevel));`
|
||||||
|
* example: `Dot p(8,11); p.set(Dot::RGB(0,0,255),8);` sets the color of each pixel in an 8-pixel device to blue
|
||||||
|
|
||||||
|
* `static Color HSV(float h, float s, float v, double drivePercent=100)`
|
||||||
|
* equivalent to `return(Color().HSV(h,s,v,drivePercent));`
|
||||||
|
* example: `Dot::Color c[]={Dot::HSV(120,100,100),Dot::HSV(60,100,100),Dot::HSV(0,100,100)};` to create a red-yellow-green traffic light pattern
|
||||||
|
|
||||||
|
Unlike the **Pixel** class, the **Dot** class does *not* utilize the ESP32's RMT peripheral and thus there are no limits to the number of **Dot** objects you can instantiate, nor are there any conflicts with using the **Dot** class and the **RFControl** library at the same time in the same sketch. Also, since the clock signal is generated by the **Dot** class itself, there are no timing parameters to set and no need for a *setTiming()* method.
|
||||||
|
|
||||||
|
### Example Sketches
|
||||||
|
|
||||||
|
A fully worked example showing how to use the Pixel library within a HomeSpan sketch to control an RGB Pixel Device, an RGBW Pixel Device, and an RGB DotStar Device, all from the Home App on your iPhone, can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → Pixel*](../Other%20Examples/Pixel).
|
||||||
|
|
||||||
|
For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Reference.md#define-custom_charnameuuidpermsformatdefaultvalueminvaluemaxvaluestaticrange) to implement a special-effects "selector" button for use in the Eve for HomeKit App.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[↩️](README.md) Back to the Welcome page
|
||||||
|
|
@ -11,7 +11,14 @@ In contrast, pairing a HomeKit device with a **QR Code** requires you to only sc
|
||||||
|
|
||||||
This is possible because the QR Code includes a 4-character *Setup ID* that is unique to the device associated with the QR Code. The QR Code also embeds other paring information about the device, such as its Category (e.g. Light, Fan, Door) and its 8-digit *Setup Code*.
|
This is possible because the QR Code includes a 4-character *Setup ID* that is unique to the device associated with the QR Code. The QR Code also embeds other paring information about the device, such as its Category (e.g. Light, Fan, Door) and its 8-digit *Setup Code*.
|
||||||
|
|
||||||
HomeSpan supports pairing with QR Codes and uses "HSPN" as its default *Setup ID*. However, if you have more than one device that you intend on pairing with a QR Code, you'll need to change each device's *Setup ID* from "HSPN" to something unique using the method `homeSpan.setQRID(const char *ID)` (see the [HomeSpan API Reference](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Reference.md) for details). If you do not intend on pairing your devices with QR Codes, it is fine for them to all have the same *Setup ID*, as this ID is only used to initiate the pairing process via a QR code and serves no other purpose.
|
HomeSpan supports pairing with QR Codes and uses "HSPN" as its default *Setup ID*. However, if you have more than one device that you intend on pairing with a QR Code, you'll need to enure each has a unique *Setup ID*. You can change the *Setup ID* on your device in one of two ways:
|
||||||
|
|
||||||
|
* Store a new code in the device NVS by typing 'O \<code\>' into the HomeSpan [Command Line Interface](https://github.com/HomeSpan/HomeSpan/blob/master/docs/CLI.md); or
|
||||||
|
* Specify the QR *Setup ID* directly in your sketch using the method `homeSpan.setQRID(const char *ID)`.
|
||||||
|
|
||||||
|
The order of preference is as follows: If your sketch contains a call to `homeSpan.setQRID(const char *ID)`, the specified ID is used. If not, HomeSpan will instead search the NVS for a stored *Setup ID*. If not found, HomeSpan defaults to using "HSPN" as the *Setup ID*.
|
||||||
|
|
||||||
|
Note that if you do not intend on pairing your devices with QR Codes, it is fine for them to all retain the default *Setup ID* of "HSPN" since this ID is only used to initiate the pairing process via a QR code and serves no other purpose.
|
||||||
|
|
||||||
### Creating Scannable QR Codes
|
### Creating Scannable QR Codes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,10 @@ HomeSpan is fully compatible with both Versions 1 and 2 of the [Arduino-ESP32 Bo
|
||||||
* Servo Motors
|
* Servo Motors
|
||||||
* Integrated Push Button functionality supporting single, double, and long presses
|
* Integrated Push Button functionality supporting single, double, and long presses
|
||||||
* Integrated access to the ESP32's on-chip Remote Control peripheral for easy generation of IR and RF signals
|
* Integrated access to the ESP32's on-chip Remote Control peripheral for easy generation of IR and RF signals
|
||||||
* 18 detailed tutorial-sketches with extensive comments, HomeSpan documentation and tips and tricks
|
* Dedicated classes to control one- and two-wire addressable RGB and RGBW LEDs and LED strips
|
||||||
|
* Extensively-commented Tutorial Sketches taking you from the very basics of HomeSpan through advanced HomeKit topics
|
||||||
|
* Additional examples and projects showcasing real-world implementations of HomeSpan
|
||||||
|
* A complete set of documentation explaining every aspect of the HomeSpan API
|
||||||
|
|
||||||
### For the HomeSpan End-User
|
### For the HomeSpan End-User
|
||||||
|
|
||||||
|
|
@ -41,22 +44,26 @@ HomeSpan is fully compatible with both Versions 1 and 2 of the [Arduino-ESP32 Bo
|
||||||
* Launch the WiFi Access Point
|
* Launch the WiFi Access Point
|
||||||
* A standalone, detailed End-User Guide
|
* A standalone, detailed End-User Guide
|
||||||
|
|
||||||
## ❗Latest Update - HomeSpan 1.4.2 (11/27/2021)
|
## ❗Latest Update - HomeSpan 1.5.0 (2/20/2022)
|
||||||
|
|
||||||
* **Updated for compatability with Arduino-ESP32 Board Manager 2.0.1**
|
* **New integrated library to control one- and two-wire Addressable RGB and RGBW LEDs and LED strips!**
|
||||||
* Maintains backward compatability with all previous versions
|
* Adds two new class:
|
||||||
|
* **Pixel()** for control of one-wire RGB and RGBW LEDs and LED strips, such as this [NeoPixel RGBW LED](https://www.adafruit.com/product/2759)
|
||||||
|
* **Dot()** for control of two-wire RGB LEDs and LED strips, such as this [DotStar RGB Strip](https://www.adafruit.com/product/2241)
|
||||||
|
|
||||||
|
* See [HomeSpan Pixels](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Pixel.md) for full details, including a detailed tutorial sketch demonstrating different ways of using the **Pixel()** and **Dot()** classes, as well an advanced HomeSpan "HolidayLights" Project that shows how to develop custom special effects!
|
||||||
|
|
||||||
* **Some new methods and options for advance-use circumstances:**
|
* **Increased the maximum number of simultaneous Controller connections from 8 to 14 (for Arduino-ESP32 version 2.0.1 and later)**
|
||||||
|
* Added new method `reserveSocketConnection(uint8_t nSockets)` to the global homeSpan object that allows for better management of custom connections
|
||||||
|
* Deprecated older `setMaxConnections(uint8_t nCon)` method
|
||||||
|
|
||||||
* Added *optional* second argument to the `setVal()` method that allows the value of a Characteristic to be updated *without* sending notification messages to HomeKit. Useful for keeping track of duration time when implementing a Sprinkler System - see [HomeSpan Reference Sprinkler](https://github.com/HomeSpan/HomeSpanReferenceSketches/tree/main/ReferenceSprinklers) for an example
|
* **Additional updates include:**
|
||||||
|
* Added new methods `setDescription(const char *desc)` and `setUnit(const char *unit)` to SpanCharacteristic. Useful when creating and working with Custom Characteristics
|
||||||
|
* Added new method `setStatusAutoOff(uint16_t duration)` to the global homeSpan object. Causes the Status LED (if used) to automatically turn off after *duration* seconds. Very handy for devices located in bedrooms or TV rooms!
|
||||||
|
* Added new method `setPairCallback(func)` to the global homeSpan object. Allows you to create custom actions whenever HomeSpan pairs or subsequently unpairs the device to the Home App
|
||||||
|
* Added new method `deleteStoredValues()` to the global homeSpan object. Provides a programmatic way of deleting the value settings of all Characteristics stored in the NVS
|
||||||
|
|
||||||
* Added `getLinks()` as a new method to SpanService. Returns a vector of pointers to SpanServices that have been linked to another Service with the addLink() method. Useful for looping over all linked services, such as checking all valves in a Shower System - see [HomeSpan Reference Shower](https://github.com/HomeSpan/HomeSpanReferenceSketches/tree/main/ReferenceShower) for an example
|
See [Releases](https://github.com/HomeSpan/HomeSpan/releases) for details on all changes and bug fixes included in this update.
|
||||||
|
|
||||||
* Added `setPerms()`, `addPerms()`, and `removePerms()` as new methods to SpanCharacteristic. Allows the user to modify (set/add/remove) the default permissions for any Characteristic. Useful for adding/deleting write-permissions for certain Characteristics - see [Television Example](https://github.com/HomeSpan/HomeSpan/tree/master/Other%20Examples/Television) for an example
|
|
||||||
|
|
||||||
* Added `setPairingCode()` method to the global homeSpan object that allows for programmatically configuring the Pairing Setup Code inside your sketch. See the HomeSpan API for important security considerations when using this function!
|
|
||||||
|
|
||||||
See [Releases](https://github.com/HomeSpan/HomeSpan/releases) for details on all changes included in this update.
|
|
||||||
|
|
||||||
# HomeSpan Resources
|
# HomeSpan Resources
|
||||||
|
|
||||||
|
|
@ -72,7 +79,9 @@ HomeSpan includes the following documentation:
|
||||||
* [HomeSpan API Reference](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Reference.md) - a complete guide to the HomeSpan Library API
|
* [HomeSpan API Reference](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Reference.md) - a complete guide to the HomeSpan Library API
|
||||||
* [HomeSpan QR Codes](https://github.com/HomeSpan/HomeSpan/blob/master/docs/QRCodes.md) - create and use QR Codes for pairing HomeSpan devices
|
* [HomeSpan QR Codes](https://github.com/HomeSpan/HomeSpan/blob/master/docs/QRCodes.md) - create and use QR Codes for pairing HomeSpan devices
|
||||||
* [HomeSpan OTA](https://github.com/HomeSpan/HomeSpan/blob/master/docs/OTA.md) - update your sketches Over-the-Air directly from the Arduino IDE without a serial connection
|
* [HomeSpan OTA](https://github.com/HomeSpan/HomeSpan/blob/master/docs/OTA.md) - update your sketches Over-the-Air directly from the Arduino IDE without a serial connection
|
||||||
* [HomeSpan Extras](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Extras.md) - integrated access to the ESP32's on-chip LED, Servo Motor, and Remote Control peripherals!
|
* [HomeSpan PWM](https://github.com/HomeSpan/HomeSpan/blob/master/docs/PWM.md) - integrated control of standard LEDs and Servo Motors using the ESP32's on-chip PWM peripheral
|
||||||
|
* [HomeSpan RFControl](https://github.com/HomeSpan/HomeSpan/blob/master/docs/RMT.md) - easy generation of RF and IR Remote Control signals using the ESP32's on-chip RMT peripheral
|
||||||
|
* [HomeSpan Pixels](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Pixels.md) - integrated control of addressable one- and two-wire RGB and RGBW LEDs and LED strips
|
||||||
* [HomeSpan Television Services](https://github.com/HomeSpan/HomeSpan/blob/master/docs/TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics
|
* [HomeSpan Television Services](https://github.com/HomeSpan/HomeSpan/blob/master/docs/TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics
|
||||||
* [HomeSpan Projects](https://github.com/topics/homespan) - real-world applications of the HomeSpan Library
|
* [HomeSpan Projects](https://github.com/topics/homespan) - real-world applications of the HomeSpan Library
|
||||||
* [HomeSpan FAQ](https://github.com/HomeSpan/HomeSpan/blob/master/docs/FAQ.md) - answers to frequently-asked questions
|
* [HomeSpan FAQ](https://github.com/HomeSpan/HomeSpan/blob/master/docs/FAQ.md) - answers to frequently-asked questions
|
||||||
|
|
|
||||||
|
|
@ -1,86 +1,10 @@
|
||||||
# HomeSpan Extras
|
# Remote Control Radio Frequency / Infrared Signal Generation
|
||||||
|
|
||||||
HomeSpan includes integrated access to a number of ESP32 features you'll likely find particularly useful when constructing your HomeSpan devices.
|
The ESP32 has an on-chip signal-generator peripheral designed to drive an RF or IR transmitter. HomeSpan includes an easy-to-use library that interfaces with this peripheral so that with a few additional electronic components you can create a HomeSpan device that controls an RF or IR appliance directly from the Home App on your iPhone, or via Siri. The library is accessed by placing the following near the top of your sketch:
|
||||||
|
|
||||||
## Pulse Width Modulation (PWM)
|
|
||||||
|
|
||||||
The ESP32 has up to 16 PWM channels that can be used to drive a variety of devices. HomeSpan includes an integrated PWM library with dedicated classes designed for controlling **Dimmable LEDs** as well as **Servo Motors**. Both classes are provided in a standalone header file that is accessed by placing the following near the top of your sketch:
|
|
||||||
|
|
||||||
`#include "extras/PwmPin.h"`
|
|
||||||
|
|
||||||
### *LedPin(uint8_t pin [,float level [,uint16_t frequency]])*
|
|
||||||
|
|
||||||
Creating an instance of this **class** configures the specified *pin* to output a PWM signal suitable for a controlling dimmable LED. Arguments, along with their defaults if left unspecified, are as follows:
|
|
||||||
|
|
||||||
* *pin* - the pin on which the PWM control signal will be output
|
|
||||||
* *level* - sets the initial %duty-cycle of the PWM from from 0 (LED completely off) to 100 (LED fully on). Default=0 (LED initially off)
|
|
||||||
* *frequency* - sets the PWM frequency, in Hz, from 1-65535 (ESP32 only) or 5-65535 (ESP32-S2 and ESP32-C3). Defaults to 5000 Hz if unspecified, or if set to 0
|
|
||||||
|
|
||||||
The following methods are supported:
|
|
||||||
|
|
||||||
* `void set(float level)`
|
|
||||||
|
|
||||||
* sets the PWM %duty-cycle to *level*, where *level* ranges from 0 (LED completely off) to 100 (LED fully on)
|
|
||||||
|
|
||||||
* `int getPin()`
|
|
||||||
|
|
||||||
* returns the pin number (or -1 if LedPin was not successfully initialized)
|
|
||||||
|
|
||||||
LedPin also includes a static class function that converts Hue/Saturation/Brightness values (typically used by HomeKit) to Red/Green/Blue values (typically used to control multi-color LEDS).
|
|
||||||
|
|
||||||
* `static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b)`
|
|
||||||
|
|
||||||
* *h* - input Hue value, range 0-360
|
|
||||||
* *s* - input Saturation value, range 0-1
|
|
||||||
* *v* - input Brightness value, range 0-1
|
|
||||||
* *r* - output Red value, range 0-1
|
|
||||||
* *g* - output Green value, range 0-1
|
|
||||||
* *b* - output Blue value, range 0-1
|
|
||||||
|
|
||||||
See tutorial sketch [#10 (RGB_LED)](../examples/10-RGB_LED) for an example of using LedPin to control an RGB LED.
|
|
||||||
|
|
||||||
### *ServoPin(uint8_t pin [,double initDegrees [,uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees]])*
|
|
||||||
|
|
||||||
Creating an instance of this **class** configures the specified *pin* to output a 50 Hz PWM signal, which is suitable for controlling most Servo Motors. There are three forms of the constructor: one with just a single argument; one with two arguments; and one with all six arguments. Arguments, along with their defaults if left unspecified, are as follows:
|
|
||||||
|
|
||||||
* *pin* - the pin on which the PWM control signal will be output. The control wire of a Servo Motor should be connected this pin
|
|
||||||
* *initDegrees* - the initial position (in degrees) to which the Servo Motor should be set (default=0°)
|
|
||||||
* *minMicros* - the pulse width (in microseconds) that moves the Servo Motor to its "minimium" position of *minDegrees* (default=1000𝛍s)
|
|
||||||
* *maxMicros* - the pulse width (in microseconds) that moves the Servo Motor to its "maximum" position of *maxDegrees* (default=2000𝛍s)
|
|
||||||
* *minDegrees* - the position (in degrees) to which the Servo Motor moves when receiving a pulse width of *minMicros* (default=-90°)
|
|
||||||
* *maxDegrees* - the position (in degrees) to which the Servo Motor moves when receiving a pulse width of *maxMicros* (default=90°)
|
|
||||||
|
|
||||||
The *minMicros* parameter must be less than the *maxMicros* parameter, but setting *minDegrees* to a value greater than *maxDegrees* is allowed and can be used to reverse the minimum and maximum positions of the Servo Motor. The following methods are supported:
|
|
||||||
|
|
||||||
* `void set(double position)`
|
|
||||||
|
|
||||||
* sets the position of the Servo Motor to *position* (in degrees). In order to protect the Servo Motor, values of *position* less than *minDegrees* are automatically reset to *minDegrees*, and values greater than *maxDegrees* are automatically reset to *maxDegrees*.
|
|
||||||
|
|
||||||
* `int getPin()`
|
|
||||||
|
|
||||||
* returns the pin number (or -1 if ServoPin was not successfully initialized)
|
|
||||||
|
|
||||||
A worked example showing how ServoPin can be used to control the Horizontal Tilt of a motorized Window Shade can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → ServoControl*](../Other%20Examples/ServoControl).
|
|
||||||
|
|
||||||
### PWM Resource Allocation and Limitations
|
|
||||||
|
|
||||||
The following PWM resources are available:
|
|
||||||
|
|
||||||
* ESP32: 16 Channels / 8 Timers (arranged in two distinct sets of 8 Channels and 4 Timers)
|
|
||||||
* ESP32-S2: 8 Channels / 4 Timers
|
|
||||||
* ESP32-C3: 6 Channels / 4 Timers
|
|
||||||
|
|
||||||
HomeSpan *automatically* allocates Channels and Timers to LedPin and ServoPin objects as they are instantiated. Every pin assigned consumes a single Channel; every *unique* frequency specified among all channels (within the same set, for the ESP32) consumes a single Timer. HomeSpan will conserve resources by re-using the same Timer for all Channels operating at the same frequency. *HomeSpan also automatically configures each Timer to support the maximum duty-resolution possible for the frequency specified.*
|
|
||||||
|
|
||||||
HomeSpan will report a non-fatal error message to the Arduino Serial Monitor when insufficient Channel or Timer resources prevent the creation of a new LedPin or ServoPin object. Calls to the `set()` method for objects that failed to be properly created are silently ignored.
|
|
||||||
|
|
||||||
## Remote Control Radio Frequency / Infrared Signal Generation
|
|
||||||
|
|
||||||
The ESP32 has an on-chip signal-generator peripheral designed to drive an RF or IR transmitter. HomeSpan includes an easy-to-use library that interfaces with this peripheral so that with a few additional electronic components you can create a HomeSpan device that controls an RF or IR appliance directly from the Home App on your iPhone, or via Siri. The library is accessed the following near the top of your sketch:
|
|
||||||
|
|
||||||
`#include "extras/RFControl.h"`
|
`#include "extras/RFControl.h"`
|
||||||
|
|
||||||
### *RFControl(int pin, boolean refClock=true)*
|
## *RFControl(int pin, boolean refClock=true)*
|
||||||
|
|
||||||
Creating an instance of this **class** initializes the RF/IR signal generator and specifies the ESP32 *pin* to output the signal. You may create more than one instance of this class if driving more than one RF/IR transmitter (each connected to different *pin*), subject to the following limitations: ESP32 - 8 instances; ESP32-S2 - 4 instances; ESP32-C3 - 2 instances. The optional parameter *refClock* is more fully described further below under the `start()` method.
|
Creating an instance of this **class** initializes the RF/IR signal generator and specifies the ESP32 *pin* to output the signal. You may create more than one instance of this class if driving more than one RF/IR transmitter (each connected to different *pin*), subject to the following limitations: ESP32 - 8 instances; ESP32-S2 - 4 instances; ESP32-C3 - 2 instances. The optional parameter *refClock* is more fully described further below under the `start()` method.
|
||||||
|
|
||||||
|
|
@ -158,7 +82,7 @@ uint32_t pulseTrain[] = {RF_PULSE(100,50), RF_PULSE(100,50), RF_PULSE(25,500)};
|
||||||
rf.start(pulseTrain,3,4,1000); // start transmission using the same parameters
|
rf.start(pulseTrain,3,4,1000); // start transmission using the same parameters
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example RFControl Sketch
|
## Example RFControl Sketch
|
||||||
|
|
||||||
Below is a complete sketch that produces two different pulse trains with the signal output linked to the ESP32 device's built-in LED (rather than an RF or IR transmitter). For illustrative purposes the tick duration has been set to a very long 100𝛍s, and pulse times range from of 1000-10,000 ticks, so that the individual pulses are easily discernable on the LED. Note this example sketch is also available in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → RemoteControl*](../Other%20Examples/RemoteControl).
|
Below is a complete sketch that produces two different pulse trains with the signal output linked to the ESP32 device's built-in LED (rather than an RF or IR transmitter). For illustrative purposes the tick duration has been set to a very long 100𝛍s, and pulse times range from of 1000-10,000 ticks, so that the individual pulses are easily discernable on the LED. Note this example sketch is also available in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → RemoteControl*](../Other%20Examples/RemoteControl).
|
||||||
|
|
||||||
|
|
@ -33,6 +33,11 @@ The following **optional** `homeSpan` methods override various HomeSpan initiali
|
||||||
|
|
||||||
* `void setStatusPin(uint8_t pin)`
|
* `void setStatusPin(uint8_t pin)`
|
||||||
* sets the ESP32 pin to use for the HomeSpan Status LED. If not specified, HomeSpan will assume there is no Status LED
|
* sets the ESP32 pin to use for the HomeSpan Status LED. If not specified, HomeSpan will assume there is no Status LED
|
||||||
|
|
||||||
|
* `void setStatusAutoOff(uint16_t duration)`
|
||||||
|
* sets Status LED to automatically turn off after *duration* seconds
|
||||||
|
* Status LED will automatically turn on, and duration timer will be reset, whenever HomeSpan activates a new blinking pattern
|
||||||
|
* if *duration* is set to zero, auto-off is disabled (Status LED will remain on indefinitely)
|
||||||
|
|
||||||
* `int getStatusPin()`
|
* `int getStatusPin()`
|
||||||
* returns the pin number of the Status LED as set by `setStatusPin(pin)`, or -1 if no pin has been set
|
* returns the pin number of the Status LED as set by `setStatusPin(pin)`, or -1 if no pin has been set
|
||||||
|
|
@ -56,12 +61,14 @@ The following **optional** `homeSpan` methods override various HomeSpan initiali
|
||||||
* 2 = all status messages plus all HAP communication packets to and from the HomeSpan device
|
* 2 = all status messages plus all HAP communication packets to and from the HomeSpan device
|
||||||
* this parameter can also be changed at runtime via the [HomeSpan CLI](CLI.md)
|
* this parameter can also be changed at runtime via the [HomeSpan CLI](CLI.md)
|
||||||
|
|
||||||
* `void setMaxConnections(uint8_t nCon)`
|
* `void reserveSocketConnections(uint8_t nSockets)`
|
||||||
* sets the desired maximum number of HAP Controllers that can be simultaneously connected to HomeSpan (default=8)
|
* reserves *nSockets* network sockets for uses **other than** by the HomeSpan HAP Server for HomeKit Controller Connections
|
||||||
* due to limitations of the ESP32 Arduino library, HomeSpan will override *nCon* if it exceed the following internal limits:
|
* for sketches compiled under Arduino-ESP32 v2.0.1 or later, HomeSpan reserves 14 sockets for HAP Controller Connections
|
||||||
* if OTA is not enabled, *nCon* will be reduced to 8 if it has been set to a value greater than 8
|
* each call to `reserveSocketConnections(nSockets)` reduces this number by *nSockets*
|
||||||
* if OTA is enabled, *nCon* will be reduced to 7 if it has been set to a value greater than 7
|
* use this method if you add code to a sketch that requires its own socket connections (e.g. a separate web service, an MQTT server, etc.)
|
||||||
* if you add code to a sketch that uses it own network resources, you will need to determine how many TCP sockets your code may need to use, and use this method to reduce the maximum number of connections available to HomeSpan accordingly
|
* multiple calls to this method are allowed - the number of sockets reserved will be the sum of *nSockets* across all calls
|
||||||
|
* note you do not need to separately reserve sockets for built-in HomeSpan functionality
|
||||||
|
* for example, `enableOTA()` already contains an embedded call to `reserveSocketConnections(1)` since HomeSpan knows one socket must be reserved to support OTA
|
||||||
|
|
||||||
* `void setPortNum(uint16_t port)`
|
* `void setPortNum(uint16_t port)`
|
||||||
* sets the TCP port number used for communication between HomeKit and HomeSpan (default=80)
|
* sets the TCP port number used for communication between HomeKit and HomeSpan (default=80)
|
||||||
|
|
@ -79,13 +86,14 @@ The following **optional** `homeSpan` methods override various HomeSpan initiali
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
The following **optional** `homeSpan` methods enable additional features and provide for further customization of the HomeSpan environment:
|
The following **optional** `homeSpan` methods enable additional features and provide for further customization of the HomeSpan environment. Unless otherwise noted, calls **should** be made before `begin()` to take effect:
|
||||||
|
|
||||||
* `void enableOTA(boolean auth=true)`
|
* `void enableOTA(boolean auth=true)`
|
||||||
* enables [Over-the-Air (OTA) Updating](OTA.md) of a HomeSpan device, which is otherwise disabled
|
* enables [Over-the-Air (OTA) Updating](OTA.md) of a HomeSpan device, which is otherwise disabled
|
||||||
* HomeSpan OTA requires an authorizing password unless *auth* is specified and set to *false*
|
* HomeSpan OTA requires an authorizing password unless *auth* is specified and set to *false*
|
||||||
* the default OTA password for new HomeSpan devices is "homespan-ota"
|
* the default OTA password for new HomeSpan devices is "homespan-ota"
|
||||||
* this can be changed via the [HomeSpan CLI](CLI.md) using the 'O' command
|
* this can be changed via the [HomeSpan CLI](CLI.md) using the 'O' command
|
||||||
|
* note enabling OTA reduces the number of HAP Controller Connections by 1
|
||||||
|
|
||||||
* `void enableAutoStartAP()`
|
* `void enableAutoStartAP()`
|
||||||
* enables automatic start-up of WiFi Access Point if WiFi Credentials are **not** found at boot time
|
* enables automatic start-up of WiFi Access Point if WiFi Credentials are **not** found at boot time
|
||||||
|
|
@ -109,7 +117,13 @@ The following **optional** `homeSpan` methods enable additional features and pro
|
||||||
> :warning: SECURITY WARNING: The purpose of this function is to allow advanced users to *dynamically* set the device's WiFi Credentials using a customized Access Point function specified by `setApFunction(func)`. It it NOT recommended to use this function to hardcode your WiFi SSID and password directly into your sketch. Instead, use one of the more secure methods provided by HomeSpan, such as typing 'W' from the CLI, or launching HomeSpan's Access Point, to set your WiFi credentials without hardcoding them into your sketch
|
> :warning: SECURITY WARNING: The purpose of this function is to allow advanced users to *dynamically* set the device's WiFi Credentials using a customized Access Point function specified by `setApFunction(func)`. It it NOT recommended to use this function to hardcode your WiFi SSID and password directly into your sketch. Instead, use one of the more secure methods provided by HomeSpan, such as typing 'W' from the CLI, or launching HomeSpan's Access Point, to set your WiFi credentials without hardcoding them into your sketch
|
||||||
|
|
||||||
* `void setWifiCallback(void (*func)())`
|
* `void setWifiCallback(void (*func)())`
|
||||||
* Sets an optional user-defined callback function, *func*, to be called by HomeSpan upon start-up just after WiFi connectivity has been established. This one-time call to *func* is provided for users that are implementing other network-related services as part of their sketch, but that cannot be started until WiFi connectivity is established. The function *func* must be of type *void* and have no arguments
|
* sets an optional user-defined callback function, *func*, to be called by HomeSpan upon start-up just after WiFi connectivity has been established. This one-time call to *func* is provided for users that are implementing other network-related services as part of their sketch, but that cannot be started until WiFi connectivity is established. The function *func* must be of type *void* and have no arguments
|
||||||
|
|
||||||
|
* `void setPairCallback(void (*func)(boolean status))`
|
||||||
|
* sets an optional user-defined callback function, *func*, to be called by HomeSpan upon completion of pairing to a controller (*status=true*) or unpairing from a controller (*status=false*)
|
||||||
|
* this one-time call to *func* is provided for users that would like to trigger additional actions when the device is first paired, or the device is later unpaired
|
||||||
|
* note this *func* is **not** called upon start-up and should not be used to simply check whether a device is paired or unpaired. It is only called when pairing status changes
|
||||||
|
* the function *func* must be of type *void* and have one *boolean* argument
|
||||||
|
|
||||||
* `void setPairingCode(const char *s)`
|
* `void setPairingCode(const char *s)`
|
||||||
* sets the Setup Pairing Code to *s*, which **must** be exactly eight numerical digits (no dashes)
|
* sets the Setup Pairing Code to *s*, which **must** be exactly eight numerical digits (no dashes)
|
||||||
|
|
@ -118,6 +132,11 @@ The following **optional** `homeSpan` methods enable additional features and pro
|
||||||
* if *s* contains an invalid code, an error will be reported and the code will *not* be saved. Instead, the currently-stored Pairing Code (or the HomeSpan default Pairing Code if no code has been stored) will be used
|
* if *s* contains an invalid code, an error will be reported and the code will *not* be saved. Instead, the currently-stored Pairing Code (or the HomeSpan default Pairing Code if no code has been stored) will be used
|
||||||
* :exclamation: SECURTY WARNING: Hardcoding a device's Pairing Code into your sketch is considered a security risk and is **not** recommended. Instead, use one of the more secure methods provided by HomeSpan, such as typing 'S \<code\>' from the CLI, or launching HomeSpan's Access Point, to set your Pairing Code without hardcoding it into your sketch
|
* :exclamation: SECURTY WARNING: Hardcoding a device's Pairing Code into your sketch is considered a security risk and is **not** recommended. Instead, use one of the more secure methods provided by HomeSpan, such as typing 'S \<code\>' from the CLI, or launching HomeSpan's Access Point, to set your Pairing Code without hardcoding it into your sketch
|
||||||
|
|
||||||
|
* `void deleteStoredValues()`
|
||||||
|
* deletes the value settings of all stored Characteristics from the NVS
|
||||||
|
* performs the same function as typing 'V' into the CLI
|
||||||
|
* can by called from anywhere in a sketch
|
||||||
|
|
||||||
* `void setSketchVersion(const char *sVer)`
|
* `void setSketchVersion(const char *sVer)`
|
||||||
* sets the version of a HomeSpan sketch to *sVer*, which can be any arbitrary character string
|
* sets the version of a HomeSpan sketch to *sVer*, which can be any arbitrary character string
|
||||||
* if unspecified, HomeSpan uses "n/a" as the default version text
|
* if unspecified, HomeSpan uses "n/a" as the default version text
|
||||||
|
|
@ -126,6 +145,7 @@ The following **optional** `homeSpan` methods enable additional features and pro
|
||||||
|
|
||||||
* `const char *getSketchVersion()`
|
* `const char *getSketchVersion()`
|
||||||
* returns the version of a HomeSpan sketch, as set using `void setSketchVersion(const char *sVer)`, or "n/a" if not set
|
* returns the version of a HomeSpan sketch, as set using `void setSketchVersion(const char *sVer)`, or "n/a" if not set
|
||||||
|
* can by called from anywhere in a sketch
|
||||||
|
|
||||||
## *SpanAccessory(uint32_t aid)*
|
## *SpanAccessory(uint32_t aid)*
|
||||||
|
|
||||||
|
|
@ -256,6 +276,16 @@ The following methods are supported:
|
||||||
* returns a pointer to the Characteristic itself so that the method can be chained during instantiation
|
* returns a pointer to the Characteristic itself so that the method can be chained during instantiation
|
||||||
* example: `(new Characteristic::ConfiguredName("HDMI 1"))->removePerms(PW);`
|
* example: `(new Characteristic::ConfiguredName("HDMI 1"))->removePerms(PW);`
|
||||||
|
|
||||||
|
* `SpanCharacteristic *setDescription(const char *desc)`
|
||||||
|
* adds an optional description, *desc*, to a Characteristic, as described in HAP-R2 Table 6-3
|
||||||
|
* this field is generally used to provide information about custom Characteristics, but does not appear to be used in any way by the Home App
|
||||||
|
* returns a pointer to the Characteristic itself so that the method can be chained during instantiation
|
||||||
|
* example: `(new Characteristic::MyCustomChar())->setDescription("Tuner Frequency");`
|
||||||
|
|
||||||
|
* `SpanCharacteristic *setUnit(const char *unit)`
|
||||||
|
* adds or overrides the *unit* for a Characteristic, as described in HAP-R2 Table 6-6
|
||||||
|
* returns a pointer to the Characteristic itself so that the method can be chained during instantiation
|
||||||
|
* example: `(new Characteristic::RotationSpeed())->setUnit("percentage");`
|
||||||
|
|
||||||
## *SpanButton(int pin, uint16_t longTime, uint16_t singleTime, uint16_t doubleTime)*
|
## *SpanButton(int pin, uint16_t longTime, uint16_t singleTime, uint16_t doubleTime)*
|
||||||
|
|
||||||
|
|
@ -299,48 +329,62 @@ To create more than one user-defined command, simply create multiple instances o
|
||||||
|
|
||||||
### *#define REQUIRED VERSION(major,minor,patch)*
|
### *#define REQUIRED VERSION(major,minor,patch)*
|
||||||
|
|
||||||
If REQUIRED is defined in the main sketch prior to including the HomeSpan library with `#include "HomeSpan.h"`, HomeSpan will throw a compile-time error unless the version of the library included is equal to, or later than, the version specified using the VERSION macro. Example:
|
If REQUIRED is defined in the main sketch *prior* to including the HomeSpan library with `#include "HomeSpan.h"`, HomeSpan will throw a compile-time error unless the version of the library included is equal to, or later than, the version specified using the VERSION macro. Example:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
#define REQUIRED VERISON(2,1,3) // throws a compile-time error unless HomeSpan library used is version 2.1.3 or later
|
#define REQUIRED VERSION(1,3,0) // throws a compile-time error unless HomeSpan library used is version 1.3.0 or later
|
||||||
|
#include "HomeSpan.h"
|
||||||
```
|
```
|
||||||
### *#define CUSTOM_CHAR(name,uuid,perms,format,defaultValue,minValue,maxValue,staticRange)*
|
### *#define CUSTOM_CHAR(name,uuid,perms,format,defaultValue,minValue,maxValue,staticRange)*
|
||||||
|
### *#define CUSTOM_CHAR_STRING(name,uuid,perms,defaultValue)*
|
||||||
|
|
||||||
Creates a custom Characteristic that can be added to any Service. Custom Characteristics are generally ignored by the Home App but may be used by other third-party applications (such as Eve for HomeKit). Parameters are as follows (note that quotes should NOT be used in any of the string parameters):
|
Creates a custom Characteristic that can be added to any Service. Custom Characteristics are generally ignored by the Home App but may be used by other third-party applications (such as Eve for HomeKit). The first form should be used create numerical Characterstics (e.g., UINT8, BOOL...). The second form is used to String-based Characteristics. Parameters are as follows (note that quotes should NOT be used in any of the macro parameters, except for defaultValue):
|
||||||
|
|
||||||
* *name* - the name of the custom Characteristic. This will be added to the Characteristic namespace so that it is accessed the same as any HomeSpan Characteristic
|
* *name* - the name of the custom Characteristic. This will be added to the Characteristic namespace so that it is accessed the same as any HomeSpan Characteristic
|
||||||
* *uuid* - the UUID of the Characteristic as defined by the manufacturer. Must be *exactly* 36 characters in the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where *X* represent a valid hexidecimal digit. Leading zeros are required if needed as described more fully in HAP-R2 Section 6.6.1
|
* *uuid* - the UUID of the Characteristic as defined by the manufacturer. Must be *exactly* 36 characters in the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where *X* represent a valid hexidecimal digit. Leading zeros are required if needed as described more fully in HAP-R2 Section 6.6.1
|
||||||
* *perms* - additive list of permissions as described in HAP-R2 Table 6-4. Valid values are PR, PW, EV, AA, TW, HD, and WR
|
* *perms* - additive list of permissions as described in HAP-R2 Table 6-4. Valid values are PR, PW, EV, AA, TW, HD, and WR
|
||||||
* *format* - specifies the format of the Characteristic value, as described in HAP-R2 Table 6-5. Valid value are BOOL, UINT8, UINT16, UNIT32, UINT64, INT, FLOAT, and STRING. Note that the HomeSpan does not presently support the TLV8 or DATA formats
|
* *format* - specifies the format of the Characteristic value, as described in HAP-R2 Table 6-5. Valid value are BOOL, UINT8, UINT16, UNIT32, UINT64, INT, and FLOAT. Note that the HomeSpan does not presently support the TLV8 or DATA formats. Not applicable for Strings-based Characteristics
|
||||||
* *defaultValue* - specifies the default value of the Characteristic if not defined during instantiation
|
* *defaultValue* - specifies the default value of the Characteristic if not defined during instantiation
|
||||||
* *minValue* - specifies the default minimum range for a valid value, which may be able to be overriden by a call to `setRange()`
|
* *minValue* - specifies the default minimum range for a valid value, which may be able to be overriden by a call to `setRange()`. Not applicable for Strings-based Characteristics
|
||||||
* *minValue* - specifies the default minimum range for a valid value, which may be able to be overriden by a call to `setRange()`
|
* *minValue* - specifies the default minimum range for a valid value, which may be able to be overriden by a call to `setRange()`. Not applicable for Strings-based Characteristics
|
||||||
* *staticRange* - set to *true* if *minValue* and *maxValue* are static and cannot be overridden with a call to `setRange()`. Set to *false* if calls to `setRange()` are allowed
|
* *staticRange* - set to *true* if *minValue* and *maxValue* are static and cannot be overridden with a call to `setRange()`. Set to *false* if calls to `setRange()` are allowed. Not applicable for Strings-based Characteristics
|
||||||
|
|
||||||
As an example, the following creates a custom Characteristic named "Voltage" with a UUID code that is recognized by Eve for HomeKit. The parameters show that the Characteristic is read-only (PR) and notifications are enabled (EV). The default range of allowed values is 0-240, with a default of 120. The range *can* be overridden by subsequent calls to `setRange()`:
|
As an example, the first line below creates a custom Characteristic named "Voltage" with a UUID code that is recognized by Eve for HomeKit. The parameters show that the Characteristic is read-only (PR) and notifications are enabled (EV). The default range of allowed values is 0-240, with a default of 120. The range *can* be overridden by subsequent calls to `setRange()`. The second line below creates a custom read-only String-based Characteristic:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
CUSTOM_CHAR(Voltage, E863F10A-079E-48FF-8F27-9C2605A29F52, PR+EV, UINT16, 120, 0, 240, false);
|
CUSTOM_CHAR(Voltage, E863F10A-079E-48FF-8F27-9C2605A29F52, PR+EV, UINT16, 120, 0, 240, false);
|
||||||
|
CUSTOM_CHAR_STRING(UserTag, AAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA, PR, "Tag 123");
|
||||||
...
|
...
|
||||||
new Service::LightBulb();
|
new Service::LightBulb();
|
||||||
new Characteristic::Name("Low-Voltage Lamp");
|
new Characteristic::Name("Low-Voltage Lamp");
|
||||||
new Characteristic::On(0);
|
new Characteristic::On(0);
|
||||||
new Characteristic::Brightness(50);
|
new Characteristic::Brightness(50);
|
||||||
new Characteristic::Voltage(12); // adds Voltage Characteristics and sets initial value to 12 volts
|
new Characteristic::Voltage(12); // adds Voltage Characteristic and sets initial value to 12 volts
|
||||||
|
new Characteristic::UserTag(); // adds UserTag Characteristic and retains default initial value of "Tag 123"
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that Custom Characteristics must be created prior to calling `homeSpan.begin()`
|
Note that Custom Characteristics must be created prior to calling `homeSpan.begin()`
|
||||||
|
|
||||||
|
> Advanced Tip: When presented with an unrecognized Custom Characteristic, Eve for HomeKit helpfully displays a *generic control* allowing you to interact with any Custom Characteristic you create in HomeSpan. However, since Eve does not recognize the Characteristic, it will only render the generic control if the Characteristic includes a **description** field, which you can add to any Characteristic using the `setDescription()` method described above. You may also want to use `setUnit()` and `setRange()` so that the Eve App displays a control with appropriate ranges for your Custom Characteristic.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### Deprecated functions (available for backwards compatibility with older sketches):
|
#### Deprecated functions (available for backwards compatibility with older sketches):
|
||||||
|
|
||||||
*SpanRange(int min, int max, int step)*
|
* `SpanRange(int min, int max, int step)`
|
||||||
|
|
||||||
* this legacy function is limited to integer-based parameters and has been re-coded to simply call the more generic `setRange(min, max, step)` method
|
* this legacy class was limited to integer-based parameters and has been re-coded to simply call the more generic `setRange(min, max, step)` method
|
||||||
* last supported version: [v1.2.0](https://github.com/HomeSpan/HomeSpan/blob/release-1.2.0/docs/Reference.md#spanrangeint-min-int-max-int-step)
|
* last supported version: [v1.2.0](https://github.com/HomeSpan/HomeSpan/blob/release-1.2.0/docs/Reference.md#spanrangeint-min-int-max-int-step)
|
||||||
* **please use** `setRange(min, max, step)` **for all new sketches**
|
* **please use** `setRange(min, max, step)` **for all new sketches**
|
||||||
|
|
||||||
|
* `void homeSpan.setMaxConnections(uint8_t nCon)`
|
||||||
|
* this legacy method was used to set the total number of HAP Controller Connections HomeSpan implements upon start-up to ensure there are still free sockets available for user-defined code requiring separate network resources
|
||||||
|
* last supported version: [v1.4.2](https://github.com/HomeSpan/HomeSpan/blob/release-1.4.2/docs/Reference.md)
|
||||||
|
* this method has been replaced by the more flexible method, `reserveSocketConnections(uint8_t nSockets)`
|
||||||
|
* allows you to simply reserve network sockets for other custom code as needed
|
||||||
|
* upon calling `homespan.begin()`, HomeSpan automatically determines how many sockets are left that it can use for HAP Controller Connections
|
||||||
|
* **please use** `homeSpan.reserveSocketConnections(uint8_t nSockets)` **for all new sketches**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[↩️](README.md) Back to the Welcome page
|
[↩️](README.md) Back to the Welcome page
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
name=HomeSpan
|
name=HomeSpan
|
||||||
version=1.4.2
|
version=1.5.0
|
||||||
author=Gregg <homespan@icloud.com>
|
author=Gregg <homespan@icloud.com>
|
||||||
maintainer=Gregg <homespan@icloud.com>
|
maintainer=Gregg <homespan@icloud.com>
|
||||||
sentence=A robust and extremely easy-to-use HomeKit implementation for the Espressif ESP32 running on the Arduino IDE.
|
sentence=A robust and extremely easy-to-use HomeKit implementation for the Espressif ESP32 running on the Arduino IDE.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -661,6 +661,9 @@ int HAPClient::postPairSetupURL(){
|
||||||
LOG1("\n*** ACCESSORY PAIRED! ***\n");
|
LOG1("\n*** ACCESSORY PAIRED! ***\n");
|
||||||
homeSpan.statusLED.on();
|
homeSpan.statusLED.on();
|
||||||
|
|
||||||
|
if(homeSpan.pairCallback) // if set, invoke user-defined Pairing Callback to indicate device has been paired
|
||||||
|
homeSpan.pairCallback(true);
|
||||||
|
|
||||||
return(1);
|
return(1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -1592,6 +1595,8 @@ void HAPClient::removeController(uint8_t *id){
|
||||||
LOG1("That was last Admin Controller! Removing any remaining Regular Controllers and unpairing Accessory\n");
|
LOG1("That was last Admin Controller! Removing any remaining Regular Controllers and unpairing Accessory\n");
|
||||||
mdns_service_txt_item_set("_hap","_tcp","sf","1"); // set Status Flag = 1 (Table 6-8)
|
mdns_service_txt_item_set("_hap","_tcp","sf","1"); // set Status Flag = 1 (Table 6-8)
|
||||||
homeSpan.statusLED.start(LED_PAIRING_NEEDED);
|
homeSpan.statusLED.start(LED_PAIRING_NEEDED);
|
||||||
|
if(homeSpan.pairCallback) // if set, invoke user-defined Pairing Callback to indicate device has been paired
|
||||||
|
homeSpan.pairCallback(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG2("\n");
|
LOG2("\n");
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -58,12 +58,11 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
|
||||||
esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); // required to avoid watchdog timeout messages from ESP32-C3
|
esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); // required to avoid watchdog timeout messages from ESP32-C3
|
||||||
|
|
||||||
controlButton.init(controlPin);
|
controlButton.init(controlPin);
|
||||||
statusLED.init(statusPin);
|
statusLED.init(statusPin,0,autoOffLED);
|
||||||
|
|
||||||
int maxLimit=CONFIG_LWIP_MAX_SOCKETS-2-otaEnabled;
|
|
||||||
if(maxConnections>maxLimit)
|
|
||||||
maxConnections=maxLimit;
|
|
||||||
|
|
||||||
|
if(requestedMaxCon<maxConnections) // if specific request for max connections is less than computed max connections
|
||||||
|
maxConnections=requestedMaxCon; // over-ride max connections with requested value
|
||||||
|
|
||||||
hap=(HAPClient **)calloc(maxConnections,sizeof(HAPClient *));
|
hap=(HAPClient **)calloc(maxConnections,sizeof(HAPClient *));
|
||||||
for(int i=0;i<maxConnections;i++)
|
for(int i=0;i<maxConnections;i++)
|
||||||
hap[i]=new HAPClient;
|
hap[i]=new HAPClient;
|
||||||
|
|
@ -85,7 +84,7 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
|
||||||
nvs_get_blob(wifiNVS,"WIFIDATA",&homeSpan.network.wifiData,&len); // retrieve data
|
nvs_get_blob(wifiNVS,"WIFIDATA",&homeSpan.network.wifiData,&len); // retrieve data
|
||||||
|
|
||||||
delay(2000);
|
delay(2000);
|
||||||
|
|
||||||
Serial.print("\n************************************************************\n"
|
Serial.print("\n************************************************************\n"
|
||||||
"Welcome to HomeSpan!\n"
|
"Welcome to HomeSpan!\n"
|
||||||
"Apple HomeKit for the Espressif ESP-32 WROOM and Arduino IDE\n"
|
"Apple HomeKit for the Espressif ESP-32 WROOM and Arduino IDE\n"
|
||||||
|
|
@ -95,8 +94,11 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
|
||||||
Serial.print("Message Logs: Level ");
|
Serial.print("Message Logs: Level ");
|
||||||
Serial.print(logLevel);
|
Serial.print(logLevel);
|
||||||
Serial.print("\nStatus LED: Pin ");
|
Serial.print("\nStatus LED: Pin ");
|
||||||
if(statusPin>=0)
|
if(statusPin>=0){
|
||||||
Serial.print(statusPin);
|
Serial.print(statusPin);
|
||||||
|
if(autoOffLED>0)
|
||||||
|
Serial.printf(" (Auto Off=%d sec)",autoOffLED);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Serial.print("- *** WARNING: Status LED Pin is UNDEFINED");
|
Serial.print("- *** WARNING: Status LED Pin is UNDEFINED");
|
||||||
Serial.print("\nDevice Control: Pin ");
|
Serial.print("\nDevice Control: Pin ");
|
||||||
|
|
@ -291,6 +293,8 @@ void Span::poll() {
|
||||||
commandMode(); // COMMAND MODE
|
commandMode(); // COMMAND MODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statusLED.check();
|
||||||
|
|
||||||
} // poll
|
} // poll
|
||||||
|
|
||||||
|
|
@ -494,6 +498,8 @@ void Span::checkConnect(){
|
||||||
mdns_service_txt_item_set("_hap","_tcp","sf","0"); // set Status Flag = 0
|
mdns_service_txt_item_set("_hap","_tcp","sf","0"); // set Status Flag = 0
|
||||||
|
|
||||||
mdns_service_txt_item_set("_hap","_tcp","hspn",HOMESPAN_VERSION); // HomeSpan Version Number (info only - NOT used by HAP)
|
mdns_service_txt_item_set("_hap","_tcp","hspn",HOMESPAN_VERSION); // HomeSpan Version Number (info only - NOT used by HAP)
|
||||||
|
mdns_service_txt_item_set("_hap","_tcp","ard-esp32",ARDUINO_ESP_VERSION); // Arduino-ESP32 Version Number (info only - NOT used by HAP)
|
||||||
|
mdns_service_txt_item_set("_hap","_tcp","board",ARDUINO_VARIANT); // Board Name (info only - NOT used by HAP)
|
||||||
mdns_service_txt_item_set("_hap","_tcp","sketch",sketchVersion); // Sketch Version (info only - NOT used by HAP)
|
mdns_service_txt_item_set("_hap","_tcp","sketch",sketchVersion); // Sketch Version (info only - NOT used by HAP)
|
||||||
mdns_service_txt_item_set("_hap","_tcp","ota",otaEnabled?"yes":"no"); // OTA Enabled (info only - NOT used by HAP)
|
mdns_service_txt_item_set("_hap","_tcp","ota",otaEnabled?"yes":"no"); // OTA Enabled (info only - NOT used by HAP)
|
||||||
|
|
||||||
|
|
@ -553,9 +559,8 @@ void Span::checkConnect(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.print("Starting Web (HTTP) Server supporting up to ");
|
Serial.printf("Starting HAP Server on port %d supporting %d simultaneous HomeKit Controller Connections...\n",tcpPortNum,maxConnections);
|
||||||
Serial.print(maxConnections);
|
|
||||||
Serial.print(" simultaneous connections...\n");
|
|
||||||
hapServer->begin();
|
hapServer->begin();
|
||||||
|
|
||||||
Serial.print("\n");
|
Serial.print("\n");
|
||||||
|
|
@ -1645,6 +1650,13 @@ int SpanCharacteristic::sprintfAttributes(char *cBuf, int flags){
|
||||||
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"minStep\":%s",uvPrint(stepValue).c_str());
|
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"minStep\":%s",uvPrint(stepValue).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(unit){
|
||||||
|
if(strlen(unit)>0)
|
||||||
|
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"unit\":\"%s\"",unit);
|
||||||
|
else
|
||||||
|
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"unit\":null");
|
||||||
|
}
|
||||||
|
|
||||||
if(validValues){
|
if(validValues){
|
||||||
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"valid-values\":%s",validValues);
|
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"valid-values\":%s",validValues);
|
||||||
}
|
}
|
||||||
|
|
@ -1722,27 +1734,47 @@ StatusCode SpanCharacteristic::loadUpdate(char *val, char *ev){
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INT:
|
case INT:
|
||||||
if(!sscanf(val,"%d",&newValue.INT))
|
if(!strcmp(val,"false"))
|
||||||
|
newValue.INT=0;
|
||||||
|
else if(!strcmp(val,"true"))
|
||||||
|
newValue.INT=1;
|
||||||
|
else if(!sscanf(val,"%d",&newValue.INT))
|
||||||
return(StatusCode::InvalidValue);
|
return(StatusCode::InvalidValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UINT8:
|
case UINT8:
|
||||||
if(!sscanf(val,"%hhu",&newValue.UINT8))
|
if(!strcmp(val,"false"))
|
||||||
|
newValue.UINT8=0;
|
||||||
|
else if(!strcmp(val,"true"))
|
||||||
|
newValue.UINT8=1;
|
||||||
|
else if(!sscanf(val,"%hhu",&newValue.UINT8))
|
||||||
return(StatusCode::InvalidValue);
|
return(StatusCode::InvalidValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UINT16:
|
case UINT16:
|
||||||
if(!sscanf(val,"%hu",&newValue.UINT16))
|
if(!strcmp(val,"false"))
|
||||||
|
newValue.UINT16=0;
|
||||||
|
else if(!strcmp(val,"true"))
|
||||||
|
newValue.UINT16=1;
|
||||||
|
else if(!sscanf(val,"%hu",&newValue.UINT16))
|
||||||
return(StatusCode::InvalidValue);
|
return(StatusCode::InvalidValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UINT32:
|
case UINT32:
|
||||||
if(!sscanf(val,"%u",&newValue.UINT32))
|
if(!strcmp(val,"false"))
|
||||||
|
newValue.UINT32=0;
|
||||||
|
else if(!strcmp(val,"true"))
|
||||||
|
newValue.UINT32=1;
|
||||||
|
else if(!sscanf(val,"%u",&newValue.UINT32))
|
||||||
return(StatusCode::InvalidValue);
|
return(StatusCode::InvalidValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UINT64:
|
case UINT64:
|
||||||
if(!sscanf(val,"%llu",&newValue.UINT64))
|
if(!strcmp(val,"false"))
|
||||||
|
newValue.UINT64=0;
|
||||||
|
else if(!strcmp(val,"true"))
|
||||||
|
newValue.UINT64=1;
|
||||||
|
else if(!sscanf(val,"%llu",&newValue.UINT64))
|
||||||
return(StatusCode::InvalidValue);
|
return(StatusCode::InvalidValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -119,10 +119,12 @@ struct Span{
|
||||||
unsigned long alarmConnect=0; // time after which WiFi connection attempt should be tried again
|
unsigned long alarmConnect=0; // time after which WiFi connection attempt should be tried again
|
||||||
|
|
||||||
const char *defaultSetupCode=DEFAULT_SETUP_CODE; // Setup Code used for pairing
|
const char *defaultSetupCode=DEFAULT_SETUP_CODE; // Setup Code used for pairing
|
||||||
int statusPin=DEFAULT_STATUS_PIN; // pin for status LED
|
int statusPin=DEFAULT_STATUS_PIN; // pin for Status LED
|
||||||
|
uint16_t autoOffLED=0; // automatic turn-off duration (in seconds) for Status LED
|
||||||
int controlPin=DEFAULT_CONTROL_PIN; // pin for Control Pushbutton
|
int controlPin=DEFAULT_CONTROL_PIN; // pin for Control Pushbutton
|
||||||
uint8_t logLevel=DEFAULT_LOG_LEVEL; // level for writing out log messages to serial monitor
|
uint8_t logLevel=DEFAULT_LOG_LEVEL; // level for writing out log messages to serial monitor
|
||||||
uint8_t maxConnections=DEFAULT_MAX_CONNECTIONS; // number of simultaneous HAP connections
|
uint8_t maxConnections=CONFIG_LWIP_MAX_SOCKETS-2; // maximum number of allowed simultaneous HAP connections
|
||||||
|
uint8_t requestedMaxCon=CONFIG_LWIP_MAX_SOCKETS-2; // requested maximum number of simultaneous HAP connections
|
||||||
unsigned long comModeLife=DEFAULT_COMMAND_TIMEOUT*1000; // length of time (in milliseconds) to keep Command Mode alive before resuming normal operations
|
unsigned long comModeLife=DEFAULT_COMMAND_TIMEOUT*1000; // length of time (in milliseconds) to keep Command Mode alive before resuming normal operations
|
||||||
uint16_t tcpPortNum=DEFAULT_TCP_PORT; // port for TCP communications between HomeKit and HomeSpan
|
uint16_t tcpPortNum=DEFAULT_TCP_PORT; // port for TCP communications between HomeKit and HomeSpan
|
||||||
char qrID[5]=""; // Setup ID used for pairing with QR Code
|
char qrID[5]=""; // Setup ID used for pairing with QR Code
|
||||||
|
|
@ -130,6 +132,7 @@ struct Span{
|
||||||
char otaPwd[33]; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
|
char otaPwd[33]; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
|
||||||
boolean otaAuth; // OTA requires password when set to true
|
boolean otaAuth; // OTA requires password when set to true
|
||||||
void (*wifiCallback)()=NULL; // optional callback function to invoke once WiFi connectivity is established
|
void (*wifiCallback)()=NULL; // optional callback function to invoke once WiFi connectivity is established
|
||||||
|
void (*pairCallback)(boolean isPaired)=NULL; // optional callback function to invoke when pairing is established (true) or lost (false)
|
||||||
boolean autoStartAPEnabled=false; // enables auto start-up of Access Point when WiFi Credentials not found
|
boolean autoStartAPEnabled=false; // enables auto start-up of Access Point when WiFi Credentials not found
|
||||||
void (*apFunction)()=NULL; // optional function to invoke when starting Access Point
|
void (*apFunction)()=NULL; // optional function to invoke when starting Access Point
|
||||||
|
|
||||||
|
|
@ -173,26 +176,34 @@ struct Span{
|
||||||
|
|
||||||
void setControlPin(uint8_t pin){controlPin=pin;} // sets Control Pin
|
void setControlPin(uint8_t pin){controlPin=pin;} // sets Control Pin
|
||||||
void setStatusPin(uint8_t pin){statusPin=pin;} // sets Status Pin
|
void setStatusPin(uint8_t pin){statusPin=pin;} // sets Status Pin
|
||||||
|
void setStatusAutoOff(uint16_t duration){autoOffLED=duration;} // sets Status LED auto off (seconds)
|
||||||
int getStatusPin(){return(statusPin);} // get Status Pin
|
int getStatusPin(){return(statusPin);} // get Status Pin
|
||||||
void setApSSID(const char *ssid){network.apSSID=ssid;} // sets Access Point SSID
|
void setApSSID(const char *ssid){network.apSSID=ssid;} // sets Access Point SSID
|
||||||
void setApPassword(const char *pwd){network.apPassword=pwd;} // sets Access Point Password
|
void setApPassword(const char *pwd){network.apPassword=pwd;} // sets Access Point Password
|
||||||
void setApTimeout(uint16_t nSec){network.lifetime=nSec*1000;} // sets Access Point Timeout (seconds)
|
void setApTimeout(uint16_t nSec){network.lifetime=nSec*1000;} // sets Access Point Timeout (seconds)
|
||||||
void setCommandTimeout(uint16_t nSec){comModeLife=nSec*1000;} // sets Command Mode Timeout (seconds)
|
void setCommandTimeout(uint16_t nSec){comModeLife=nSec*1000;} // sets Command Mode Timeout (seconds)
|
||||||
void setLogLevel(uint8_t level){logLevel=level;} // sets Log Level for log messages (0=baseline, 1=intermediate, 2=all)
|
void setLogLevel(uint8_t level){logLevel=level;} // sets Log Level for log messages (0=baseline, 1=intermediate, 2=all)
|
||||||
void setMaxConnections(uint8_t nCon){maxConnections=nCon;} // sets maximum number of simultaneous HAP connections (HAP requires devices support at least 8)
|
void reserveSocketConnections(uint8_t n){maxConnections-=n;} // reserves n socket connections *not* to be used for HAP
|
||||||
void setHostNameSuffix(const char *suffix){hostNameSuffix=suffix;} // sets the hostName suffix to be used instead of the 6-byte AccessoryID
|
void setHostNameSuffix(const char *suffix){hostNameSuffix=suffix;} // sets the hostName suffix to be used instead of the 6-byte AccessoryID
|
||||||
void setPortNum(uint16_t port){tcpPortNum=port;} // sets the TCP port number to use for communications between HomeKit and HomeSpan
|
void setPortNum(uint16_t port){tcpPortNum=port;} // sets the TCP port number to use for communications between HomeKit and HomeSpan
|
||||||
void setQRID(const char *id); // sets the Setup ID for optional pairing with a QR Code
|
void setQRID(const char *id); // sets the Setup ID for optional pairing with a QR Code
|
||||||
void enableOTA(boolean auth=true){otaEnabled=true;otaAuth=auth;} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password
|
|
||||||
void setSketchVersion(const char *sVer){sketchVersion=sVer;} // set optional sketch version number
|
void setSketchVersion(const char *sVer){sketchVersion=sVer;} // set optional sketch version number
|
||||||
const char *getSketchVersion(){return sketchVersion;} // get sketch version number
|
const char *getSketchVersion(){return sketchVersion;} // get sketch version number
|
||||||
void setWifiCallback(void (*f)()){wifiCallback=f;} // sets an optional user-defined function to call once WiFi connectivity is established
|
void setWifiCallback(void (*f)()){wifiCallback=f;} // sets an optional user-defined function to call once WiFi connectivity is established
|
||||||
|
void setPairCallback(void (*f)(boolean isPaired)){pairCallback=f;} // sets an optional user-defined function to call when Pairing is established (true) or lost (false)
|
||||||
void setApFunction(void (*f)()){apFunction=f;} // sets an optional user-defined function to call when activating the WiFi Access Point
|
void setApFunction(void (*f)()){apFunction=f;} // sets an optional user-defined function to call when activating the WiFi Access Point
|
||||||
|
|
||||||
void setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead
|
|
||||||
|
|
||||||
void enableAutoStartAP(){autoStartAPEnabled=true;} // enables auto start-up of Access Point when WiFi Credentials not found
|
void enableAutoStartAP(){autoStartAPEnabled=true;} // enables auto start-up of Access Point when WiFi Credentials not found
|
||||||
void setWifiCredentials(const char *ssid, const char *pwd); // sets WiFi Credentials
|
void setWifiCredentials(const char *ssid, const char *pwd); // sets WiFi Credentials
|
||||||
|
|
||||||
|
void setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead
|
||||||
|
void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS
|
||||||
|
|
||||||
|
void enableOTA(boolean auth=true){otaEnabled=true;otaAuth=auth;reserveSocketConnections(1);} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password
|
||||||
|
|
||||||
|
[[deprecated("Please use reserveSocketConnections(n) method instead.")]]
|
||||||
|
void setMaxConnections(uint8_t n){requestedMaxCon=n;} // sets maximum number of simultaneous HAP connections
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
@ -260,6 +271,7 @@ struct SpanCharacteristic{
|
||||||
uint8_t perms; // Characteristic Permissions
|
uint8_t perms; // Characteristic Permissions
|
||||||
FORMAT format; // Characteristic Format
|
FORMAT format; // Characteristic Format
|
||||||
char *desc=NULL; // Characteristic Description (optional)
|
char *desc=NULL; // Characteristic Description (optional)
|
||||||
|
char *unit=NULL; // Characteristic Unit (optional)
|
||||||
UVal minValue; // Characteristic minimum (not applicable for STRING)
|
UVal minValue; // Characteristic minimum (not applicable for STRING)
|
||||||
UVal maxValue; // Characteristic maximum (not applicable for STRING)
|
UVal maxValue; // Characteristic maximum (not applicable for STRING)
|
||||||
UVal stepValue; // Characteristic step size (not applicable for STRING)
|
UVal stepValue; // Characteristic step size (not applicable for STRING)
|
||||||
|
|
@ -601,6 +613,18 @@ struct SpanCharacteristic{
|
||||||
return(setPerms(perms&(~dPerms)));
|
return(setPerms(perms&(~dPerms)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpanCharacteristic *setDescription(const char *c){
|
||||||
|
desc = (char *)realloc(desc, strlen(c) + 1);
|
||||||
|
strcpy(desc, c);
|
||||||
|
return(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpanCharacteristic *setUnit(const char *c){
|
||||||
|
unit = (char *)realloc(unit, strlen(c) + 1);
|
||||||
|
strcpy(unit, c);
|
||||||
|
return(this);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -35,8 +35,8 @@
|
||||||
// HomeSpan Version //
|
// HomeSpan Version //
|
||||||
|
|
||||||
#define HS_MAJOR 1
|
#define HS_MAJOR 1
|
||||||
#define HS_MINOR 4
|
#define HS_MINOR 5
|
||||||
#define HS_PATCH 2
|
#define HS_PATCH 0
|
||||||
|
|
||||||
#define STRINGIFY(x) _STR(x)
|
#define STRINGIFY(x) _STR(x)
|
||||||
#define _STR(x) #x
|
#define _STR(x) #x
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (REQUIRED>VERSION(HS_MAJOR,HS_MINOR,HS_PATCH))
|
#if (REQUIRED>VERSION(HS_MAJOR,HS_MINOR,HS_PATCH))
|
||||||
#error THIS SKETCH REQUIRES A LATER VERISON OF THE HOMESPAN LIBRARY
|
#error THIS SKETCH REQUIRES A LATER VERSION OF THE HOMESPAN LIBRARY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ARDUINO_ESP_VERSION STRINGIFY(ARDUINO_ESP32_GIT_DESC)
|
#define ARDUINO_ESP_VERSION STRINGIFY(ARDUINO_ESP32_GIT_DESC)
|
||||||
|
|
@ -79,7 +79,6 @@
|
||||||
|
|
||||||
#define DEFAULT_LOG_LEVEL 0 // change with homeSpan.setLogLevel(level)
|
#define DEFAULT_LOG_LEVEL 0 // change with homeSpan.setLogLevel(level)
|
||||||
|
|
||||||
#define DEFAULT_MAX_CONNECTIONS 8 // change with homeSpan.setMaxConnections(num);
|
|
||||||
#define DEFAULT_TCP_PORT 80 // change with homeSpan.setPort(port);
|
#define DEFAULT_TCP_PORT 80 // change with homeSpan.setPort(port);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -529,4 +529,6 @@ namespace Characteristic {
|
||||||
HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),FORMAT,STATIC_RANGE}; \
|
HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),FORMAT,STATIC_RANGE}; \
|
||||||
namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME} { init(val,nvsStore,(FORMAT##_t)MINVAL,(FORMAT##_t)MAXVAL); } }; }
|
namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME} { init(val,nvsStore,(FORMAT##_t)MINVAL,(FORMAT##_t)MAXVAL); } }; }
|
||||||
|
|
||||||
|
#define CUSTOM_CHAR_STRING(NAME,UUID,PERMISISONS,DEFVAL) \
|
||||||
|
HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),STRING,true}; \
|
||||||
|
namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME} { init(val,nvsStore); } }; }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -232,13 +232,13 @@ Blinker::Blinker(){
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
Blinker::Blinker(int pin, int timerNum){
|
Blinker::Blinker(int pin, int timerNum, uint16_t autoOffDuration){
|
||||||
init(pin, timerNum);
|
init(pin, timerNum, autoOffDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
void Blinker::init(int pin, int timerNum){
|
void Blinker::init(int pin, int timerNum, uint16_t autoOffDuration){
|
||||||
|
|
||||||
this->pin=pin;
|
this->pin=pin;
|
||||||
if(pin<0)
|
if(pin<0)
|
||||||
|
|
@ -247,6 +247,8 @@ void Blinker::init(int pin, int timerNum){
|
||||||
pinMode(pin,OUTPUT);
|
pinMode(pin,OUTPUT);
|
||||||
digitalWrite(pin,0);
|
digitalWrite(pin,0);
|
||||||
|
|
||||||
|
pauseDuration=autoOffDuration*1000;
|
||||||
|
|
||||||
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP>1 // ESP32 and ESP32-S2 contains two timers per timer group
|
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP>1 // ESP32 and ESP32-S2 contains two timers per timer group
|
||||||
group=((timerNum/2)%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
group=((timerNum/2)%2==0)?TIMER_GROUP_0:TIMER_GROUP_1;
|
||||||
idx=(timerNum%2==0)?TIMER_0:TIMER_1; // ESP32-C3 only contains one timer per timer group
|
idx=(timerNum%2==0)?TIMER_0:TIMER_1; // ESP32-C3 only contains one timer per timer group
|
||||||
|
|
@ -327,7 +329,9 @@ void Blinker::start(int period, float dutyCycle, int nBlinks, int delayTime){
|
||||||
if(pin<0)
|
if(pin<0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT); // needed to ensure digitalRead() functions correctly on ESP32-C3
|
pauseTime=millis();
|
||||||
|
isPaused=false;
|
||||||
|
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT); // needed to ensure digitalRead() functions correctly on ESP32-C3; also needed to re-enable after pause()
|
||||||
|
|
||||||
period*=10;
|
period*=10;
|
||||||
onTime=dutyCycle*period;
|
onTime=dutyCycle*period;
|
||||||
|
|
@ -357,6 +361,10 @@ void Blinker::on(){
|
||||||
if(pin<0)
|
if(pin<0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pauseTime=millis();
|
||||||
|
isPaused=false;
|
||||||
|
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT);
|
||||||
|
|
||||||
stop();
|
stop();
|
||||||
digitalWrite(pin,1);
|
digitalWrite(pin,1);
|
||||||
}
|
}
|
||||||
|
|
@ -368,6 +376,25 @@ void Blinker::off(){
|
||||||
if(pin<0)
|
if(pin<0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pauseTime=millis();
|
||||||
|
isPaused=false;
|
||||||
|
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT_OUTPUT);
|
||||||
|
|
||||||
stop();
|
stop();
|
||||||
digitalWrite(pin,0);
|
digitalWrite(pin,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
void Blinker::check(){
|
||||||
|
|
||||||
|
if(pin<0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pauseDuration==0 || isPaused || (millis()-pauseTime)<pauseDuration)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Serial.print("Pausing Status LED\n");
|
||||||
|
isPaused=true;
|
||||||
|
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_DISABLE);
|
||||||
|
}
|
||||||
|
|
|
||||||
41
src/Utils.h
41
src/Utils.h
|
|
@ -1,7 +1,7 @@
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2021 Gregg E. Berman
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
*
|
*
|
||||||
* https://github.com/HomeSpan/HomeSpan
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
*
|
*
|
||||||
|
|
@ -165,13 +165,17 @@ class Blinker {
|
||||||
int offTime;
|
int offTime;
|
||||||
int delayTime;
|
int delayTime;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
|
unsigned long pauseDuration;
|
||||||
|
unsigned long pauseTime;
|
||||||
|
boolean isPaused=false;
|
||||||
|
|
||||||
static void isrTimer(void *arg);
|
static void isrTimer(void *arg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Blinker();
|
Blinker();
|
||||||
Blinker(int pin, int timerNum=0);
|
Blinker(int pin, int timerNum=0, uint16_t autoOffDuration=0);
|
||||||
|
|
||||||
// Creates a generic blinking LED on specified pin controlled
|
// Creates a generic blinking LED on specified pin controlled
|
||||||
// in background via interrupts generated by an ESP32 Alarm Timer.
|
// in background via interrupts generated by an ESP32 Alarm Timer.
|
||||||
|
|
@ -183,19 +187,29 @@ class Blinker {
|
||||||
// In the second form, a Blinker is instantiated and initialized with
|
// In the second form, a Blinker is instantiated and initialized with
|
||||||
// the specified pin, obviating the need for a separate call to init().
|
// the specified pin, obviating the need for a separate call to init().
|
||||||
//
|
//
|
||||||
// pin: Pin mumber to control. Blinker will set pinMode to OUTPUT automatically
|
// pin: Pin mumber to control. Blinker will set pinMode to OUTPUT automatically
|
||||||
// timerNum: ESP32 Alarm Timer to use.
|
//
|
||||||
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
// timerNum: ESP32 Alarm Timer to use.
|
||||||
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
||||||
|
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
||||||
|
//
|
||||||
|
// autoOffDuration: If greater than zero, Blinker will automatically turn off after autoOffDuration (in seconds) has elapsed
|
||||||
|
// Blinker will resume normal operation upon next call to start(), on(), or off()
|
||||||
|
// Program must periodically call check() for auto-off functionality to work
|
||||||
|
|
||||||
void init(int pin, int timerNum=0);
|
void init(int pin, int timerNum=0, uint16_t autoOffDuration=0);
|
||||||
|
|
||||||
// Initializes Blinker, if not configured during instantiation.
|
// Initializes Blinker, if not configured during instantiation.
|
||||||
//
|
//
|
||||||
// pin: Pin mumber to control. Blinker will set pinMode to OUTPUT automatically
|
// pin: Pin mumber to control. Blinker will set pinMode to OUTPUT automatically
|
||||||
// timerNum: ESP32 Alarm Timer to use.
|
//
|
||||||
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
// timerNum: ESP32 Alarm Timer to use.
|
||||||
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
// For ESP32 and ESP32-S2: 0=Group0/Timer0, 1=Group0/Timer1, 2=Group1/Timer0, 3=Group1/Timer1
|
||||||
|
// For ESP32-C3: 0=Group0/Timer0, 1=Group1/Timer0
|
||||||
|
//
|
||||||
|
// autoOffDuration: If greater than zero, Blinker will automatically turn off after autoOffDuration (in seconds) has elapsed
|
||||||
|
// Blinker will resume normal operation upon next call to start(), on(), or off()
|
||||||
|
// Program must periodically call check() for auto-off functionality to work
|
||||||
|
|
||||||
void start(int period, float dutyCycle=0.5);
|
void start(int period, float dutyCycle=0.5);
|
||||||
|
|
||||||
|
|
@ -225,4 +239,9 @@ class Blinker {
|
||||||
|
|
||||||
// Stops current blinking pattern and turns off LED
|
// Stops current blinking pattern and turns off LED
|
||||||
|
|
||||||
|
void check();
|
||||||
|
|
||||||
|
// Optional check to see if LED output should be paused (check is bypassed if pauseDuration=0)
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Addressable LEDs //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Pixel.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Single-Wire RGB/RGBW NeoPixels //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
Pixel::Pixel(int pin, boolean isRGBW){
|
||||||
|
|
||||||
|
rf=new RFControl(pin,false,false); // set clock to 1/80 usec, no default driver
|
||||||
|
if(!*rf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(isRGBW)
|
||||||
|
this->lastBit=0;
|
||||||
|
else
|
||||||
|
this->lastBit=8;
|
||||||
|
|
||||||
|
setTiming(0.32, 0.88, 0.64, 0.56, 80.0); // set default timing parameters (suitable for most SK68 and WS28 RGB pixels)
|
||||||
|
|
||||||
|
rmt_isr_register(loadData,NULL,0,NULL); // set custom interrupt handler
|
||||||
|
|
||||||
|
rmt_set_tx_thr_intr_en(rf->getChannel(),false,8); // disable threshold interrupt
|
||||||
|
txThrMask=RMT.int_ena.val; // save interrupt enable vector
|
||||||
|
rmt_set_tx_thr_intr_en(rf->getChannel(),true,8); // enable threshold interrupt to trigger every 8 pulses
|
||||||
|
txThrMask^=RMT.int_ena.val; // find bit that flipped and save as threshold mask for this channel
|
||||||
|
|
||||||
|
rmt_set_tx_intr_en(rf->getChannel(),false); // disable end-of-transmission interrupt
|
||||||
|
txEndMask=RMT.int_ena.val; // save interrupt enable vector
|
||||||
|
rmt_set_tx_intr_en(rf->getChannel(),true); // enable end-of-transmission interrupt
|
||||||
|
txEndMask^=RMT.int_ena.val; // find bit that flipped and save as end-of-transmission mask for this channel
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
void Pixel::setTiming(float high0, float low0, float high1, float low1, uint32_t lowReset){
|
||||||
|
|
||||||
|
pattern[0]=RF_PULSE(high0*80+0.5,low0*80+0.5);
|
||||||
|
pattern[1]=RF_PULSE(high1*80+0.5,low1*80+0.5);
|
||||||
|
resetTime=lowReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
void Pixel::set(Color *c, int nPixels, boolean multiColor){
|
||||||
|
|
||||||
|
if(!*rf || nPixels==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
status.nPixels=nPixels;
|
||||||
|
status.color=c;
|
||||||
|
status.iMem=0;
|
||||||
|
status.iBit=32;
|
||||||
|
status.started=true;
|
||||||
|
status.px=this;
|
||||||
|
status.multiColor=multiColor;
|
||||||
|
|
||||||
|
loadData(this); // load first two bytes of data to get started
|
||||||
|
loadData(this);
|
||||||
|
|
||||||
|
rmt_tx_start(rf->getChannel(),true);
|
||||||
|
|
||||||
|
while(status.started); // wait for transmission to be complete
|
||||||
|
delayMicroseconds(resetTime); // end-of-marker delay
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
void IRAM_ATTR Pixel::loadData(void *arg){
|
||||||
|
|
||||||
|
if(RMT.int_st.val & status.px->txEndMask){
|
||||||
|
RMT.int_clr.val=status.px->txEndMask;
|
||||||
|
status.started=false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RMT.int_clr.val=status.px->txThrMask; // if loadData() is called and it is NOT because of an END interrupt (above) then must either be a pre-load, or a threshold trigger
|
||||||
|
|
||||||
|
if(status.nPixels==0){
|
||||||
|
RMTMEM.chan[status.px->rf->getChannel()].data32[status.iMem].val=0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<8;i++)
|
||||||
|
RMTMEM.chan[status.px->rf->getChannel()].data32[status.iMem++].val=status.px->pattern[(status.color->val>>(--status.iBit))&1];
|
||||||
|
|
||||||
|
if(status.iBit==status.px->lastBit){
|
||||||
|
status.iBit=32;
|
||||||
|
status.color+=status.multiColor;
|
||||||
|
status.nPixels--;
|
||||||
|
}
|
||||||
|
|
||||||
|
status.iMem%=status.px->memSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
volatile Pixel::pixel_status_t Pixel::status;
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Two-Wire RGB DotStars //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
Dot::Dot(uint8_t dataPin, uint8_t clockPin){
|
||||||
|
|
||||||
|
pinMode(dataPin,OUTPUT);
|
||||||
|
pinMode(clockPin,OUTPUT);
|
||||||
|
digitalWrite(dataPin,LOW);
|
||||||
|
digitalWrite(clockPin,LOW);
|
||||||
|
|
||||||
|
dataMask=1<<(dataPin%32);
|
||||||
|
clockMask=1<<(clockPin%32);
|
||||||
|
|
||||||
|
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
dataSetReg=&GPIO.out_w1ts.val;
|
||||||
|
dataClearReg=&GPIO.out_w1tc.val;
|
||||||
|
clockSetReg=&GPIO.out_w1ts.val;
|
||||||
|
clockClearReg=&GPIO.out_w1tc.val;
|
||||||
|
#else
|
||||||
|
if(dataPin<32){
|
||||||
|
dataSetReg=&GPIO.out_w1ts;
|
||||||
|
dataClearReg=&GPIO.out_w1tc;
|
||||||
|
} else {
|
||||||
|
dataSetReg=&GPIO.out1_w1ts.val;
|
||||||
|
dataClearReg=&GPIO.out1_w1tc.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clockPin<32){
|
||||||
|
clockSetReg=&GPIO.out_w1ts;
|
||||||
|
clockClearReg=&GPIO.out_w1tc;
|
||||||
|
} else {
|
||||||
|
clockSetReg=&GPIO.out1_w1ts.val;
|
||||||
|
clockClearReg=&GPIO.out1_w1tc.val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
void Dot::set(Color *c, int nPixels, boolean multiColor){
|
||||||
|
|
||||||
|
*dataClearReg=dataMask; // send all zeros
|
||||||
|
for(int j=0;j<31;j++){
|
||||||
|
*clockSetReg=clockMask;
|
||||||
|
*clockClearReg=clockMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<nPixels;i++){
|
||||||
|
for(int b=31;b>=0;b--){
|
||||||
|
if((c->val>>b)&1)
|
||||||
|
*dataSetReg=dataMask;
|
||||||
|
else
|
||||||
|
*dataClearReg=dataMask;
|
||||||
|
*clockSetReg=clockMask;
|
||||||
|
*clockClearReg=clockMask;
|
||||||
|
}
|
||||||
|
c+=multiColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dataClearReg=dataMask; // send all zeros
|
||||||
|
for(int j=0;j<31;j++){
|
||||||
|
*clockSetReg=clockMask;
|
||||||
|
*clockClearReg=clockMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
@ -0,0 +1,253 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Addressable LEDs //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RFControl.h"
|
||||||
|
#include "PwmPin.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Single-Wire RGB/RGBW NeoPixels //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
class Pixel {
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Color {
|
||||||
|
union{
|
||||||
|
struct {
|
||||||
|
uint8_t white:8;
|
||||||
|
uint8_t blue:8;
|
||||||
|
uint8_t red:8;
|
||||||
|
uint8_t green:8;
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0){ // returns Color based on provided RGB(W) values where r/g/b/w=[0-255]
|
||||||
|
this->red=r;
|
||||||
|
this->green=g;
|
||||||
|
this->blue=b;
|
||||||
|
this->white=w;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color HSV(float h, float s, float v, double w=0){ // returns Color based on provided HSV(W) values where h=[0,360] and s/v/w=[0,100]
|
||||||
|
float r,g,b;
|
||||||
|
LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b);
|
||||||
|
this->red=r*255;
|
||||||
|
this->green=g*255;
|
||||||
|
this->blue=b*255;
|
||||||
|
this->white=w*2.555;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Color& color){
|
||||||
|
return(val==color.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Color& color){
|
||||||
|
return(val!=color.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color operator+(const Color& color){
|
||||||
|
Color newColor;
|
||||||
|
newColor.white=white+color.white;
|
||||||
|
newColor.blue=blue+color.blue;
|
||||||
|
newColor.red=red+color.red;
|
||||||
|
newColor.green=green+color.green;
|
||||||
|
return(newColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& operator+=(const Color& color){
|
||||||
|
white+=color.white;
|
||||||
|
red+=color.red;
|
||||||
|
blue+=color.blue;
|
||||||
|
green+=color.green;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color operator-(const Color& color){
|
||||||
|
Color newColor;
|
||||||
|
newColor.white=white-color.white;
|
||||||
|
newColor.blue=blue-color.blue;
|
||||||
|
newColor.red=red-color.red;
|
||||||
|
newColor.green=green-color.green;
|
||||||
|
return(newColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& operator-=(const Color& color){
|
||||||
|
white-=color.white;
|
||||||
|
red-=color.red;
|
||||||
|
blue-=color.blue;
|
||||||
|
green-=color.green;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // Color
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct pixel_status_t {
|
||||||
|
int nPixels;
|
||||||
|
Color *color;
|
||||||
|
int iBit;
|
||||||
|
int iMem;
|
||||||
|
boolean started;
|
||||||
|
Pixel *px;
|
||||||
|
boolean multiColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
RFControl *rf; // Pixel utilizes RFControl
|
||||||
|
uint32_t pattern[2]; // storage for zero-bit and one-bit pulses
|
||||||
|
uint32_t resetTime; // minimum time (in usec) between pulse trains
|
||||||
|
uint32_t txEndMask; // mask for end-of-transmission interrupt
|
||||||
|
uint32_t txThrMask; // mask for threshold interrupt
|
||||||
|
uint32_t lastBit; // 0=RGBW; 8=RGB
|
||||||
|
|
||||||
|
const int memSize=sizeof(RMTMEM.chan[0].data32)/4; // determine size (in pulses) of one channel
|
||||||
|
|
||||||
|
static void loadData(void *arg); // interrupt handler
|
||||||
|
volatile static pixel_status_t status; // storage for volatile information modified in interupt handler
|
||||||
|
|
||||||
|
public:
|
||||||
|
Pixel(int pin, boolean isRGBW=false); // creates addressable single-wire RGB (false) or RGBW (true) LED connected to pin (such as the SK68 or WS28)
|
||||||
|
void set(Color *c, int nPixels, boolean multiColor=true); // sets colors of nPixels based on array of Colors c; setting multiColor to false repeats Color in c[0] for all nPixels
|
||||||
|
void set(Color c, int nPixels=1){set(&c,nPixels,false);} // sets color of nPixels to be equal to specific Color c
|
||||||
|
|
||||||
|
static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0){return(Color().RGB(r,g,b,w));} // an alternative method for returning an RGB Color
|
||||||
|
static Color HSV(float h, float s, float v, double w=0){return(Color().HSV(h,s,v,w));} // an alternative method for returning an HSV Color
|
||||||
|
|
||||||
|
int getPin(){return(rf->getPin());} // returns pixel pin if valid, else returns -1
|
||||||
|
void setTiming(float high0, float low0, float high1, float low1, uint32_t lowReset); // changes default timings for bit pulse - note parameters are in MICROSECONDS
|
||||||
|
|
||||||
|
operator bool(){ // override boolean operator to return true/false if creation succeeded/failed
|
||||||
|
return(*rf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Two-Wire RGB DotStars //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
class Dot {
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Color {
|
||||||
|
union{
|
||||||
|
struct {
|
||||||
|
uint8_t red:8;
|
||||||
|
uint8_t green:8;
|
||||||
|
uint8_t blue:8;
|
||||||
|
uint8_t drive:5;
|
||||||
|
uint8_t flags:3;
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31){ // returns Color based on provided RGB values where r/g/b=[0-255] and current-limiting drive level=[0,31]
|
||||||
|
this->red=r;
|
||||||
|
this->green=g;
|
||||||
|
this->blue=b;
|
||||||
|
this->drive=driveLevel;
|
||||||
|
this->flags=7;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color HSV(float h, float s, float v, double drivePercent=100){ // returns Color based on provided HSV values where h=[0,360], s/v=[0,100], and current-limiting drive percent=[0,100]
|
||||||
|
float r,g,b;
|
||||||
|
LedPin::HSVtoRGB(h,s/100.0,v/100.0,&r,&g,&b);
|
||||||
|
this->red=r*255;
|
||||||
|
this->green=g*255;
|
||||||
|
this->blue=b*255;
|
||||||
|
this->drive=drivePercent*0.315;
|
||||||
|
this->flags=7;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Color& color){
|
||||||
|
return(val==color.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Color& color){
|
||||||
|
return(val!=color.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color operator+(const Color& color){
|
||||||
|
Color newColor;
|
||||||
|
newColor.blue=blue+color.blue;
|
||||||
|
newColor.red=red+color.red;
|
||||||
|
newColor.green=green+color.green;
|
||||||
|
return(newColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& operator+=(const Color& color){
|
||||||
|
red+=color.red;
|
||||||
|
blue+=color.blue;
|
||||||
|
green+=color.green;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color operator-(const Color& color){
|
||||||
|
Color newColor;
|
||||||
|
newColor.blue=blue-color.blue;
|
||||||
|
newColor.red=red-color.red;
|
||||||
|
newColor.green=green-color.green;
|
||||||
|
return(newColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& operator-=(const Color& color){
|
||||||
|
red-=color.red;
|
||||||
|
blue-=color.blue;
|
||||||
|
green-=color.green;
|
||||||
|
return(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t dataMask;
|
||||||
|
uint32_t clockMask;
|
||||||
|
volatile uint32_t *dataSetReg;
|
||||||
|
volatile uint32_t *dataClearReg;
|
||||||
|
volatile uint32_t *clockSetReg;
|
||||||
|
volatile uint32_t *clockClearReg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Dot(uint8_t dataPin, uint8_t clockPin); // creates addressable two-wire RGB LED connected to dataPin and clockPin (such as the DotStar SK9822 or APA102)
|
||||||
|
void set(Color *c, int nPixels, boolean multiColor=true); // sets colors of nPixels based on array of Colors c; setting multiColor to false repeats Color in c[0] for all nPixels
|
||||||
|
void set(Color c, int nPixels=1){set(&c,nPixels,false);} // sets color of nPixels to be equal to specific Color c
|
||||||
|
|
||||||
|
static Color RGB(uint8_t r, uint8_t g, uint8_t b, uint8_t driveLevel=31){return(Color().RGB(r,g,b,driveLevel));} // an alternative method for returning an RGB Color
|
||||||
|
static Color HSV(float h, float s, float v, double drivePercent=100){return(Color().HSV(h,s,v,drivePercent));} // an alternative method for returning an HSV Color
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
@ -1,4 +1,30 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
#include "PwmPin.h"
|
#include "PwmPin.h"
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,30 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ----- PWM Pin Control -----
|
// ----- PWM Pin Control -----
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -14,6 +40,8 @@
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <driver/ledc.h>
|
#include <driver/ledc.h>
|
||||||
|
|
||||||
|
|
@ -34,6 +62,10 @@ class LedC {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int getPin(){return(channel?channel->gpio_num:-1);} // returns the pin number
|
int getPin(){return(channel?channel->gpio_num:-1);} // returns the pin number
|
||||||
|
|
||||||
|
operator bool(){ // override boolean operator to return true/false if creation succeeded/failed
|
||||||
|
return(channel);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,35 @@
|
||||||
|
/*********************************************************************************
|
||||||
#include <Arduino.h>
|
* MIT License
|
||||||
#include <soc/rmt_reg.h>
|
*
|
||||||
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
#include "RFControl.h"
|
#include "RFControl.h"
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
RFControl::RFControl(uint8_t pin, boolean refClock){
|
RFControl::RFControl(uint8_t pin, boolean refClock, boolean installDriver){
|
||||||
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||||
if(nChannels==RMT_CHANNEL_MAX/2){
|
if(nChannels==RMT_CHANNEL_MAX/2){
|
||||||
|
|
@ -32,7 +55,9 @@ RFControl::RFControl(uint8_t pin, boolean refClock){
|
||||||
config->tx_config.loop_en=false;
|
config->tx_config.loop_en=false;
|
||||||
|
|
||||||
rmt_config(config);
|
rmt_config(config);
|
||||||
rmt_driver_install(config->channel,0,0);
|
|
||||||
|
if(installDriver)
|
||||||
|
rmt_driver_install(config->channel,0,0);
|
||||||
|
|
||||||
// If specified, set the base clock to 1 MHz so tick-units are in microseconds (before any CLK_DIV is applied), otherwise default will be 80 MHz APB clock
|
// If specified, set the base clock to 1 MHz so tick-units are in microseconds (before any CLK_DIV is applied), otherwise default will be 80 MHz APB clock
|
||||||
|
|
||||||
|
|
@ -129,7 +154,6 @@ void RFControl::enableCarrier(uint32_t freq, float duty){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serial.printf("%d %g %d %d\n",freq,period,highTime,lowTime);
|
|
||||||
rmt_set_tx_carrier(config->channel,true,highTime,lowTime,RMT_CARRIER_LEVEL_HIGH);
|
rmt_set_tx_carrier(config->channel,true,highTime,lowTime,RMT_CARRIER_LEVEL_HIGH);
|
||||||
} else {
|
} else {
|
||||||
rmt_set_tx_carrier(config->channel,false,0,0,RMT_CARRIER_LEVEL_HIGH);
|
rmt_set_tx_carrier(config->channel,false,0,0,RMT_CARRIER_LEVEL_HIGH);
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,57 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2022 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
// RF Control Module //
|
// RF Control Module //
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <soc/rmt_reg.h>
|
||||||
#include "driver/rmt.h"
|
#include "driver/rmt.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
class RFControl {
|
class RFControl {
|
||||||
|
friend class Pixel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rmt_config_t *config=NULL;
|
rmt_config_t *config=NULL;
|
||||||
vector<uint32_t> data;
|
vector<uint32_t> data;
|
||||||
boolean lowWord=true;
|
boolean lowWord=true;
|
||||||
boolean refClock;
|
boolean refClock;
|
||||||
static uint8_t nChannels;
|
static uint8_t nChannels;
|
||||||
|
|
||||||
|
RFControl(uint8_t pin, boolean refClock, boolean installDriver); // private constructor (only used by Pixel class)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RFControl(uint8_t pin, boolean refClock=true); // creates transmitter on pin, using 1-MHz Ref Tick clock
|
RFControl(uint8_t pin, boolean refClock=true):RFControl(pin,refClock,true){}; // public constructor to create transmitter on pin, using 1-MHz Ref Tick clock or 80-MHz APB clock
|
||||||
|
|
||||||
void start(uint32_t *data, int nData, uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from specified data pointer, repeated for numCycles, where each tick in pulse is tickTime microseconds long
|
void start(uint32_t *data, int nData, uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from specified data pointer, repeated for numCycles, where each tick in pulse is tickTime microseconds long
|
||||||
void start(uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from internal data structure, repeated for numCycles, where each tick in pulse is tickTime microseconds long
|
void start(uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from internal data structure, repeated for numCycles, where each tick in pulse is tickTime microseconds long
|
||||||
|
|
@ -27,9 +61,16 @@ class RFControl {
|
||||||
void phase(uint32_t nTicks, uint8_t phase); // adds either a HIGH phase or LOW phase lasting numTicks ticks
|
void phase(uint32_t nTicks, uint8_t phase); // adds either a HIGH phase or LOW phase lasting numTicks ticks
|
||||||
void enableCarrier(uint32_t freq, float duty=0.5); // enables carrier wave if freq>0, else disables carrier wave; duty is a fraction from 0-1
|
void enableCarrier(uint32_t freq, float duty=0.5); // enables carrier wave if freq>0, else disables carrier wave; duty is a fraction from 0-1
|
||||||
void disableCarrier(){enableCarrier(0);} // disables carrier wave
|
void disableCarrier(){enableCarrier(0);} // disables carrier wave
|
||||||
|
|
||||||
|
int getPin(){return(config?config->gpio_num:-1);} // returns the pin number, or -1 if no channel defined
|
||||||
|
rmt_channel_t getChannel(){return(config?config->channel:RMT_CHANNEL_0);} // returns channel, or channel_0 is no channel defined
|
||||||
|
|
||||||
|
operator bool(){ // override boolean operator to return true/false if creation succeeded/failed
|
||||||
|
return(config);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper macro for creating your own storage of uint32_t data array elements - used with first variation of start() above
|
// Helper macro for creating your own storage of uint32_t data array elements - used with first variation of start() above
|
||||||
|
|
||||||
#define RF_PULSE(highTicks,lowTicks) (1 << 15 | highTicks | lowTicks << 16)
|
#define RF_PULSE(highTicks,lowTicks) (1 << 15 | uint32_t(highTicks) | uint32_t(lowTicks) << 16)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
/* HomeSpan Remote Control Example */
|
// This is a placeholder .ino file that allows you to easily edit the contents of this files using the Arduino IDE,
|
||||||
|
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
|
||||||
|
|
||||||
#include "RFControl.h" // include RF Control Library
|
#include "Pixel.h"
|
||||||
|
|
||||||
#define PRONTO_N 0.241246
|
//#define PixelType Pixel
|
||||||
|
#define PixelType Dot
|
||||||
|
|
||||||
uint16_t pronto[]={0000,0x006D,0x0000,0x0022,0x00AC,0x00AC,0x0015,0x0040,0x0015,0x0040,0x0015,0x0040,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0040,0x0015,0x0040,0x0015,0x0040,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0040,0x0015,0x0015,0x0015,0x0015,0x0015,0x0040,0x0015,0x0040,0x0015,0x0015,0x0015,0x0015,0x0015,0x0040,0x0015,0x0015,0x0015,0x0040,0x0015,0x0040,0x0015,0x0015,0x0015,0x0015,0x0015,0x0040,0x0015,0x0040,0x0015,0x0015,0x0015,0x0689};
|
//Pixel p(8);
|
||||||
//uint16_t pronto[]={0000,0x006D,0x0000,0x0022,0x00AC,0x00AC,0x0017,0x003E,0x0017,0x003E,0x0017,0x003E,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x003E,0x0017,0x003E,0x0017,0x003E,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x0013,0x0017,0x003E,0x0017,0x003E,0x0017,0x0013,0x0017,0x0013,0x0017,0x003E,0x0017,0x003E,0x0018,0x003E,0x0017,0x003E,0x0017,0x0013,0x0017,0x0013,0x0017,0x003E,0x0017,0x003E,0x0017,0x0013,0x0017,0x0746};
|
Dot p(0,1);
|
||||||
//uint16_t pronto[]={0000,0x0067,0x0000,0x000d,0x0060,0x0018,0x0018,0x0018,0x0030,0x0018,0x0030,0x0018,0x0030,0x0018,0x0018,0x0018,0x0030,0x0018,0x0018,0x0018,0x0030,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x03f6};
|
|
||||||
|
|
||||||
uint32_t data[100];
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
|
|
@ -16,33 +15,29 @@ void setup() {
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
delay(1000); // wait for interface to flush
|
delay(1000); // wait for interface to flush
|
||||||
|
|
||||||
Serial.println("\n\nHomeSpan RF Transmitter Example\n\n");
|
Serial.println("\n\nHomeSpan Pixel Example\n");
|
||||||
|
|
||||||
RFControl rf(17);
|
PixelType::Color off=PixelType::RGB(0,0,0);
|
||||||
rf.enableCarrier(38000,0.5);
|
|
||||||
|
|
||||||
uint32_t code = 0xE0E019E6; // OFF
|
p.set(PixelType::RGB(0,0,255),3);
|
||||||
// uint32_t code = 0xE0E09966; // ON
|
delay(1000);
|
||||||
|
|
||||||
int unit=563;
|
p.set(off,3);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
rf.add(4500,4500);
|
PixelType::Color c[]={p.HSV(120,100,30),p.HSV(0,0,0),p.HSV(0,0,0)};
|
||||||
|
p.set(c,3);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
c[0].HSV(0,0,0);
|
||||||
|
c[1].HSV(60,100,30);
|
||||||
|
p.set(c,3);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
for(int i=31;i>=0;i--){
|
c[1].HSV(0,0,0);
|
||||||
rf.add(unit,unit*((code&(1<<i))?3:1));
|
c[2].HSV(0,100,30);
|
||||||
Serial.print((code&(1<<i))?1:0);
|
p.set(c,3);
|
||||||
if(!(i%8))
|
}
|
||||||
Serial.print(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
rf.add(unit,45000);
|
|
||||||
|
|
||||||
rf.start(2);
|
|
||||||
|
|
||||||
Serial.println("Done!");
|
|
||||||
|
|
||||||
} // end of setup()
|
|
||||||
|
|
||||||
void loop(){
|
void loop(){
|
||||||
|
}
|
||||||
} // end of loop()
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@
|
||||||
|
|
||||||
#include "HomeSpan.h"
|
#include "HomeSpan.h"
|
||||||
|
|
||||||
CUSTOM_CHAR(CustomActive, E863F10A-079E-48FF-8F27-9C2605A29F52, PR+EV, UINT16, 0, 0, 4800, false);
|
#define STRING_t const char * // WORK-AROUND
|
||||||
|
|
||||||
|
CUSTOM_CHAR(LightMode, AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA, PR, STRING, "ANY_VALUE", NULL, NULL, true);
|
||||||
|
CUSTOM_CHAR_STRING(DarkMode, AAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA, PR, "MY_VALUE");
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
|
|
@ -45,7 +48,8 @@ void setup() {
|
||||||
|
|
||||||
new Service::LightBulb();
|
new Service::LightBulb();
|
||||||
new Characteristic::On(0);
|
new Characteristic::On(0);
|
||||||
new Characteristic::CustomActive(1200);
|
new Characteristic::LightMode("HELLO");
|
||||||
|
new Characteristic::DarkMode();
|
||||||
new Characteristic::Brightness(50);
|
new Characteristic::Brightness(50);
|
||||||
new Characteristic::Name("Light 1");
|
new Characteristic::Name("Light 1");
|
||||||
new Characteristic::ColorTemperature();
|
new Characteristic::ColorTemperature();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue