initial commit

This commit is contained in:
Kevin Matz 2020-12-01 19:40:58 -05:00
commit 6f4c3e3357
11 changed files with 891 additions and 0 deletions

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2020 Kevin Matz
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.

166
README.md Normal file
View File

@ -0,0 +1,166 @@
# WiFlash
Uses a GPIO to control a lighting console over OSC, whilst also controlling an LED strobe light with DMX data received over sACN.
This software is designed for the ESP32, but will probably be usable on other Espressif platforms,
![example](assets/wiflash_schem.png)
## Requirements
* [Arduino IDE](https://www.arduino.cc/en/software)
> Refer to the [Getting Started](https://www.arduino.cc/en/Guide/) page for Installation instructions.
* [Arduino core for ESP32](https://github.com/espressif/arduino-esp32)
> - Start Arduino and open Preferences window.
- Enter `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json` into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas.
- Open Boards Manager from Tools > Board menu and install *esp32* platform (and don't forget to select your ESP32 board from Tools > Board menu after installation).
* [ArduinoOSC](https://github.com/hideakitai/ArduinoOSC) - OSC subscriber / publisher for Arduino
> Install from the Arduino library manager.
* [WiFlash for ESP32](https://git.company235.com/kevin/wiflash)
> - Unzip the downloaded file.
- Open `wiflash_esp32.ino` in Arduino.
- Select your ESP32 board from the Tools > Board menu.
## Configuring
### WiFi
```
// -----------------------------------
// Configure the WiFi network
// -----------------------------------
const char ssid[] = "WiFi NETWORK";
const char pwd[] = "PASSWORD";
```
Change these lines to enter your own SSID and WEP/WPA2 password.
### IPv4
```
// -----------------------------------
// Configure the IPv4 network
// -----------------------------------
const IPAddress ip(127, 0, 0, 1);
const IPAddress gateway(0, 0, 0, 0);
const IPAddress subnet(255, 255, 255, 255);
```
Enter your own IP configuration. **Note the commas** between bytes in the address.
### OSC
```
// -----------------------------------
// Configure OSC
// -----------------------------------
const String host = "2.0.0.1";
const uint16_t port = 7001;
```
Set the value of `host` to be the IP address of the OSC server. Here, **the IP address bytes are separated by a period**.
```
const String pressed_addr = "/hog/playback/go/0";
const String pressed_value = "99.1";
const String released_addr = "/hog/playback/go/0";
const String released_value = "99.2";
```
Change these lines to suit your setup. These examples will send `GOTO LIST 99 CUE 1` when the button is pressed, and `GOTO LIST 99 CUE 2` when the button is released. Check the [Hog 4 OSC mappings](https://www.highend.com/pub/support/controllers/documents/HTML/en/sect-osc_mappings.htm) manual page for additional inspiration.
### E1.31 sACN
```
// -----------------------------------
// Configure E1.31 sACN
// -----------------------------------
Strobe strobe(E131_MULTICAST, 1, 001);
```
Set these 3 arguments to configure sACN.
1. Change this to `E131_MULTICAST` to receive multicast sACN, or `E131_UNICAST` to receive unicast sACN.
1. This is the sACN universe to respond to.
1. Set the DMX start address for the strobe light.
###### Hog4 fixture profile:
[Import from XML](728%20Fixtures%20Wiflash%20rev%200.xml)
#### DMX Mapping
<table>
<thead>
<tr>
<th>Chan</th>
<th>Command</th>
<th>DMX Range</th>
<th>Value Range</th>
<th>Resolution</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Intensity Coarse</td>
<td rowspan=2>0 - 65535</td>
<td rowspan=2>0 - 100%</td>
<td rowspan=2>15 bit<br/>2.4kHz PWM</td>
</tr>
<tr>
<td>2</td>
<td>Intensity Fine</td>
</tr>
<tr>
<td>3</td>
<td>Duration</td>
<td>0 - 255</td>
<td>0.02 - 0.5s</td>
<td>0.004s</td>
</tr>
<tr>
<td>4</td>
<td>Rate</td>
<td>0 - 255</td>
<td>0.5 - 25Hz</td>
<td>0.1Hz</td>
</tr>
</tbody>
</table>
### Hardware
```
/*
* This section to be configured by the Fixtures Dept.
*/
const int button = A0;
const int led = LED_BUILTIN;
```
These values need to match the hardware setup.
## Finishing
Use the upload button in Arduino to compile your changes and upload the software to your ESP32 device.
## Credits
While not the first device of this class to be constructed, this version is credited to:
- Concept & electronics: Phil Abeyta
- System design & firmware: Kevin Matz
## Copying
This Software is released under the MIT License.
Copyright &copy; 2020, Kevin Matz
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.

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<Hog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schema.hogfour.com/Fixture" xsi:schemaLocation="http://schema.hogfour.com/Fixture http://schema.hogfour.com/fixture.xsd">
<Creator name="Hog" version="v3.14.0 (b 3042)"/>
<Library>
<Manufacturer name="User Created">
<Product name="WiFlash">
<Types>
<Type name="WiFlash" revisionid="0" status="User" uuid="e604bef7-3306-11eb-8385-dc85deefb016">
<History revision="0" author="" date="2020-11-30" comment=""/>
<Origin>User</Origin>
<Icon type="circle" size="medium"/>
<Defaults>
<Default function="Strobe" feature="Rate" value="1"/>
<Default function="Strobe Duration" feature="Duration" value="0.50"/>
</Defaults>
<Protocols>
<Protocol name="DMX">
<Dmxfootprint size="4"/>
<Channels>
<Channel number="1">
<AttachedChannels>
<AttachedChannel>2</AttachedChannel>
</AttachedChannels>
<Ranges>
<Range dmxstart="0" dmxend="65535" function="Intensity" feature="Intensity" start="0" end="100"/>
</Ranges>
</Channel>
<Channel number="3">
<Ranges>
<Range dmxstart="0" dmxend="255" function="Strobe Duration" feature="Duration" start="0.02" end="1"/>
</Ranges>
</Channel>
<Channel number="4">
<Ranges>
<Range dmxstart="1" dmxend="255" function="Strobe" feature="Rate" start="0.50" end="25"/>
</Ranges>
</Channel>
</Channels>
</Protocol>
</Protocols>
</Type>
</Types>
</Product>
</Manufacturer>
</Library>
</Hog>

BIN
assets/DMX values.ods Normal file

Binary file not shown.

BIN
assets/wiflash.fzz Normal file

Binary file not shown.

BIN
assets/wiflash_schem.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

132
wiflash_esp32/sacn.cpp Normal file
View File

@ -0,0 +1,132 @@
/*
ESPAsyncE131.cpp
Project: ESPAsyncE131 - Asynchronous E.131 (sACN) library for Arduino ESP8266 and ESP32
Copyright (c) 2019 Shelby Merrick
http://www.forkineye.com
This program is provided free for you to use in any way that you wish,
subject to the laws and regulations where you are using it. Due diligence
is strongly suggested before using this code. Please give credit where due.
The Author makes no warranty of any kind, express or implied, with regard
to this program or the documentation contained in this document. The
Author shall not be liable in any event for incidental or consequential
damages in connection with, or arising out of, the furnishing, performance
or use of these programs.
*/
#include <Arduino.h>
#include <WiFi.h>
#include "sacn.h"
// E1.17 ACN Packet Identifier
const uint8_t ESPAsyncE131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
ESPAsyncE131::ESPAsyncE131(uint8_t buffers) {
stats.num_packets = 0;
stats.packet_errors = 0;
_handler = NULL;
}
bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe) {
bool success = false;
if (type == E131_UNICAST)
success = initUnicast();
if (type == E131_MULTICAST)
success = initMulticast(universe);
return success;
}
bool ESPAsyncE131::initUnicast() {
bool success = false;
if (udp.listen(E131_DEFAULT_PORT)) {
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
std::placeholders::_1));
success = true;
}
return success;
}
bool ESPAsyncE131::initMulticast(uint16_t universe) {
bool success = false;
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
((universe >> 0) & 0xff));
if (udp.listenMulticast(address, E131_DEFAULT_PORT)) {
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
std::placeholders::_1));
success = true;
}
return success;
}
void ESPAsyncE131::parsePacket(AsyncUDPPacket _packet) {
e131_error_t error = ERROR_NONE;
sbuff = reinterpret_cast<e131_packet_t *>(_packet.data());
if (memcmp(sbuff->acn_id, ESPAsyncE131::ACN_ID, sizeof(sbuff->acn_id)))
error = ERROR_ACN_ID;
else if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
error = ERROR_VECTOR_ROOT;
else if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
error = ERROR_VECTOR_FRAME;
else if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
error = ERROR_VECTOR_DMP;
else if (sbuff->property_values[0] != 0)
error = ERROR_IGNORE;
if (error == ERROR_NONE) {
stats.num_packets++;
stats.last_clientIP = _packet.remoteIP();
stats.last_clientPort = _packet.remotePort();
stats.last_seen = millis();
if (_handler) {
_handler(sbuff);
}
} else if (error == ERROR_IGNORE) {
// Do nothing
} else {
if (Serial)
dumpError(sbuff, error);
stats.packet_errors++;
}
}
void ESPAsyncE131::dumpError(e131_packet_t *packet, e131_error_t error) {
switch (error) {
case ERROR_ACN_ID:
Serial.print(F("INVALID PACKET ID: "));
for (uint i = 0; i < sizeof(ACN_ID); i++)
Serial.print(packet->acn_id[i], HEX);
Serial.println("");
break;
case ERROR_PACKET_SIZE:
Serial.println(F("INVALID PACKET SIZE: "));
break;
case ERROR_VECTOR_ROOT:
Serial.print(F("INVALID ROOT VECTOR: 0x"));
Serial.println(htonl(packet->root_vector), HEX);
break;
case ERROR_VECTOR_FRAME:
Serial.print(F("INVALID FRAME VECTOR: 0x"));
Serial.println(htonl(packet->frame_vector), HEX);
break;
case ERROR_VECTOR_DMP:
Serial.print(F("INVALID DMP VECTOR: 0x"));
Serial.println(packet->dmp_vector, HEX);
case ERROR_NONE:
break;
case ERROR_IGNORE:
break;
}
}
void ESPAsyncE131::onPacket(E131PacketHandlerFunction callback)
{
_handler = callback;
}

147
wiflash_esp32/sacn.h Normal file
View File

@ -0,0 +1,147 @@
/*
ESPAsyncE131.h
Project: ESPAsyncE131 - Asynchronous E.131 (sACN) library for Arduino ESP8266 and ESP32
Copyright (c) 2019 Shelby Merrick
http://www.forkineye.com
This program is provided free for you to use in any way that you wish,
subject to the laws and regulations where you are using it. Due diligence
is strongly suggested before using this code. Please give credit where due.
The Author makes no warranty of any kind, express or implied, with regard
to this program or the documentation contained in this document. The
Author shall not be liable in any event for incidental or consequential
damages in connection with, or arising out of, the furnishing, performance
or use of these programs.
*/
#ifndef ESPASYNCE131_H_
#define ESPASYNCE131_H_
#include <AsyncUDP.h>
// Defaults
#define E131_DEFAULT_PORT 5568
// E1.31 Packet Offsets
#define E131_ROOT_PREAMBLE_SIZE 0
#define E131_ROOT_POSTAMBLE_SIZE 2
#define E131_ROOT_ID 4
#define E131_ROOT_FLENGTH 16
#define E131_ROOT_VECTOR 18
#define E131_ROOT_CID 22
#define E131_FRAME_FLENGTH 38
#define E131_FRAME_VECTOR 40
#define E131_FRAME_SOURCE 44
#define E131_FRAME_PRIORITY 108
#define E131_FRAME_RESERVED 109
#define E131_FRAME_SEQ 111
#define E131_FRAME_OPT 112
#define E131_FRAME_UNIVERSE 113
#define E131_DMP_FLENGTH 115
#define E131_DMP_VECTOR 117
#define E131_DMP_TYPE 118
#define E131_DMP_ADDR_FIRST 119
#define E131_DMP_ADDR_INC 121
#define E131_DMP_COUNT 123
#define E131_DMP_DATA 125
// E1.31 Packet Structure
typedef union {
struct {
// Root Layer
uint16_t preamble_size;
uint16_t postamble_size;
uint8_t acn_id[12];
uint16_t root_flength;
uint32_t root_vector;
uint8_t cid[16];
// Frame Layer
uint16_t frame_flength;
uint32_t frame_vector;
uint8_t source_name[64];
uint8_t priority;
uint16_t reserved;
uint8_t sequence_number;
uint8_t options;
uint16_t universe;
// DMP Layer
uint16_t dmp_flength;
uint8_t dmp_vector;
uint8_t type;
uint16_t first_address;
uint16_t address_increment;
uint16_t property_value_count;
uint8_t property_values[513];
} __attribute__((packed));
uint8_t raw[638];
} e131_packet_t;
// Error Types
typedef enum {
ERROR_NONE,
ERROR_IGNORE,
ERROR_ACN_ID,
ERROR_PACKET_SIZE,
ERROR_VECTOR_ROOT,
ERROR_VECTOR_FRAME,
ERROR_VECTOR_DMP
} e131_error_t;
// E1.31 Listener Types
typedef enum {
E131_UNICAST,
E131_MULTICAST
} e131_listen_t;
// Status structure
typedef struct {
uint32_t num_packets;
uint32_t packet_errors;
IPAddress last_clientIP;
uint16_t last_clientPort;
unsigned long last_seen;
} e131_stats_t;
typedef std::function<void(e131_packet_t *packet)> E131PacketHandlerFunction;
class ESPAsyncE131 {
public:
ESPAsyncE131(uint8_t buffers = 1);
void onPacket(E131PacketHandlerFunction callback);
bool begin(e131_listen_t type, uint16_t universe = 1);
static void dumpError(e131_packet_t *packet, e131_error_t error);
e131_stats_t stats; // Statistics tracker
protected:
E131PacketHandlerFunction _handler;
private:
// Constants for packet validation
static const uint8_t ACN_ID[];
static const uint32_t VECTOR_ROOT = 4;
static const uint32_t VECTOR_FRAME = 2;
static const uint8_t VECTOR_DMP = 2;
e131_packet_t *sbuff; // Pointer to scratch packet buffer
AsyncUDP udp; // AsyncUDP
// Internal Initializers
bool initUnicast();
bool initMulticast(uint16_t universe);
// UDP packet parser callback
void parsePacket(AsyncUDPPacket _packet);
};
#endif // ESPASYNCE131_H_

View File

@ -0,0 +1,153 @@
/*
strobe_esp32.cpp
Part of WiFlash_esp32
Copyright (c) 2020 Kevin Matz (kevin.matz@gmail.com)
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 <Arduino.h>
#include "strobe_esp32.h"
/*
calculate period from DMX value
*/
uint32_t hz_to_micros(uint8_t dmx) {
if (dmx == 0) {
return 0;
}
// ( millis / ( percent * scalor ) + offset ) * micros
return (1000 / (((dmx / 255.0) * 24.5) + 0.5)) * 1000;
}
/*
calculate duration from DMX value
*/
uint32_t dr_to_micros(uint8_t dmx) {
// (( percent * scalor) + offset) * micros
return (((dmx / 255.0) * .5 ) + .01 ) * 1000 * 1000;
}
/*
Constructor
*/
Strobe::Strobe(e131_listen_t type, uint16_t universe, uint16_t address) {
m_type = type;
m_universe = universe;
m_address = address;
m_e131 = new ESPAsyncE131(1);
m_e131->onPacket(std::bind(&Strobe::recvData, this,
std::placeholders::_1));
}
/*
call durring setup()
*/
bool Strobe::begin(uint8_t pin, uint8_t pwm) {
bool success = false;
// set state
m_pwm = pwm;
m_state = STROBE_INACTIVE;
m_level = 0;
// configure hardware
ledcAttachPin(pin, m_pwm); // Attach GPIO to PWM timer
ledcSetup(m_pwm, 2400, 15); // 2.4KHz PWM, 15 bit resolutio
ledcWrite(m_pwm, m_level); // LED to 0%
// start sACN
if (!m_e131->begin(m_type, m_universe)) {
Serial.println("Failed to start E1.31");
} else {
Serial.println("Listening for sACN");
success = true;
}
return success;
}
void Strobe::update(void * args) {
// stop stobing on sACN loss of signal
// if (millis() - m_e131->stats.last_seen > 10000) {
// Serial.println("No Signal!");
// m_int = 0;
// }
// intensity changes start/stop the cycle
if (m_int == 0) {
// intensity off breaks the cycle
m_state = STROBE_INACTIVE;
} else {
if (m_state == STROBE_INACTIVE) {
// going active
m_state = STROBE_ACTIVE_ON;
}
}
// time based cycle changes
if (m_state == STROBE_ACTIVE_ON ||
m_state == STROBE_ACTIVE_OFF) {
uint32_t now, elapsed, period, durr;
now = micros();
elapsed = now - m_time;
period = hz_to_micros(m_rat);
durr = dr_to_micros(m_dur);
if (elapsed > period || // hz period completed
now < m_time) { // micros() wraps 32 bits every ~70 min.
// cycle restarts
m_state = STROBE_ACTIVE_ON;
m_time = now;
} else if (elapsed > durr) { // durration period completed
// cycle enters dark phase
m_state = STROBE_ACTIVE_OFF;
}
}
// set LED output
if (m_state == STROBE_ACTIVE_ON) {
setLevel(m_int);
} else {
setLevel(0);
}
}
/*
Write a 15bit level to PWM
*/
void Strobe::setLevel(uint16_t level) {
if (level != m_level) {
m_level = level;
ledcWrite(m_pwm, ((m_level >> 1) & 0xffff)); // write at 15 bit PWM
}
}
void Strobe::recvData(e131_packet_t *packet) {
//Serial.println(m_e131->stats.num_packets);
m_int = packet->property_values[m_address + 0] << 8 |
packet->property_values[m_address + 1];
m_dur = packet->property_values[m_address + 2];
m_rat = packet->property_values[m_address + 3];
}

View File

@ -0,0 +1,75 @@
/*
strobe_esp32.h
Part of WiFlash_esp32
Copyright (c) 2020 Kevin Matz (kevin.matz@gmail.com)
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.
*/
#ifndef STROBE_ESP32_H_
#define STROBE_ESP32_H_
#include "sacn.h"
inline uint32_t hz_to_micros(uint8_t dmx) __attribute__((always_inline));
inline uint32_t dr_to_micros(uint8_t dmx) __attribute__((always_inline));
typedef enum {
STROBE_INACTIVE,
STROBE_ACTIVE_ON,
STROBE_ACTIVE_OFF
} strState;
class Strobe {
public:
Strobe(e131_listen_t type, uint16_t universe = 1, uint16_t address = 1);
bool begin(uint8_t pin, uint8_t pwm); // call in setup()
void update(void *args = NULL); // update task
const uint8_t profile = 4; // DMX profile length
private:
e131_listen_t m_type; // IP Unicast/Multicast
uint16_t m_universe; // sACN universe
uint16_t m_address; // DMX address
uint16_t m_int; // state machine intensity
uint8_t m_dur; // state machine durration
uint8_t m_rat; // state machine rate
strState m_state; // state machine cycle state
uint16_t m_level; // state machine LED level
uint8_t m_pwm; // LEDc PWM channel
uint32_t m_time; // micros() of current cycle start
ESPAsyncE131 *m_e131; // ESPAsyncE131 instance
void recvData(e131_packet_t *packet); // data recieved callback
inline void setLevel(uint16_t level) __attribute__((always_inline));
};
#endif // STROBE_ESP32_H_

View File

@ -0,0 +1,153 @@
/*
WiFlash_esp32 - Concept & electronics: Phil Abeyta
- System design & firmware: Kevin Matz
Uses a GPIO to control a lighting console over OSC, whilst also
controlling an LED strobe light with DMX data recieved over sACN.
Copyright (c) 2020 Kevin Matz (kevin.matz@gmail.com)
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 <WiFi.h>
#include "sacn.h"
#include <ArduinoOSC.h>
#include "strobe_esp32.h"
/*
* This section to be configured by Lighting Control
*/
// -----------------------------------
// Configure the WiFi network
// -----------------------------------
const char ssid[] = "........";
const char pwd[] = "........";
// -----------------------------------
// Configure the IPv4 network
// -----------------------------------
const IPAddress ip(127, 0, 0, 1);
const IPAddress subnet(255, 255, 255, 0);
const IPAddress gateway(127, 0, 0, 1);
// -----------------------------------
// Configure OSC
// -----------------------------------
const String host = "127.0.0.1";
const uint16_t port = 7001;
const String pressed_addr = "/hog/playback/go/0";
const String pressed_value = "99.1";
const String released_addr = "/hog/playback/go/0";
const String released_value = "99.2";
// -----------------------------------
// Configure E1.31 sACN
// -----------------------------------
Strobe strobe(E131_UNICAST, 1, 001); // (uni|multi)cast, sACN Universe, Address
/* DMX Value
* | chan | Command | range | range |
* |------+-----------+-------+------------|
* | 1 | Intensity | 0- | 0-100% | 15 bit 2.4kHz PWM
* | 2 | fine | 65535 | |
* |------+-----------+-------+------------|
* | 3 | Duration | 0-255 | 0.02-0.5s | 0.002s resolution
* |------+-----------+-------+------------|
* | 4 | Rate | 0-255 | 0.5-25hz | 0.1 hz resolution
* |------+-----------+-------+------------|
*/
/*
* This section to be configured by the Fixtures Dept.
*/
const int button = A0; // A0, use 100nF to ground
const int led = LED_BUILTIN; // IO13
/*
* Change nothing else unless you're really sure.
*/
//// Global button variables
bool pressed = false; // track button state
uint32_t change_time; // time of button press (ms)
/*
* Arduino powerup
*/
void setup() {
Serial.begin(115200);
//// start WiFi:
// set IPv4
WiFi.mode(WIFI_STA);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, pwd);
// join 802.11
if (WiFi.config(ip, gateway, subnet)) {
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address is ");
Serial.println(WiFi.localIP());
} else {
Serial.println("STA Failed to configure");
}
//// start fixtures hardware:
// button
pinMode(button, INPUT_PULLUP);
// led_trigPres_trigPress _trigPress _trigPress _trigPress s
if (!strobe.begin(led, 0)) {
Serial.println("Strobe failed to configure.");
}
}
/*
* Arduino process loop
*/
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Waiting for WiFi...");
delay(1000);
return;
}
strobe.update();
// Be a remote trigger
//
bool val = !digitalRead(button);
if (val != pressed) {
pressed = val;
change_time = millis();
if (pressed) {
Serial.println("Pressed");
OscWiFi.send(host, port, pressed_addr, pressed_value);
} else {
Serial.println("Released");
OscWiFi.send(host, port, released_addr, released_value);
}
}
}