Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for IPSTUBE H401 #74

Closed
wants to merge 10 commits into from

Conversation

Martinius79
Copy link
Collaborator

Added support for IPSTUBE clock - Model H401

Added new configuration in platform.io, because H401 has 8MB flash.
Also partition file and copy scripts and the board config json file.

Added a "One Button" menu beside the "normal" menu, but implementation is not great (only right button emulation on long click).
Changed the checked state for buttons to "up_edge" instead of "down_edge".

Added different types of debug print outs (verbose, menu, buttons, tft).

Updated firmware to V1.0.1 and created single file firmware bins.

TODO:
LCD panel on the ground (if installed) not working (or only sometimes).
Implement a better "One Button" menu. Like single, double and triple click for menu choices.

@eadmaster
Copy link

eadmaster commented Jul 9, 2024

EDIT: on further investigation, it seems you have to change the casing in these path strings which are case-sensitive on linux and do not match atm: './.pio/libdeps/esp32dev8mb -> ./.pio/libdeps/esp32dev8MB

(found in script_configure_tft_lib_8MB.py and script_adjust_gesture_sensor_lib_8MB.py)

EDIT2: compiled and updated the firmware. i see the wifi connection messages and i can navigate the menu by pressing the button on the back, but the screen stays black (no time is shown).

The debug serial monitor shows these error messages repeated:

[2024-07-09 16:29:17] .File not found: /7.bmp

@Martinius79
Copy link
Collaborator Author

Thx for mentioning the case sensitive folder name problem in the copy scripts. Fix this to "8MB" all over the place...

The second problem normaly means, that you didn't upload the filesystem image yet (spiffs.bin). Click also on "Build Filesystem Image" and then "Upload Filesystem Image".
image

Copy link

@eku eku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

Could you please add some documentation and a list of what works and what doesn't?

EleksTubeHAX_pio/MyEleksTubeHAX - Kopie.code-workspace Outdated Show resolved Hide resolved
EleksTubeHAX_pio/partition_noOta_1Mapp_7Mspiffs.csv Outdated Show resolved Hide resolved
EleksTubeHAX_pio/platformio.ini Outdated Show resolved Hide resolved
EleksTubeHAX_pio/platformio.ini Show resolved Hide resolved
EleksTubeHAX_pio/src/Backlights.cpp Outdated Show resolved Hide resolved
EleksTubeHAX_pio/src/ChipSelect.h Show resolved Hide resolved
EleksTubeHAX_pio/src/Clock.cpp Show resolved Hide resolved
EleksTubeHAX_pio/src/Clock.cpp Show resolved Hide resolved
EleksTubeHAX_pio/src/Menu.cpp Show resolved Hide resolved
pre-built-firmware/FW_NovelLife_SE_HAX_1.0.1.bin Outdated Show resolved Hide resolved
@eadmaster
Copy link

eadmaster commented Jul 10, 2024

s, that you didn't upload the filesystem image yet (spiffs.bin). Click also on "Build Filesystem Image" and then "Upload Files

i prefer to use the cmdline directly:

platformio run --target uploadfs --environment esp32dev8MB

now the error message is different :

[2024-07-10 08:17:59] Can't openfile. Make sure you upload the SPIFFs image with BMPs. : /9.bmp

Indeed there is no "9.bmp" here.

Switching clock theme via the menu made the numbers appear, i guess the default value 0 is not correct, should be 1 instead.

Another suggestion: ONE_BUTTON_ONLY_MENU should be defined automatically when compiling for HARDWARE_IPSTUBE_H401_CLOCK.

@eadmaster
Copy link

eadmaster commented Jul 10, 2024

side question: is it possible to reduce the TFT brightness? I've noticed they run a bit hot after a while.
I've found this method, but i am not sure if it will work in this case.

@aly-fly
Copy link
Owner

aly-fly commented Jul 10, 2024

side question: is it possible to reduce the TFT brightness?

If your version of the clock has backlight LED supply (signals LEDK or LEDA) routed to the connector, then it is possible. Add a fast MOSFET and wire it to the hardware PWM output of the ESP32. Connect the displays LED pins to the transistor. Do NOT modulate the Vdd of the complete display. Maybe the transistor is already on the main board.
If signal/pin is not present, you can hack the displays and route a new signal to the connector.

If your clock is compatible with this (Hardware SI HAI clock (chinese copy)), then it is a good candidate to have brightness modulation added.

@Foamier
Copy link

Foamier commented Jul 10, 2024

