Tannoo / Marlin

Optimized firmware for RepRap 3D printers based on the Arduino platform.
http://www.marlinfw.org/
GNU General Public License v3.0
1 stars 0 forks source link

UBL LCD Matrix Plotting #4

Closed Tannoo closed 7 years ago

Tannoo commented 7 years ago

@Roxy-3D, this is the 'new and improved' version... ready for improvement.

https://github.com/Tannoo/Marlin/tree/UBL_Mesh_Plotting

Tannoo commented 7 years ago

I take that back.... I still need to scale up the 3x3 grid.

Tannoo commented 7 years ago

Ok... Scaling issues..

Still trying to get this right.

    void _lcd_ubl_plot_drawing(uint8_t x_plot, uint8_t y_plot) {
      uint8_t x_frame_offset, y_frame_offset,
              x_frame_max, y_frame_max,
              x_pixel_scaling, y_pixel_scaling,
              x_pixel, y_pixel;

      // Starting points for the "box"
      x_frame_offset = (LCD_PIXEL_WIDTH / 6);
      y_frame_offset = (LCD_PIXEL_HEIGHT / 10);

      // Ending points for the "box"
      x_frame_max = x_frame_offset - 2;
      y_frame_max = y_frame_offset + 13;

      // Scaling for the pixel placement
      x_pixel_scaling = map(GRID_MAX_POINTS_X, 3, 15, 75, 10);
      y_pixel_scaling = map(GRID_MAX_POINTS_Y, 3, 15, 75, 10);

      // Points for pixel placement
      x_pixel = (x_plot * (x_pixel_scaling / 10)) + x_frame_offset + 2;
      y_pixel = (y_plot * (y_pixel_scaling / 10)) + y_frame_offset + 2;

      // Show X and Y positions at top of screen
      u8g.setColorIndex(1);
      u8g.setPrintPos(10, 8);
      lcd_print("X:");
      lcd_print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]))));
      u8g.setPrintPos(70, 8);
      lcd_print("Y:");
      lcd_print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));

      // Draw frame and location pixel
      #if IS_KINEMATIC
        u8g.drawCircle(x_frame_offset * 2,
                       y_frame_offset * 2, y_frame_max / 2);
      #endif
      // Double the size of the "box" and pixel
      u8g.setScale2x2();
      // Draw the "box"
      u8g.drawFrame(x_frame_offset, y_frame_offset, x_frame_max, y_frame_max);
      // Plot the pixel
      u8g.drawPixel(x_pixel, y_pixel);

      // Print plot position
      u8g.undoScale();
      u8g.setPrintPos(10, 63);
      lcd_print("(");
      u8g.print(x_plot);
      lcd_print(",");
      u8g.print(y_plot);
      lcd_print(")");

      // Show the location value
      u8g.setPrintPos(60, 63);
      lcd_print("Z:");
      if (!isnan(ubl.z_values[x_plot][y_plot])) {
        lcd_print(ftostr43sign(ubl.z_values[x_plot][y_plot]));
      }
      else {
        lcd_print(" -----");
      }
    }
Roxy-3D commented 7 years ago

I don't see the problem yet...

Tannoo commented 7 years ago

Okay, I've somewhat made progress, but still not ready.

3x3 maps just fine.... maybe I need the box to be the same size as the 15x15 that also maps just fine.

But, anything else between those are all jacked up.

Tannoo commented 7 years ago

Okay, @Roxy-3D, I created a new branch to get it updated with the latest bugfix-1.1.x.

This is also the latest I have that works with 3x3 and 15x15 and removed most of the BS math that was only getting confusing and not helping much.

I've updated the posts above with current link and snipplet.

Roxy-3D commented 7 years ago

I'll load it up as soon as I can....

Tannoo commented 7 years ago

I think I found that I need to scale another number.

      x_pixel = (x_plot * (x_pixel_scaling / 10)) + <<x_frame_offset + 2>>; <-- This one.
      y_pixel = (y_plot * (y_pixel_scaling / 10)) + <<y_frame_offset + 2>>; <-- And this one.

I will try in the morning with:


     x_pixel_offset = map(GRID_MAX_POINTS_X, 3, 15, x_frame-offset +2, 0);
     y_pixel_offset = map(GRID_MAX_POINTS_Y, 3, 15, y_frame-offset +2, 0);

      x_pixel = x_plot * (x_pixel_scaling / 10) + x_pixel_offset;
      y_pixel = y_plot * (y_pixel_scaling / 10) + y_pixel_offset;
Roxy-3D commented 7 years ago

It seems like I'm at a stand still.... I need the Configuration.h files that cause the UBL Z lift problem and they are not posted yet. So... If you can have the 'current code' in your branch, I'll start debugging it tomorrow. Most likely, it will be easier to just do a re-write. But I'll start with what you have.

