From ce4e3b5ff71b888811a14e88f2490de7b647dc11 Mon Sep 17 00:00:00 2001 From: Dmitry Shalnoff Date: Mon, 9 Sep 2024 19:40:30 +0200 Subject: [PATCH 1/1] initial commit --- .gitignore | 60 ++ README.md | 102 +++ Serial_RGB/Serial_RGB.ino | 900 ++++++++++++++++++++++++++ Serial_RGB/version.c | 1 + bidirectonal-mosfet-level-shifter.png | Bin 0 -> 14297 bytes make | 45 ++ serial | 32 + 7 files changed, 1140 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 Serial_RGB/Serial_RGB.ino create mode 100644 Serial_RGB/version.c create mode 100644 bidirectonal-mosfet-level-shifter.png create mode 100755 make create mode 100755 serial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dab8ca3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +memo +info +dev +todo +BKP/* +Serial_RGB_test/* + +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.bin +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/README.md b/README.md new file mode 100644 index 0000000..89a21a1 --- /dev/null +++ b/README.md @@ -0,0 +1,102 @@ +# Serial RGB LED driver, Interplay Medium dendrite module (for ESP8266) + +This is IM denrite module (remote wifi network device) created for [Interplay Medium™](https://interplaymedium.org) project. + +![Interplay Medium RGB Serial LED Dendrite](https://repository.interplaymedium.org/RGBW%20Controller/IM_RGBW_LED_dendrite.jpeg) + +## Pinouts + +For LEDs be sure to add MOSFETs and current limiting resistors appropriately. Wiring scheme will be added probably later. + +![ESP8266 Pinout](https://repository.interplaymedium.org/RGBW%20Controller/esppinout_.png) +![ESP8266 Programming](https://repository.interplaymedium.org/RGBW%20Controller/usbprogram_.png) + +## Preparing the building environment + +Make sure that you have the environment installed as described at + +1. [makeEspArduino.mk](https://github.com/plerup/makeEspArduino.git) +2. [esp8266 Arduino SDK](https://github.com/esp8266/Arduino) + +3. In the *make* script, change path for each variable approprately: + MAKE_FILE=.... + ESP_SDK_ROOT=.... + +## Change your IM AXOD microserver or AP (router) WIFI login and password + +create the file + vim ../info + +assign SSID and PASSWORD of your local IM AXOD microserver or Access Point in there + + WIFI_SSID="ssid" + WIFI_PASS="ssid password" + +You can change it later whenewer you want using HTTP interface + +## Building + +initial buildong and flashing firmware at once + + ./make Serial_RGB upload + +after that you may just build the binary and uload it using remote HTTP interface + + ./make Serial_RGB + curl -F image=@Serial_RGB.bin -s im_<....>.lan/update + +## Usage + + +By default dendrite can be reached "im_serial_[last 4 digits of MAC address]" doman + +Change it with + + curl "im_serial_[last 4 digits of MAC address]?rename=NEWNAME" + +Turn on the color and effect + + curl "im_serial_[last 4 digits of MAC address]?gradient=ffffffccff44&slidez=-1&delay=100" + +Other options + + curl "im_serial_[last 4 digits of MAC address]/help" + +## Todo + +The development of this firmware is in progress. Here is a brief list of upcoming changes: + +* features (save, reset....) +* state return in 2 variants + txt (default) + JSON + html UI +* add commands + dimm and soft state changing + rgbwdef -- save default values in EEPROM, which is returning on reset command + +* switching AP/slave, AP by defuault + remote access setup (host name, AP/slave, SSID, passw) + save in EEPROM + +## License + +Copyright © 2016 Dmitry Shalnov [interplaymedium.org] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this files except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + + + + diff --git a/Serial_RGB/Serial_RGB.ino b/Serial_RGB/Serial_RGB.ino new file mode 100644 index 0000000..8db32e9 --- /dev/null +++ b/Serial_RGB/Serial_RGB.ino @@ -0,0 +1,900 @@ +/* + * Serial LED Controller, IM Dendrite module (for ESP8266) + * Created for Interplaymedium™ project (https://interplaymedium.org) + * Copyright © 2016 Dmitry Shalnov [interplaymedium.org] + * Licensed under the Apache License, Version 2.0 +*/ + +#define SERIAL 0 + +#include "../../info" +#include "version.c" + +#include + +#include +#include +#include +#include +#include + +#define LED_STRIPE WS2811 // WS2812B // APA106 // type of LEDs Supported LED chipsets: http://fastled.io/docs/3.1/md__r_e_a_d_m_e.html + +// -------------------- FastLED settings -------------- + +#define FASTLED_ESP8266_RAW_PIN_ORDER +#define FASTLED_INTERNAL // to remove #pragma diagnostics messages + +#include + // Serial // Switch 4 channel +#define DATA_PIN 3 // 3 // 2 // DIn controller pin (GPIO2) TODO: switch to GPIO0 + pull down (to avoid blink on reset) +#define ENABLE_GATE_PIN 2 // 2 // 3 // common ping for SN74HC08 AND gate (to prevent blink on power on + pull up the level) +#define MAX_NUM_LEDS 256 // maximum number of leds in stripe +#define DEF_NUM_LEDS 24 // default number of leds in stripe +#define DEF_MAIN_DELAY 1 // default FX delay (in loop) + +#define FULL_OUTPUT 2 // default quiet level + +CRGB LEDStripe_RGB[ MAX_NUM_LEDS ]; // This is an array of leds. One item for each led in your stripe. +CHSV color_HSV; +String param; + +uint8_t paramCnt = 0; +uint8_t JSONon = 0; + +uint8_t numberOfLEDs = DEF_NUM_LEDS; + +uint16_t mainDelay = 0, mainDelayNew = 0; + +unsigned char FX_PhaseXDelay = 0, FX_PhaseYDelay = 0, FX_PhaseZDelay = 0; + +// uint8_t EXP[ 256 ]; // lookup table + +unsigned long timeStamp = 0; +uint8_t changeColor = 0, quiet = FULL_OUTPUT, commandReboot = false; + +// -------------------- EEPROM addresing --------------- + +#define EEPROM_HOST 0 + +#define EEPROM_HOST_MAX_LEN 57 // Host name max length, can't be > 57 (could be 64, buth there is a bug in avahi https://github.com/lathiat/avahi/issues/273) +#define EEPROM_OTHER_MAX_LEN 13 // total size of other EEPROM parameters (summ of all EEPROM values below, included EEPROM_FLAG) + + +#define EEPROM_FLAG EEPROM_HOST_MAX_LEN + 1 // EEPROM has been changed (avoid overlap: EEPROM_HOST_MAX_LEN) + +#define EEPROM_numberOfLEDs EEPROM_HOST_MAX_LEN + 2 + +#define EEPROM_HgradBegin EEPROM_HOST_MAX_LEN + 3 // (the order of defines matter) +#define EEPROM_SgradBegin EEPROM_HOST_MAX_LEN + 4 +#define EEPROM_VgradBegin EEPROM_HOST_MAX_LEN + 5 + +#define EEPROM_HgradEnd EEPROM_HOST_MAX_LEN + 6 +#define EEPROM_SgradEnd EEPROM_HOST_MAX_LEN + 7 +#define EEPROM_VgradEnd EEPROM_HOST_MAX_LEN + 8 + +#define EEPROM_PERIOD EEPROM_HOST_MAX_LEN + 9 + +#define EEPROM_FX_PhaseX EEPROM_HOST_MAX_LEN + 10 +#define EEPROM_FX_PhaseY EEPROM_HOST_MAX_LEN + 11 +#define EEPROM_FX_PhaseZ EEPROM_HOST_MAX_LEN + 12 + +#define EEPROM_mainDelayNew EEPROM_HOST_MAX_LEN + 13 + + +// ------------------- array of parameters ------------- (the order of defines matter) + +#define NUMBER_OF_PARAM 10 + +#define H_GRAD_BEG 0 +#define S_GRAD_BEG 1 +#define V_GRAD_BEG 2 +#define H_GRAD_END 3 +#define S_GRAD_END 4 +#define V_GRAD_END 5 +#define PERIOD 6 +#define PHASE_X_INC 7 +#define PHASE_Y_INC 8 +#define PHASE_Z_INC 9 + +float FX_Arr[ NUMBER_OF_PARAM ] = {}; +float FX_ArrNew[ NUMBER_OF_PARAM ] = {}; +float FX_Coeff[ NUMBER_OF_PARAM ] = {}; +float Phase[ 3 ] = {}; + +float FX_CoeffMax = 1.0; + +#define PHASE_X 0 +#define PHASE_Y 1 +#define PHASE_Z 2 + + +// ------------------- server settings ----------------- + +#define HOST_DEFAULT "im_serial_" +#define NTP_SERVER "europe.pool.ntp.org" + +char host[ EEPROM_HOST_MAX_LEN ]; + +// const char* ssid = "axod_ap"; +// const char* password = "superstrongpassword" + +const char* ssid = IM_WIFI_SSID; +const char* password = IM_WIFI_PASS; + +ESP8266WebServer server(80); + +String hostDefURI; +String HTTPOut; +String HTTPErr; + +WiFiUDP ntpUDP; +NTPClient timeClient(ntpUDP, NTP_SERVER , 0, 60000); + +// ---------------- EEPROM String r/w ------------------ + +void EEPROMStrRead( uint8_t addr, char * str ){ + for (uint8_t a = addr; a < EEPROM_HOST_MAX_LEN; a++ ){ + str[ a ] = EEPROM.read( a ); + if (str[ a ] == 0) break; + } +} + +void EEPROMStrWrite( uint8_t addr, char * str ){ + uint8_t a = 0; + for (a = addr; a < EEPROM_HOST_MAX_LEN; a++ ){ + EEPROM.write( a, str[ a ] ); + if (str[ a ] == 0) break; + } + EEPROM.write( a, 0 ); +} + +// ---------------- misc ------------------------------- + +int str2HEX(const String str) { + return strtol( str.c_str(), 0, 16 ); +} + +String printNum(unsigned long num, int base, char sign) { + + char outbuf[12]; + + int i = 12; + int j = 0; + int n; + + do { + outbuf[i] = "0123456789ABCDEF"[num % base]; + i--; + num = num/base; + } while ( num > 0 ); + + if ( sign != ' ' ){ + outbuf[0] = sign; + ++j; + } + + while ( ++i < 13 ){ + outbuf[j++] = outbuf[i]; + } + + if ( j == 1 ) { outbuf[ 1 ] = outbuf[ 0 ]; outbuf[ 0 ] = '0'; ++j; } + + outbuf[j] = 0; + + return outbuf; + +} + +uint8_t is_number( const char *s ){ + + while (*s) { + Serial.printf("s: %c\n", *s); + if ( *s++ <48 || *s >57 ) return 0; + } + return true; +} + +// ----------- explode for selected substring ----------- + +String expld( String str, unsigned int numb, char delimiter ){ + + unsigned int cnt = 0, a = 0, p2 = 0, p1 = 0, lng = 0; + + lng = str.length(); + + for ( a = 0; a < lng; a++ ){ + if ( str.charAt( a ) == delimiter ) { + p2 = p1; + p1 = a; + if ( cnt == numb ) break; + cnt ++; + } + } + + if ( cnt < numb ) return ""; + + if ( a == lng ) { + p2 = p1; + p1 = lng; + } + + if ( numb > 0 ) p2 ++; + + return str.substring(p2, p1); + +} + +// ---------------- FX --------------------------------- + +void FX_Gradient_RT( uint8_t HgradBegin, uint8_t SgradBegin, uint8_t VgradBegin, uint8_t HgradEnd, uint8_t SgradEnd, uint8_t VgradEnd, uint8_t period, uint8_t phaseX, uint8_t phaseY, uint8_t phaseZ ) { + + unsigned int i = 0; + CHSV color; + + #define Y_PHASE_SHIFT 128 // 128 // to avoid solid fill on phase = 0 + + // NOTE! phaseZ is for color component only since it is cyclic + + for (i = 0; i < numberOfLEDs; i++) { + +// newHueColor = pow( (float)sin( (float)i*PI / (period * 2) ) ,2 ) * (gradEnd - gradBegin) + gradBegin; // MEMO! floating point + + if ( HgradEnd != HgradBegin ) color.h = ( ((int)cos8( (i + phaseX) * 128 / period ) - 128) * ((int)sin8( (phaseY + Y_PHASE_SHIFT) * 128 / period ) - 128) / 128 + 128 ) / ( 256 / ( HgradEnd - HgradBegin ) ) + HgradBegin; else color.h = HgradEnd; + if ( SgradEnd != SgradBegin ) color.s = ( ((int)cos8( (i + phaseX) * 128 / period ) - 128) * ((int)sin8( (phaseY + Y_PHASE_SHIFT) * 128 / period ) - 128) / 128 + 128 ) / ( 256 / ( SgradEnd - SgradBegin ) ) + SgradBegin; else color.s = SgradEnd; + if ( VgradEnd != VgradBegin ) color.v = ( ((int)cos8( (i + phaseX) * 128 / period ) - 128) * ((int)sin8( (phaseY + Y_PHASE_SHIFT) * 128 / period ) - 128) / 128 + 128 ) / ( 256 / ( VgradEnd - VgradBegin ) ) + VgradBegin; else color.v = VgradEnd; + +// LEDStripe_RGB[ i ] = CHSV( color.h + phaseZ , color.s, color.v ); + + color.h += phaseZ; + hsv2rgb_spectrum(color, LEDStripe_RGB[ i ]); + + } +} + +// ----------------------------------------------------- +// --------------- Init -------------------------------- +// ----------------------------------------------------- + +void setup(void) { + + HTTPOut.reserve(800); // lenght of Help message generally + + hostDefURI.reserve( EEPROM_HOST_MAX_LEN ); + hostDefURI = HOST_DEFAULT + WiFi.macAddress().substring(12, 14) + WiFi.macAddress().substring(15, 17); // 00:00:00:00:00:00 + + // calculate lookup array + +// for (unsigned int a = 1; a <= 255; a++) EXP[ a ] = round( pow( 255, (double)a / (255) ) ); // calculate exponential lookup array (for PWM etc..) + + // reset FX_Coeff (maybe not required) + + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) FX_Coeff[ a ] = 1.0; + +#if SERIAL == 1 + + // Serial init + + Serial.begin(115200); + Serial.println(); + Serial.println("Booting Sketch..."); +#endif + + // read parameters from EEPROM (if it has been saved early) + + EEPROM.begin( EEPROM_HOST_MAX_LEN + EEPROM_OTHER_MAX_LEN ); + + if ( EEPROM.read( EEPROM_FLAG ) == 1 ){ + + EEPROMStrRead( EEPROM_HOST, host ); + + numberOfLEDs = EEPROM.read( EEPROM_numberOfLEDs ); + mainDelayNew = EEPROM.read( EEPROM_mainDelayNew ); + + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) FX_ArrNew[ a ] = EEPROM.read( EEPROM_HgradBegin + a ); + + changeColor = true; + + } else { + + FX_ArrNew[ PERIOD ] = DEF_NUM_LEDS; + strcpy( host, (char*)hostDefURI.c_str() ); // default URI and host name + } + + // Fast LED RGB init + + pinMode(ENABLE_GATE_PIN, OUTPUT); + digitalWrite( ENABLE_GATE_PIN, HIGH ); + + delay(1000); // 2000 // sanity check delay - allows reprogramming if accidently blowing power w/leds + + FastLED.addLeds( LEDStripe_RGB, numberOfLEDs ); + fill_solid( LEDStripe_RGB, numberOfLEDs, CRGB(0, 0, 0) ); + FastLED.show(); + + // WiFi init + + if ( host == "" ) strcpy( host, (char*)hostDefURI.c_str() ); // if it was changed without parameters by mistake + + WiFi.hostname( host ); + +// WiFi.softAP(APssid, APpassword); +// WiFi.mode(WIFI_AP); +// WiFi.mode(WIFI_AP_STA); + + WiFi.mode(WIFI_STA); + WiFi.setAutoReconnect( true ); + WiFi.begin(ssid, password); + + // main events handlers + + if (WiFi.waitForConnectResult() == WL_CONNECTED) { + + MDNS.begin( host ); + + // get time + +// timeClient.setTimeOffset(0); + timeClient.begin(); + timeClient.update(); + + // start server + + server.begin(); + MDNS.addService("http", "tcp", 80); + +#if SERIAL == 1 + Serial.printf("Ready. Try \"curl %s/help\" to see the list of commands and parameters.\n", host); +#endif + + server.onNotFound( []() { + + server.sendHeader("Connection", "close"); + + param = ""; +// HTTPOut = ""; + + // no command given (see handlers of commands below) + + if ( server.uri() != "/" )HTTPErr += "Command '" + server.uri() + "' not exist.\n"; + + + for ( uint8_t i=0; i < server.args(); i++ ){ + + paramCnt = 0; + + // ------------- specific parameters ----------------- + + // change number of leds in stripe + + if ( server.argName(i) == "number" ) { + + // TODO make it in MAIN with dimming + + fill_solid( LEDStripe_RGB, numberOfLEDs, CRGB(0, 0, 0) ); + FastLED.show(); + + numberOfLEDs = server.arg("number").toInt(); + FastLED.addLeds( LEDStripe_RGB, numberOfLEDs ); + + paramCnt++; + } + + // color gradient (hex) + + if ( server.argName(i) == "gradient" ) { + + param = server.arg("gradient"); + + for ( uint8_t a = 0; a < 6; a++ ) FX_ArrNew[ H_GRAD_BEG + a ] = str2HEX( param.substring( a*2, a*2+2) ); + + changeColor = true; + paramCnt++; + + } + + // sin/cos period (dec) + + if ( server.argName(i) == "period" ) { + + FX_ArrNew[ PERIOD ] = server.arg("period").toInt(); + + changeColor = true; + paramCnt++; + } + + + // pattern motion parameters (dec) + + if ( server.argName(i) == "slidex" ) { + FX_ArrNew [ PHASE_X_INC ] = (float)server.arg("slidex").toInt(); + changeColor = true; + paramCnt++; + } + + if ( server.argName(i) == "slidey" ) { + FX_ArrNew [ PHASE_Y_INC ] = (float)server.arg("slidey").toInt(); + changeColor = true; + paramCnt++; + } + + if ( server.argName(i) == "slidez" ) { + FX_ArrNew [ PHASE_Z_INC ] = (float)server.arg("slidez").toInt(); + changeColor = true; + paramCnt++; + } + + + // delay between frames + + if ( server.argName(i) == "delay" ) { + mainDelayNew = server.arg("delay").toInt(); +// changeColor = true; + paramCnt++; + } + + // ------------- common parameters ------------------- + + // debug data {Number R G B H S V} + + if ( server.argName(i) == "debug" ){ // || param != 0 + + HTTPOut += "Stripe [debug]: "; + + for (unsigned int i = 0; i < numberOfLEDs; i++) { + color_HSV = rgb2hsv_approximate( LEDStripe_RGB[ i ] ); + HTTPOut += String( i ) + "\t" + String( LEDStripe_RGB[ i ].r ) + "\t" + String( LEDStripe_RGB[ i ].g ) + "\t" + String( LEDStripe_RGB[ i ].b ) + "\t" + String( color_HSV.h ) + "\t" + String( color_HSV.s ) + "\t" + String( color_HSV.v ) + "\n"; + } + + paramCnt++; + } + + // set time + + if ( server.argName(i) == "time" ){ // || param != 0 + + if ( is_number( server.arg("time").c_str() ) ) { + timeClient.update(); + timeStamp = strtol( server.arg("time").c_str(), 0, 10 ); + } else { + HTTPErr += "Parameter 'time' must be specified in UNIX timestamp format.\n"; // 1631848103 + } + + paramCnt++; + } + + // rename host + + if ( server.argName(i) == "host" ) { + + if ( server.arg("host") == "" ) { + + HTTPErr += "Please specify new unit hostname.\n"; + + } else if ( server.arg("host").length() > EEPROM_HOST_MAX_LEN ) { + + HTTPErr += "Unit hostname can not exceed " + String( EEPROM_HOST_MAX_LEN ) + " symbols.\n"; + + } else { + + strcpy( host, (char*)server.arg("host").c_str() ); // host = (char *)server.arg("host").c_str(); + WiFi.hostname( host ); + MDNS.begin( host ); + + HTTPOut += "The host name has been changed to '" + String( host ) + "'. Do not forget to save current settings using the '/save' command.\n"; + } + + paramCnt++; + } + + // save all parameters to EEPROM + + if (server.argName(i) == "save" ){ + + EEPROM.write( EEPROM_numberOfLEDs, numberOfLEDs ); + EEPROM.write( EEPROM_mainDelayNew, mainDelayNew ); + + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) EEPROM.write( EEPROM_HgradBegin + a, (uint8_t)roundf( FX_Arr[ a ] ) ); + + EEPROMStrWrite( EEPROM_HOST, host ); + EEPROM.write( EEPROM_FLAG, 1 ); // EEPROM changed + EEPROM.commit(); + + HTTPOut += "The current settings are saved.\n"; + + paramCnt++; + } + + // reset to default parameters + + if ( server.argName(i) == "reset" ){ + + numberOfLEDs = DEF_NUM_LEDS; + mainDelayNew = DEF_MAIN_DELAY; + + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) FX_ArrNew[ a ] = 0; + + FX_Arr[ PERIOD ] = DEF_NUM_LEDS; + FX_ArrNew[ PERIOD ] = DEF_NUM_LEDS; + + strcpy( host, (char*)hostDefURI.c_str() ); + WiFi.hostname( host ); + + server.begin(); + + if ( quiet > 1 ) HTTPOut += "All parameters are set to default values. Don't forget to /save them.\n"; + + paramCnt++; + + changeColor = true; + + } + + // reboot + + if ( server.argName(i) == "reboot" ){ + + FX_ArrNew[ V_GRAD_BEG ] = 0; + FX_ArrNew[ V_GRAD_END ] = 0; + + mainDelayNew = DEF_MAIN_DELAY; + + if ( quiet > 1 ) { + + server.send_P(200, "text/plain", PSTR("Unit rebooting...\n") ); + server.begin(); + } + + paramCnt++; + + changeColor = true; + commandReboot = true; + } + + // quiet, level of output + + if ( server.argName(i) == "quiet" ) { + + quiet = str2HEX( server.arg("quiet") ); + paramCnt++; + } else { + quiet = FULL_OUTPUT; + } + + // json on + + if ( server.argName(i) == "json" ) { + JSONon = true; + paramCnt++; + } + + if ( !paramCnt ) HTTPErr += "Parameter '" + server.argName(i) + "' not exist.\n"; + } + + + // ---------------- host default return ------------------------ + + if (HTTPErr != "" ) { + + // list of errors + + String Err = ""; + + paramCnt = 0; + + if (quiet > 0) { + + if ( JSONon ) { + + HTTPOut += "{["; + + while ( 1 ){ + Err = expld( HTTPErr, paramCnt, '\n' ); + if ( Err != "" ) HTTPOut += "\"" + Err + "\""; else break; + if ( expld( HTTPErr, paramCnt+1, '\n' ) != "" ) HTTPOut += ","; + paramCnt ++; + } + + HTTPOut += "]}"; + + } else { + + while ( 1 ){ + Err = expld( HTTPErr, paramCnt, '\n' ); + if ( Err != "" ) HTTPOut += "Error: " + Err + "\n"; else break; + paramCnt ++; + } +// HTTPOut += "See '/help' for details\n"; + } + } + + } else { + + // standart output + + if ( quiet > 1 && HTTPOut == "" ) { + + if ( JSONon ){ + + HTTPOut = "{"; + HTTPOut += "\"MAC\":\"" + String( WiFi.macAddress() ) + "\",\n"; + HTTPOut += "\"Host\":\"" + String( host ) + "\",\n"; + HTTPOut += "\"Timestamp\":\"" + String( timeClient.getEpochTime() ) + "\",\n"; + HTTPOut += "\"Target_timestamp\":\"" + String( timeStamp ) + "\",\n"; + + HTTPOut += "\"TNumber_of_LEDs\":\"" + String( numberOfLEDs ) + "\",\n"; + + HTTPOut += "\"SlideX:\":\"" + String( (int)roundf( FX_ArrNew[ PHASE_X_INC ] ) ) + "\",\n"; + HTTPOut += "\"SlideY:\":\"" + String( (int)roundf( FX_ArrNew[ PHASE_Y_INC ] ) ) + "\",\n"; + HTTPOut += "\"SlideZ:\":\"" + String( (int)roundf( FX_ArrNew[ PHASE_Z_INC ] ) ) + "\",\n"; + + HTTPOut += "\"Period:\":\"" + String( (int)roundf( FX_ArrNew[ PERIOD ] ) ) + "\",\n"; + HTTPOut += "\"Delay:\":\"" + String( mainDelayNew ) + "\",\n"; + + HTTPOut += "\"Gradient_HSV:\":\""; + + for ( uint8_t a = 0; a < 6 ; a++ ) HTTPOut += String( printNum( FX_ArrNew[ a ], 16, ' ') ); + + HTTPOut += "\",\n"; + + HTTPOut += "}"; + + } else { + + HTTPOut = "MAC:" + String( WiFi.macAddress() ) + "\n"; + HTTPOut += "Host:" + String( host ) + "\n"; + HTTPOut += "Timestamp:" + String( timeClient.getEpochTime() ) + "\n"; + HTTPOut += "Target timestamp:" + String( timeStamp ) + "\n"; + + HTTPOut += "Number of LEDs:" + String( numberOfLEDs ) + "\n"; + + HTTPOut += "Slide X:" + String( (int)roundf( FX_ArrNew[ PHASE_X_INC ] ) ) + "\n"; + HTTPOut += "Slide Y:" + String( (int)roundf( FX_ArrNew[ PHASE_Y_INC ] ) ) + "\n"; + HTTPOut += "Slide Z:" + String( (int)roundf( FX_ArrNew[ PHASE_Z_INC ] ) ) + "\n"; + + HTTPOut += "Period:" + String( (int)roundf( FX_ArrNew[ PERIOD ] ) ) + "\n"; + HTTPOut += "Delay:" + String( mainDelayNew ) + "\n"; + + HTTPOut += "Gradient (HSV):"; + + for ( uint8_t a = 0; a < 6 ; a++ ) HTTPOut += String( printNum( roundf( FX_ArrNew[ a ] ), 16, ' ') ) + " "; + + HTTPOut += "\n"; + + } + } + } + + server.send(200, "text/plain", HTTPOut ); + + HTTPOut = ""; + HTTPErr = ""; + JSONon = 0; + + }); + + // ui interface TODO xml inteface + + server.on("/ui", HTTP_GET, []() { + HTTPOut = "User interface. Not yet implemented.\n"; + server.send(200, "text/plain", HTTPOut); + }); + + // help + + server.on("/help", HTTP_GET, []() { + + HTTPOut = "Interplay Medium ESP8266 Serial LED Controller. Version: " + String(VERSION) + "\n"; + HTTPOut += "Created by Dmitry Shalnov (c) 2017. License GPLv3+: GNU GPL version 3 or later . \n\n"; + + HTTPOut += "Parameters:\n"; + + HTTPOut += " ?number= Number of LEDs in stripe (max MAX_NUM_LEDS)\n"; + HTTPOut += " ?gradient= Start and end colors of gradient (hex, 24bit/color in HLS format, e.g. 001122FFEECC)\n"; + HTTPOut += " ?period= Sine period (number of leds)\n"; + HTTPOut += " ?delay= Delay of state changing, integer\n"; + + HTTPOut += " ?slidex= Step of X shift per cycle, signed integer\n"; + HTTPOut += " ?slidey= Step of Y shift per cycle, signed integer\n"; + HTTPOut += " ?slidez= Step of Z shift per cycle, signed integer\n"; + + HTTPOut += " ?time= Target timestamp (when the changes will take effect, good for synch), decimal UNIX Timestamp\n\n"; + + HTTPOut += " ?host= Rename the unit\n"; + HTTPOut += " ?quiet= Level of output (0/empty = no output, 1 = OK/Error)\n\n"; + + HTTPOut += "Commands:\n"; + + HTTPOut += " ?save Save current settings\n"; + HTTPOut += " ?reset Reset to initial settings\n"; + HTTPOut += " ?reboot Reboot unit\n"; + + HTTPOut += " \n"; + HTTPOut += " /ui Output in XML UI format\n"; + HTTPOut += " /json Output in JSON format\n"; + HTTPOut += " /update Wireless update of firmware (see example below)\n"; + HTTPOut += " /help This help\n\n"; + + HTTPOut += "Usage: curl " + String(host) + "?=\n"; + HTTPOut += " curl " + String(host) + "/\n"; + HTTPOut += "Examples: curl \"" + String(host) + "?gradient=ffffffddff00&period=30\" \n"; + HTTPOut += " curl -F image=@firmware.bin " + String(host) + "/update \n"; + + server.sendHeader("Connection", "close"); + server.send( 200, "text/plain", HTTPOut ); + + }); + + // firmware update + + server.on("/update", HTTP_POST, []() { + + server.sendHeader("Connection", "close"); + server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK"); + + ESP.restart(); + + }, []() { + + HTTPUpload& upload = server.upload(); + + if (upload.status == UPLOAD_FILE_START) { + +#if SERIAL == 1 + Serial.setDebugOutput(true); +#endif + WiFiUDP::stopAll(); + +#if SERIAL == 1 + Serial.printf("Update: %s\n", upload.filename.c_str()); +#endif + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + + if (!Update.begin(maxSketchSpace)) { //start with max available size +#if SERIAL == 1 + Update.printError(Serial); +#endif + } + } else if (upload.status == UPLOAD_FILE_WRITE) { + if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { +#if SERIAL == 1 + Update.printError(Serial); +#endif + } + } else if (upload.status == UPLOAD_FILE_END) { + if (Update.end(true)) { //true to set the size to the current progress + + server.sendHeader("Connection", "close"); + server.send_P(200, "text/plain", PSTR("Success. Please wait until device replace firmware and boot up...\n") ); +#if SERIAL == 1 + Serial.printf("Update Success: %u\nRebooting....\n", upload.totalSize); +#endif + } else { + server.sendHeader("Connection", "close"); + server.send_P(200, "text/plain", PSTR("Something went wrong. Please reset device and try again.\n") ); +#if SERIAL == 1 + Update.printError(Serial); +#endif + } +#if SERIAL == 1 + Serial.setDebugOutput(false); +#endif + } + + yield(); + }); + + } else { +#if SERIAL == 1 + Serial.println("WiFi Failed"); +#endif + } +} + +// ----------------------------------------------------- +// ------------------- MAIN ---------------------------- +// ----------------------------------------------------- + +// uint8_t rebootColorsCnt = 0; + +void loop(void) { + + server.handleClient(); + MDNS.update(); + + // reconnect + + if ( WiFi.status() != WL_CONNECTED ) { +#if SERIAL == 1 + Serial.printf("."); +#endif + if (WiFi.waitForConnectResult() == WL_CONNECTED) { +#if SERIAL == 1 + Serial.println("Reconnected"); +#endif + MDNS.begin( host ); + + timeClient.begin(); + timeClient.update(); + } + + } + + if ( changeColor ) { + + // set float coefficents + + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) { + FX_Coeff[ H_GRAD_BEG + a ] = (float)FX_ArrNew[ H_GRAD_BEG + a ] - FX_Arr[ H_GRAD_BEG + a ]; + if ( abs( FX_Coeff[ H_GRAD_BEG + a ] ) > FX_CoeffMax ) FX_CoeffMax = abs( FX_Coeff[ H_GRAD_BEG + a ] ); + } + + for ( uint8_t a = 0; a < 6; a++ ) FX_Coeff[ H_GRAD_BEG + a ] = FX_Coeff[ H_GRAD_BEG + a ] / FX_CoeffMax; + + changeColor = false; + +#if SERIAL == 1 + Serial.printf("FX_ArrNew: "); + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) Serial.printf("%f ", FX_ArrNew[ a ] ); + Serial.printf("\n"); + Serial.printf("FX_Coeff: "); + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) Serial.printf("%f ", FX_Coeff[ a ] ); + Serial.printf("\n"); +#endif + + } else { + + if ( ++mainDelay == mainDelayNew /* && FX_Delay != 0 */ ) { + +#if SERIAL == 1 +// Serial.printf("FX_Arr: "); +// for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) Serial.printf("%f ", FX_Arr[ a ] ); +// Serial.printf("\n"); +// Serial.printf("Phase: %f %f %f\n", Phase[ PHASE_X ], Phase[ PHASE_Y ], Phase[ PHASE_Z ] ); +#endif + + mainDelay = 0; + + // fade out and reboot + + if ( commandReboot && roundf( FX_Arr[ V_GRAD_BEG ] ) == 0 && roundf( FX_Arr[ V_GRAD_END ]) == 0 ) { + commandReboot = false; +#if SERIAL == 1 + Serial.printf("Reboot......\n"); +#endif + ESP.restart(); +// Serial.printf("Reboot.2...\n"); + } + + if ( timeClient.getEpochTime() > timeStamp ) { + + // change color + + for ( uint8_t a = 0; a < NUMBER_OF_PARAM; a++ ) { + if ( FX_ArrNew [ a ] != roundf( FX_Arr[ a ] ) ) { FX_Arr[ a ] += FX_Coeff[ a ]; } else FX_Arr[ a ] = (float)FX_ArrNew [ a ]; + } + + // change phase + + for ( uint8_t a = 0; a < 3; a++ ) { + + if ( FX_Arr[ PHASE_X_INC + a ] == 0 ) { + // shift phase to 0 after slide. = 0 + if ( (uint8_t)round( Phase[ a ] ) != 0 ) Phase[ a ] -= FX_Coeff[ PHASE_X_INC + a ]/100; else Phase[ a ] = 0; + } else { + // routine shift phase + Phase[ a ] += FX_Arr[ PHASE_X_INC + a ]/100; + } + } + + } + + if ( FX_Arr[ PERIOD ] == 0 ) FX_Arr[ PERIOD ] = 1; + + FX_Gradient_RT( roundf( FX_Arr[ H_GRAD_BEG ] ), roundf( FX_Arr[ S_GRAD_BEG ] ), roundf( FX_Arr[ V_GRAD_BEG ] ), roundf( FX_Arr[ H_GRAD_END ] ), roundf( FX_Arr[ S_GRAD_END ] ), roundf( FX_Arr[ V_GRAD_END ] ), roundf( FX_Arr[ PERIOD ] ), roundf( Phase[ PHASE_X ] ), roundf( Phase[ PHASE_Y ] ), roundf( Phase[ PHASE_Z ] ) ); + FastLED.show(); + delay(3); + + } + } +} diff --git a/Serial_RGB/version.c b/Serial_RGB/version.c new file mode 100644 index 0000000..1438826 --- /dev/null +++ b/Serial_RGB/version.c @@ -0,0 +1 @@ +#define VERSION "10.05.24" diff --git a/bidirectonal-mosfet-level-shifter.png b/bidirectonal-mosfet-level-shifter.png new file mode 100644 index 0000000000000000000000000000000000000000..469ace347744500392f3e600e5865e03be9da0dd GIT binary patch literal 14297 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 [upload]" + exit 0 +fi + +# assign WIFI_SSID and WIFI_PASS in external file ../info +# source "../info" + +SKETCH="$1/$1.ino" + +TMP="/tmp/ESPcompile.tmp" + +# MAKE_FILE="/home/dmitry/Bin/SDK/ESP/makeEspArduino.21.02.22/makeEspArduino.mk" +MAKE_FILE="/home/dmitry/Bin/SDK/ESP/makeEspArduino/makeEspArduino.mk" +# ESP_SDK_ROOT=/home/dmitry/Bin/SDK/ESP/esp8266 # keep it without quotation marks + +# ESP_SDK_ROOT=~/Bin/SDK/ESP/Arduino +# ESP_SDK_ROOT=~/Bin/SDK/ESP/esp8266_3.1.2 +# ESP_SDK_ROOT=~/Bin/SDK/ESP/esp8266_3.0.2 +ESP_SDK_ROOT=~/Bin/SDK/ESP/esp8266_2.5.0 + + +# LIBS=/home/dmitry/Bin/SDK/ESP/esp8266/libraries +# USER_SRC_PATTERN="version.h" + +DATE=$(date +"%d.%m.%y") +echo "#define VERSION \"$DATE\"" > "$1/version.c" + +# nodemcuv2, generic, esp8285 +make -f "$MAKE_FILE" ESP_ROOT="$ESP_SDK_ROOT" F_CPU=160000000L CHIP=esp8266 BOARD=esp8285 SKETCH="$SKETCH" $2 2>&1 | tee "$TMP" + +if [ -s "$TMP" ]; then + binSRC=$( cat "$TMP" | grep Linking | sed -e 's/Linking //g' ) + cp "$binSRC" . + + serialPort=$(cat "$TMP" | grep "opening port" | awk '{split($0,a," "); print a[3]}') +else + serialPort=/dev/ttyUSB0 +fi + + + + diff --git a/serial b/serial new file mode 100755 index 0000000..679915c --- /dev/null +++ b/serial @@ -0,0 +1,32 @@ +#!/bin/bash + +if [ -s "$TMP" ]; then + binSRC=$( cat "$TMP" | grep Linking | sed -e 's/Linking //g' ) + cp "$binSRC" . + + serialPort=$(cat "$TMP" | grep "opening port" | awk '{split($0,a," "); print a[3]}') +else + serialPort=/dev/ttyUSB0 +fi + +echo "Serial: $serialPort" + + +if cat "$TMP" | grep -q 'error'; then + echo "exit" +else + if [ "$1" != "noserial" ]; then + + echo "Connecting $serialPort" + + stty -F $serialPort cs8 cstopb -ixon raw speed 115200 + + while [ 1 ]; do + cat $serialPort + sleep 1 + done + else + echo "Serial terminal omited" + fi +fi + -- 2.34.1