For the IPSTube hardware it is technically possible to do a brightness mod since the backlight LED power is a separate pin on the FPC connectors. There are a few complications with it though:

  • The led power is connected to the same PCB trace as the LCD power. Not sure where the 3V3 comes from (close to or far end of pin1.
  • A software solution will need to use a pin on the ESP32 chip that is suitable for connecting. Since the bare ESP32 chip is mounted on the PCB, the pins are very small, and the unused pins do not have decent solder pads that make the solder surface any longer. If a pin on a corner of the ESP32 could be used that could potentially work so there is less risk soldering two or more pins together (see picture). These pins are really tiny, at least for my soldering skills.

IPSTube ESP32

001222

Pin 1 (LED backlight) and pin7 (3V3) are connected together:

IPSTube LCD LED power pin1

If adjustment through software is not required, after separating the LED pin from the 3V3 line, the LED backlight pins could also be fed with a lower voltage supplied by some kind of voltage regulator or power conversion chip of e.g. 2.5V. Some testing with a variable power buck converter is probably a good idea to see what is most suitable in the required situation. Going over 3V3 is probably a bad idea.

Perhaps the simplest option could be is to add a resistor in-line with pin1 of the backlight LED for each display. Guess this again requires some testing and measurements to make sure the chosen resistor is capable of dissipating the required power for the desired voltage drop to power the white LED.

@eadmaster
Copy link

Thank you for the tips, but i'd like to avoid any hardware mod if possible.

@Martinius79
Copy link
Collaborator Author

...

Indeed there is no "9.bmp" here.

Switching clock theme via the menu made the numbers appear, i guess the default value 0 is not correct, should be 1 instead.

I am not sure, where this 7 or 9.bmp without a prefix is coming from -> where do you see this default 0?

Another suggestion: ONE_BUTTON_ONLY_MENU should be defined automatically when compiling for HARDWARE_IPSTUBE_H401_CLOCK.

Done. I only left it inside, because I use the MQTT messages instead and for them four buttons are usefull.
In a later version, the seperation is maybe not needed anymore.

@Martinius79
Copy link
Collaborator Author

Could you please add some documentation and a list of what works and what doesn't?

The IPSTUBE clock has 8MB flash, so no default board from PIO is fitting. I created a JSON file with the modified values (esp32dev8MB.json) under the subfolder "boards" so it can be used in the PIO project.

I created a new "partition table file" (partition_noOta_1Mapp_7Mspiffs.csv) for the 8MB flash version.

I added a new environment in the platform.ini file (env:esp32dev8MB), to use the new board configuration file and the new partition table file.

Because each environment has its own target directory (PROJECTDIR.pio\build\ENVNAME), the helper scripts to copy and modify the libs files needs another target folder. So I created script_adjust_gesture_sensor_lib_8MB.py and script_configure_tft_lib_8MB.py and added it to the new env.

I added/copied a section to define the IPSTUBE clock configs in the GLOBAL_DEFINES.H file.
See section "#ifdef HARDWARE_IPSTUBE_H401_CLOCK" in the file.
Specials:
New defintion for a one button menu (#define ONE_BUTTON_ONLY_MENU), because only one hardware button is available for IPSTUBE.
Removed the shift register pin config definitions (CSSR_DATA_PIN,CSSR_CLOCK_PIN, CSSR_LATCH_PIN).
Removed defintion of "TFT_ENABLE_PIN", because the LCDs are always on for the IPSTUBE and then the exisitng logic can be used.
Added "#define TOUCH_CS -1" to get rid of a warning (also possible with #define DISABLE_ALL_LIBRARY_WARNINGS).
Set TFT_CS to -1
Also:
Increased FIRMWARE_VERSION to 1.0.1

I modified the _USER_DEFINES - empty.h file
Added five more debug output levels
Added "#define HARDWARE_IPSTUBE_H401_CLOCK as "Type of clock"
changed some comments for the MQTT section with further explanations

Main work was to modify the chip_select logic for the IPSTUBE, because no shift register is used to have only one CS for the LCDs. Instead 6 pins from the ESP32 are directly connected.

I modified the ChipSelect class.
Moved inline defined methods from ChipSelect.H file to ChipSelect.CPP file.
Modified the existing "digit" select methods, that they work with IPSTUBE and other clocks. Normaly by keeping the existing logic and just switching or leaving out code where needed by checking, which hardware is defined.
Added the array for the CS pins of the IPSTUBE.
Added some IPSTUBE specific methods to select the right LCDs. enableDigitCSPinsH401, disableDigitCSPinsH401, enableAllCSPinsH401 and disableAllCSPinsH401.
So the existing logic for selecting and activating/disabling the LCDs from the TFTs class can be used without modification.

I modified the TFTs class.
Moved some inline defined methods from TFTs.H file to TFTs.CPP file (enableAllDisplays, disableAllDisplays, toggleAllDisplays).
Modified existing methods that they work with IPSTUBE and other clocks. Normaly by keeping the existing logic and just switching or leaving out code where needed by checking, which hardware is defined.
Added a debug serial print output to each method if DEBUG_OUTPUT_TFT is defined.

I renamed the Button.CPP file to Buttons.CPP and modified the header file as well to use the new file.
I modified the Button class.
I added debug serial print outs to the loop() method (if DEBUG_OUTPUT_BUTTONS is defined)
I added some public helper methods, to be able to set button states from outside of the instance of the class (setDownLongEdgeState, setUpEdgeState, setUpLongEdgeState)

I modified the Buttons class.
Two constructors are needed now, depending on the definition of ONE_BUTTON_ONLY_MENU or not. Classic way, Buttons instance with four buttons is created, new, Buttons instance with only one button is created -> this can also be done by overriding the constructors!
Moved some inline defined methods for Buttons class from Buttons.H file to Buttons.CPP file (loop, begin, stateChanged). Also for the one button menu implementation.

I modified the Menu class.
I added debug serial print outs to the loop() method(s) (if DEBUG_OUTPUT_MENU is defined)
Two loop methods are now implemented. One for the one button menu (ONE_BUTTON_ONLY_MENU defined) ot the classic one, with four buttons.
The "edge" logic for the buttons is changed now, from "down_edge" to "up_edge". So the software (here the menu) only reacts, if a button is "released", not while it is pressed.
This makes "long pressed button" possible without having a "wrong" button state left.
So in the one button mode, a long press of the button, is interpreted as a "move to the right" (right button).
I added a method to print out the names of the menu states (getStateStr).

I modified the Clock class file.
IPSTUBE is using the DS1302 as RTC chip, so needs to be defined as well, to use another driver as for HARDWARE_SI_HAI_CLOCK.
Modified to "#if defined(HARDWARE_SI_HAI_CLOCK) || defined(HARDWARE_IPSTUBE_H401_CLOCK)"
defaulting to start timezone CEST (more or less by accident).

Modified the main.cpp file.
I created some functions out of the code from the existing main function (drawMenu, handlePowerSwitchPressed, handleMQTTCommands). To shorten the main function.
I renamed some existing functions (checkOnEveryFullHour, updateDstEveryNight, handleGestureInterupt, gestureInterruptRoutine, handleGesture, gestureStart). To follow exisitng naming shema/idea.
Init TFTs first, before gesture in the setup function.
Added and modified debug outputs.
Modified code of the handleMQTTCommands function to handle some new "MQTT states" for "button pressing" and clock face changing.
MqttCommandState between 10 and 95 is a clock face change command (faces 1 to 13 possible).
MqttCommandState between 100 and 120 is a button click (MODE=100, RIGHT=120, LEFT=110, POWER=115).
Modified code for handlePowerSwitchPressed, because the is no Power button defined in the one button setup.

I modified the Mqtt_client_ips.CPP
I added debug serial print outs to most of the functions (if DEBUG_OUTPUT_MQTT is defined) --------------------> ARGH! I FAILED to use this definition! MY BAD! Have to change it!
I added new topics (like /MQTT_CLIENT/buttons/up or /MQTT_CLIENT/clockface/change), see CPP file for all new topics.
Each topic sets the "MqttCommandState" and they are interpreted in the main function then (by calling handleMQTTCommands)
So button pressed can be send via MQTT. Clock face changes now also have a "better" topic IMHO.
Fixed some "problems" while setting the states.
This MQTT stuff has a great "refactoring potential" ;)

I modified the Backlights class.
I added debug serial print outs to each method (if DEBUG_OUTPUT_VERBOSE is defined) -> Should be changed to DEBUG_OUTPUT_BACKLIGHT maybe)

Added a new file for saving 8MB firmware files (_ESP32 save flash 8MB.cmd)

Minor changes to a lot of files, like formating, the way I like it or adding/modifing debug print outs.

Don't know, what I missed. It is late now, so I am too tired to go on more detailed. Just ask, what you wanna know.

And yes, working and not working tomorrow then....

@eadmaster
Copy link

I am not sure, where this 7 or 9.bmp without a prefix is coming from -> where do you see this default 0?

this selected_graphic should be inited to 1. It was 0 after flashing my board.

@Martinius79
Copy link
Collaborator Author

I am not sure, where this 7 or 9.bmp without a prefix is coming from -> where do you see this default 0?

this selected_graphic should be inited to 1. It was 0 after flashing my board.

Actually, if the config load was not valid, like an initial start after a flash erase and flash, the "default" values should be loaded, and the default clock face index is set to 1. See:
https://github.com/Martinius79/EleksTubeHAX/blob/a94cb430d12147b413694929e11d927d03920a49/EleksTubeHAX_pio/src/Clock.cpp#L69

So I really don't understand, where this non 1X.bmp prefixed values coming from...

@Martinius79
Copy link
Collaborator Author

I am not sure, where this 7 or 9.bmp without a prefix is coming from -> where do you see this default 0?

this selected_graphic should be inited to 1. It was 0 after flashing my board.

Actually, if the config load was not valid, like an initial start after a flash erase and flash, the "default" values should be loaded, and the default clock face index is set to 1. See: https://github.com/Martinius79/EleksTubeHAX/blob/a94cb430d12147b413694929e11d927d03920a49/EleksTubeHAX_pio/src/Clock.cpp#L69

So I really don't understand, where this non 1X.bmp prefixed values coming from...

Ok, found the problem. A bit of an edge case.
If the file system image is not uploaded before the firmware image, the inital count of the clock faces failes, so it is then set to 0 and then stored in the config...I do a "workaround" now, by setting the index to 1 at least, if the count fails -> that does not fix the missing file system image ;)

