Skip to content

Commit 24b9724

Browse files
authored
Merge pull request #61 from sidoh/v2.6.0
v2.6.0
2 parents 9c94a7d + 7b108c7 commit 24b9724

14 files changed

Lines changed: 174 additions & 92 deletions

README.md

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ Template-oriented driver for e-paper displays using Arduino. Define a layout wi
1111
- [Setup](#setup)
1212
- [Requirements](#requirements)
1313
- [Quickstart](#quickstart)
14+
- [Hardware Setup](#hardware-setup)
1415
- [Deep Sleep](#deep-sleep)
15-
- [SPI Bus and Pin Selection](#spi-bus-and-pin-selection)
1616
- [Concepts](#concepts)
1717
- [Variables](#variables)
1818
- [Regions](#regions)
@@ -59,42 +59,55 @@ The [examples directory](./examples) has a few sample templates. Here are a few
5959

6060
## Quickstart
6161

62-
1. Connect display to MCU. (see [waveshare site](https://www.waveshare.com/wiki/1.54inch_e-Paper_Module) and **SPI Bus and Pin Selection** below for more information)
62+
1. Connect display to MCU. See [Hardware Setup](#hardware-setup) below for more information.
6363
1. Flash your MCU.
6464
1. Use a pre-compiled binary from the [releases page](https://github.com/sidoh/epaper_templates/releases). **Make sure to select the file starting with `INITIALIZER_`**. You can use [esptool](https://github.com/espressif/esptool) or the [ESP32 flash tool](https://www.espressif.com/en/support/download/other-tools). Example command:
6565
```
6666
esptool.py --chip esp32 --baud 460800 write_flash 0x1000 INITIALIZER_epaper_templates_esp32-v2.3.0.bin
6767
```
6868
2. With PlatformIO: for example `pio run -e esp32 -t upload`. You will need to have [nodejs](https://nodejs.org/en/) installed in order to buidl the web assets.
6969
2. Setup WiFi. A setup AP will appear named `epaper_XXXXXX`. The default password is **waveshare**.
70-
3. Visit the Web UI to configure further.
70+
3. Visit the Web UI to configure further. If you used custom pins, make sure to configure those.
7171
72-
## Deep Sleep
72+
## Hardware Setup
7373
74-
e-paper templates can function in _deep sleep_ mode. When configured, the system will continuously:
74+
Waveshare SPI modules have six total data pins that needs to be mapped onto your ESP32. There are **3x SPI pins** and **3x configurable non-SPI pins** you'll need to connect:
7575
76-
1. Wake from sleep
77-
2. Check if a configurable GPIO pin is set. If it is, stays awake until next reboot
78-
3. Otherwise, stay awake for a configurable period to receive updates and refresh the screen.
79-
4. Put both the ESP32 and the e-paper display into deep sleep mode.
76+
|Pin Name|Description|Default pin|
77+
|-|-|-|
78+
|DIN|SPI MOSI|GPIO 13 (HSPI MOSI)|
79+
|CLK|SPI clock|GPIO 14 (HSPI CLK)|
80+
|CS|SPI chip select|GPIO 15 (HSPI SS)
81+
|DC|Data/Command control pin (configurable)|GPIO 17|
82+
|RST|External reset|GPIO 16|
83+
|BUSY|Busy state output pin|GPIO 7|
8084
81-
This is useful if trying to conserve power. Deep sleep mode can be configured in the "Power" tab within the web UI.
85+
If you wish to use different data (non-SPI) pins, those are all configurable in the UI.
8286
83-
## SPI Bus and Pin Selection
87+
#### Custom SPI bus
8488
85-
The ESP32 has 4 SPI busses, however, one is reserved for the chips Flash. (SPI0) and another is often used by PSRAM (SP1).
89+
The ESP32 has two available SPI busses. The default is HSPI, but you can select VSPI in the settings page. Some driver boards like the [Waveshare ESP32 Driver](https://www.waveshare.com/wiki/E-Paper_ESP32_Driver_Board) use custom SPI pins.
8690
8791
In the **Hardware** tab of the settings page, you can select one of the two free SPI busses on the ESP32. (HSPI and VSPI)
8892
89-
| | VSPI | HSPI (default) |
90-
|-----------|------|----------------|
91-
| DI (MOSI) | 19 | 12 |
92-
| CLK | 18 | 14 |
93-
| CS (SS) | 5 | 15 |
93+
| | VSPI | HSPI (default) | Waveshare Custom |
94+
|-----------|------|----------------|-|
95+
| DI (MOSI) | 19 | 12 |14|
96+
| CLK | 18 | 14 |13|
97+
| CS (SS) | 5 | 15 |15|
9498
95-
Additionally, the displays will require extra pins to be configured to work properly. These are also selectable in the **Hardware** tab.
99+
Ensure that you do not select pins that conflict with the your SPI Bus/Deep Sleep configurations.
100+
101+
## Deep Sleep
96102
97-
Please ensure that you do not select pins that conflict with the your SPI Bus/Deep Sleep configurations.
103+
e-paper templates can function in _deep sleep_ mode. When configured, the system will continuously:
104+
105+
1. Wake from sleep
106+
2. Check if a configurable GPIO pin is set. If it is, stays awake until next reboot
107+
3. Otherwise, stay awake for a configurable period to receive updates and refresh the screen.
108+
4. Put both the ESP32 and the e-paper display into deep sleep mode.
109+
110+
This is useful if trying to conserve power. Deep sleep mode can be configured in the "Power" tab within the web UI.
98111
99112
# Concepts
100113

lib/Display/DisplayTemplateDriver.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ DisplayTemplateDriver::DisplayTemplateDriver(
2626
void DisplayTemplateDriver::init() {
2727
display->init(115200);
2828
display->mirror(false);
29+
30+
#if defined(ESP32)
31+
if (settings.hardware.spi_bus == VSPI){
32+
SPI.end();
33+
SPI.begin(18, 23, 19, settings.hardware.getSsPin());
34+
} else if (settings.hardware.spi_bus == HardwareSettings::WAVESHARE_SPI) {
35+
SPI.end();
36+
SPI.begin(13, 12, 14, settings.hardware.getSsPin());
37+
}
38+
#endif
39+
2940
vars.load();
3041
}
3142

lib/Display/DisplayTypeHelpers.cpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
#include <utility>
99

1010
template <class Display>
11-
inline static GxEPD2_GFX* __gxepd2_build_bw_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy) {
12-
return new GxEPD2_BW<Display, Display::HEIGHT>(Display(SS, dc, rst, busy));
11+
inline static GxEPD2_GFX* __gxepd2_build_bw_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy, const uint8_t ssPin) {
12+
return new GxEPD2_BW<Display, Display::HEIGHT>(Display(ssPin, dc, rst, busy));
1313
}
1414

1515
template <class Display>
16-
inline static GxEPD2_GFX* __gxepd2_build_3c_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy) {
17-
return new GxEPD2_3C<Display, Display::HEIGHT>(Display(SS, dc, rst, busy));
16+
inline static GxEPD2_GFX* __gxepd2_build_3c_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy, const uint8_t ssPin) {
17+
return new GxEPD2_3C<Display, Display::HEIGHT>(Display(ssPin, dc, rst, busy));
1818
}
1919

2020
const std::map<const char*, GxEPD2::Panel, cmp_str> DisplayTypeHelpers::PANELS_BY_NAME = {
@@ -162,59 +162,59 @@ bool DisplayTypeHelpers::is3Color(GxEPD2::Panel type) {
162162
}
163163
}
164164

165-
GxEPD2_GFX* DisplayTypeHelpers::buildDisplay(GxEPD2::Panel type, uint8_t dc, uint8_t rst, uint8_t busy) {
165+
GxEPD2_GFX* DisplayTypeHelpers::buildDisplay(GxEPD2::Panel type, uint8_t dc, uint8_t rst, uint8_t busy, uint8_t ss) {
166166
switch (type) {
167167
// black/white displays
168168
case GxEPD2::Panel::GDEP015OC1:
169-
return __gxepd2_build_bw_driver<GxEPD2_154>(dc, rst, busy);
169+
return __gxepd2_build_bw_driver<GxEPD2_154>(dc, rst, busy, ss);
170170
case GxEPD2::Panel::GDE0213B1:
171-
return __gxepd2_build_bw_driver<GxEPD2_213>(dc, rst, busy);
171+
return __gxepd2_build_bw_driver<GxEPD2_213>(dc, rst, busy, ss);
172172
case GxEPD2::Panel::GDEH0213B72:
173-
return __gxepd2_build_bw_driver<GxEPD2_213_B72>(dc, rst, busy);
173+
return __gxepd2_build_bw_driver<GxEPD2_213_B72>(dc, rst, busy, ss);
174174
case GxEPD2::Panel::GDEW0213I5F:
175-
return __gxepd2_build_bw_driver<GxEPD2_213_flex>(dc, rst, busy);
175+
return __gxepd2_build_bw_driver<GxEPD2_213_flex>(dc, rst, busy, ss);
176176
case GxEPD2::Panel::GDEH029A1:
177-
return __gxepd2_build_bw_driver<GxEPD2_290>(dc, rst, busy);
177+
return __gxepd2_build_bw_driver<GxEPD2_290>(dc, rst, busy, ss);
178178
case GxEPD2::Panel::GDEW029T5:
179-
return __gxepd2_build_bw_driver<GxEPD2_290_T5>(dc, rst, busy);
179+
return __gxepd2_build_bw_driver<GxEPD2_290_T5>(dc, rst, busy, ss);
180180
case GxEPD2::Panel::GDEW027W3:
181-
return __gxepd2_build_bw_driver<GxEPD2_270>(dc, rst, busy);
181+
return __gxepd2_build_bw_driver<GxEPD2_270>(dc, rst, busy, ss);
182182
case GxEPD2::Panel::GDEW042T2:
183-
return __gxepd2_build_bw_driver<GxEPD2_420>(dc, rst, busy);
183+
return __gxepd2_build_bw_driver<GxEPD2_420>(dc, rst, busy, ss);
184184
case GxEPD2::Panel::GDEW0583T7:
185-
return __gxepd2_build_bw_driver<GxEPD2_583>(dc, rst, busy);
185+
return __gxepd2_build_bw_driver<GxEPD2_583>(dc, rst, busy, ss);
186186
case GxEPD2::Panel::GDEW075T8:
187-
return __gxepd2_build_bw_driver<GxEPD2_750>(dc, rst, busy);
187+
return __gxepd2_build_bw_driver<GxEPD2_750>(dc, rst, busy, ss);
188188
case GxEPD2::Panel::GDEH0213B73:
189-
return __gxepd2_build_bw_driver<GxEPD2_213_B73>(dc, rst, busy);
189+
return __gxepd2_build_bw_driver<GxEPD2_213_B73>(dc, rst, busy, ss);
190190
case GxEPD2::Panel::GDEW026T0:
191-
return __gxepd2_build_bw_driver<GxEPD2_260>(dc, rst, busy);
191+
return __gxepd2_build_bw_driver<GxEPD2_260>(dc, rst, busy, ss);
192192
case GxEPD2::Panel::GDEW0371W7:
193-
return __gxepd2_build_bw_driver<GxEPD2_371>(dc, rst, busy);
193+
return __gxepd2_build_bw_driver<GxEPD2_371>(dc, rst, busy, ss);
194194
case GxEPD2::Panel::GDEW075T7:
195-
return __gxepd2_build_bw_driver<GxEPD2_750_T7>(dc, rst, busy);
195+
return __gxepd2_build_bw_driver<GxEPD2_750_T7>(dc, rst, busy, ss);
196196

197197
// Color displays
198198
case GxEPD2::Panel::ED060SCT:
199-
return __gxepd2_build_3c_driver<GxEPD2_it60>(dc, rst, busy);
199+
return __gxepd2_build_3c_driver<GxEPD2_it60>(dc, rst, busy, ss);
200200
case GxEPD2::Panel::GDEW0154Z04:
201-
return __gxepd2_build_3c_driver<GxEPD2_154c>(dc, rst, busy);
201+
return __gxepd2_build_3c_driver<GxEPD2_154c>(dc, rst, busy, ss);
202202
case GxEPD2::Panel::GDEW0213Z16:
203-
return __gxepd2_build_3c_driver<GxEPD2_213c>(dc, rst, busy);
203+
return __gxepd2_build_3c_driver<GxEPD2_213c>(dc, rst, busy, ss);
204204
case GxEPD2::Panel::GDEW029Z10:
205-
return __gxepd2_build_3c_driver<GxEPD2_290c>(dc, rst, busy);
205+
return __gxepd2_build_3c_driver<GxEPD2_290c>(dc, rst, busy, ss);
206206
case GxEPD2::Panel::GDEW027C44:
207-
return __gxepd2_build_3c_driver<GxEPD2_270c>(dc, rst, busy);
207+
return __gxepd2_build_3c_driver<GxEPD2_270c>(dc, rst, busy, ss);
208208
case GxEPD2::Panel::GDEW042Z15:
209-
return __gxepd2_build_3c_driver<GxEPD2_420c>(dc, rst, busy);
209+
return __gxepd2_build_3c_driver<GxEPD2_420c>(dc, rst, busy, ss);
210210
case GxEPD2::Panel::GDEW0583Z21:
211-
return __gxepd2_build_3c_driver<GxEPD2_583c>(dc, rst, busy);
211+
return __gxepd2_build_3c_driver<GxEPD2_583c>(dc, rst, busy, ss);
212212
case GxEPD2::Panel::GDEW075Z09:
213-
return __gxepd2_build_3c_driver<GxEPD2_750c>(dc, rst, busy);
213+
return __gxepd2_build_3c_driver<GxEPD2_750c>(dc, rst, busy, ss);
214214
case GxEPD2::Panel::GDEW075Z08:
215-
return __gxepd2_build_3c_driver<GxEPD2_750c_Z08>(dc, rst, busy);
215+
return __gxepd2_build_3c_driver<GxEPD2_750c_Z08>(dc, rst, busy, ss);
216216
default:
217217
Serial.printf_P(PSTR("Unsupported display type, using default. Provided display: %d\n"), static_cast<size_t>(type));
218-
return buildDisplay(DisplayTypeHelpers::DEFAULT_PANEL, dc, rst, busy);
218+
return buildDisplay(DisplayTypeHelpers::DEFAULT_PANEL, dc, rst, busy, ss);
219219
}
220220
}

lib/Display/DisplayTypeHelpers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class DisplayTypeHelpers {
1515
static GxEPD2::Panel stringToDisplayType(const String& displayType);
1616
static bool is3Color(GxEPD2::Panel type);
1717

18-
static GxEPD2_GFX* buildDisplay(GxEPD2::Panel type, uint8_t dcPin, uint8_t rstPin, uint8_t busyPin);
18+
static GxEPD2_GFX* buildDisplay(GxEPD2::Panel type, uint8_t dcPin, uint8_t rstPin, uint8_t busyPin, uint8_t ssPin);
1919

2020
static const GxEPD2::Panel DEFAULT_PANEL;
2121
static const char* DISPLAY_NAMES[];

lib/Settings/Settings.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,19 @@ void SettingsCallbackObserver::onConfigurationChanged(const ConfigurationPropert
6969
if (this->callback) {
7070
this->callback(value);
7171
}
72+
}
73+
74+
const uint8_t HardwareSettings::getSsPin() const {
75+
if (this->ss_pin_override != -1) {
76+
return static_cast<uint8_t>(this->ss_pin_override);
77+
}
78+
79+
switch (this->spi_bus) {
80+
case HSPI:
81+
case WAVESHARE_SPI:
82+
return 15;
83+
case VSPI:
84+
default:
85+
return 5;
86+
}
7287
}

lib/Settings/Settings.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,27 @@ class WebSettings : public Configuration {
7979

8080
class HardwareSettings : public Configuration {
8181
public:
82+
static const uint8_t WAVESHARE_SPI = VSPI + HSPI;
83+
static const uint8_t WAVESHARE_SS_PIN = 15;
84+
8285
persistentVar(
8386
uint8_t,
8487
spi_bus,
8588
EPD_DEFAULT_SPI_BUS,
8689
{
8790
if (spi_busString.equalsIgnoreCase("vspi")) {
8891
spi_bus = VSPI;
92+
} else if (spi_busString.equalsIgnoreCase("waveshare")) {
93+
spi_bus = WAVESHARE_SPI;
8994
} else {
9095
spi_bus = HSPI;
9196
}
9297
},
9398
{
9499
if (spi_bus == VSPI) {
95100
spi_busString = "VSPI";
101+
} else if (spi_bus == WAVESHARE_SPI) {
102+
spi_busString = "waveshare";
96103
} else {
97104
spi_busString = "HSPI";
98105
}
@@ -101,12 +108,16 @@ class HardwareSettings : public Configuration {
101108
persistentIntVar(dc_pin, EPD_DEFAULT_DC_PIN);
102109
persistentIntVar(rst_pin, EPD_DEFAULT_RST_PIN);
103110
persistentIntVar(busy_pin, EPD_DEFAULT_BUSY_PIN);
111+
persistentIntVar(ss_pin_override, -1);
112+
113+
const uint8_t getSsPin() const;
104114
};
105115

106116
class NetworkSettings : public Configuration {
107117
public:
108118
persistentStringVar(hostname, DEFAULT_DISPLAY_NAME);
109119
persistentStringVar(mdns_name, DEFAULT_DISPLAY_NAME);
120+
persistentStringVar(ntp_server, "pool.ntp.org");
110121
persistentStringVar(setup_ap_password, "waveshare");
111122
persistentStringVar(wifi_ssid, "");
112123
persistentStringVar(wifi_password, "");

lib/Variables/VariableDictionary.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ String VariableDictionary::get(const String &key) {
3838
}
3939

4040
void VariableDictionary::clear() {
41+
SPIFFS.remove(VariableDictionary::FILENAME);
4142
SPIFFS.open(VariableDictionary::FILENAME, "w").close();
4243

4344
db.open(SPIFFS.open(VariableDictionary::FILENAME, "r+"));

platformio.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ framework = arduino
1313
board_f_cpu = 80000000L
1414
lib_deps_builtin =
1515
lib_deps_external =
16-
ArduinoJson@~6.10.1
16+
ArduinoJson@~6.17.1
1717
Adafruit GFX Library@~1.6.1
1818
Timezone@~1.2.2
1919
AsyncMqttClient@~0.8.2
@@ -31,7 +31,7 @@ lib_deps_external =
3131
; and the webserver builtin to the espressif SDKs define.
3232
WiFiManager=https://github.com/sidoh/WiFiManager#async_support
3333

34-
GxEPD2=https://github.com/ZinggJM/GxEPD2#1.2.3
34+
GxEPD2=https://github.com/ZinggJM/GxEPD2#1.2.14
3535
extra_scripts =
3636
pre:scripts/platformio/build_web.py
3737
post:scripts/platformio/build_full_image.py

src/main.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ GxEPD2_GFX* display = NULL;
3737
DisplayTemplateDriver* driver = NULL;
3838
EpaperWebServer* webServer = NULL;
3939
MqttClient* mqttClient = NULL;
40+
NTPClient* timeClient;
4041

4142
// Don't attempt to reconnect to wifi if we've never connected
4243
volatile bool hasConnected = false;
4344
volatile bool shouldRestart = false;
4445

4546
WiFiUDP ntpUDP;
46-
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000);
4747

4848
uint8_t lastSecond = 60;
4949

@@ -73,13 +73,6 @@ void cancelSleep() {
7373
}
7474

7575
void initDisplay() {
76-
#if defined(ESP32)
77-
if (settings.hardware.spi_bus == VSPI){
78-
SPI.end();
79-
SPI.begin(18, 23, 19, 5);
80-
}
81-
#endif
82-
8376
if (display) {
8477
delete display;
8578
display = NULL;
@@ -88,7 +81,8 @@ void initDisplay() {
8881
display = DisplayTypeHelpers::buildDisplay(settings.display.display_type,
8982
settings.hardware.dc_pin,
9083
settings.hardware.rst_pin,
91-
settings.hardware.busy_pin);
84+
settings.hardware.busy_pin,
85+
settings.hardware.getSsPin());
9286

9387
if (driver != NULL) {
9488
delete driver;
@@ -115,6 +109,14 @@ void applySettings() {
115109

116110
Timezones.setDefaultTimezone(*settings.system.timezone);
117111

112+
if (timeClient != NULL) {
113+
delete timeClient;
114+
timeClient = NULL;
115+
}
116+
117+
timeClient = new NTPClient(ntpUDP, settings.network.ntp_server.c_str(), 0, 60000);
118+
timeClient->begin();
119+
118120
if (hasConnected && settings.network.wifi_ssid.length() > 0 &&
119121
settings.network.wifi_ssid != WiFi.SSID()) {
120122
Serial.println(F("Switching WiFi networks"));
@@ -255,8 +257,6 @@ void setup() {
255257
}
256258
}
257259

258-
timeClient.begin();
259-
260260
applySettings();
261261
}
262262

@@ -265,9 +265,9 @@ void loop() {
265265
ESP.restart();
266266
}
267267

268-
if (timeClient.update() && lastSecond != second()) {
268+
if (timeClient != NULL && timeClient->update() && lastSecond != second()) {
269269
lastSecond = second();
270-
driver->updateVariable("timestamp", String(timeClient.getEpochTime()));
270+
driver->updateVariable("timestamp", String(timeClient->getEpochTime()));
271271
}
272272

273273
if (webServer) {

0 commit comments

Comments
 (0)