Tannoo commented 7 years ago

I'm not pushing you... I'm just keeping you up to date.

It is up to date as of this morning. https://github.com/Tannoo/Marlin/tree/UBL_Mesh_Plotting

Tannoo commented 7 years ago

I have some serial outputs happening to see what each variable is at any given point.

Roxy-3D commented 7 years ago

OK! Great! If I don't have the needed Configuration.h files to duplicate the problem... I'll start trying to get the Postage Stamp map to work for all mesh dimensions in the morning....

Tannoo commented 7 years ago

x_pixel and y_pixel are the only ones that go out of range now.

Roxy-3D commented 7 years ago

I'm starting to dip my toes into the water.

Probably _lcd_ubl_plot_draw(x_plot, y_plot); should be in ultralcd.cpp instead of in a .h file. If you keep working on that function.... In a day or two, I'll have a different implementation of it. And you can take what ever ideas you like and incorporate them into your code.

UPDATE: Oh! I think I see why you did that. That is the graphical version of the function. But the thing is, it is enough C++ code, it probably still belongs in ultralcd.cpp with conditional compilation flags around it.

YET ANOTHER UPDATE: I've got some problems trying to do things with Map Type 3. I have trouble even selecting it because my encoder wheel multiplier is too large. So, I have to back up and re-tune some of my settings. If you are open to suggestions.... You can work to get the title for each map type to display as the user rotates the dial. Maybe 'Map Type' should be a whole menu page with line items and when you pick one, it does it???

And if you are willing to work together on this... I'll just focus on the 'Output to LCD Grid' version. The way you have 'Output to LCD Grid' setup looks nice. It would seem it isn't just a map option. It probably belongs in the map category also, but it would seem it should be a line item right under Activate and Deactivate. And maybe with a title 'Edit Mesh'.

And in fact, you have it setup so when a click happens, the mesh point gets edited. So, if you have other things you don't mind working on... Let me see if I can get the display to work right for all screen dimensions and maybe you can just paste the code in???

Tannoo commented 7 years ago

Yeah.... I couldn't get the u8g.fuctions to work in ultralcd.cpp.

After drowning in this for the last month or so, I was going to try and move it into ultralcd.cpp after getting it working.

Tannoo commented 7 years ago

I have found that the scaling is not working because it's not linear. So, I'm trying to get everything to work individually and then incorporate a multimap function I found. Like mapping an array.

Tannoo commented 7 years ago

The K.I.S.S. method is what I reminding myself. lol

Roxy-3D commented 7 years ago

I didn't see these comments until after I edited my post up above.

Tannoo commented 7 years ago

I didn't post them until after your edit. lol

Tannoo commented 7 years ago

So far, I have gotten 3x3 - 11x11 to work, the numbers are all over the place to make it work. Now, I can see why the maps were giving me such a fit.

Roxy-3D commented 7 years ago

OK! I'm not sure how fast I'll make progress. Even with no interruptions (like more important things coming up) this is tricky code (as you know)!!!! But, it should be a fun piece of code to write!

Who knows... I might be able to get it working for all mesh sizes within 3 or 4 days....

Tannoo commented 7 years ago