@eadmaster
Copy link

Thank you for the tips, but i'd like to avoid any hardware mod if possible.

i've managed to reduce the brightness via software by passing all the colors to this method.

@aly-fly
Copy link
Owner

aly-fly commented Jul 12, 2024

Thank you for the tips, but i'd like to avoid any hardware mod if possible.

i've managed to reduce the brightness via software by passing all the colors to this method.

Dimming is already integrated. See Night mode section. This will reduce brightness of the displayed image, not the TFT backlight. If your concern is to reduce temperature of the TFTs, this method will not do anything. It has constant backlight; this is not an OLED screen.

@eadmaster
Copy link

eadmaster commented Jul 12, 2024

Thank you for the tips, but i'd like to avoid any hardware mod if possible.

i've managed to reduce the brightness via software by passing all the colors to this method.

Dimming is already integrated. See Night mode section. This will reduce brightness of the displayed image, not the TFT backlight. If your concern is to reduce temperature of the TFTs, this method will not do anything. It has constant backlight; this is not an OLED screen.

understood... PWM-ing the TFT_ENABLE_PIN as suggested here won't do?

e.g. replace this line with

analogWrite(TFT_ENABLE_PIN, (float)dimming/100);

EDIT: found a discussion here, as alternative there may be a specific SPI command to set the brightness.

