MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
15.97k stars 19.09k forks source link

[Help] How to make Menu Items for Neopixel ? #8280

Closed timmit99 closed 6 years ago

timmit99 commented 6 years ago

I am working to add the ability to controll the color of the neopixel strips on my printer from the LCD. I have gotten the single R, G, and B controls to work, setting the strip to full red,green,or blue. Now i'm trying to add a sub-menu that will allow live updating of the colors. I want the function to run when the color component (Red Green or BLue) is selected however on compile it gives me an error telling my that "pixels" and "set_neopixel_color" aren't declared in this scope.

I am running Marlin 1.1.6

The error is as follows:

Arduino: 1.8.2 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

sketch\ultralcd.cpp: In function 'void update_led_strip()':

ultralcd.cpp:1034: error: 'pixels' was not declared in this scope

   set_neopixel_color(pixels.Color(led_red_brightness, led_green_brightness, led_blue_brightness, 0));
                      ^
ultralcd.cpp:1034: error: 'set_neopixel_color' was not declared in this scope

   set_neopixel_color(pixels.Color(led_red_brightness, led_green_brightness, led_blue_brightness, 0));
                                                                                                    ^
Multiple libraries were found for "LiquidCrystal.h"
 Used: C:\Program Files (x86)\Arduino\libraries\LiquidCrystal
 Not used: C:\Users\Timothy Abraham\Documents\Arduino\libraries\NewliquidCrystal
exit status 1
'pixels' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Here is the code i have added to acomplish this directly

This is the top of ultralcd.cpp:

void lcd_main_menu();
void lcd_tune_menu();
void lcd_prepare_menu();
void lcd_move_menu();
void lcd_control_menu();
void lcd_control_temperature_menu();
void lcd_control_temperature_preheat_material1_settings_menu();
void lcd_control_temperature_preheat_material2_settings_menu();
void lcd_control_motion_menu();
void lcd_control_filament_menu();

and i added:

void lcd_led_menu();
void lcd_led_custom_menu();

as well as adding the following directly at the end of the "lcd_main_menu" function

  MENU_ITEM(submenu, "LED Control", lcd_led_menu);
  END_MENU();
}    // end of main menu function

void lcd_led_menu() {
  START_MENU();
  MENU_BACK(MSG_MAIN);

  MENU_ITEM(gcode, "Turn Off Lights" , PSTR("M150")); 
  MENU_ITEM(gcode, "Turn on Red Lights" ,   PSTR("M150 R255 U0 B0"));
  MENU_ITEM(gcode, "Turn on Green Lights" , PSTR("M150 R0 U255 B0"));
  MENU_ITEM(gcode, "Turn on Blue Lights" ,  PSTR("M150 R0 U0 B255"));
  MENU_ITEM(submenu, "Custom LED", lcd_led_custom_menu);

  END_MENU();
}

uint8_t led_red_brightness;
uint8_t led_green_brightness;
uint8_t led_blue_brightness;

void update_led_strip() {
  set_neopixel_color(pixels.Color(led_red_brightness, led_green_brightness, led_blue_brightness, 0));
}

void lcd_led_custom_menu() {
  START_MENU();
  MENU_BACK("LED Control");

  MENU_ITEM_EDIT_CALLBACK(int8, "Red Intensity", &led_red_brightness, 0, 255, update_led_strip, true);
  MENU_ITEM_EDIT_CALLBACK(int8, "Blue Intensity", &led_green_brightness, 0, 255, update_led_strip, true);
  MENU_ITEM_EDIT_CALLBACK(int8, "Green Intensity", &led_blue_brightness, 0, 255, update_led_strip, true);

  END_MENU();
}
Tannoo commented 6 years ago

If that is all you added, I will add it to mine and try to help out. I had a similar menu working and dropped it several updates ago.

Tannoo commented 6 years ago

I believe this should be there to control all LED types... not just Neopixels.

Tannoo commented 6 years ago

Oooh... that works nicely.

In bugfix-2.0.x:

Configuration.h

/**
 * Printer Event LEDs and LCD Control Menu
 *
 * During printing, the LEDs will reflect the printer status:
 *
 *  - Gradually change from blue to violet as the heated bed gets to target temp
 *  - Gradually change from violet to red as the hotend gets to temperature
 *  - Change to white to illuminate work surface
 *  - Change to green once print has finished
 *  - Turn off after the print has finished and the user has pushed a button
 *  - Other events as desired
 */
#if ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED)
  #define LED_CONTROL_MENU
  #define PRINTER_EVENT_LEDS

ultralcd.cpp ~Line 58