I have some "dirty" code that works for most of it now. And I want to clean it up by implementing the multimap function:

    // note: the _in array should have increasing values
    int multiMap(int val, int* _in, int* _out, uint8_t size)
    {
      // take care the value is within range
      // val = constrain(val, _in[0], _in[size-1]);
      if (val <= _in[0]) return _out[0];
      if (val >= _in[size-1]) return _out[size-1];

      // search right interval
      uint8_t pos = 1;  // _in[0] allready tested
      while(val > _in[pos]) pos++;

      // this will handle all exact "points" in the _in array
      if (val == _in[pos]) return _out[pos];

      // interpolate in the right segment for the rest
      return (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
    }

Unless you have a better way to handle data that looks more like an X,Y scatter chart. lol

Roxy-3D commented 7 years ago

It would seem the simplest way would be to just enque a command for the .CSV and Topography Map to host. That would be just a "G29 T0" or a "G29 T1".

I think the problem with the current LCD Map and that code up above is I think differently than that. So I'll have to work through both and see what I can do with it.

Tannoo commented 7 years ago

My code enques G29 T3 for the lcd map.

I have: T0 for host output. T1 for CSV. T2 for X,Y list // Not sure what else you call it. T3 for lcd map

Tannoo commented 7 years ago

G29 T2:

Bed Topography Report List:

M421 I 0 J 0 Z 0.000000 ; X 10.00, Y 10.00
M421 I 0 J 1 Z 0.000000 ; X 10.00, Y 26.50
M421 I 0 J 2 Z 0.000000 ; X 10.00, Y 43.00
M421 I 0 J 3 Z 0.000000 ; X 10.00, Y 59.50
M421 I 0 J 4 Z 0.000000 ; X 10.00, Y 76.00
M421 I 0 J 5 Z 0.000000 ; X 10.00, Y 92.50
M421 I 0 J 6 Z 0.000000 ; X 10.00, Y 109.00
M421 I 0 J 7 Z 0.000000 ; X 10.00, Y 125.50
M421 I 0 J 8 Z 0.000000 ; X 10.00, Y 142.00
M421 I 0 J 9 Z 0.000000 ; X 10.00, Y 158.50
M421 I 0 J 10 Z 0.000000 ; X 10.00, Y 175.00
M421 I 1 J 0 Z 0.000000 ; X 28.00, Y 10.00
M421 I 1 J 1 Z 0.000000 ; X 28.00, Y 26.50
M421 I 1 J 2 Z 0.000000 ; X 28.00, Y 43.00
M421 I 1 J 3 Z 0.000000 ; X 28.00, Y 59.50
...
Roxy-3D commented 7 years ago

T2 for X,Y list // Not sure what else you call it.

I'm not sure how to convert it to a short and descriptive name. But it produces the gcode so that you can later print it and get it re-absorbed into the printer. Pretty much, it is an 'off printer backup of your mesh'

Tannoo commented 7 years ago

Pretty much, it is an 'off printer backup of your mesh'

OOOOhhhh.

Tannoo commented 7 years ago

I'll change the name to "Mesh Backup Output".

Tannoo commented 7 years ago

OR "Mesh G-coded Output"

Roxy-3D commented 7 years ago

Even "Off Printer Backup" would be good. And when people look at it and see the M421 commands... They will understand what is happening.

Tannoo commented 7 years ago

K...done.

Tannoo commented 7 years ago

Here's my "dirty" code so far:

    void _lcd_ubl_plot_drawing(uint8_t x_plot, uint8_t y_plot) {
      uint8_t x_frame_offset, y_frame_offset,
              x_frame_max, y_frame_max,
              x_pixel_scaling, y_pixel_scaling,
              x_pixel, y_pixel;

      // Starting points for the "box"
      if (GRID_MAX_POINTS_Y == GRID_MAX_POINTS_X) {
        if(GRID_MAX_POINTS_X == 3)  { x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2; y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 4)  { x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2; y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 5)  { x_frame_offset = LCD_PIXEL_WIDTH / 6;     y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 6)  { x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2; y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 7)  { x_frame_offset = LCD_PIXEL_WIDTH / 6 + 3; y_frame_offset = LCD_PIXEL_HEIGHT / 9;  }
        if(GRID_MAX_POINTS_X == 8)  { x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2; y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 9)  { x_frame_offset = LCD_PIXEL_WIDTH / 6 + 1; y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 10) { x_frame_offset = LCD_PIXEL_WIDTH / 6;     y_frame_offset = LCD_PIXEL_HEIGHT / 10 - 1; }
        if(GRID_MAX_POINTS_X == 11) { x_frame_offset = LCD_PIXEL_WIDTH / 5;     y_frame_offset = LCD_PIXEL_HEIGHT / 8 + 1; }
        if(GRID_MAX_POINTS_X == 12) { x_frame_offset = LCD_PIXEL_WIDTH / 5;     y_frame_offset = LCD_PIXEL_HEIGHT / 8; }
        if(GRID_MAX_POINTS_X == 13) { x_frame_offset = LCD_PIXEL_WIDTH / 5;     y_frame_offset = LCD_PIXEL_HEIGHT / 8; }
        if(GRID_MAX_POINTS_X == 14) { x_frame_offset = LCD_PIXEL_WIDTH / 6;     y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
        if(GRID_MAX_POINTS_X == 15) { x_frame_offset = LCD_PIXEL_WIDTH / 6;     y_frame_offset = LCD_PIXEL_HEIGHT / 10; }
      }
      else {
      x_frame_offset = LCD_PIXEL_WIDTH / 6;
      y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      }

      // Ending points for the "box"
      if (GRID_MAX_POINTS_Y == GRID_MAX_POINTS_X) {
        if(GRID_MAX_POINTS_X == 3)  { x_frame_max = x_frame_offset - 4;  y_frame_max = y_frame_offset + 13; }
        if(GRID_MAX_POINTS_X == 4)  { x_frame_max = x_frame_offset - 3;  y_frame_max = y_frame_offset + 14; }
        if(GRID_MAX_POINTS_X == 5)  { x_frame_max = x_frame_offset;      y_frame_max = y_frame_offset + 15; }
        if(GRID_MAX_POINTS_X == 6)  { x_frame_max = x_frame_offset - 3;  y_frame_max = y_frame_offset + 14; }
        if(GRID_MAX_POINTS_X == 7)  { x_frame_max = x_frame_offset - 7;  y_frame_max = y_frame_offset + 10; }
        if(GRID_MAX_POINTS_X == 8)  { x_frame_max = x_frame_offset - 4;  y_frame_max = y_frame_offset + 13; }
        if(GRID_MAX_POINTS_X == 9)  { x_frame_max = x_frame_offset - 1;  y_frame_max = y_frame_offset + 15; }
        if(GRID_MAX_POINTS_X == 10) { x_frame_max = x_frame_offset - 2;  y_frame_max = y_frame_offset + 15; }
        if(GRID_MAX_POINTS_X == 11) { x_frame_max = x_frame_offset - 10; y_frame_max = y_frame_offset + 6; }
        if(GRID_MAX_POINTS_X == 12) { x_frame_max = x_frame_offset - 9;  y_frame_max = y_frame_offset + 8; }
        if(GRID_MAX_POINTS_X == 13) { x_frame_max = x_frame_offset - 8;  y_frame_max = y_frame_offset + 10; }
        if(GRID_MAX_POINTS_X == 14) { x_frame_max = x_frame_offset - 2;  y_frame_max = y_frame_offset + 14; }
        if(GRID_MAX_POINTS_X == 15) { x_frame_max = x_frame_offset - 2;  y_frame_max = y_frame_offset + 14; }
      }
      else {
        x_frame_max = x_frame_offset - 2;
        y_frame_max = y_frame_offset + 14;
      }

      // Scaling for the pixel placement
      if (GRID_MAX_POINTS_Y == GRID_MAX_POINTS_X) {
        if(GRID_MAX_POINTS_X == 3)  x_pixel_scaling = 75;
        if(GRID_MAX_POINTS_X == 4)  x_pixel_scaling = 50;
        if(GRID_MAX_POINTS_X == 5)  x_pixel_scaling = 40;
        if(GRID_MAX_POINTS_X == 6)  x_pixel_scaling = 30;
        if(GRID_MAX_POINTS_X == 7)  x_pixel_scaling = 28;
        if(GRID_MAX_POINTS_X == 8)  x_pixel_scaling = 20;
        if(GRID_MAX_POINTS_X == 9)  x_pixel_scaling = 20;
        if(GRID_MAX_POINTS_X == 10) x_pixel_scaling = 20;
        if(GRID_MAX_POINTS_X == 11) x_pixel_scaling = 15;
        if(GRID_MAX_POINTS_X == 12) x_pixel_scaling = 15;
        if(GRID_MAX_POINTS_X == 13) x_pixel_scaling = 15;
        if(GRID_MAX_POINTS_X == 14) x_pixel_scaling = 15;
        if(GRID_MAX_POINTS_X == 15) x_pixel_scaling = 10;
        y_pixel_scaling = x_pixel_scaling;
      }
      else {
        x_pixel_scaling = map(GRID_MAX_POINTS_X, 3, 15, 55, 1) / 10;
        y_pixel_scaling = map(GRID_MAX_POINTS_Y, 3, 15, 55, 1) / 10;
      }

      // Points for pixel placement
      x_pixel = x_plot * (x_pixel_scaling / 10) + x_frame_offset + 2;
      y_pixel = y_plot * (y_pixel_scaling / 10) + y_frame_offset + 2;

      // Show X and Y positions at top of screen
      u8g.setColorIndex(1);
      u8g.setPrintPos(10, 8);
      lcd_print("X:");
      lcd_print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]))));
      u8g.setPrintPos(70, 8);
      lcd_print("Y:");
      lcd_print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));

      // Draw frame and location pixel
      #if IS_KINEMATIC
        u8g.drawCircle(x_frame_offset * 2,
                       y_frame_offset * 2, y_frame_max / 2);
      #endif
      // Double the size of the "box" and pixel
      u8g.setScale2x2();
      // Draw the "box"
      u8g.drawFrame(x_frame_offset, y_frame_offset, x_frame_max, y_frame_max);
      // Plot the pixel
      u8g.drawPixel(x_pixel, y_pixel);

      // Print plot position
      u8g.undoScale();
      u8g.setPrintPos(10, 63);
      lcd_print("(");
      u8g.print(x_plot);
      lcd_print(",");
      u8g.print(y_plot);
      lcd_print(")");

      // Show the location value
      u8g.setPrintPos(60, 63);
      lcd_print("Z:");
      if (!isnan(ubl.z_values[x_plot][y_plot])) {
        lcd_print(ftostr43sign(ubl.z_values[x_plot][y_plot]));
      }
      else {
        lcd_print(" -----");
      }

    SERIAL_ECHOLNPAIR("LCD_PIXEL_WIDTH: ", LCD_PIXEL_WIDTH);
    SERIAL_ECHOLNPAIR("LCD_PIXEL_HEIGHT: ", LCD_PIXEL_HEIGHT);

    SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X: ", GRID_MAX_POINTS_X);
    SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y: ", GRID_MAX_POINTS_Y);

    SERIAL_ECHOLNPAIR("x_frame_offset: ", x_frame_offset);
    SERIAL_ECHOLNPAIR("y_frame_offset: ", y_frame_offset);

    SERIAL_ECHOLNPAIR("x_frame_max: ", x_frame_max);
    SERIAL_ECHOLNPAIR("y_frame_max: ", y_frame_max);

    SERIAL_ECHOLNPAIR("x_pixel_scaling: ", x_pixel_scaling);
    SERIAL_ECHOLNPAIR("y_pixel_scaling: ", y_pixel_scaling);

    SERIAL_ECHOLNPAIR("x_pixel: ", x_pixel);
    SERIAL_ECHOLNPAIR("y_pixel: ", y_pixel);
    SERIAL_EOL;

    }
