RGB LED illumination with full PWM

I thought it was kinda sad K8800 didn’t get a LED kit like the K8400, so i decided to give it some bling on my own :wink:

Yes, it has PWM.
No, it’s not Neopixels.
I’ve desoldered the beeper and its resistor (couldn’t hear it unless my face was practically in the printer anyways), as well as the pin 13 LED and its resistor, and reused those pins for G and B. Then i’ve soldered an enamel wire to one of the unused PWM pins on the Atmega 2560, immobilised it with hotglue, and soldered the R to that.

R, G, B and GND from the board go to a little piece of scrap veroboard with NPN transistors and resistors, that serves as the driver for the strips. The power comes from the unused 15V header, and goes through a DC-DC buck converter i had (incidentally, Velleman’s), tuned to about 9-10V so the strips don’t glare too much.

By the way, whoever designed the board for the K8800 wasn’t quite thinking straight - almost all of the PWM pins on the Atmega are unused, those that are used were used for silly things that don’t need PWM at all, and the extra unused GPIO header is all non-PWM pins, except for pin 5, which is a PWM pin, but not when using Marlin, since its timer is used for other things (namely, the stepper ISR). So wasteful.

PS: Please excuse the mess, i ran out of space on my workbench and ended up doing the final reassembly on the kitchen table.

3 Likes

Very interesting mod!
Would you also share us your modifications to the Marlin firmware? Sorry, I’m not so deeply in that matter, but what is the problem with the PWM of pin 5?

No modifications needed, really.
You just need to uncomment this bit in the Configuration.h:

//#define RGB_LED

and configure the pins immediately below:

#if ENABLED(RGB_LED) || ENABLED(RGBW_LED)
  #define RGB_LED_R_PIN 34
  #define RGB_LED_G_PIN 43
  #define RGB_LED_B_PIN 35
  #define RGB_LED_W_PIN -1
#endif

The problem with the PWM on pin 5 is there is no PWM on pin 5 if you’re using Marlin. PWM on AVR microprocessors is ran via its hardware based timers. Atmega 2560 has 6 timers, but not all of them are available to all pins - they’re hardwired to specific timers.

The timer used to drive PWM on pin 5 happens to be the same timer that Marlin uses to time its stepper interrupt routine, so it cannot be repurposed for driving PWM. Pin 5 also happens to be literally the ONLY available PWM pin on the header Velleman/Vertex people pulled out to the (unused) expansion header on the PCB.

Of the remaining PWM enabled pins, only two have traces leading from the Atmega - the one that goes to the buzzer, and the one that goes to the CPU LED. The rest are left floating and unused.

Thank you for your explanation.

This Arduino pin numbering puzzles me all the time. I think PCB5 is pin 11 not 5. (??)

So you are using pin 6 aka beeper_PIN, aka PH3 for RGB_LED_G_PIN and pin 13 aka PB7 for RGB_LED_B_PIN ?

I’m wondering why in Configuration.h the comment says:
“If pins are PWM capable (e.g., 4, 5, 6, 11) then a range of luminance values can be set from 0 to 255.”
both 5 and 11 should work.
Pins 34, 43 and 35 are not even PWM

here is some pinout that I found:
https://camo.githubusercontent.com/23bfc6526ff789019be6888d094ca88f9603e4d5/68747470733a2f2f692e696d6775722e636f6d2f4f37577457416a2e6a7067

Sorry, yeah, meant pin 11, i.e. PB5.
You can’t use that one for PWM, its timer is tied up with the stepper ISR (OC1A).
If you don’t believe me, try it for yourself.

You can use PB7 (CPU LED) and PH3 (BEEPER). Everything else is either necessary for normal functioning of the printer, or not routed from the MCU.

That means you need to solder a wire to one pin yourself if you want RGB with PWM.

No worries, I do believe you. I’m just wondering that the Marlin Configuration.h comment recommends the use of pin 11 when it is known that it is not usable fort standard PWM. I think pin 12 and 13 are tied to the same timer 1 and should not work either.

here I ran a M43 (debug pins) on my K8800:

