Skip to content

Commit faf4234

Browse files
authored
Merge pull request #91 from limpkin/main
moving pin high and low out of the define, handling low level rs485
2 parents 60df77d + f9dc619 commit faf4234

File tree

7 files changed

+161
-17
lines changed

7 files changed

+161
-17
lines changed

docs/moonbase/inputoutput.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ For each board the following presets are defined:
3333
* Button LightsOn 🛎️/𓐟: sets on/off in [Light Control](../../moonlight/lightscontrol/), Push (🛎️) and Toggle (𓐟)
3434
* Relay LightsOn 🔀: sets on/off in [Light Control](../../moonlight/lightscontrol/)
3535
* SPI_SCK, SPI_MISO, SPI_MOSI, PHY_CS, PHY_IRQ 🔗: S3 Ethernet, Used by the Ethernet module, see [Ethernet](../../network/ethernet/)
36+
* High / Low: to indefinitely set high or low a GPIO pin
37+
* RS-485 DE/TX/RX: when all set, for upcoming DMX and RS485 communications
3638
* Planned soon
3739
* Battery
38-
* DMX
3940
* Planned later
4041
* I2S for microphone and line in
4142
* I2C
@@ -86,7 +87,16 @@ For each board the following presets are defined:
8687

8788
### SE16 v1
8889

89-
![SE-16p](../firmware/installer/images/esp32-s3-stephanelec-16p.jpg){: style="width:100px"}
90+
![SE-16p](../firmware/installer/images/esp32-s3-stephanelec-16p.jpg)
9091