Roxy-3D commented 7 years ago

I'll start with yours...

Tannoo commented 7 years ago

Ok. I would love to see what you end up with. Being the math and code wizard you are, you are bound to come up with something better and more elegant than I.

Tannoo commented 7 years ago

I've got to get another Mega.... I know I'm wearing it out. lol

Roxy-3D commented 7 years ago

I've got to get another Mega.... I know I'm wearing it out. lol

nah... You get a minimum of 10,000 different firmware uploads. (That is the guaranteed number. Most likely it is 4 or 5 times that high.) but for $10 (including shipping) you can get a new one. So it doesn't hurt to have an extra one sitting around.

I've been thinking how I'm going to write the code. I'm going to add a new M command (just for development) where I can set the mesh dimensions. And I'm going to point the Double Click handler at my code so I don't have to go through a complicated menu path to try things.

I'm also going to do some something like:

const expression int _GRID_MAX_POINTS_X = GRID_MAX_POINTS_X;
const expression int _GRID_MAX_POINTS_Y = GRID_MAX_POINTS_Y;

so I can set the _GRID_MAX_POINTSX&Y with the M command but when you are done testing, you just delete the M command and those 2 lines... (and delete the '' in front of any GRID_MAX_POINT and everything is back to normal.

I think you can work in any part of the code and you won't affect me. And my guess is, what ever I do, will just be a cut and paste for you to make use of... Do I still have write privileges to your repository? If so.... I can easily update your repository so you can see where I'm at.

Tannoo commented 7 years ago

I have not removed you.... I'm not sure if you are a collaborator, but I will invite you anyway to be sure.

Also, I have some "dirty" code that works now. Even for asymmetrical matrices.

    void _lcd_ubl_plot_drawing(uint8_t x_plot, uint8_t y_plot) {
      uint8_t x_frame_offset, y_frame_offset,
              x_frame_max, y_frame_max,
              x_pixel_scaling, y_pixel_scaling,
              x_pixel, y_pixel;

      // Starting X point for the "box"
      if(GRID_MAX_POINTS_X == 3)  x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2;
      if(GRID_MAX_POINTS_X == 4)  x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2;
      if(GRID_MAX_POINTS_X == 5)  x_frame_offset = LCD_PIXEL_WIDTH / 6;
      if(GRID_MAX_POINTS_X == 6)  x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2;
      if(GRID_MAX_POINTS_X == 7)  x_frame_offset = LCD_PIXEL_WIDTH / 6 + 3;
      if(GRID_MAX_POINTS_X == 8)  x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2;
      if(GRID_MAX_POINTS_X == 9)  x_frame_offset = LCD_PIXEL_WIDTH / 6 + 1;
      if(GRID_MAX_POINTS_X == 10) x_frame_offset = LCD_PIXEL_WIDTH / 6;
      if(GRID_MAX_POINTS_X == 11) x_frame_offset = LCD_PIXEL_WIDTH / 5;
      if(GRID_MAX_POINTS_X == 12) x_frame_offset = LCD_PIXEL_WIDTH / 5;
      if(GRID_MAX_POINTS_X == 13) x_frame_offset = LCD_PIXEL_WIDTH / 5 - 1;
      if(GRID_MAX_POINTS_X == 14) x_frame_offset = LCD_PIXEL_WIDTH / 5 - 1;
      if(GRID_MAX_POINTS_X == 15) x_frame_offset = LCD_PIXEL_WIDTH / 6 + 2;

      // Starting Y point for the "box"
      if(GRID_MAX_POINTS_Y == 3)  y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      if(GRID_MAX_POINTS_Y == 4)  y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      if(GRID_MAX_POINTS_Y == 5)  y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      if(GRID_MAX_POINTS_Y == 6)  y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      if(GRID_MAX_POINTS_Y == 7)  y_frame_offset = LCD_PIXEL_HEIGHT / 9;
      if(GRID_MAX_POINTS_Y == 8)  y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      if(GRID_MAX_POINTS_Y == 9)  y_frame_offset = LCD_PIXEL_HEIGHT / 10;
      if(GRID_MAX_POINTS_Y == 10) y_frame_offset = LCD_PIXEL_HEIGHT / 10 - 2;
      if(GRID_MAX_POINTS_Y == 11) y_frame_offset = LCD_PIXEL_HEIGHT / 8 + 1;
      if(GRID_MAX_POINTS_Y == 12) y_frame_offset = LCD_PIXEL_HEIGHT / 8;
      if(GRID_MAX_POINTS_Y == 13) y_frame_offset = LCD_PIXEL_HEIGHT / 8;
      if(GRID_MAX_POINTS_Y == 14) y_frame_offset = LCD_PIXEL_HEIGHT / 9;
      if(GRID_MAX_POINTS_Y == 15) y_frame_offset = LCD_PIXEL_HEIGHT / 10;

      // Ending X point for the "box"
      if(GRID_MAX_POINTS_X == 3)  x_frame_max = x_frame_offset - 4;
      if(GRID_MAX_POINTS_X == 4)  x_frame_max = x_frame_offset - 3;
      if(GRID_MAX_POINTS_X == 5)  x_frame_max = x_frame_offset;
      if(GRID_MAX_POINTS_X == 6)  x_frame_max = x_frame_offset - 3;
      if(GRID_MAX_POINTS_X == 7)  x_frame_max = x_frame_offset - 7;
      if(GRID_MAX_POINTS_X == 8)  x_frame_max = x_frame_offset - 4;
      if(GRID_MAX_POINTS_X == 9)  x_frame_max = x_frame_offset - 1;
      if(GRID_MAX_POINTS_X == 10) x_frame_max = x_frame_offset + 2;
      if(GRID_MAX_POINTS_X == 11) x_frame_max = x_frame_offset - 10;
      if(GRID_MAX_POINTS_X == 12) x_frame_max = x_frame_offset - 9;
      if(GRID_MAX_POINTS_X == 13) x_frame_max = x_frame_offset - 7;
      if(GRID_MAX_POINTS_X == 14) x_frame_max = x_frame_offset - 6;
      if(GRID_MAX_POINTS_X == 15) x_frame_max = x_frame_offset - 4;

      // Ending Y point for the "box"
      if(GRID_MAX_POINTS_Y == 3)  y_frame_max = y_frame_offset + 13;
      if(GRID_MAX_POINTS_Y == 4)  y_frame_max = y_frame_offset + 14;
      if(GRID_MAX_POINTS_Y == 5)  y_frame_max = y_frame_offset + 15;
      if(GRID_MAX_POINTS_Y == 6)  y_frame_max = y_frame_offset + 14;
      if(GRID_MAX_POINTS_Y == 7)  y_frame_max = y_frame_offset + 10;
      if(GRID_MAX_POINTS_Y == 8)  y_frame_max = y_frame_offset + 13;
      if(GRID_MAX_POINTS_Y == 9)  y_frame_max = y_frame_offset + 15;
      if(GRID_MAX_POINTS_Y == 10) y_frame_max = y_frame_offset + 19;
      if(GRID_MAX_POINTS_Y == 11) y_frame_max = y_frame_offset + 6;
      if(GRID_MAX_POINTS_Y == 12) y_frame_max = y_frame_offset + 8;
      if(GRID_MAX_POINTS_Y == 13) y_frame_max = y_frame_offset + 9;
      if(GRID_MAX_POINTS_Y == 14) y_frame_max = y_frame_offset + 11;
      if(GRID_MAX_POINTS_Y == 15) y_frame_max = y_frame_offset + 13;

      // Scaling for X pixel placement
      if(GRID_MAX_POINTS_X == 3)  x_pixel_scaling = 75;
      if(GRID_MAX_POINTS_X == 4)  x_pixel_scaling = 50;
      if(GRID_MAX_POINTS_X == 5)  x_pixel_scaling = 40;
      if(GRID_MAX_POINTS_X == 6)  x_pixel_scaling = 30;
      if(GRID_MAX_POINTS_X == 7)  x_pixel_scaling = 28;
      if(GRID_MAX_POINTS_X == 8)  x_pixel_scaling = 20;
      if(GRID_MAX_POINTS_X == 9)  x_pixel_scaling = 20;
      if(GRID_MAX_POINTS_X == 10) x_pixel_scaling = 20;
      if(GRID_MAX_POINTS_X == 11) x_pixel_scaling = 15;
      if(GRID_MAX_POINTS_X == 12) x_pixel_scaling = 15;
      if(GRID_MAX_POINTS_X == 13) x_pixel_scaling = 15;
      if(GRID_MAX_POINTS_X == 14) x_pixel_scaling = 15;
      if(GRID_MAX_POINTS_X == 15) x_pixel_scaling = 10;

      // Scaling for Y pixel placement
      if(GRID_MAX_POINTS_Y == 3)  y_pixel_scaling = 75;
      if(GRID_MAX_POINTS_Y == 4)  y_pixel_scaling = 50;
      if(GRID_MAX_POINTS_Y == 5)  y_pixel_scaling = 40;
      if(GRID_MAX_POINTS_Y == 6)  y_pixel_scaling = 30;
      if(GRID_MAX_POINTS_Y == 7)  y_pixel_scaling = 28;
      if(GRID_MAX_POINTS_Y == 8)  y_pixel_scaling = 20;
      if(GRID_MAX_POINTS_Y == 9)  y_pixel_scaling = 20;
      if(GRID_MAX_POINTS_Y == 10) y_pixel_scaling = 20;
      if(GRID_MAX_POINTS_Y == 11) y_pixel_scaling = 15;
      if(GRID_MAX_POINTS_Y == 12) y_pixel_scaling = 15;
      if(GRID_MAX_POINTS_Y == 13) y_pixel_scaling = 15;
      if(GRID_MAX_POINTS_Y == 14) y_pixel_scaling = 15;
      if(GRID_MAX_POINTS_Y == 15) y_pixel_scaling = 10;

      // Points for pixel placement
      x_pixel = x_plot * (x_pixel_scaling / 10) + x_frame_offset + 2;
      y_pixel = y_plot * (y_pixel_scaling / 10) + y_frame_offset + 2;

      // Show X and Y positions at top of screen
      u8g.setColorIndex(1);
      u8g.setPrintPos(10, 7);
      lcd_print("X:");
      lcd_print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]))));
      u8g.setPrintPos(70, 7);
      lcd_print("Y:");
      lcd_print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));

      // Draw frame and location pixel
      #if IS_KINEMATIC
        u8g.drawCircle(x_frame_offset * 2,
                       y_frame_offset * 2, y_frame_max / 2);
      #endif
      // Double the size of the "box" and pixel
      u8g.setScale2x2();
      // Draw the "box"
      u8g.drawFrame(x_frame_offset, y_frame_offset, x_frame_max, y_frame_max);
      // Plot the pixel
      u8g.drawPixel(x_pixel, y_pixel);

      // Print plot position
      u8g.undoScale();
      u8g.setPrintPos(10, 64);
      lcd_print("(");
      u8g.print(x_plot);
      lcd_print(",");
      u8g.print(y_plot);
      lcd_print(")");

      // Show the location value
      u8g.setPrintPos(64, 64);
      lcd_print("Z:");
      if (!isnan(ubl.z_values[x_plot][y_plot])) {
        lcd_print(ftostr43sign(ubl.z_values[x_plot][y_plot]));
      }
      else {
        lcd_print(" -----");
      }

    SERIAL_ECHOLNPAIR("LCD_PIXEL_WIDTH: ", LCD_PIXEL_WIDTH);
    SERIAL_ECHOLNPAIR("LCD_PIXEL_HEIGHT: ", LCD_PIXEL_HEIGHT);

    SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X: ", GRID_MAX_POINTS_X);
    SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y: ", GRID_MAX_POINTS_Y);

    SERIAL_ECHOLNPAIR("x_frame_offset: ", x_frame_offset);
    SERIAL_ECHOLNPAIR("y_frame_offset: ", y_frame_offset);

    SERIAL_ECHOLNPAIR("x_frame_max: ", x_frame_max);
    SERIAL_ECHOLNPAIR("y_frame_max: ", y_frame_max);

    SERIAL_ECHOLNPAIR("x_pixel_scaling: ", x_pixel_scaling);
    SERIAL_ECHOLNPAIR("y_pixel_scaling: ", y_pixel_scaling);

    SERIAL_ECHOLNPAIR("x_pixel: ", x_pixel);
    SERIAL_ECHOLNPAIR("y_pixel: ", y_pixel);
    SERIAL_EOL;

    }
Tannoo commented 7 years ago

3x3 -- 15x15 all work along with some tested variants like 10x15, 3x15, 15x3, 7x11.

Now, I'm on to make the new multiMap function work for me to clean it up.

Roxy-3D commented 7 years ago

If you really enjoy messing with this.... Great! But there isn't a lot of sense to duplicating effort. Software takes so much time to develop, it just makes sense to do new stuff that somebody else isn't already doing. And the UBL LCD Menu code is pretty big already.... For sure, there is a lot of stuff you can do that isn't a duplication of what I'm working on.

Seriously... You will like what I'm cooking up...

Tannoo commented 7 years ago

Okay. Should I stop and see what you get?

Roxy-3D commented 7 years ago

Yeah... Just for a few days.... And you can cut & paste pieces that you like into your stuff.

Please keep your branch up to date. I think I can keep out of your way. But it wouldn't hurt for us to both see where the other person is.

Tannoo commented 7 years ago

I have not updated the branch with this... this is just the local I am working on.

Tannoo commented 7 years ago

Okay... I will be working Sunday night, so you won't have me messing with anything then.. lol

Tannoo commented 7 years ago

I sent you a collaborator invite.

Roxy Edit: You are behind the game. I've already accepted! :) Time to go to bed. But I'll be doing merges tomorrow afternoon (with lots of comments) so you can see what I'm up to.