@aly-fly
Copy link
Owner

aly-fly commented Jul 12, 2024

understood... PWM-ing the TFT_ENABLE_PIN as suggested here won't do? analogWrite(TFT_ENABLE_PIN, (float)dimming/100);

TFT enable signal is present only on a few clock variants. Others have displays constantly powered.
This signal completely cuts the power to the displays (logic and BL). It can't be PWM'ed or voltage reduced.

EDIT: found a discussion here, as alternative there may be a specific SPI command to set the brightness.

As far as I can see on these displays, the BL LED is hardwired on the PCB and is not connected to the LCD driver chip (that talks over SPI). Maybe this register only varies LCD modulation and not the BL at all.

p.s. I wouldn't care too much if displays are a bit warm, if this is the only concern.

@@ -49,21 +48,24 @@ uint8_t yesterday = 0;
// Helper function, defined below.
void updateClockDisplay(TFTs::show_t show=TFTs::yes);
void setupMenu(void);
void EveryFullHour(bool loopUpdate=false);
Copy link

@eku eku Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's hard to resist, but please let's just make functional changes in the first step and not make the source code prettier yet. Only change as little as absolutely necessary.

@Martinius79
Copy link
Collaborator Author

And yes, working and not working tomorrow then....

Working and Not-Working list for IPSTUBE H401:

Working:
All "normal" clock functions are working.
Possible to flash all needed partitions to the clock (button needs to be pressed while connecting USB-C cable and then released to go into download mode every time you want to flash)
Passing the setup() function with initalizing messages on the LCDs.
Connecting to Wifi network.
Getting time from NTP server ("Refreshing" after some time seems to be buggy for all clocks, so working as expected).
Loading the images for the clock faces from the SPIFFS partition.
Showing the actual time on the LCDs with the loaded clock face images.
Running the main loop function.
Menu is working (see below for limitations with the one button menu). Able to go through all sub-menu points and select the functionalities (backlight pattern selection, backlight color if pattern is constant, backlight intensity, 24/12h clock, blank zero, time zone offset hours, time zone offset 15 min, clock face selection, WPS menu if activated).
Loading and storing config values from the config partition.
Connecting to the MQTT broker server for sending and receiving MQTT messages. Switching clock faces and "pressing" buttons is possible.
"Dimming" the images of the clock face.
"Normal" LED backlights on the bottom of each LCD are working. Turning on and off is possible. Dimming is possible. All patters working.
Night and Daytime mode is working.

Can't tell if working:
Geolocation broker based time zone selection -> no account, so not tested.
WPS connect -> never used, never tested.
Temperature sensor -> There is no connector/socket on the PCB for this, so no temp sensor support for this clock!

Limited working:
The PCB has only one button!
There is a special menu mode activated for the IPSTUBE hardware, that short pressing brings up the menu and long pressing changes the value of the actual selected menu then.
The value always changes "to the right", because the long button press is emulating a "rigth button" press in the menu only in the moment.
This limits the setup of the timezone values and makes the selection of the other menu values a bit "unhandy", because you have to pass all values, to be at first option again, but it works for now.
Alternativly, the button presses can be send by MQTT commands to the clock, if a MQTT broker is setup in the code configuration. Then the "One Button Mode" should be disabled.
Future plans: Implement a "singe, double, tripple" press mechanism in general for all clocks to have an alternative to the three/four real buttons. Rework the menu.

Not working:
LED stribe:
On some versions there is a LED stribe on the bottom of the device installed. It is connected to a socket on the PCB between FPC5 and FPC6. So it can be retrofitted, if you find the right LED stripe.
This LED stribe is not working in the moment, because no specifiv initialization is done. Sometimes, the LED stripe is turning on by accident, so it seems, as if this is somehow connected to same lines, as the "normal" LED backlights on the bottom of each LCD.
Needs further investigation.
TFT LCD disable/enable:
TFT LCDs can not turned on/enabled or turned off/disabled on the device without modifing the hardware!
The pin 1 and pin 7 of each FPC for each TFT LCDs are connected together directly to the +V3.3 line of the PCB.
Pin 1 is the general VCC power (LED Anode) and pin 7 is the VDD (Power Supply for Analog).
So there is no way to control the VDD on pin 7 seperately or to turn on or turn off power to pin 1.
One possible solution would be disconnecting pin 1 and pin 7 and connecting pin 1 to the existing "switchable" power control lines, like the one from the backlights.
Connecting all pin 7 somehow to an unused pin on the ESP32 is really really tricky and I don't belive, the chip would survice this procedure (just my opinion).

…dateClockDisplay-> Redraws all TFTs always! (needs >1 sec everytime) - changed debug output for clock face counting in setup()
@Martinius79
Copy link
Collaborator Author

I created a "minimum" changes version now. See #77

@Foamier
Copy link

Foamier commented Jul 22, 2024

Hi @Martinius79,
Thanks so much for your efforts. I've installed this version of the code onto my IPSTube and it works very well.
Uploading was easy enough once you get the hang of VS code and PlatformIO. For those who want to try:

  • pulled https://github.com/Martinius79/EleksTubeHAX/ in VSCode.
  • made a copy of the empty USER_DEFINES and saved to USER_DEFINES.h
  • Set hardware type #define HARDWARE_IPSTUBE_H401_CLOCK
  • under [env:esp32dev8MB] added the COM port with "upload_port = COM8"
    In PlatformIO:
  • erase/build/upload the file system in esp32dev8MB/Platform
  • build/upload the code in esp32dev8MB/General

The button action takes getting a bit used to, but works non the less. Sometimes the button presses don't register well but I think that is due to the meager quality of the button. Perhaps the short button detection time could be a bit lower/sooner.
WiFi works well when I put the SSID and preshared key, as I don't have WPS to test here.
I can think of a lot of features to add, but for now excellent stuff!

Foamy

@Martinius79 Martinius79 deleted the AddedIPSTUBEH401 branch September 15, 2024 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants