Upstream openinverter bug surfaced after recent SKUDAK PRs.
Symptom (reported by Kyle on the bench): teslacharger detects EVSE,
shows the AC limit, but stays stuck in WaitStart and never proceeds
to Enable / Activate / Run. State machine looks like it's the OFF
state but it's actually one step further on.
Root cause in src/charger.cpp:85-91:
bool CheckDelay()
{
uint32_t now = rtc_get_counter_val();
uint32_t start = Param::GetInt(Param::timedly) * 60;
return start <= 0 || (now - startTime) > start;
}
With timedly = -1 (the param's documented "no delay" sentinel and its
default value), the math is:
Param::GetInt(timedly) -> -1 (signed int)
-1 * 60 -> -60 (signed)
assigned to uint32_t -> 0xFFFFFFC4 (~4.29 billion)
start <= 0 -> false (uint32_t can't be negative)
(now - startTime) > 4294967236 -> false for ~136 years
So CheckDelay() returns false forever; charger wedges in WaitStart.
Why "it was working before": every SKUDAK PR that bumped the param
table (uaux broadcast, expanded 0x210, 0x210->0x211, version suffix)
invalidates the saved-params CRC and resets timedly to its -1 default.
Kyle had a non-default value (probably 0) saved before.
Fix: signed math for the short-circuit so timedly <= 0 still means
"start immediately." Cast to uint32_t only on the right operand, which
is only evaluated when start > 0 — can't reinterpret negative as huge.
The companion CheckTimeout() at line 75 has the same uint32_t pattern
but works "correctly by accident" because timelim = -1 makes timeout
huge and (now - startTime) > timeout is false, which matches the
intended "no timeout" semantics. Leaving that alone — fixing it would
change behaviour, not bugs.
VER suffix bumped -S1 -> -S2 so the OI web UI clearly shows the
deployed firmware (post-fix). Confirmed in built binary as
"4=1.19.R-S2".
Build: text=25192, links clean, pre-existing pedantic warning unchanged.
This bug is also present upstream (johanneshuebner/stm32-charger);
worth a PR upstream once we've confirmed the fix on the bench.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
stm32-template
This project can be a starting point to your own STM32 project. It contains facilities that make software development easier and ensures compatibility with the esp8266 web interface.
It provides
- Mostly object oriented syntax
- A simple, hardware based scheduler for recurring tasks
- Analog input management, fully independent with DMA
- Digital I/O management
- CAN library supporting up to 2 CAN interfaces
- hardware filter support
- No limitation on number of messages
- Automatic mapping from/to parameter module
- CAN Open SDO support
- Fully interrupt driven
- Error memory
- ligthweight fixed point arithmetic
- string functions to be independent of stdlib
- Parameter module that interfaces to esp8266 web GUI
- Saving parameters to flash
- Serial terminal with custom commands and DMA transfer
- Mathematical functions (sin/cos, arctan, square root)
- PI controller class
- Functions for field oriented control
OTA (over the air upgrade)
The firmware is linked to leave the 4 kb of flash unused. Those 4 kb are reserved for the bootloader that you can find here: https://github.com/jsphuebner/tumanako-inverter-fw-bootloader When flashing your device for the first time you must first flash that bootloader. After that you can use the ESP8266 module and its web interface to upload your actual application firmware. The web interface is here: https://github.com/jsphuebner/esp8266-web-interface
Compiling
You will need the arm-none-eabi toolchain: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads On Ubuntu type
sudo apt-get install git gcc-arm-none-eabi
The only external depedencies are libopencm3 and libopeninv. You can download and build these dependencies by typing
make get-deps
Now you can compile stm32- by typing
make
And upload it to your board using a JTAG/SWD adapter, the updater.py script or the esp8266 web interface.
Editing
The repository provides a project file for Code::Blocks, a rather leightweight IDE for cpp code editing. For building though, it just executes the above command. Its build system is not actually used. Consequently you can use your favority IDE or editor for editing files.
Adding classes or modules
As your firmware grows you probably want to add classes. To do so, put the header file in include/ and the source file in src/ . Then add your module to the object list in Makefile that starts in line 43 with .o extension. So if your files are called "mymodule.cpp" and "mymodule.h" you add "mymodule.o" to the list.
When changing a header file the build system doesn't always detect this, so you have to "make clean" and then make. This is especially important when editing the "*_prj.h" files.