Tannoo commented 7 years ago

I know there is more than one way to skin a cat....I'm sure that I've been using a butcher knife. lol

Tannoo commented 7 years ago

Maybe 'Map Type' should be a whole menu page with line items and when you pick one, it does it??? Topography to Host CVS for Spreadsheet Output to LCD Grid

I can do that....

Done, tested, and updated the branch.

Roxy-3D commented 7 years ago

I've been fighting computer issues ever since I got up this morning. But I finally cloned your fork. And then it took me a while to find the correct branch. (What I always do after a fork is go to the web page / settings and set the default branch to bugfix-v1.1.0)

Any way... I finally figured things out and it looks like you beat me to it. But I have a couple of things to change... I'll sync in a little bit. I added some comments here and there. But one thing we need to do is start turning off sub-options that require a Graphical LCD Panel if the system doesn't have one. For example... The new map type 2.

Also... Your multiMap() function's logic is very similar to what I was thinking should be done. But what I was going to do was have a couple of #define's to set the max number of X and Y pixels that could be used on the LCD Panel. And those numbers should roughly be of square shape on the LCD Panel.

Then what I was going to do was subtract off a couple of pixels just because I was going to draw a line all around the box. And at that point.... I was going to calculate how many pixels were required for each mesh cell.

I was going to have very similar logic to yours. But I was going to make it so there were not magical hard coded constants in the mix. I'll see if I can get it converted to what I was thinking.

