Browse Source

MY9291 and color picker

fastled
Xose Pérez 7 years ago
parent
commit
8924d1b173
13 changed files with 733 additions and 56 deletions
  1. +2
    -2
      code/espurna/config/data.h
  2. +22
    -0
      code/espurna/config/general.h
  3. +15
    -0
      code/espurna/config/hardware.h
  4. BIN
      code/espurna/data/index.html.gz
  5. +160
    -41
      code/espurna/relay.ino
  6. +14
    -1
      code/espurna/web.ino
  7. +28
    -0
      code/html/custom.js
  8. +19
    -12
      code/html/index.html
  9. +13
    -0
      code/html/jquery.wheelcolorpicker-3.0.2.min.js
  10. +158
    -0
      code/html/wheelcolorpicker.css
  11. +187
    -0
      code/lib/my9291/my9291.cpp
  12. +94
    -0
      code/lib/my9291/my9291.h
  13. +21
    -0
      code/platformio.ini

+ 2
- 2
code/espurna/config/data.h
File diff suppressed because it is too large
View File


+ 22
- 0
code/espurna/config/general.h View File

@ -51,6 +51,14 @@
#define RELAY_PULSE_OFF 1
#define RELAY_PULSE_ON 2
#define RELAY_PROVIDER_RELAY 0
#define RELAY_PROVIDER_DUAL 1
#define RELAY_PROVIDER_MY9291 2
#ifndef RELAY_PROVIDER
#define RELAY_PROVIDER RELAY_PROVIDER_RELAY
#endif
// Pulse time in seconds
#define RELAY_PULSE_TIME 1
@ -138,6 +146,7 @@
#define MQTT_ACTION_TOPIC "/action"
#define MQTT_RELAY_TOPIC "/relay"
#define MQTT_LED_TOPIC "/led"
#define MQTT_COLOR_TOPIC "/color"
#define MQTT_BUTTON_TOPIC "/button"
#define MQTT_IP_TOPIC "/ip"
#define MQTT_VERSION_TOPIC "/version"
@ -164,6 +173,19 @@
#define I2C_CLOCK_STRETCH_TIME 200
#define I2C_SCL_FREQUENCY 1000
// -----------------------------------------------------------------------------
// MY9291
// -----------------------------------------------------------------------------
#define MY9291_DI_PIN 13
#define MY9291_DCKI_PIN 15
#define MY9291_COMMAND MY9291_COMMAND_DEFAULT
#define MY9291_COLOR_RED 0
#define MY9291_COLOR_GREEN 0
#define MY9291_COLOR_BLUE 0
#define MY9291_COLOR_WHITE 192
// -----------------------------------------------------------------------------
// DOMOTICZ
// -----------------------------------------------------------------------------


+ 15
- 0
code/espurna/config/hardware.h View File

@ -142,6 +142,8 @@
#define LED1_PIN_INVERSE 1
#undef SERIAL_BAUDRATE
#define SERIAL_BAUDRATE 19230
#undef RELAY_PROVIDER
#define RELAY_PROVIDER RELAY_PROVIDER_DUAL
#elif defined(SONOFF_4CH)
@ -240,6 +242,19 @@
#define LED1_PIN 2
#define LED1_PIN_INVERSE 0
// -----------------------------------------------------------------------------
// AI Thinker
// -----------------------------------------------------------------------------
#elif defined(AI_LIGHT)
#define MANUFACTURER "AI THINKER"
#define DEVICE "AI LIGHT"
#define RELAY1_PIN 2
#define RELAY1_PIN_INVERSE 0
#undef RELAY_PROVIDER
#define RELAY_PROVIDER RELAY_PROVIDER_MY9291
// -----------------------------------------------------------------------------
// Jan Goedeke Wifi Relay
// https://github.com/JanGoe/esp8266-wifi-relay


BIN
code/espurna/data/index.html.gz View File


+ 160
- 41
code/espurna/relay.ino View File

@ -26,6 +26,110 @@ Ticker pulseTicker;
bool recursive = false;
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
#include <my9291.h>
typedef struct {
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char white;
} color_t;
my9291 _my9291 = my9291(MY9291_DI_PIN, MY9291_DCKI_PIN, MY9291_COMMAND);
bool _my9291_status = false;
color_t _my9291_color = {0, 0, 0, 255};
Ticker colorTicker;
#endif
// -----------------------------------------------------------------------------
// PROVIDER
// -----------------------------------------------------------------------------
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
void setLightColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char white) {
_my9291_color.red = red;
_my9291_color.green = green;
_my9291_color.blue = blue;
_my9291_color.white = white;
// Force color change
relayProviderStatus(0, _my9291_status);
// Delay saving to EEPROM 5 seconds to avoid wearing it out unnecessarily
colorTicker.once(5, saveLightColor);
}
String getLightColor() {
char buffer[16];
sprintf(buffer, "%d,%d,%d,%d", _my9291_color.red, _my9291_color.green, _my9291_color.blue, _my9291_color.white);
return String(buffer);
}
void saveLightColor() {
setSetting("colorRed", _my9291_color.red);
setSetting("colorGreen", _my9291_color.green);
setSetting("colorBlue", _my9291_color.blue);
setSetting("colorWhite", _my9291_color.white);
saveSettings();
}
void retrieveLightColor() {
_my9291_color.red = getSetting("colorRed", MY9291_COLOR_RED).toInt();
_my9291_color.green = getSetting("colorGreen", MY9291_COLOR_GREEN).toInt();
_my9291_color.blue = getSetting("colorBlue", MY9291_COLOR_BLUE).toInt();
_my9291_color.white = getSetting("colorWhite", MY9291_COLOR_WHITE).toInt();
}
#endif
void relayProviderStatus(unsigned char id, bool status) {
#if RELAY_PROVIDER == RELAY_PROVIDER_DUAL
dualRelayStatus ^= (1 << id);
Serial.flush();
Serial.write(0xA0);
Serial.write(0x04);
Serial.write(dualRelayStatus);
Serial.write(0xA1);
Serial.flush();
#endif
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
if (status) {
_my9291.send(_my9291_color.red,_my9291_color.green,_my9291_color.blue,_my9291_color.white);
} else {
_my9291.send(0, 0, 0, 0);
}
_my9291_status = status;
#endif
#if RELAY_PROVIDER == RELAY_PROVIDER_RELAY
digitalWrite(_relays[id].pin, _relays[id].reverse ? !status : status);
#endif
}
bool relayProviderStatus(unsigned char id) {
#if RELAY_PROVIDER == RELAY_PROVIDER_DUAL
if (id >= 2) return false;
return ((dualRelayStatus & (1 << id)) > 0);
#endif
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
return _my9291_status;
#endif
#if RELAY_PROVIDER == RELAY_PROVIDER_RELAY
if (id >= _relays.size()) return false;
bool status = (digitalRead(_relays[id].pin) == HIGH);
return _relays[id].reverse ? !status : status;
#endif
}
// -----------------------------------------------------------------------------
// RELAY
// -----------------------------------------------------------------------------
@ -43,14 +147,7 @@ String relayString() {
}
bool relayStatus(unsigned char id) {
#ifdef SONOFF_DUAL
if (id >= 2) return false;
return ((dualRelayStatus & (1 << id)) > 0);
#else
if (id >= _relays.size()) return false;
bool status = (digitalRead(_relays[id].pin) == HIGH);
return _relays[id].reverse ? !status : status;
#endif
return relayProviderStatus(id);
}
void relayPulse(unsigned char id) {
@ -120,19 +217,7 @@ bool relayStatus(unsigned char id, bool status, bool report) {
DEBUG_MSG("[RELAY] %d => %s\n", id, status ? "ON" : "OFF");
changed = true;
#ifdef SONOFF_DUAL
dualRelayStatus ^= (1 << id);
Serial.flush();
Serial.write(0xA0);
Serial.write(0x04);
Serial.write(dualRelayStatus);
Serial.write(0xA1);
Serial.flush();
#else
digitalWrite(_relays[id].pin, _relays[id].reverse ? !status : status);
#endif
relayProviderStatus(id, status);
if (_relays[id].led > 0) {
ledStatus(_relays[id].led - 1, status);
@ -370,42 +455,72 @@ void relayMQTTCallback(unsigned int type, const char * topic, const char * paylo
if (type == MQTT_CONNECT_EVENT) {
relayMQTT();
char buffer[strlen(MQTT_RELAY_TOPIC) + mqttSetter.length() + 10];
char buffer[strlen(MQTT_RELAY_TOPIC) + mqttSetter.length() + 20];
sprintf(buffer, "%s/+%s", MQTT_RELAY_TOPIC, mqttSetter.c_str());
mqttSubscribe(buffer);
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
sprintf(buffer, "%s%s", MQTT_COLOR_TOPIC, mqttSetter.c_str());
mqttSubscribe(buffer);
#endif
}
if (type == MQTT_MESSAGE_EVENT) {
// Match topic
char * t = mqttSubtopic((char *) topic);
if (strncmp(t, MQTT_RELAY_TOPIC, strlen(MQTT_RELAY_TOPIC)) != 0) return;
int len = mqttSetter.length();
if (strncmp(t + strlen(t) - len, mqttSetter.c_str(), len) != 0) return;
// Get value
unsigned int value = (char)payload[0] - '0';
// Color topic
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
if (strncmp(t, MQTT_COLOR_TOPIC, strlen(MQTT_COLOR_TOPIC)) == 0) {
char * p;
p = strtok((char *) payload, ",");
unsigned char red = atoi(p);
p = strtok(NULL, ",");
unsigned char green = atoi(p);
p = strtok(NULL, ",");
unsigned char blue = atoi(p);
if ((red == green) && (green == blue)) {
setLightColor(0, 0, 0, red);
} else {
setLightColor(red, green, blue, 0);
}
return;
// Pulse topic
if (strncmp(t + strlen(MQTT_RELAY_TOPIC) + 1, "pulse", 5) == 0) {
relayPulseMode(value, !sameSetGet);
return;
}
}
#endif
// Get relay ID
unsigned int relayID = topic[strlen(topic) - mqttSetter.length() - 1] - '0';
if (relayID >= relayCount()) {
DEBUG_MSG("[RELAY] Wrong relayID (%d)\n", relayID);
return;
}
// Relay topic
if (strncmp(t, MQTT_RELAY_TOPIC, strlen(MQTT_RELAY_TOPIC)) == 0) {
// Get value
unsigned int value = (char)payload[0] - '0';
// Pulse topic
if (strncmp(t + strlen(MQTT_RELAY_TOPIC) + 1, "pulse", 5) == 0) {
relayPulseMode(value, !sameSetGet);
return;
}
// Get relay ID
unsigned int relayID = topic[strlen(topic) - mqttSetter.length() - 1] - '0';
if (relayID >= relayCount()) {
DEBUG_MSG("[RELAY] Wrong relayID (%d)\n", relayID);
return;
}
// Action to perform
if (value == 2) {
relayToggle(relayID);
} else {
relayStatus(relayID, value > 0, !sameSetGet);
}
// Action to perform
if (value == 2) {
relayToggle(relayID);
} else {
relayStatus(relayID, value > 0, !sameSetGet);
}
}
@ -448,6 +563,10 @@ void relaySetup() {
EEPROM.begin(4096);
byte relayMode = getSetting("relayMode", RELAY_MODE).toInt();
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
retrieveLightColor();
#endif
for (unsigned int i=0; i < _relays.size(); i++) {
pinMode(_relays[i].pin, OUTPUT);
if (relayMode == RELAY_MODE_OFF) relayStatus(i, false);


+ 14
- 1
code/espurna/web.ino View File

@ -101,7 +101,7 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
EEPROM.write(i, 0xFF);
}
for (auto element : data){
for (auto element : data) {
if (strcmp(element.key, "app") == 0) continue;
if (strcmp(element.key, "version") == 0) continue;
setSetting(element.key, element.value.as<char*>());
@ -121,6 +121,13 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
if (action.equals("on")) relayStatus(relayID, true);
if (action.equals("off")) relayStatus(relayID, false);
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
if (action.equals("color") && root.containsKey("data")) {
JsonArray& data = root["data"];
setLightColor(data[0], data[1], data[2], data[3]);
}
#endif
};
// Check config
@ -381,6 +388,12 @@ void _wsStart(uint32_t client_id) {
for (unsigned char relayID=0; relayID<relayCount(); relayID++) {
relay.add(relayStatus(relayID));
}
#if RELAY_PROVIDER == RELAY_PROVIDER_MY9291
root["colorVisible"] = 1;
root["color"] = getLightColor();
#endif
root["relayMode"] = getSetting("relayMode", RELAY_MODE);
root["relayPulseMode"] = getSetting("relayPulseMode", RELAY_PULSE_MODE);
root["relayPulseTime"] = getSetting("relayPulseTime", RELAY_PULSE_TIME);


+ 28
- 0
code/html/custom.js View File

@ -31,6 +31,24 @@ function validateForm(form) {
}
function doColor() {
var color = $(this).wheelColorPicker('getColor');
var data = [];
if ((color.r == color.g) && (color.g == color.b)) {
data.push(0);
data.push(0);
data.push(0);
data.push(parseInt(color.r * 255));
} else {
data.push(parseInt(color.r * 255));
data.push(parseInt(color.g * 255));
data.push(parseInt(color.b * 255));
data.push(0);
}
websock.send(JSON.stringify({'action': 'color', 'data' : data}));
}
function doUpdate() {
var form = $("#formSave");
if (validateForm(form)) {
@ -274,6 +292,13 @@ function processData(data) {
}
if (key == "color") {
var color = data[key].split(",");
if (color[3] > 0) color[0] = color[1] = color[2] = color[3];
$("input[name='color']").wheelColorPicker('setRgb', color[0] / 255, color[1] / 255, color[2] / 255, true);
return;
}
if (key == "maxNetworks") {
maxNetworks = parseInt(data.maxNetworks);
return;
@ -441,6 +466,9 @@ function init() {
$(".button-add-network").on('click', function() {
$("div.more", addNetwork()).toggle();
});
$('input[name="color"]').wheelColorPicker({
sliders: 'wsvp'
}).on('sliderup', doColor);
var host = window.location.hostname;
var port = location.port;


+ 19
- 12
code/html/index.html View File

@ -13,6 +13,7 @@
<link rel="stylesheet" href="grids-responsive-min.css" />
<link rel="stylesheet" href="checkboxes.css" />
<link rel="stylesheet" href="custom.css" />
<link rel="stylesheet" href="wheelcolorpicker.css" />
<!-- endbuild -->
</head>
@ -225,6 +226,11 @@
<div id="relays">
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Color</label>
<input class="pure-u-1 pure-u-sm-1-4" data-wcp-layout="block" name="color" readonly />
</div>
</fieldset>
</form>
@ -254,7 +260,7 @@
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="relayMode">Relay boot mode</label>
<label class="pure-u-1 pure-u-md-1-4" for="relayMode">Switch boot mode</label>
<div class="pure-u-1 pure-u-md-3-4">
<select name="relayMode" class="pure-u-3-4" tabindex="2">
<option value="0">Always OFF</a>
@ -264,25 +270,25 @@
</select>
</div>
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Here you can define what will be the status of the relay after a reboot.</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Here you can define what will be the status of the switch after a reboot.</div>
</div>
<div class="pure-g module module-multirelay">
<label class="pure-u-1 pure-u-md-1-4" for="relaySync">Relay sync mode</label>
<label class="pure-u-1 pure-u-md-1-4" for="relaySync">Switch sync mode</label>
<div class="pure-u-1 pure-u-md-3-4">
<select name="relaySync" class="pure-u-3-4" tabindex="3">
<option value="0">No synchonisation</a>
<option value="1">Zero or one relays active</a>
<option value="2">One and just one relay active</a>
<option value="1">Zero or one switches active</a>
<option value="2">One and just one switches active</a>
<option value="3">All synchonised</a>
</select>
</div>
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Define how the different relays should be synchronized.</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Define how the different switches should be synchronized.</div>
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="relayPulseMode">Relay pulse mode</label>
<label class="pure-u-1 pure-u-md-1-4" for="relayPulseMode">Switch pulse mode</label>
<div class="pure-u-1 pure-u-md-3-4">
<select name="relayPulseMode" class="pure-u-3-4" tabindex="4">
<option value="0">Don't pulse</a>
@ -291,11 +297,11 @@
</select>
</div>
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">When pulse mode is enabled the relay will automatically switch back to its normal state after the pulse time (below).</div>
<div class="pure-u-1 pure-u-md-3-4 hint">When pulse mode is enabled the switch will automatically switch back to its normal state after the pulse time (below).</div>
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="relayPulseTime">Relay pulse time</label>
<label class="pure-u-1 pure-u-md-1-4" for="relayPulseTime">Switch pulse time</label>
<input name="relayPulseTime" class="pure-u-1 pure-u-md-3-4" type="number" min="1" tabindex="5" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Pulse time in seconds.</div>
@ -435,7 +441,7 @@
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">
This is the root topic for this device. The {identifier} placeholder will be replaces by the device hostname.<br />
- <strong>&lt;root&gt;/relay/#</strong> Send a 0 or a 1 as a payload to this topic to switch it on or off. You can also send a 2 to toggle its current state. Replace # with the relay ID (starting from 0). If the board has only one relay it will be 0.<br />
- <strong>&lt;root&gt;/relay/#</strong> Send a 0 or a 1 as a payload to this topic to switch it on or off. You can also send a 2 to toggle its current state. Replace # with the switch ID (starting from 0). If the board has only one switch it will be 0.<br />
- <strong>&lt;root&gt;/led/#</strong> Send a 0 or a 1 as a payload to this topic to set the onboard LED to the given state, send a 3 to turn it back to WIFI indicator. Replace # with the LED ID (starting from 0). If the board has only one LED it will be 0.<br />
- <strong>&lt;root&gt;/button/#</strong> For each button in the board subscribe to this topic to know when it is pressed (payload 1) or released (payload 0).<br />
- <strong>&lt;root&gt;/ip</strong> The device will report to this topic its IP.<br />
@ -617,14 +623,14 @@
<div id="relayTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Relay<span class="relay_id"></span> Status</label>
<label class="pure-u-1 pure-u-sm-1-4">Switch<span class="relay_id"></span> Status</label>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" class="relayStatus" data="0" /></div>
</div>
</div>
<div id="idxTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4" for="dczRelayIdx">Relay<span class="id"></span> IDX</label>
<label class="pure-u-1 pure-u-sm-1-4" for="dczRelayIdx">Switch<span class="id"></span> IDX</label>
<div class="pure-u-1 pure-u-sm-1-8"><input class="pure-u-sm-23-24 dczRelayIdx" name="dczRelayIdx" type="number" min="0" tabindex="0" data="0" /></div>
<div class="pure-u-1 pure-u-sm-5-8 hint center">Set to 0 to disable notifications.</div>
</div>
@ -639,6 +645,7 @@
<script src="jquery-1.12.3.min.js"></script>
<script src="checkboxes.js"></script>
<script src="custom.js"></script>
<script src="jquery.wheelcolorpicker-3.0.2.min.js"></script>
<!-- endbuild -->
</html>

+ 13
- 0
code/html/jquery.wheelcolorpicker-3.0.2.min.js
File diff suppressed because it is too large
View File


+ 158
- 0
code/html/wheelcolorpicker.css View File

@ -0,0 +1,158 @@
/**
* jQuery Wheel Color Picker
* Base Stylesheet
*
* http://www.jar2.net/projects/jquery-wheelcolorpicker
*
* Copyright © 2011-2016 Fajar Chandra. All rights reserved.
* Released under MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
* Note: Width, height, left, and top properties are handled by the
* plugin. These values might change on the fly.
*/
.jQWCP-wWidget {
position: absolute;
width: 250px;
height: 180px;
background: #eee;
box-shadow: 1px 1px 4px rgba(0,0,0,.5);
border-radius: 4px;
border: solid 1px #aaa;
padding: 10px;
z-index: 1001;
}
.jQWCP-wWidget.jQWCP-block {
position: relative;
border-color: #aaa;
box-shadow: inset 1px 1px 1px #ccc;
}
.jQWCP-wWheel {
background-size: contain;
position: relative;
float: left;
width: 180px;
height: 180px;
-webkit-border-radius: 90px;
-moz-border-radius: 50%;
border-radius: 50%;
border: solid 1px #aaa;
margin: -1px;
margin-right: 10px;
transition: border .15s;
cursor: crosshair;
}
.jQWCP-wWheel:hover {
border-color: #666;
}
.jQWCP-wWheelOverlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
opacity: 0;
-webkit-border-radius: 90px;
-moz-border-radius: 50%;
border-radius: 50%;
}
.jQWCP-wWheelCursor {
width: 8px;
height: 8px;
position: absolute;
top: 50%;
left: 50%;
margin: -6px -6px;
cursor: crosshair;
border: solid 2px #fff;
box-shadow: 1px 1px 2px #000;
border-radius: 50%;
}
.jQWCP-slider-wrapper,
.jQWCP-wPreview {
position: relative;
width: 20px;
height: 180px;
float: left;
margin-right: 10px;
}
.jQWCP-wWheel:last-child,
.jQWCP-slider-wrapper:last-child,
.jQWCP-wPreview:last-child {
margin-right: 0;
}
.jQWCP-slider,
.jQWCP-wPreviewBox {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
box-sizing: border-box;
border: solid 1px #aaa;
margin: -1px;
-moz-border-radius: 4px;
border-radius: 4px;
transition: border .15s;
}
.jQWCP-slider {
cursor: crosshair;
}
.jQWCP-slider-wrapper:hover .jQWCP-slider {
border-color: #666;
}
.jQWCP-scursor {
position: absolute;
left: 0;
top: 0;
right: 0;
height: 6px;
margin: -5px -1px -5px -3px;
cursor: crosshair;
border: solid 2px #fff;
box-shadow: 1px 1px 2px #000;
border-radius: 4px;
}
.jQWCP-wAlphaSlider,
.jQWCP-wPreviewBox {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEVAQEB/f39eaJUuAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYRBDgK9dKdMgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAARSURBVAjXY/jPwIAVYRf9DwB+vw/x6vMT1wAAAABJRU5ErkJggg==') center center;
}
.jQWCP-overlay {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1000;
}
/*********************/
/* Mobile layout */
.jQWCP-mobile.jQWCP-wWidget {
position: fixed;
bottom: 0;
left: 0 !important;
top: auto !important;
width: 100%;
height: 75%;
max-height: 240px;
box-sizing: border-box;
border-radius: 0;
}

+ 187
- 0
code/lib/my9291/my9291.cpp View File

@ -0,0 +1,187 @@
/*
MY9291 LED Driver Arduino library 0.1.0
Copyright (c) 2016 - 2026 MaiKe Labs
Copyright (C) 2017 - Xose Pérez (for the library)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "my9291.h"
extern "C" {
void os_delay_us(unsigned int);
}
void my9291::_di_pulse(unsigned int times) {
unsigned int i;
for (i = 0; i < times; i++) {
digitalWrite(_pin_di, HIGH);
digitalWrite(_pin_di, LOW);
}
}
void my9291::_dcki_pulse(unsigned int times) {
unsigned int i;
for (i = 0; i < times; i++) {
digitalWrite(_pin_dcki, HIGH);
digitalWrite(_pin_dcki, LOW);
}
}
void my9291::_set_cmd(my9291_cmd_t command) {
unsigned char i;
unsigned char command_data = *(unsigned char *) (&command);
_command = command;
// ets_intr_lock();
// TStop > 12us.
os_delay_us(12);
// Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12
// pulse's rising edge convert to command mode.
_di_pulse(12);
// Delay >12us, begin send CMD data
os_delay_us(12);
// Send CMD data
for (i = 0; i < 4; i++) {
// DCK = 0;
digitalWrite(_pin_dcki, LOW);
if (command_data & 0x80) {
// DI = 1;
digitalWrite(_pin_di, HIGH);
} else {
// DI = 0;
digitalWrite(_pin_di, LOW);
}
// DCK = 1;
digitalWrite(_pin_dcki, HIGH);
command_data = command_data << 1;
if (command_data & 0x80) {
// DI = 1;
digitalWrite(_pin_di, HIGH);
} else {
// DI = 0;
digitalWrite(_pin_di, LOW);
}
// DCK = 0;
digitalWrite(_pin_dcki, LOW);
// DI = 0;
digitalWrite(_pin_di, LOW);
command_data = command_data << 1;
}
// TStart > 12us. Delay 12 us.
os_delay_us(12);
// Send 16 DI pulse,at 14 pulse's falling edge store CMD data, and
// at 16 pulse's falling edge convert to duty mode.
_di_pulse(16);
// TStop > 12us.
os_delay_us(12);
// ets_intr_unlock();
}
void my9291::send(unsigned int duty_r, unsigned int duty_g, unsigned int duty_b, unsigned int duty_w) {
unsigned char i = 0;
unsigned char channel = 0;
unsigned char bit_length = 8;
unsigned int duty_current = 0;
// Definition for RGBW channels
unsigned int duty[4] = { duty_r, duty_g, duty_b, duty_w };
switch (_command.bit_width) {
case MY9291_CMD_BIT_WIDTH_16:
bit_length = 16;
break;
case MY9291_CMD_BIT_WIDTH_14:
bit_length = 14;
break;
case MY9291_CMD_BIT_WIDTH_12:
bit_length = 12;
break;
case MY9291_CMD_BIT_WIDTH_8:
bit_length = 8;
break;
default:
bit_length = 8;
break;
}
// ets_intr_lock();
// TStop > 12us.
os_delay_us(12);
for (channel = 0; channel < 4; channel++) { //RGBW 4CH
// RGBW Channel
duty_current = duty[channel];
// Send 8bit/12bit/14bit/16bit Data
for (i = 0; i < bit_length / 2; i++) {
// DCK = 0;
digitalWrite(_pin_dcki, LOW);
if (duty_current & (0x01 << (bit_length - 1))) {
// DI = 1;
digitalWrite(_pin_di, HIGH);
} else {
// DI = 0;
digitalWrite(_pin_di, LOW);
}
// DCK = 1;
digitalWrite(_pin_dcki, HIGH);
duty_current = duty_current << 1;
if (duty_current & (0x01 << (bit_length - 1))) {
// DI = 1;
digitalWrite(_pin_di, HIGH);
} else {
// DI = 0;
digitalWrite(_pin_di, LOW);
}
//DCK = 0;
digitalWrite(_pin_dcki, LOW);
//DI = 0;
digitalWrite(_pin_di, LOW);
duty_current = duty_current << 1;
}
}
// TStart > 12us. Ready for send DI pulse.
os_delay_us(12);
// Send 8 DI pulse. After 8 pulse falling edge, store old data.
_di_pulse(8);
// TStop > 12us.
os_delay_us(12);
// ets_intr_unlock();
}
my9291::my9291(unsigned char di, unsigned char dcki, my9291_cmd_t command) {
_pin_di = di;
_pin_dcki = dcki;
pinMode(_pin_di, OUTPUT);
pinMode(_pin_dcki, OUTPUT);
digitalWrite(_pin_di, LOW);
digitalWrite(_pin_dcki, LOW);
// Clear all duty register
_dcki_pulse(64 / 2);
_set_cmd(command);
}

+ 94
- 0
code/lib/my9291/my9291.h View File

@ -0,0 +1,94 @@
/*
MY9291 LED Driver Arduino library 0.1.0
Copyright (c) 2016 - 2026 MaiKe Labs
Copyright (C) 2017 - Xose Pérez
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _my9291_h
#define _my9291_h
#include <Arduino.h>
typedef enum my9291_cmd_one_shot_t {
MY9291_CMD_ONE_SHOT_DISABLE = 0X00,
MY9291_CMD_ONE_SHOT_ENFORCE = 0X01,
} my9291_cmd_one_shot_t;
typedef enum my9291_cmd_reaction_t {
MY9291_CMD_REACTION_FAST = 0X00,
MY9291_CMD_REACTION_SLOW = 0X01,
} my9291_cmd_reaction_t;
typedef enum my9291_cmd_bit_width_t {
MY9291_CMD_BIT_WIDTH_16 = 0X00,
MY9291_CMD_BIT_WIDTH_14 = 0X01,
MY9291_CMD_BIT_WIDTH_12 = 0X02,
MY9291_CMD_BIT_WIDTH_8 = 0X03,
} my9291_cmd_bit_width_t;
typedef enum my9291_cmd_frequency_t {
MY9291_CMD_FREQUENCY_DIVIDE_1 = 0X00,
MY9291_CMD_FREQUENCY_DIVIDE_4 = 0X01,
MY9291_CMD_FREQUENCY_DIVIDE_16 = 0X02,
MY9291_CMD_FREQUENCY_DIVIDE_64 = 0X03,
} my9291_cmd_frequency_t;
typedef enum my9291_cmd_scatter_t {
MY9291_CMD_SCATTER_APDM = 0X00,
MY9291_CMD_SCATTER_PWM = 0X01,
} my9291_cmd_scatter_t;
typedef struct {
my9291_cmd_scatter_t scatter:1;
my9291_cmd_frequency_t frequency:2;
my9291_cmd_bit_width_t bit_width:2;
my9291_cmd_reaction_t reaction:1;
my9291_cmd_one_shot_t one_shot:1;
unsigned char resv:1;
} __attribute__ ((aligned(1), packed)) my9291_cmd_t;
#define MY9291_COMMAND_DEFAULT { \
.scatter = MY9291_CMD_SCATTER_APDM, \
.frequency = MY9291_CMD_FREQUENCY_DIVIDE_1, \
.bit_width = MY9291_CMD_BIT_WIDTH_8, \
.reaction = MY9291_CMD_REACTION_FAST, \
.one_shot = MY9291_CMD_ONE_SHOT_DISABLE, \
.resv = 0 \
}
class my9291 {
public:
my9291(unsigned char di, unsigned char dcki, my9291_cmd_t command);
void send(unsigned int duty_r, unsigned int duty_g, unsigned int duty_b, unsigned int duty_w);
private:
void _di_pulse(unsigned int times);
void _dcki_pulse(unsigned int times);
void _set_cmd(my9291_cmd_t command);
my9291_cmd_t _command;
unsigned char _pin_di;
unsigned char _pin_dcki;
};
#endif

+ 21
- 0
code/platformio.ini View File

@ -384,3 +384,24 @@ build_flags = ${common.build_flags_1m128} -DWIFI_RELAYS_BOARD_KIT
upload_speed = 115200
upload_port = "192.168.4.1"
upload_flags = --auth=fibonacci --port 8266
[env:ai-light-debug]
platform = espressif8266
framework = arduino
board = esp8285
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
extra_script = pio_hooks.py
build_flags = ${common.build_flags_1m128} -DAI_LIGHT
[env:ai-light-debug-ota]
platform = espressif8266
framework = arduino
board = esp8285
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
extra_script = pio_hooks.py
build_flags = ${common.build_flags_1m128} -DAI_LIGHT
upload_speed = 115200
upload_port = "192.168.4.1"
upload_flags = --auth=Algernon1 --port 8266

Loading…
Cancel
Save