#if HAS_LEVELING
  #include "../feature/bedlevel/bedlevel.h"
#endif

#if ENABLED(LED_CONTROL_MENU)
  #include "../feature/leds/leds.h"
#endif

// For i2c define BUZZ to use lcd_buzz

~Line 186

  #endif // LCD_INFO_MENU

  #if ENABLED(LED_CONTROL_MENU)
    void lcd_led_menu();
    void lcd_led_custom_menu();
  #endif

  #if ENABLED(ADVANCED_PAUSE_FEATURE)

~Line 1019

    #if ENABLED(LCD_INFO_MENU)
      MENU_ITEM(submenu, MSG_INFO_MENU, lcd_info_menu);
    #endif

    #if ENABLED(LED_CONTROL_MENU)
      MENU_ITEM(submenu, "LED Control", lcd_led_menu);
    #endif
    END_MENU();
  }

  /**
   *
   * "Tune" submenu items
   *
   */

~Line 3990

    }
  #endif // LCD_INFO_MENU

  /**
   *
   * LED Menu
   *
   */

#if ENABLED(LED_CONTROL_MENU)

   uint8_t led_red_brightness;
   uint8_t led_green_brightness;
   uint8_t led_blue_brightness;

   void update_led_strip() {
     set_led_color(led_red_brightness, led_green_brightness, led_blue_brightness, 0);
   }

   void lcd_led_custom_menu() {
     START_MENU();
     MENU_BACK("LED Control");
     MENU_ITEM_EDIT_CALLBACK(int8, "Red Intensity", &led_red_brightness, 0, 255, update_led_strip, true);
     MENU_ITEM_EDIT_CALLBACK(int8, "Blue Intensity", &led_green_brightness, 0, 255, update_led_strip, true);
     MENU_ITEM_EDIT_CALLBACK(int8, "Green Intensity", &led_blue_brightness, 0, 255, update_led_strip, true);
     END_MENU();
   }

  void lcd_led_menu() {
    START_MENU();
    MENU_BACK(MSG_MAIN);
    MENU_ITEM(gcode, "Turn Off Lights" , PSTR("M150"));
    MENU_ITEM(gcode, "Turn on Red Lights" ,   PSTR("M150 R255 U0 B0"));
    MENU_ITEM(gcode, "Turn on Green Lights" , PSTR("M150 R0 U255 B0"));
    MENU_ITEM(gcode, "Turn on Blue Lights" ,  PSTR("M150 R0 U0 B255"));
    MENU_ITEM(submenu, "Custom LED", lcd_led_custom_menu);
    END_MENU();
  }

#endif // LED_CONTROL_MENU

  /**
   *
   * Filament Change Feature Screens
   *
   */
Tannoo commented 6 years ago

This should work with all RGBs... now to get the RGBWs added.

Tannoo commented 6 years ago

I changed update_led_strip to update_leds. Trying to leave strip out of the wording as not all LEDs on everyone's system are strips.

Tannoo commented 6 years ago

I added this in language_en.h: ~Line 359

#ifndef MSG_LED_CONTROL
  #define MSG_LED_CONTROL                     _UxGT("LED Control")
#endif
#ifndef MSG_LEDS_OFF
  #define MSG_LEDS_OFF                        _UxGT("Turn Off Lights")
#endif
#ifndef MSG_LED_ON
  #define MSG_LED_ON                          _UxGT("Turn on ")
#endif
#ifndef MSG_RED
  #define MSG_RED                             _UxGT("Red ")
#endif
#ifndef MSG_GREEN
  #define MSG_GREEN                           _UxGT("Green ")
#endif
#ifndef MSG_BLUE
  #define MSG_BLUE                            _UxGT("Blue ")
#endif
#ifndef MSG_WHITE
  #define MSG_WHITE                           _UxGT("White ")
#endif
#ifndef MSG_LIGHTS
  #define MSG_LIGHTS                          _UxGT("Lights")
#endif
#ifndef MSG_LED_INTENSITY
  #define MSG_LED_INTENSITY                   _UxGT("Intensity")
#endif
#ifndef MSG_LED_CUSTOM
  #define MSG_LED_CUSTOM                      _UxGT("Custom LED")
#endif

and changed the functions accordingly in ultralcd.cpp: ~Line 3996

#if ENABLED(LED_CONTROL_MENU)

   uint8_t led_red_brightness;
   uint8_t led_green_brightness;
   uint8_t led_blue_brightness;
   #if ENABLED(RGBW_LED)
     uint8_t led_white_brightness;
   #endif

   void update_leds() {
     set_led_color(led_red_brightness, led_green_brightness, led_blue_brightness,
       #if ENABLED(RGBW_LED)
         led_white_brightness
       #else
         0
       #endif
     );
   }

   void lcd_led_custom_menu() {
     START_MENU();
     MENU_BACK(MSG_LED_CONTROL);
     MENU_ITEM_EDIT_CALLBACK(int8, MSG_RED MSG_LED_INTENSITY, &led_red_brightness, 0, 255, update_leds, true);
     MENU_ITEM_EDIT_CALLBACK(int8, MSG_GREEN MSG_LED_INTENSITY, &led_green_brightness, 0, 255, update_leds, true);
     MENU_ITEM_EDIT_CALLBACK(int8, MSG_BLUE MSG_LED_INTENSITY, &led_blue_brightness, 0, 255, update_leds, true);
     #if ENABLED(RGBW_LED)
       MENU_ITEM_EDIT_CALLBACK(int8, MSG_WHITE MSG_LED_INTENSITY, &led_white_brightness, 0, 255, update_leds, true);
     #endif
     END_MENU();
   }

  void lcd_led_menu() {
    START_MENU();
    MENU_BACK(MSG_MAIN);
    MENU_ITEM(gcode, MSG_LEDS_OFF, PSTR("M150"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_RED MSG_LIGHTS, PSTR("M150 R255"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_GREEN MSG_LIGHTS, PSTR("M150 U255"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_BLUE MSG_LIGHTS, PSTR("M150 B255"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_WHITE MSG_LIGHTS, PSTR("M150 W255"));
    MENU_ITEM(submenu, MSG_LED_CUSTOM, lcd_led_custom_menu);
    END_MENU();
  }

#endif // LED_CONTROL_MENU
Tannoo commented 6 years ago

Now, changed:

leds.cpp ~Line 33:

#if ENABLED(LED_CONTROL_MENU)
  uint8_t led_red_brightness,
          led_green_brightness,
          led_blue_brightness
  #if ENABLED(RGBW_LED)
    , led_white_brightness
  #endif
  #if ENABLED(NEOPIXEL_LED)
    , led_brightness = NEOPIXEL_BRIGHTNESS
  #endif
  ;
#endif

and ~Line 88:

  #if ENABLED(PCA9632)
    pca9632_set_led_color(r, g, b); // Update I2C LED driver
  #endif

  led_red_brightness = r;
  led_green_brightness = g;
  led_blue_brightness = b;
  #if ENABLED(RGBW_LED)
    led_white_brightness = w;
  #endif
};

ultralcd.cpp ~Line 3990:

  /**
   *
   * LED Menu
   *
   */

  #if ENABLED(LED_CONTROL_MENU)
    extern uint8_t led_red_brightness,
                   led_green_brightness,
                   led_blue_brightness
    #if ENABLED(RGBW_LED)
      , led_white_brightness
    #endif
    #if ENABLED(NEOPIXEL_LED)
      , led_brightness
    #endif
    ;

    void update_leds() {
     set_led_color(led_red_brightness, led_green_brightness, led_blue_brightness,
       #if ENABLED(RGBW_LED)
         led_white_brightness
       #endif
       #if ENABLED(NEOPIXEL_LED)
         0, led_brightness
       #endif
     );
    }

    void lcd_led_custom_menu() {
     START_MENU();
     MENU_BACK(MSG_LED_CONTROL);
     MENU_ITEM_EDIT_CALLBACK(int8, MSG_RED MSG_LED_INTENSITY, &led_red_brightness, 0, 255, update_leds, true);
     MENU_ITEM_EDIT_CALLBACK(int8, MSG_GREEN MSG_LED_INTENSITY, &led_green_brightness, 0, 255, update_leds, true);
     MENU_ITEM_EDIT_CALLBACK(int8, MSG_BLUE MSG_LED_INTENSITY, &led_blue_brightness, 0, 255, update_leds, true);
     #if ENABLED(RGBW_LED)
       MENU_ITEM_EDIT_CALLBACK(int8, MSG_WHITE MSG_LED_INTENSITY, &led_white_brightness, 0, 255, update_leds, true);
     #endif
     #if ENABLED(NEOPIXEL_LED)
       MENU_ITEM_EDIT_CALLBACK(int8, MSG_LED_INTENSITY, &led_brightness, 0, 255, update_leds, true);
     #endif
     END_MENU();
    }

    void lcd_led_menu() {
      START_MENU();
      MENU_BACK(MSG_MAIN);
      MENU_ITEM(gcode, MSG_LEDS_OFF, PSTR("M150"));
      MENU_ITEM(gcode, MSG_LED_ON MSG_RED MSG_LIGHTS, PSTR("M150 R255"));
      MENU_ITEM(gcode, MSG_LED_ON MSG_GREEN MSG_LIGHTS, PSTR("M150 U255"));
      MENU_ITEM(gcode, MSG_LED_ON MSG_BLUE MSG_LIGHTS, PSTR("M150 B255"));
      MENU_ITEM(gcode, MSG_LED_ON MSG_WHITE MSG_LIGHTS, PSTR("M150 W255"));
      MENU_ITEM(submenu, MSG_LED_CUSTOM, lcd_led_custom_menu);
      END_MENU();
    }

  #endif // LED_CONTROL_MENU
Tannoo commented 6 years ago

I now have full control of the leds through the lcd screen without loosing the light levels while adjusting.

timmit99 commented 6 years ago

Awesome work, this is great to see someone else here to help me. One change i have done is change the working from "brightness" to intensity" as to not confuse them with the LED brightness parameter "P".

   uint8_t led_red_brightness;
   uint8_t led_green_brightness;
   uint8_t led_blue_brightness;
   #if ENABLED(RGBW_LED)
     uint8_t led_white_brightness;
   #endif

Becomes

   uint8_t led_red_intensity;
   uint8_t led_green_intensity;
   uint8_t led_blue_intensity;
   #if ENABLED(RGBW_LED)
     uint8_t led_white_intensity;
   #endif

This will avoid confusion because with my RGB Neopixel strip i can send an M150 R255 U255 B255 P10 where the "P" controls the ACTUAL brightness of the overall LEDS.

Also, the MENU_ITEM(gcode, MSG_LED_ON MSG_WHITE MSG_LIGHTS, PSTR("M150 W255")); only works if you have an RGBW strip. There should be something akin to:

    START_MENU();
    MENU_BACK(MSG_MAIN);
    MENU_ITEM(gcode, MSG_LEDS_OFF, PSTR("M150"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_RED MSG_LIGHTS, PSTR("M150 R255"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_GREEN MSG_LIGHTS, PSTR("M150 U255"));
    MENU_ITEM(gcode, MSG_LED_ON MSG_BLUE MSG_LIGHTS, PSTR("M150 B255"));
    #if ENABLED(RGBW_LED)
        MENU_ITEM(gcode, MSG_LED_ON MSG_WHITE MSG_LIGHTS, PSTR("M150 W255"));
    #else
        MENU_ITEM(gcode, MSG_LED_ON MSG_WHITE MSG_LIGHTS, PSTR("M150 R255 U255 B255"));
    MENU_ITEM(submenu, MSG_LED_CUSTOM, lcd_led_custom_menu);
    END_MENU();
  }
Tannoo commented 6 years ago

It would be easier to do this, if I had a branch to submit PR's against.

Tannoo commented 6 years ago

Well... the W will work with Neopixels... and I only have the GRB strip. NEO_WHITE will be called if all RGB are 255.

Tannoo commented 6 years ago

I haven't checked if it will work with RGB's the same way.

timmit99 commented 6 years ago

I only have the NeoPixel GRB strip and the M150 W255 doesnt work for me; I'm on 1.1.6 right now.

timmit99 commented 6 years ago

Do you think it would be worth it for me to update to bugfix 2.0.x? I'm willing to do that to be on the same page as you with this.

Tannoo commented 6 years ago

I think so. It's the latest codebase.

Tannoo commented 6 years ago

It also should be made to work with bugfix-1.1.x. Once it's working like you want it.

timmit99 commented 6 years ago

Ok, Im curently tring to get the basic marlin 2.0.x bugfix running on my I3. give me afew to copy over the LED settings and test.

My issue with the 1.0.x was the oder of compilation and it saying that 'set_neopixel_color' was not declared in this scope

Tannoo commented 6 years ago

I have a NEOPIXEL RGB and a standard RGB strip that I can test. My printer is an i3 clone.

Tannoo commented 6 years ago
#if ENABLED(LED_CONTROL_MENU)
  #include "../feature/leds/leds.h"
#endif

is needed for bugfix-2.0.x in ultralcd.cpp.

Tannoo commented 6 years ago

I used set_led_color as it covers all the leds.... not just Neopixel.

Tannoo commented 6 years ago

I don't know if the neopixels were introduced in 1.0.x.

timmit99 commented 6 years ago

Sorry, dont know why i put 1.0.x ... I was running 1.1.6 before wheree i had the issue with it not being declared

Tannoo commented 6 years ago

Ok... in 1.1.x, there are NEOPIXELS... use set_led_color.

timmit99 commented 6 years ago

Are you sure that in Configuration_adv.h is where you added the #define LED_CONTROL_MENU ? for me that is showing up in Configuration.h.

Tannoo commented 6 years ago

You are correct... my mistake. I corrected the post now.

timmit99 commented 6 years ago

Ok, just making sure im not loosing my mind. and what version Arduino IDE are you using? Do all the separate files show up for you as tabs anymore or is that not a thing anymore? All i have when running the Marlin.ide is just config and config_adv as well as the readme.

Tannoo commented 6 years ago

OH....Well, the Arduino IDE doesn't show all the files. You can edit them via a text editor of your choice. The IDE will still compile it just fine.

I am using PlatformIO.

Tannoo commented 6 years ago

PlatformIO is quite different than the Arduino IDE. I think it would be good to switch to it. But you don't have to do that now.

Using PlatformIO gives the ability to compile and upload for many different board types. The AVR (Arduino) and many 32-bit as well.

Tannoo commented 6 years ago

I have Arduino IDE 1.8.4. I still use it for smaller projects. It doesn't show all the files and folders (yet) to the user.

timmit99 commented 6 years ago

Ok, thats fine by me. Im using notepadd++ to do the editing right now.

Tannoo commented 6 years ago

The Arduino IDE will not compile any 32-bit stuff. At least PlatformIO is needed for that.

Tannoo commented 6 years ago

When you want to start with PlatformIO, here's the link: http://platformio.org/

timmit99 commented 6 years ago

I'm Just running this on my ATmega Ramps setup so the IDE works fine right now. I DO want to use this on my ReArm board in the future but we can cross that bridge when we get to it.

Tannoo commented 6 years ago

Ah... yes. PlatformIO will be needed for the Re-Arm. I have that board also, but not on a printer yet.

timmit99 commented 6 years ago

Are you willing to do the PR for this once we verify that it is working as intended? I'm pretty new to the Github desktop client and its operation.

Tannoo commented 6 years ago

I can. I will mention you in it. Meaning... giving you the credit.

Tannoo commented 6 years ago

I can also help guide you in making the PR.

timmit99 commented 6 years ago

Ok, I had a minor heart attack when it all compiled and uploaded correctly yet i saw none of the menu items. Took me a second but then i realized i never ACTUALLY un-commented the #define NEOPIXEL_LED. Fixed that and its all working great now except for the Turn On White Light option. It just turns my LEDS off.

In the past i was using the M150 R255 U255 B255 to get the white light as the pixels i have dont have a while die in them.

timmit99 commented 6 years ago

for the PR I would need to download the Bugfix 2.0.x repo through the desktop client, make the changes and then comment on the changes?

Tannoo commented 6 years ago

Well, I don't have the white die either... This takes care of that:

  #if ENABLED(NEOPIXEL_LED)
    if ((w == 255) || ((r == 255) && (g == 255) && (b == 255)))
      neopixel_set_led_color(NEO_WHITE, p);
    else
      neopixel_set_led_color(r, g, b, w, p);
  #endif
Tannoo commented 6 years ago

The only way to 'fade' the 'white' (via the lcd) is the P value.

timmit99 commented 6 years ago

strange, I'm not sure why yours works when mine doesn't then. Where was this code placed?

Tannoo commented 6 years ago

for the PR I would need to download the Bugfix 2.0.x repo through the desktop client, make the changes and then comment on the changes?

Well, you would create another branch in your repo base on bugfix-2.0.x, then make and commit any changes to that branch. Once the PR is created.... any commits to that same branch will be automatically applied to the PR.

Tannoo commented 6 years ago

Where was this code placed?

That snipplet was from leds.cpp. It should already be there.

timmit99 commented 6 years ago

That code is not in my leds.cpp file. Was it an addition of yours?

Tannoo commented 6 years ago

Well... hmm. Maybe it was a layover from another PR.

Tannoo commented 6 years ago
leds cpp
Tannoo commented 6 years ago

In the set_led_color function.

Tannoo commented 6 years ago

Yep, it's not there. Maybe add it to this PR?

timmit99 commented 6 years ago

image

This is what my branch has in leds.cpp. Shoudl i overwrite the

#if ENABLED(NEOPIXEL_LED)

    const uint32_t color = pixels.Color(r, g, b, w);
    static uint16_t nextLed = 0;

    pixels.setBrightness(p);
    if (!isSequence)
      set_neopixel_color(color);
    else {
      pixels.setPixelColor(nextLed, color);
      pixels.show();
      if (++nextLed >= pixels.numPixels()) nextLed = 0;
      return;
    }

  #endif