logo elektroda
logo elektroda
X
logo elektroda

Reverse engineering and LED lamp actuation on the SM15155 chip (similar to WS2812B), datasheet

p.kaczmarek2 3321 2

TL;DR

  • Reverse-engineering the SM15155 RGBCW lamp driver in a BK7231N Tuya smart wall lamp, comparing its control scheme to WS2812B-style LEDs.
  • Captured P16 traffic with a logic analyser, decoded 14-byte frames, and mapped five 16-bit colour channels plus trailing configuration bytes.
  • The protocol uses 1-wire return-to-zero signalling, 16-bit colour resolution, and five constant-current LED drivers on one SM15155 chip.
  • OpenBeken gained an SM15155 driver, the lamp lit correctly, and Home Assistant pairing worked, though the purpose of the extra 8 bits remains unclear.
Generated by the language model.
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
📢 Listen (AI):
  • Wall lamp with open casing, connected by cable, emitting bright light. .
    Here I will present an interesting RGBCW lamp driver with a communication protocol very similar to the WS2812B diodes. I became interested in the subject at the request of a reader from Germany, who even sent me a "smart" lamp with this very driver so that I could try to decrypt it and run it in my environment. The aim, of course, was to make it cloud-free. We started the adventure by reverse-engineering, although after we had already decrypted some of the communication, someone else from the readers shared the catalogue note, so things got simpler too. But one step at a time...

    This topic is the result of a thread from Elektroda.com:
    OpenBeken Driver Connection Issues with RGBIC SM15155E and BK7231N in Smart Wall Lamp .
    SM15155 is used in at least one of the Tuya lamps available to buy online:
    Modern outdoor LYTLM wall lamp with color-changing feature. .
    It can be found under LYTLM Smart Alexa LED Wandleuchte Aussen & Innen, Dimmbare RGB Bunt Farbwechsel Aussenleuchten IP65 wasserdichte, CCT WiFi APP Steuerung Kompatibel Google Home, Up Down Modern Garten Wandlampe,1 Pack . The brand is allegedly LYTLM .
    The lamp itself looks quite good, there is something to fight for:
    Colorful wall lighting in various outdoor and indoor settings. .


    Stage 0 - hardware interview
    The reader initially already reported that the SM15155 is used in the lamp with the BK7231N module. Additionally, he noted that it is connected to P16 of the BK7231N, this pin is known to be the data output of the hardware SPI port:
    Close-up of an integrated circuit on a printed circuit board. .
    The other two pins in the picture are ground and power.
    This has already lit the green light for me - this is probably a WS2812B style controller. The WS2812B also uses P16, as it too is controlled by a single signal that requires very precise timing. It's hard to get such timings in software, so a clever use of the SPI port is often made - choosing the bits of the bytes sent so that they form the signal expected by the WS2812B:
    Comparison table of communication protocols WS2812/WS2812S and WS2812B. .
    At some point, I will also address this topic separately.

    Step 1 - data capture with logic analyser .
    The reader then shared with us just the batch from the WiFi module from inside. There was a BK7231N in there. We simply uploaded this batch to one of our modules with P16 out:
    How to access the hardware SPI port on the CB2S? We solder P16 (MOSI) to the QFN .
    We used our BK7231 development board for this:
    [Youtube] How to make a BK7231 development board - NodeMCU ESP8266 conversion
    We managed to pair this with Tuya:
    CB3S module connected to a computer and a smartphone with a device-adding app .
    Smartphone displaying an app for controlling a smart LED lamp, showing color temperature settings. .
    We started to control the 'lamp' via the Tuya app, setting different colours and at the same time capturing data on P16 with our Sigrok analyser:
    Reverse engineering an unknown I2C protocol with the Sigrok analyser using an LED controller as an example .
    A glance with an oscilloscope already shows the timings:
    Screenshot of a digital oscilloscope showing a square wave signal. Oscilloscope displaying a square wave signal with time and voltage parameters. Screenshot of a digital oscilloscope displaying a square wave signal. .
    High state 340ns, low 1.16us, this is reminiscent of the WS2812B. Not ideal, but maybe...
    The PulseView analyser, on the other hand, showed that although the timings resemble the WS2812B, the number of bytes seems to be different. Also, the meaning of the bytes themselves seems to disagree.
    Screenshot from PulseView software showing an analysis of an RGB LED (WS281x) signal using a decoder. .

    Step 2 - first impressions of the protocol .
    Due to the suspicion that this is essentially the same way of communicating as the WS2812B (similar timing) but a different meaning of bytes, I modified the WS2812B PulseView decoder script so that it decodes separate bytes:
    Code: C / C++
    Log in, to see the code
    .
    Immediately better:
    LED signal graph with color coding for WS281x and SM1515E LEDs. .
    You can see that the frame is 14 bytes long.
    Now you can collect some data....

    Step 3 - analysing the collected data .
    I compared the data collected for the different colour settings. This lamp is of the RGBCW type, meaning it can operate in either colour mode (red, green, blue) or white colours (cold and warm white). Data analysis confirmed this. An example package for the red colour is:
    
    FA000000000000000000739CE71F
    
    .
    For green, on the other hand, other bits are lit:
    
    00006200000000000000739CE71F
    
    .
    I observed that when we change the value of a given colour the corresponding pair of bytes changes. It can therefore be concluded that the split is as follows:
    
    0000 0000 0000 0000 0000 739CE71F
    
    .
    First we have five 16-bit colour values, and then there are some additional four bytes (perhaps mode configuration or current limits).
    Now it remains to test this in practice....

    By the way, I didn't detect any checksum here, and already once a single sum with another LED driver caused me a problem:
    Reverse engineering an unknown I2C protocol with a Sigrok analyser using an LED controller as an example .

    Step 4 - lamp in practice, WiFi module
    At this stage it would be useful to have this lamp physically at home. Remotely it is difficult to test it. Fortunately, there was an option here too - just a reader sent me this lamp. Due to transport costs, I received the base alone, without the lampshade:
    Electrical enclosure with installed LEDs on a wooden table. View of module interior with wiring and wrapped component. Interior of a black smart lamp with visible LED diodes on a circuit board. .
    I quickly took to disassembling the whole thing, also to check what kind of WiFi module was sitting there. Neither of the two LED boards were firmly glued to the rest of the lamp, and the module was easily soldered off too:
    WiFi module and LED board on a wooden surface. LED board with connected electronic module and tool on wooden surface. .
    The WiFi module is FL_M129_V3 (BK7231N), dated 2021-12-17, and was worth soldering as it has signed leads on the underside:
    Back of WiFi module with pin designations WiFi module on a wooden surface. .
    I started by changing the batch. I uploaded my OpenBeken in there:
    https://github.com/openshwprojects/OpenBK7231T_App
    According to the flasher instructions:
    https://github.com/openshwprojects/BK7231GUIFlashTool
    Close-up of a circuit board with visible connections and soldering .
    In the photo above you can see where the power (3.3V), ground, RX and TX are.
    Flashing:
    Breadboard with an electronic circuit connected to several wires. .
    Circuit assembled for test, without cooling (you have to be careful with this to avoid overheating the LEDs):
    Disassembled power supply unit and LED module on a wooden table. Close-up of a lamp's electronic module with LEDs. LED module mounted on a white base. 1fcb1fc29f Electronic board with LEDs and an integrated circuit on a wooden surface.


    Step 5 - practical test on WS2812B controller .
    At the previous stage, I established that the byte sending itself is compatible with the WS2812B, so also with, for example, the SM16703P supported by my software. Only the number and meaning of the bytes is different. This means that I can use my existing SPI-based WS2812B driver to send an artificially prepared frame for the SM15155.
    OpenBeken supports scripting, so based on my earlier analysis I prepared a script that sends packets that I suspect will set the next LED colours.
    I was hoping that there was no checksum in this packet, although I don't know the meaning of the last bytes....
    Here is my script:
    
    
    startDriver SM16703P
    
    SM16703P_Init 5
    
    again:
    
    SM16703P_SetRaw 1 0 FF000000000000000000739CE71F00
    delay_s 1
    SM16703P_SetRaw 1 0 0000FF00000000000000739CE71F00
    delay_s 1
    SM16703P_SetRaw 1 0 00000000FF0000000000739CE71F00
    delay_s 1
    SM16703P_SetRaw 1 0 000000000000FF000000739CE71F00
    delay_s 1
    SM16703P_SetRaw 1 0 0000000000000000FF00739CE71F00
    // offf
    delay_s 1
    SM16703P_SetRaw 1 0 00000000000000000000739CE71F00
    
    goto again
    
    .
    The command SM16703P_SetRaw has always been to just blindly send bytes to the WS2812B for quick colour setting, but here it turned out to be like that too. That null byte at the end can be ignored.
    The result:


    .
    Success! Everything works, now it's time for the dedicated driver under SM15155.

    Step 6 - code integration .
    This paragraph is no longer so important. I simply added the driver for the SM15155 based on separate communication via SPI for the WS2812B to my software here and hooked it up to the other RGBCW drivers such as SM2135, BP5758, etc. This lamp doesn't have "per pixel" colours, it just globally sets one colour, so the logic fits with SM2135 and similar.
    Here is a glimpse of my code:
    Code: C / C++
    Log in, to see the code
    .
    My tests have shown that this particular product does pick up 8-bit values though, I don't know what the other 8 bits from each tube are for. I will have to test it some more.

    Step 7 - final test .
    Since the base works, the lamp can be put together. I took the opportunity to add paste between the LED plates and the metal housing:
    Black lamp housing with a layer of thermal paste on a metal base. .
    A short test and everything works:
    LED lamp illuminating a wooden surface. Wall lamp with open casing, connected by cable, emitting bright light. Lamp with connected wires on a workshop table. Preview module with green light on a desk Smart LED lamp emitting blue light on a wooden workbench. .
    The lamp now correctly displays the control panel on the OBK home page and can be paired with Home Assistant.

    Additional - power supply
    I took the opportunity to take an interest in the power supply module:
    Close-up of a power supply module with visible capacitors on a circuit board. Close-up of a power supply module on a wooden surface Power supply module with components on a circuit board Power supply module and LED circuit boards on a wooden table. .
    The power supply first creates the voltage for the LEDs, and then has a separate step down inverter on the secondary side generating 3.3V for the WiFi module. What exactly the flyback inverter controller is in there, I don't know.

    Additional - catalogue note .
    There was no this catalogue note available online when my colleague @DeDaMrAz and I searched for it, but then someone at our forum specifically registered to share it with us. This might clarify for us the meaning of the last bytes.
    First page - general information. This protocol is called "1-wire, return-to-zero", I didn't even know. Operating on voltages from 5 to 40V. 16 bits of colour resolution (that's weird, I thought it was 8 though, I'll check it):
    Technical datasheet page for the SM15115E chip by Shenzhen Sunmoon Microelectronics. .
    And yet the SM15155 can be cascaded.
    Internal construction:
    Detailed internal function block diagram of the SM15155E chip. .
    There are five constant-current LED drivers inside.
    Timings, communication protocol - fairly compatible with WS2812B:
    Communication protocol schematic for SM15155E with data description. .
    That is, however, there are 16 bits per channel, 5 channels and then five times 5 bits each (current settings), 2 standby enable bits and 5 unused bits.
    This is what the cascading of the SM15155 looks like:
    Application schematic of SM15155E with current adjustment settings. .


    Addition - is how to finally run this driver in OpenBeken? .
    To start the SM15155 in OpenBeken, simply add the command to the autostart:
    
    startDriver SM15155 
    
    .
    Alternatively, colour mapping can also be performed with the LED_Map command. Nothing else is needed. The rest will work automatically, pairing with HA will also work itself as with other devices.

    Summary .
    The lamp was successfully commissioned and my SM15155 driver (although incomplete) is probably the first open source driver for this circuit. We couldn't find the datasheet at all, it only appeared when one of its owners took pity and agreed to share it with us.... We already had the base decrypted by then, but the meaning of the last bytes made it clear to us after all. Nonetheless, we probably would have guessed it without that too - separately the brightness levels and separately the current limits are analogously sent in, for example, the BP5758D chip, so such a division is not surprising to me. The enable bit I would also have discovered by trial and error, and in the current driver I don't even use it (although I probably should - I'll rework it).
    In summary - the operation was successful, the patient lit up. Another IoT device can already work with my open source software and by the way we also have another satisfied (I hope) reader from Germany. .
    @HalliHalo - thanks for sending the lamp, without your package the development of this topic would not have been possible.

    Cool? Ranking DIY
    Helpful post? Buy me a coffee.
    About Author
    p.kaczmarek2
    Moderator Smart Home
    Offline 
    p.kaczmarek2 wrote 14573 posts with rating 12595, helped 654 times. Been with us since 2014 year.
  • ADVERTISEMENT
  • #2 21127601
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14573
    Help: 654
    Rate: 12595
    I have described the continuing adventures with this light in a separate topic:
    Why change the batch of IoT devices? What does it do? Extending the functionality of the light .
    Helpful post? Buy me a coffee.
  • #3 21128586
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14573
    Help: 654
    Rate: 12595
    OBK lamp template:
    Code: JSON
    Log in, to see the code
    .
    Helpful post? Buy me a coffee.
📢 Listen (AI):

FAQ

TL;DR: This FAQ shows how to decode a 14-byte SM15155 lamp frame and drive it cloud-free; as the author put it, "Success! Everything works" after reusing a WS2812B-style SPI sender on a BK7231N Tuya wall lamp. It helps OpenBeken users identify the data pin, capture timing, map RGBCW bytes, and bring the lamp into Home Assistant. [#21121650]

Why it matters: It turns an undocumented Tuya RGBCW wall lamp into a locally controlled OpenBeken device with a repeatable reverse-engineering method.

Feature SM15155 WS2812B-style control path used in testing
Physical signaling 1-wire, return-to-zero Similar single-wire timing
Practical frame seen in thread 14-byte payload, plus ignored trailing 00 in one raw send test Commonly treated as per-LED RGB bytes
Channels 5 channels for RGBCW 3 channels for RGB-style workflows
Control method in project Dedicated SM15155E driver or raw SPI byte sender Existing SPI-based sender reused successfully

Key insight: The SM15155 does not need a fully new transport layer. Its timing is close enough to WS2812B that an existing SPI-based byte sender works once you send the correct 5-channel frame and trailing configuration bytes. [#21121650]

Quick Facts

  • The captured SM15155 frame was 14 bytes long: five 16-bit channel values followed by 4 configuration bytes, which the author later linked to current and standby-related settings from the shared datasheet. [#21121650]
  • Oscilloscope capture showed about 340 ns high and 1.16 µs low, which looked close enough to WS2812B signaling to justify decoder and SPI-sender reuse. [#21121650]
  • The shared datasheet notes a 1-wire, return-to-zero protocol, 5 V to 40 V operating range, 5 constant-current outputs, and 16-bit color resolution per channel. [#21121650]
  • The lamp used an FL_M129_V3 Wi-Fi module with BK7231N, and flashing OpenBeken required access to 3.3 V, GND, RX, and TX pads. [#21121650]
  • The published OpenBeken template starts the driver with startDriver SM15155E and applies channel remapping using LED_Map 0 1 3 2 4. [#21128586]

How do you reverse engineer the SM15155 LED lamp protocol from a BK7231N-based Tuya wall lamp using a logic analyzer?

You reverse engineer it by capturing the BK7231N data pin while changing lamp colors in the Tuya app. 1. Identify the SM15155 connection on the BK7231N board, especially P16. 2. Pair the dumped module, change RGBCW settings, and capture P16 with Sigrok or PulseView. 3. Compare frames across colors to map which byte pairs change with red, green, blue, cold white, and warm white. That process exposed a 14-byte frame and showed the signaling was close to WS2812B timing. [#21121650]

What is the SM15155 chip, and how is it used in RGBCW smart lamps like the LYTLM WiFi wall light?

The SM15155 is a 5-channel constant-current LED driver used in RGBCW smart lamps. In the LYTLM WiFi wall light from the thread, it sits behind a BK7231N Wi-Fi module and drives red, green, blue, cold white, and warm white outputs. The shared datasheet says it works from 5 V to 40 V and supports cascading. In this lamp, it enabled one global RGBCW color output rather than per-pixel effects. [#21121650]

Why does the SM15155 communication look similar to WS2812B timing, but use a different frame format?

It looks similar because both use a tightly timed single-wire signal, but the payload meaning is different. The author measured pulses that resembled WS2812B, then found the decoded stream did not match normal RGB byte grouping. SM15155 sends five channel values for RGBCW, not standard RGB triplets, and appends configuration bytes after the channel data. That is why the transport feels familiar while the frame format does not. [#21121650]

What is a 1-wire return-to-zero LED protocol, and how does it relate to the SM15155 datasheet?

"1-wire return-to-zero" is a serial LED-control protocol that sends data on one line, with each bit returning low before the next bit, which makes timing-critical decoding possible. The shared SM15155 datasheet explicitly names its interface as a 1-wire, return-to-zero protocol. That matched the oscilloscope captures from the lamp and explained why WS2812B-style timing tools were useful, even though the SM15155 frame content differed. [#21121650]

How was P16 on the BK7231N identified as the data output pin for the SM15155 driver?

P16 was identified from the reader’s hardware report and from BK7231N pin behavior. The thread states the SM15155 data line was connected to BK7231N P16, and that pin is known as the hardware SPI data output. That was a strong clue because single-wire LED protocols often reuse SPI to generate precise pulse timings that are hard to produce reliably in software. [#21121650]

What does the 14-byte SM15155 frame mean, including the five 16-bit channel values and the final configuration bytes?

The 14-byte frame carries five 16-bit channel values, then four configuration bytes. The author first inferred the layout from color-change captures, then the later shared datasheet clarified that after 5 × 16-bit channel data come five 5-bit current settings, 2 standby-enable bits, and 5 unused bits. In practical tests, the packet tail 73 9C E7 1F stayed constant and allowed the lamp to work. [#21121650]

How do you modify the PulseView or Sigrok WS2812B decoder to analyze SM15155 byte streams correctly?

You modify the WS2812B decoder so it outputs raw bytes instead of assuming RGB grouping. The author changed the Sigrok decoder to collect bits, emit one annotation every 8 bits, and keep reset detection based on a low period above 50 µs. That immediately revealed a 14-byte frame. This approach works because the signal timing is close enough to WS2812B for the bit-level logic to remain useful. [#21121650]

Which timing values were observed on the SM15155 data line, and how close are they to WS2812B signaling requirements?

The author observed about 340 ns high and 1.16 µs low on the data line. He described those timings as reminiscent of WS2812B, though not ideal. They were still close enough for practical reuse of a WS2812B-style decoder and SPI transmission method. That timing similarity was the key reason the lamp could be controlled with an existing SPI-based LED sender before a dedicated driver existed. [#21121650]

SM15155 vs WS2812B: what are the key differences in channel count, byte meaning, and practical control method?

SM15155 differs by channel model, frame meaning, and intended lamp use. WS2812B workflows usually assume RGB bytes for addressable LEDs, while the SM15155 lamp in the thread used 5 channels for RGBCW and one global lamp color. The SM15155 frame also included configuration bytes after channel data. In practice, both could share a timing-compatible SPI sender, but only after the author prepared the correct SM15155 raw packet format. [#21121650]

How can you control an SM15155 lamp in OpenBeken by reusing the SPI-based SM16703P or WS2812B-style raw byte sender?

You can control it by sending a handcrafted SM15155 frame through the existing SPI-based SM16703P raw-byte path. The author started SM16703P, initialized 5 outputs, and used SM16703P_SetRaw with frames such as FF000000000000000000739CE71F00. That cycled the lamp through RGBCW channels successfully. The extra trailing 00 was ignored in his test, which made the existing sender a practical bridge before native integration. [#21121650]

What is the purpose of the last bytes like 73 9C E7 1F in the SM15155 packet, and how do they relate to current settings or standby bits?

Those final bytes encode non-color configuration, not visible RGBCW intensity data. After the datasheet appeared, the author linked that packet tail to five 5-bit current settings, 2 standby-enable bits, and 5 unused bits. That explains why color control still depended on keeping 73 9C E7 1F in place during successful tests. It also explains an edge case: changing only channel bytes may fail if the configuration tail is invalid. [#21121650]

How do you flash OpenBeken onto the FL_M129_V3 BK7231N module inside this lamp and wire up 3.3V, RX, and TX safely?

You flash it by removing the FL_M129_V3 module, then wiring the programming pads to a 3.3 V serial adapter. The thread shows the author soldered to 3.3 V, GND, RX, and TX and flashed OpenBeken using the BK7231 toolchain. Use only 3.3 V logic and avoid powering the module from higher voltage rails. The module was worth desoldering because its underside pads were clearly labeled. [#21121650]

Why did the author conclude that this particular SM15155 lamp appears to react to 8-bit values even though the datasheet mentions 16-bit color resolution?

He concluded that because his practical tests changed only one byte per 16-bit channel and the lamp still responded correctly. In the integrated code, he wrote 8-bit values into packet positions i * 2 and left the paired bytes at zero, yet the lamp produced the expected colors. He explicitly noted the mismatch and said more testing was needed to explain what the other 8 bits were doing in this product. [#21121650]

What steps are needed to start the SM15155E driver and apply LED_Map in OpenBeken so the lamp works with Home Assistant?

You need to start the driver and apply the lamp’s channel remap. The thread says the minimum autostart command is startDriver SM15155, and the later template uses backlog startDriver SM15155E; LED_Map 0 1 3 2 4. After that, the lamp exposes the proper control panel in OpenBeken and pairs with Home Assistant like other supported RGBCW devices. The template also lists BK7231N board details for this exact lamp. [#21128586]

What safety precautions matter when testing this disassembled RGBCW lamp without proper heatsinking or cooling?

You must limit run time and watch LED temperature because the lamp can overheat when disassembled. The author explicitly warned that his bench setup had no cooling and required care to avoid overheating the LEDs. He later added thermal paste between the LED plates and the metal housing before final assembly. That detail matters because open-air testing without the intended thermal path can damage LEDs or skew results. [#21121650]
Generated by the language model.
ADVERTISEMENT