07:38:22.948 : PIN:   0   Port: E0        RXD                         protected
07:38:22.949 : PIN:   1   Port: E1        TXD                         protected
07:38:22.953 : PIN:   2   Port: E4        <unused/unknown>            Input  = 0    TIMER3B   PWM:     0    WGM: 1    COM3B: 0    CS: 3    TCCR3A: 1    TCCR3B: 3    TIMSK3: 0
07:38:22.954 : PIN:   3   Port: E5        X_MAX_PIN                   protected
07:38:22.959 : PIN:   4   Port: G5        <unused/unknown>            Input  = 0    TIMER0B   PWM:   128    WGM: 3    COM0B: 0    CS: 3    TCCR0A: 3    TCCR0B: 3    TIMSK0: 5   compare interrupt enabled   overflow interrupt enabled
07:38:22.962 : PIN:   5   Port: E3        <unused/unknown>            Input  = 0    TIMER3A   PWM:     0    WGM: 1    COM3A: 0    CS: 3    TCCR3A: 1    TCCR3B: 3    TIMSK3: 0
07:38:22.966 : PIN:   6   Port: H3        BEEPER_PIN                  Output = 0    TIMER4A   PWM:     0    WGM: 1    COM4A: 0    CS: 3    TCCR4A: 1    TCCR4B: 3    TIMSK4: 0
07:38:22.969 : PIN:   7   Port: H4        CASE_LIGHT_PIN              Output = 1    TIMER4B   PWM:     0    WGM: 1    COM4B: 0    CS: 3    TCCR4A: 1    TCCR4B: 3    TIMSK4: 0
07:38:22.971 : PIN:   8   Port: H5        FAN_PIN                     protected
07:38:22.972 : PIN:   9   Port: H6        CONTROLLER_FAN_PIN          protected
07:38:22.973 : .                          FAN1_PIN                    protected
07:38:22.975 : PIN:  10   Port: B4        HEATER_0_PIN                protected
07:38:22.980 : PIN:  11   Port: B5        <unused/unknown>            Input  = 0    TIMER1A   PWM:  2000    WGM: 4    COM1A: 0    CS: 2    TCCR1A: 0    TCCR1B: 10    TIMSK1: 2   non-standard PWM mode   compare interrupt enabled
07:38:22.984 : PIN:  12   Port: B6        <unused/unknown>            Input  = 0    TIMER1B   PWM:     0    WGM: 4    COM1B: 0    CS: 2    TCCR1A: 0    TCCR1B: 10    TIMSK1: 2   non-standard PWM mode
07:38:22.988 : PIN:  13   Port: B7        <unused/unknown>            Output = 1    TIMER0A   PWM:     0    WGM: 3    COM0A: 0    CS: 3    TCCR0A: 3    TCCR0B: 3    TIMSK0: 5   overflow interrupt enabled
07:38:22.991 : .                  TIMER1C is also tied to this pin                  TIMER1C   PWM:     0    WGM: 4    COM1C: 0    CS: 2    TCCR1A: 0    TCCR1B: 10    TIMSK1: 2   non-standard PWM mode
07:38:22.993 : PIN:  14   Port: J1        Y_MAX_PIN                   protected
07:38:22.995 : PIN:  15   Port: J0        <unused/unknown>            Input  = 0
07:38:22.996 : PIN:  16   Port: H1        BTN_EN2                     Input  = 1
07:38:22.998 : PIN:  17   Port: H0        BTN_EN1                     Input  = 1
07:38:22.999 : PIN:  18   Port: D3        <unused/unknown>            Input  = 0
07:38:23.001 : PIN:  19   Port: D2        <unused/unknown>            Input  = 0
07:38:23.002 : PIN:  20   Port: D1        KILL_PIN                    Input  = 1
07:38:23.003 : .                          SDA                         Input  = 1
07:38:23.005 : PIN:  21   Port: D0        SCL                         Input  = 0
07:38:23.006 : .                          SD_DETECT_PIN               Input  = 0
07:38:23.008 : PIN:  22   Port: A0        <unused/unknown>            Input  = 0
07:38:23.010 : PIN:  23   Port: A1        BTN_ENC                     Input  = 1
07:38:23.011 : PIN:  24   Port: A2        E0_ENABLE_PIN               protected
07:38:23.013 : PIN:  25   Port: A3        SDSS                        Output = 1
07:38:23.014 : PIN:  26   Port: A4        E0_STEP_PIN                 protected
07:38:23.015 : PIN:  27   Port: A5        DOGLCD_A0                   Output = 1
07:38:23.017 : .                          LCD_PINS_RS                 Output = 1
07:38:23.018 : PIN:  28   Port: A6        E0_DIR_PIN                  protected
07:38:23.020 : PIN:  29   Port: A7        DOGLCD_CS                   Output = 1
07:38:23.021 : .                          LCD_PINS_ENABLE             Output = 1
07:38:23.022 : PIN:  30   Port: C7        E1_ENABLE_PIN               Output = 1
07:38:23.025 : PIN:  31   Port: C6        LCD_PINS_D7                 Input  = 0
07:38:23.026 : PIN:  32   Port: C5        E1_STEP_PIN                 Output = 0
07:38:23.028 : PIN:  33   Port: C4        LCD_PINS_D6                 Input  = 0
07:38:23.029 : PIN:  34   Port: C3        E1_DIR_PIN                  Output = 0
07:38:23.031 : PIN:  35   Port: C2        LCD_PINS_D5                 Input  = 0
07:38:23.032 : PIN:  36   Port: C1        HEATER_BED_PIN              protected
07:38:23.033 : PIN:  37   Port: C0        LCD_PINS_D4                 Input  = 0
07:38:23.035 : PIN:  38   Port: D7        X_ENABLE_PIN                protected
07:38:23.036 : PIN:  39   Port: G2        <unused/unknown>            Input  = 0
07:38:23.039 : PIN:  40   Port: G1        <unused/unknown>            Input  = 0
07:38:23.040 : PIN:  41   Port: G0        <unused/unknown>            Input  = 0
07:38:23.041 : PIN:  42   Port: L7        <unused/unknown>            Input  = 0
07:38:23.043 : PIN:  43   Port: L6        <unused/unknown>            Input  = 0
07:38:23.046 : PIN:  44   Port: L5        <unused/unknown>            Input  = 0    TIMER5C   PWM:     0    WGM: 1    COM5C: 0    CS: 3    TCCR5A: 1    TCCR5B: 3    TIMSK5: 0
07:38:23.050 : PIN:  45   Port: L4        <unused/unknown>            Input  = 0    TIMER5B   PWM:     0    WGM: 1    COM5B: 0    CS: 3    TCCR5A: 1    TCCR5B: 3    TIMSK5: 0
07:38:23.051 : PIN:  46   Port: L3        Z_STEP_PIN                  protected
07:38:23.053 : PIN:  47   Port: L2        <unused/unknown>            Input  = 0
07:38:23.054 : PIN:  48   Port: L1        Z_DIR_PIN                   protected
07:38:23.056 : PIN:  49   Port: L0        <unused/unknown>            Input  = 0
07:38:23.058 : PIN:  50   Port: B3        AVR_MISO_PIN                Input  = 1
07:38:23.059 : .                          MISO_PIN                    Input  = 1
07:38:23.060 : PIN:  51   Port: B2        AVR_MOSI_PIN                Output = 1
07:38:23.062 : .                          MOSI_PIN                    Output = 1
07:38:23.075 : PIN:  52   Port: B1        AVR_SCK_PIN                 Output = 0
07:38:23.075 : .                          SCK_PIN                     Output = 0
07:38:23.075 : PIN:  53   Port: B0        AVR_SS_PIN                  Output = 1
07:38:23.075 : .                          LCD_SDSS                    Output = 1
07:38:23.075 : .                          SS_PIN                      Output = 1
07:38:23.075 : PIN:  54   Port: F0 (A 0)  X_STEP_PIN                  protected
07:38:23.075 : PIN:  55   Port: F1 (A 1)  X_DIR_PIN                   protected
07:38:23.076 : PIN:  56   Port: F2 (A 2)  Y_ENABLE_PIN                protected
07:38:23.076 : PIN:  57   Port: F3 (A 3)  <unused/unknown>   Analog in =   499   Input  = 0
07:38:23.077 : PIN:  58   Port: F4 (A 4)  <unused/unknown>   Analog in =   429   Input  = 0
07:38:23.079 : PIN:  59   Port: F5 (A 5)  <unused/unknown>   Analog in =   372   Input  = 0
07:38:23.081 : PIN:  60   Port: F6 (A 6)  Y_STEP_PIN                  protected
07:38:23.082 : PIN:  61   Port: F7 (A 7)  Y_DIR_PIN                   protected
07:38:23.084 : PIN:  62   Port: K0 (A 8)  TEMP_BED_PIN                protected
07:38:23.085 : PIN:  63   Port: K1 (A 9)  Z_ENABLE_PIN                protected
07:38:23.088 : PIN:  64   Port: K2 (A10)  <unused/unknown>   Analog in =   689   Input  = 1
07:38:23.090 : PIN:  65   Port: K3 (A11)  <unused/unknown>   Analog in =   578   Input  = 1
07:38:23.091 : PIN:  66   Port: K4 (A12)  Z_MAX_PIN                   protected
07:38:23.093 : PIN:  67   Port: K5 (A13)  TEMP_0_PIN                  protected
07:38:23.094 : PIN:  68   Port: K6 (A14)  Z_MIN_PIN                   protected
07:38:23.095 : PIN:  69   Port: K7 (A15)  FIL_RUNOUT_PIN              Input  = 1