Mean while... I already made a change so I could compile! :)

WOW!!!! Very nice. So far, I've only played with the LCD Mesh Map. There are a couple of small things to change. The (X,Y) = (0,0) should be in the lower left corner. That probably isn't going to be hard to invert. And the other thing we need to add is to let the user click on a 'dot' to edit it. Right now, if you click, it doesn't go to the mesh editor. But when the LCD Display times out... It does go there. And once that screen is active... You can't get out of the mesh editor.

BUT.... VERY NICE!!!!!

Roxy-3D commented 7 years ago

Do you see my changes? Later... I'll try to collapse all the hard coded constants and see if I can get that stuff to magically adjust.

Tannoo commented 7 years ago

The (X,Y) = (0,0) should be in the lower left corner.

I think it should be the upper-right, but if you make a dynamic generator, you should be able to change the starting point based on the printer setup, correct?

And the other thing we need to add is to let the user click on a 'dot' to edit it. Right now, if you click, it doesn't go to the mesh editor.

For me, it works just fine, I can select a dot and click to edit it and upto 9 points around that dot. Then after the editing is complete, it returns to the "radar". Mine will not time out from that screen, I have to click and hold for several seconds for the edit routine to exit.

Tannoo commented 7 years ago

Do you see my changes?

I cannot fine where you did anything other than Marlin's site.

Roxy-3D commented 7 years ago

Look at: https://github.com/Tannoo/Marlin/tree/UBL_Mesh_Plotting/Marlin

I committed things with a 'First Pass Clean Up' You should see changes.... I bet your encoder wheel has 1 step per pulse. I have 5. So, I'm adding some scaling right now to the map scanner....

I'll go fight the edit issue next.

The reason for the (0,0) being in the lower left corner is that is how most Cartesian printers are setup. It makes it easier for people to just look at the map and visualize where they are on the printer. And on graph paper, that is typically where (0,0) is also. So mostly, it is just to try to help people.