9192
* Choose the esp32-s3-devkitc-1-n8r8v board in the [MoonLight Installer](../../gettingstarted/installer/)
92-
* Set Switch1 the same as you set the jumper on the board: off / default: Infrared. on: Ethernet.
93+
* Set Switch1 the same as you set the jumper on the board: off / default: Infrared. on: Ethernet.
94+
* Only 5 boards were ever produced. If you are one of the lucky few, feel free to reach out to limpkin on [Discord](https://discord.gg/TC8NSUSCdV)
95+
96+
97+
### LightCrafter16
98+
99+
![SE-16p](../firmware/installer/images/esp32-s3-lightcrafter16.jpg)
100+
101+
* Choose the esp32-s3-devkitc-1-n8r8v board in the [MoonLight Installer](../../gettingstarted/installer/)
102+
* Documentation to be soon published on [limpkin's website](https://www.limpkin.fr)

docs/moonlight/layouts.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Want to add a a Layout to MoonLight, see [develop](https://moonmodules.org/MoonL
2626
| Single Line | ![Single line](https://github.com/user-attachments/assets/4ba5a3ac-9312-4bac-876d-cfa3dce41215) | <img width="320" alt="Single line" src="https://github.com/user-attachments/assets/70455279-646c-467d-b8e5-492b1aeae0fa" /> | |
2727
| Single Row | ![Single row](https://github.com/user-attachments/assets/a88cea0f-9227-4da4-9a43-b944fd8bef97) | <img width="320" alt="Single row" src="https://github.com/user-attachments/assets/9f9918b9-e1ee-43a8-a02d-7f1ee182888b" /> | |
2828
| SE16 | ![SE16](https://github.com/user-attachments/assets/45c7bec7-2386-4c42-8f24-5a57b87f0df9) | <img width="320" alt="SE16" src="https://github.com/user-attachments/assets/0efe941a-acf5-4a2c-a7d6-bdfa91574d1a" /> | Layout(s) including pins for Stephan Electronics 16-Pin ESP32-S3 board<br>see below |
29+
| LightCrafter16 | ![LightCrafter16](https://github.com/user-attachments/assets/45c7bec7-2386-4c42-8f24-5a57b87f0df9) | <img width="320" alt="LightCrafter16" src="https://github.com/user-attachments/assets/0efe941a-acf5-4a2c-a7d6-bdfa91574d1a" /> | Layout(s) for Stephan Electronics LightCrafter16 ESP32-S3 board<br>see below |
2930

3031
!!! warning "Choosing pins"
3132

@@ -36,11 +37,21 @@ Want to add a a Layout to MoonLight, see [develop](https://moonmodules.org/MoonL
3637

3738
### SE16
3839

39-
16 channel LED strip driver by Stephane Electronics
40+
16-channel LED strip driver by Stephan Electronics
4041

41-
<img width="320" alt="SE16" src="/firmware/installer/images/esp32-s3-stephanelec-16p.jpg"/>
42+
![SE-16p](../firmware/installer/images/esp32-s3-stephanelec-16p.jpg)
4243

4344
* Leds Per Pin: the number of LEDs connected to each pin
4445
* Pins Are Columns: are the LEDs on a pin a row of the effect (width is 1 (or 2) x ledsPerPin). If not set the LEDs are a column (height is 1 (or 2) x ledsPerPin)
4546
* Mirrored Pins: If set it is assumed that LEDs are connected with increasing positions on 8 pins on one side of the board and decreasing positions on the 8 pins of the other side of the board. The resulting size will have a width of 8 and the height (or width) will be 2 * ledsPerPin. If not set, the width will be 16 and the height (or width) = ledsPerPin
46-
* Pins: 47,48,21,38,14,39,13,40,12,41,11,42,10,2,3,1
47+
48+
### LightCrafter16
49+
50+
16-channel LED strip driver by Stephan Electronics
51+
52+
![SE-16p](../firmware/installer/images/esp32-s3-lightcrafter16.jpg)
53+
54+
* Leds Per Pin: the number of LEDs connected to each pin
55+
* Pins Are Columns: are the LEDs on a pin a row of the effect (width is 1 (or 2) x ledsPerPin). If not set the LEDs are a column (height is 1 (or 2) x ledsPerPin)
56+
57+
X0Y0 position is on the top left when the board is positioned in such a way that the Ethernet connector is on the top left.
62.4 KB
Loading
-69.5 KB
Loading

src/MoonBase/Modules/ModuleIO.h

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#if FT_MOONBASE == 1
1616

1717
#include "MoonBase/Module.h"
18+
#include "driver/uart.h"
1819

1920
enum IO_PinUsageEnum {
2021
pin_Unused, // 0
@@ -80,7 +81,7 @@ enum IO_BoardsEnum {
8081
board_SergUniShieldV5,
8182
board_SergMiniShield,
8283
board_SE16V1,
83-
board_SE16V2,
84+
board_LightCrafter16,
8485
board_MHCV43, // by Wladi
8586
board_MHCP4NanoV1, // by Wladi V1.0
8687
board_YvesV48,
@@ -309,15 +310,15 @@ class ModuleIO : public Module {
309310
pinAssigner.assignPin(5, pin_Infrared);
310311
}
311312

312-
} else if (boardID == board_SE16V2) {
313+
} else if (boardID == board_LightCrafter16) {
313314
object["maxPower"] = 500;
314315
uint8_t ledPins[] = {47, 21, 14, 9, 8, 16, 15, 7, 1, 2, 42, 41, 40, 39, 38, 48}; // LED_PINS
315316
for (uint8_t gpio : ledPins) pinAssigner.assignPin(gpio, pin_LED);
316317
pinAssigner.assignPin(3, pin_High); // WIZ850_nRST, needs to be high to access RS485_DE, VBUS_DET, WIZ580_nINT. Also drives an LED.
317318
gpio_set_direction((gpio_num_t)3, GPIO_MODE_OUTPUT); // LEAVE here: guarantees the pin is set to high at platform boot so the ethernet module can initialize correctly
318319
gpio_set_level((gpio_num_t)3, 1); // LEAVE here: guarantees the pin is set to high at platform boot so the ethernet module can initialize correctly
319-
pinAssigner.assignPin(17, pin_Serial_TX);
320-
pinAssigner.assignPin(18, pin_Serial_RX);
320+
pinAssigner.assignPin(17, pin_RS485_TX);
321+
pinAssigner.assignPin(18, pin_RS485_RX);
321322
pinAssigner.assignPin(46, pin_RS485_DE);
322323
pinAssigner.assignPin(0, pin_Dig_Input); // Native USB port vbus detection
323324
pinAssigner.assignPin(5, pin_Voltage); // Input voltage
@@ -602,7 +603,12 @@ class ModuleIO : public Module {
602603
}
603604
}
604605

606+
605607
void readPins() {
608+
uint8_t pinRS485TX = UINT8_MAX;
609+
uint8_t pinRS485RX = UINT8_MAX;
610+
uint8_t pinRS485DE = UINT8_MAX;
611+
606612
#if FT_ENABLED(FT_ETHERNET)
607613
EXT_LOGD(MB_TAG, "Try to configure ethernet");
608614
EthernetSettingsService* ess = _sveltekit->getEthernetSettingsService();
@@ -664,7 +670,15 @@ class ModuleIO : public Module {
664670
} else if (usage == pin_Battery) {
665671
pinBattery = pinObject["GPIO"];
666672
EXT_LOGD(ML_TAG, "pinBattery found %d", pinBattery);
667-
} else if (usage == pin_High) {
673+
}
674+
}
675+
#endif
676+
677+
// GPIOs & RS485
678+
bool rs485_ios_updated = false;
679+
for (JsonObject pinObject : _state.data["pins"].as<JsonArray>()) {
680+
uint8_t usage = pinObject["usage"];
681+
if (usage == pin_High) {
668682
uint8_t pinHigh = pinObject["GPIO"];
669683
if (GPIO_IS_VALID_OUTPUT_GPIO(pinHigh)) {
670684
gpio_set_direction((gpio_num_t)pinHigh, GPIO_MODE_OUTPUT);
@@ -678,9 +692,62 @@ class ModuleIO : public Module {
678692
gpio_set_level((gpio_num_t)pinLow, 0);
679693
}
680694
EXT_LOGD(ML_TAG, "Setting pin %d to low", pinLow);
681-
}
695+
} else if (usage == pin_RS485_DE) {
696+
rs485_ios_updated = true;
697+
pinRS485DE = pinObject["GPIO"];
698+
} else if (usage == pin_RS485_RX) {
699+
rs485_ios_updated = true;
700+
pinRS485RX = pinObject["GPIO"];
701+
} else if (usage == pin_RS485_TX) {
702+
rs485_ios_updated = true;
703+
pinRS485TX = pinObject["GPIO"];
704+
}
705+
}
706+
707+
// Check if all RS485 pins are specified
708+
if (rs485_ios_updated && (pinRS485TX != UINT8_MAX) && (pinRS485RX != UINT8_MAX) && (pinRS485DE != UINT8_MAX)) {
709+
EXT_LOGD(ML_TAG, "RS485 init with pins %d %d %d", pinRS485TX, pinRS485RX, pinRS485DE);
710+
711+
// test code to be replaced with functional code. use UART1 as UART0 is (AFAIK) always for debug serial
712+
uart_config_t uart_config = {
713+
.baud_rate = 9600,
714+
.data_bits = UART_DATA_8_BITS,
715+
.parity = UART_PARITY_DISABLE,
716+
.stop_bits = UART_STOP_BITS_1,
717+
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, // Flow control handled by RS485 driver
718+
.source_clk = UART_SCLK_DEFAULT,
719+
};
720+
uart_driver_delete(UART_NUM_1);
721+
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, 128 * 2, 0, 0, NULL, 0));
722+
ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config));
723+
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, pinRS485TX, pinRS485RX, pinRS485DE, UART_PIN_NO_CHANGE));
724+
ESP_ERROR_CHECK(uart_set_mode(UART_NUM_1, UART_MODE_RS485_HALF_DUPLEX));
725+
726+
#ifdef DEMOCODE_FOR_SHT30_SENSOR
727+
// Modbus RTU Request: [Addr][Func][RegHi][RegLo][CountHi][CountLo][CRC_L][CRC_H]
728+
// To read Reg 0 & 1 from Slave 0x01: 01 03 00 00 00 02 C4 0B
729+
const uint8_t request[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B};
730+
uint8_t response[128];
731+
// Send request
732+
uart_write_bytes(UART_NUM_1, (const char*)request, sizeof(request));
733+
EXT_LOGD(ML_TAG, "Request sent");
734+
735+
// Wait for response (timeout 1 second)
736+
int len = uart_read_bytes(UART_NUM_1, response, 128, pdMS_TO_TICKS(100));
737+
738+
if (len > 8) {
739+
EXT_LOGD(ML_TAG, "Answer received: %d %d %d %d %d %d %d %d %d", response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7], response[8]);
740+
float humidity = ((float)response[3])*256 + (float)response[4];
741+
float temperature = ((float)response[5])*256 +(float)response[6];
742+
EXT_LOGD(ML_TAG, "humidity: %f temperature: %f", humidity/10, temperature/10);
743+
// Process registers here (response[3] to response[6] contain the data)
744+
} else if (len > 0) {
745+
EXT_LOGD(ML_TAG, "Invalid answer length");
746+
} else {
747+
EXT_LOGD(ML_TAG, "No response from sensor");
748+
}
749+
#endif
682750
}
683-
#endif
684751
}
685752

686753
#if FT_BATTERY

src/MoonLight/Modules/ModuleDrivers.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,12 @@ class ModuleDrivers : public NodeManager {
9999
addControlValue(control, getNameAndTags<IRDriver>());
100100
addControlValue(control, getNameAndTags<HUB75Driver>());
101101

102-
// custom
103-
addControlValue(control, getNameAndTags<SE16Layout>());
102+
// board preset specific
103+
_moduleIO->read([&](ModuleState& state) {
104+
uint8_t boardPreset = state.data["boardPreset"];
105+
if (boardPreset == board_SE16V1) addControlValue(control, getNameAndTags<SE16Layout>());
106+
if (boardPreset == board_LightCrafter16) addControlValue(control, getNameAndTags<LightCrafter16Layout>());
107+
});
104108
}
105109

106110
Node* addNode(const uint8_t index, const char* name, const JsonArray& controls) const override {
@@ -128,8 +132,12 @@ class ModuleDrivers : public NodeManager {
128132
if (!node) node = checkAndAlloc<IRDriver>(name);
129133
if (!node) node = checkAndAlloc<HUB75Driver>(name);
130134

131-
// custom
132-
if (!node) node = checkAndAlloc<SE16Layout>(name);
135+
// board preset specific
136+
_moduleIO->read([&](ModuleState& state) {
137+
uint8_t boardPreset = state.data["boardPreset"];
138+
if (!node && boardPreset == board_SE16V1) node = checkAndAlloc<SE16Layout>(name);
139+
if (!node && boardPreset == board_LightCrafter16) node = checkAndAlloc<LightCrafter16Layout>(name);
140+
});
133141

134142
#if FT_LIVESCRIPT
135143
if (!node) {

src/MoonLight/Nodes/Layouts/L_SE16.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,52 @@ class SE16Layout : public Node {
8080
}
8181
};
8282

83+
// LightCrafter16 board
84+
class LightCrafter16Layout : public Node {
85+
public:
86+
static const char* name() { return "LightCrafter16"; }
87+
static uint8_t dim() { return _2D; }
88+
static const char* tags() { return "🚥"; }
89+
90+
bool pinsAreColumns = false;
91+
uint16_t ledsPerPin = 10;
92+
93+
void setup() override {
94+
addControl(pinsAreColumns, "pinsAreColumns", "checkbox");
95+
addControl(ledsPerPin, "ledsPerPin", "number", 1, 2047);
96+
}
97+
98+
void addStrip(uint16_t xposition, uint16_t start_y, uint16_t stop_y) {
99+
bool increasing = start_y < stop_y;
100+
for (int y = start_y; increasing ? (y <= stop_y) : (y >= stop_y); y += increasing ? 1 : -1) {
101+
if (pinsAreColumns)
102+
addLight(Coord3D(xposition, y, 0)); // limpkin
103+
else
104+
addLight(Coord3D(y, xposition, 0)); // ewowi
105+
}
106+
107+
nextPin(); // each strip it's own pin
108+
}
109+
110+
bool hasOnLayout() const override { return true; }
111+
void onLayout() override {
112+
addStrip(0, ledsPerPin - 1, 0);
113+
addStrip(1, ledsPerPin - 1, 0);
114+
addStrip(2, ledsPerPin - 1, 0);
115+
addStrip(3, ledsPerPin - 1, 0);
116+
addStrip(4, ledsPerPin - 1, 0);
117+
addStrip(5, ledsPerPin - 1, 0);
118+
addStrip(6, ledsPerPin - 1, 0);
119+
addStrip(7, ledsPerPin - 1, 0);
120+
addStrip(7, ledsPerPin, 2 * ledsPerPin - 1);
121+
addStrip(6, ledsPerPin, 2 * ledsPerPin - 1);
122+
addStrip(5, ledsPerPin, 2 * ledsPerPin - 1);
123+
addStrip(4, ledsPerPin, 2 * ledsPerPin - 1);
124+
addStrip(3, ledsPerPin, 2 * ledsPerPin - 1);
125+
addStrip(2, ledsPerPin, 2 * ledsPerPin - 1);
126+
addStrip(1, ledsPerPin, 2 * ledsPerPin - 1);
127+
addStrip(0, ledsPerPin, 2 * ledsPerPin - 1);
128+
}
129+
};
130+
83131
#endif // FT_MOONLIGHT

0 commit comments

Comments
 (0)