I guess “non-standard PWM mode” means software PWM.

Check this:

So, we do not have enough PWM pins broken pout, I2C pins are also reused, but we do have SPI MOSI/MISO pins available (SK7).

So what do you think about this:

It is a SPI controlled 24 channel PWM driver so you can control 8 RGB-LEDs with it. There is just a little modification in Marlin required as I haven’t seen a TLC5947 support there yet.

Marlin already uses SPI to talk to some of the SPI-configured Trinamic drivers, so that should be fairly easy to implement. An easier (but more expensive) way out is to just use Neopixels (WS2812) since there’s already fully built in support for that, i believe.

Ah! Neopixels are Brightdots right? (please correct me if I’m wrong)

I think that are not that expensive and it looks like super easy to implement:

 // Support for Adafruit Neopixel LED driver
//#define NEOPIXEL_LED
#if ENABLED(NEOPIXEL_LED)
  #define NEOPIXEL_TYPE   NEO_GRBW // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h)
  #define NEOPIXEL_PIN    4        // LED driving pin on motherboard 4 => D4 (EXP2-5 on Printrboard) / 30 => PC7 (EXP3-13 on Rumba)
  #define NEOPIXEL_PIXELS 30       // Number of LEDs in the strip
  #define NEOPIXEL_IS_SEQUENTIAL   // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once.
  #define NEOPIXEL_BRIGHTNESS 127  // Initial brightness (0-255)
  //#define NEOPIXEL_STARTUP_TEST  // Cycle through colors at startup
#endif

AFAIK, yeah, they’re one and the same. Everyone has their own name for it nowadays.
The chip (integrated into each LED) is WS28xx (usually WS2812).

Communication is fairly simple and bitbanged, so it doesn’t require any specific pins, as far as i know.

Hi,
I gave it a try with Velleman’s Large Brightdot module. I realized that the Marlin Neopixel support was not there in 1.1.4 and I did not want to change to a more recent version so I tried to back port the required stuff. You can find my changes to the firmware here:

Marlin 1.1.4 changed for Brightdot/Neopixel

This is now when heating up the nozzle:




2 Likes

Awesome stuff!
There’s one more tweak i keep meaning to do but keep not finding the time to…

Original LED strip “event” support in Marlin was built for printers with heated beds, so the color status indication and progression is kinda wonky on the K8800. It should be fairly easy to change the range a bit.

1 Like

My modified K8800 has a heated bed.

I agree it can be done nicer. Instead going from blue to violet and then from violet to red it would be better to go from blue to red for both bed and nozzle. And in case for the Neopixels it would also work to dedicate have of the pixels to the bed and the other half to the nozzle.