diff --git a/screws.scad b/screws.scad
index b52855c..793b245 100644
--- a/screws.scad
+++ b/screws.scad
@@ -16,7 +16,7 @@ include <structs.scad>
 include <threading.scad>
 include <screw_drive.scad>
 
-// Section: Screw Parameters
+// Section: Screw and Nut Parameters
 //    This modules in this file create standard ISO (metric) and UTS (English) threaded screws.
 //    The {{screw()}} and {{nut()}} modules produce
 //    screws and nuts that comply with the relevant ISO and ASME standards,
@@ -98,7 +98,22 @@ include <screw_drive.scad>
 //    in cases where no default exists you can specify it.  Flat head screws have variations such as 100 degree
 //    angle for UTS, or undercut heads.  You can also request a "sharp" screw which will set the screw diameter 
 //    the theoretical maximum and produce sharp corners instead of a flat edge on the head.  The flat head options
-//    can be mixed in any order, for example, "flat sharp undercut" or "flat undercut sharp".  
+//    can be mixed in any order, for example, "flat sharp undercut" or "flat undercut sharp".
+// Subsection: Nuts
+//    Nuts come in standard sizes and BOSL2 has tables to produce sizes for both Imperial and metric nuts.
+//    A nut for a given thread size is defined by its shape, width and thickness.  The shape is either "hex"
+//    for hexagonal nuts or "square" for square nuts.  For hexagonal Imperial nuts, you can choose from thickness values
+//    of "thin", "normal" or "thick", but the thin and thick nuts are defined only for thread sizes of 1/4 inch and above.
+//    .
+//    Metric nut standards are more complicated because ISO has a series of standards and DIN has a series of conflicting
+//    standards.  Nuts from McMaster-Carr in the USA comply with DIN rather than ISO.  Furthermore, ISO does not appear
+//    to specify dimensions for square nuts.  For metric nuts you can specify "thin", "normal" and "thick" and the
+//    nut will be constructed to ISO standards (ISO 4035, ISO 4032, and ISO 4033 respectively).  The DIN standard for thin
+//    nuts matches ISO, but the DIN normal thickness nuts are thinner than ISO nuts.  You can request DIN nuts
+//    by specifying a thickness of "DIN" or "undersized".  If you request a square nut it necessariliy derives from DIN
+//    instead of ISO.  For most nut sizes, the nut widths match between ISO and DIN, but they do differ for M10, M12, M14 and M22.
+//    .
+//    You can of course specify nuts by giving an explicit numerical width and thickness in millimeters. 
 // Subsection: Tolerance
 //    Without tolerance requirements, screws would not fit together.  The screw standards specify a
 //    nominal size, but the tolerance determines a range of allowed sizes based on that nominal size.
@@ -171,7 +186,7 @@ Torx values:  https://www.stanleyengineeredfastening.com/-/media/web/sef/resourc
 // Usage:
 //   screw([spec], [head], [drive], [thread=], [drive_size=], [length=|l=], [thread_len=], [undersize=], [shaft_undersize=], [head_undersize=], [tolerance=], [details=], [anchor=], [atype=], [orient=], [spin=]) [ATTACHMENTS];
 // Description:
-//   Create a screw.  See [screw parameters](#section-screw-parameters) for details on the parameters that define a screw.
+//   Create a screw.  See [screw and nut parameters](#section-screw-and-nut-parameters) for details on the parameters that define a screw.
 //   The tolerance determines the dimensions of the screw
 //   based on ISO and ASME standards.  Screws fabricated at those dimensions will mate properly with standard hardware.
 //   Note that the $slop argument does not affect the size of screws: it only adjusts screw holes.  This will work fine
@@ -423,8 +438,9 @@ function _get_spec(spec, needtype, origin, thread,   // common parameters
                    shape, thickness                  // nut parameters
                   ) =
     assert(needtype=="screw_info" || needtype=="nut_info")
-    assert(is_undef(thickness) || (is_num(thickness) && thickness>0) || in_list(thickness,["thin","normal","thick"]),
-          "thickness must be a positive number of one of \"thin\", \"thick\", or \"normal\"")
+    assert(is_undef(thickness) || (is_num(thickness) && thickness>0) ||
+           in_list(_downcase_if_str(thickness),["thin","normal","thick","undersized","din"]),
+          "thickness must be a positive number of one of \"thin\", \"thick\", \"normal\", \"undersized\", or \"DIN\"")
     assert(!(is_undef(spec) && is_undef($screw_spec)), "No screw spec given and no parent spec available to inherit")
     let(spec=is_undef(spec) ? $screw_spec : spec)
     assert(is_string(spec) || is_struct(spec), "Screw/nut specification must be a string or struct")
@@ -647,7 +663,7 @@ module screw(spec, head, drive, thread, drive_size,
 // Usage:
 //   screw_hole([spec], [head], [thread=], [length=|l=], [oversize=], [hole_oversize=], [head_oversize], [tolerance=], [$slop=], [anchor=], [atype=], [orient=], [spin=]) [ATTACHMENTS];
 // Description:
-//   Create a screw hole mask.  See [screw parameters](#section-screw-parameters) for details on the parameters that define a screw.
+//   Create a screw hole mask.  See [screw and nut parameters](#section-screw-and-nut-parameters) for details on the parameters that define a screw.
 //   The screw hole can be threaded to receive a screw or it can be an unthreaded clearance hole.  
 //   The tolerance determines the dimensions of the screw
 //   based on ISO and ASME standards.  Screws fabricated at those dimensions will mate properly with standard hardware.
@@ -863,7 +879,7 @@ module screw_hole(spec, head, thread, oversize, hole_oversize, head_oversize,
 // Usage:
 //   shoulder_screw(s, d, length, [head=], [thread_len=], [tolerance=], [head_size=], [drive=], [drive_size=], [thread=], [undersize=], [shaft_undersize=], [head_undersize=], [shoulder_undersize=],[atype=],[anchor=],[orient=],[spin=]) [ATTACHMENTS];
 // Description:
-//   Create a shoulder screw.  See [screw parameters](#section-screw-parameters) for details on the parameters that define a screw.
+//   Create a shoulder screw.  See [screw and nut parameters](#section-screw-and-nut-parameters) for details on the parameters that define a screw.
 //   The tolerance determines the dimensions of the screw
 //   based on ISO and ASME standards.  Screws fabricated at those dimensions will mate properly with standard hardware.
 //   Note that the $slop argument does not affect the size of screws: it only adjusts screw holes.  This will work fine
@@ -1362,16 +1378,18 @@ module screw_head(screw_info,details=false, counterbore=0,flat_height) {
 //   nut([spec], [shape], [thickness], [nutwidth], [thread=], [tolerance=], [hole_oversize=], [bevel=], [$slop=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
 
 // Description:
-//   Generates a hexagonal nut.  See [screw parameters](#section-screw-parameters) for details on the parameters that define a nut.
-//   As for screws, you can give the specification in `spec` and then omit the name.  The diameter is the flat-to-flat
-//   size of the nut produced.  
+//   Generates a hexagonal or square nut.  See [screw and nut parameters](#section-screw-and-nut-parameters) for details on the parameters that define a nut.
+//   As with screws, you can give the specification in `spec` and then omit the name.  The diameter is the flat-to-flat
+//   size of the nut produced.  The thickness can be "thin", "normal" or "thick" to choose standard nut dimensions.  For metric
+//   nuts you can also use thickness values of "DIN" or "undersized".  The nut's shape is hexagonal by default; set shape to "square" for
+//   a square nut.  
 //   .
 //   The tolerance determines the actual thread sizing based on the nominal size in accordance with standards.  
 //   The $slop parameter determines extra gaps left to account for printing overextrusion.  It defaults to 0.
 // Arguments:
 //   spec = nut specification, e.g. "M5x1" or "#8-32".  See [screw naming](#subsection-screw-naming).  This can also be a nut or screw specification structure of the form produced by {{nut_info()}} or {{screw_info()}}.  
 //   shape = "hex" or "square" to specify nut shape.  Default: "hex"
-//   thickness = "thin", "normal", "thick", or a thickness in mm.  Default: "normal"
+//   thickness = "thin", "normal", "thick", or a thickness in mm.  See [nuts](#subsection-nuts).  Default: "normal"
 //   ---
 //   nutwidth = width of nut (overrides table values)
 //   thread = thread type or specification. See [screw pitch](#subsection-standard-screw-pitch). Default: "coarse"
@@ -1390,7 +1408,20 @@ module screw_head(screw_info,details=false, counterbore=0,flat_height) {
 //       nut("3/8",thickness="normal");
 //       nut("3/8",thickness="thick");
 //       nut("3/8",shape="square");
-//    }   
+//   }
+// Example: All the ISO (and DIN) nuts at one size.  Note that M10 is one of the four cases where the DIN nut width is larger.  
+//   ydistribute(spacing=30){
+//      xdistribute(spacing=22){
+//         nut("M10", thickness="thin");
+//         nut("M10",thickness="undersized");
+//         nut("M10",thickness="normal");
+//         nut("M10",thickness="thick");
+//      }
+//      xdistribute(spacing=25){
+//         nut("M10", shape="square", thickness="thin");
+//         nut("M10", shape="square", thickness="normal");      
+//      }
+//   }
 // Example: The three different UTS nut tolerances (thickner than normal nuts)
 //   module mark(number)
 //   {
@@ -1419,6 +1450,7 @@ module nut(spec, shape, thickness, nutwidth, thread, tolerance, hole_oversize,
                                 ["width", nutwidth],
                                 ["threads_oversize", hole_oversize],
                                ]);
+   dummy=_validate_nut_spec(spec);
    $screw_spec = spec;
    shape = struct_val(spec, "shape");
    pitch =  struct_val(spec, "pitch") ;
@@ -1426,7 +1458,7 @@ module nut(spec, shape, thickness, nutwidth, thread, tolerance, hole_oversize,
    nutwidth = struct_val(spec, "width");
    thickness = struct_val(spec, "thickness");
    threaded_nut(
-        od=nutwidth,
+        nutwidth=nutwidth,
         id=[mean(struct_val(threadspec, "d_minor")),
             mean(struct_val(threadspec, "d_pitch")),
             mean(struct_val(threadspec, "d_major"))],
@@ -1440,7 +1472,7 @@ module nut(spec, shape, thickness, nutwidth, thread, tolerance, hole_oversize,
 
 // Module: nut_trap_side()
 // Usage:
-//   nut_trap_side(trap_width, [spec], [shape], [poke_len=], [poke_diam=], [$slop=], [anchor=], [orient=], [spin=]) [ATTACHMENTS];
+//   nut_trap_side(trap_width, [spec], [shape], [thickness], [nutwidth=], [poke_len=], [poke_diam=], [$slop=], [anchor=], [orient=], [spin=]) [ATTACHMENTS];
 // Description:
 //   Create a nut trap that extends sideways, so the nut slides in perpendicular to the screw axis.
 //   The CENTER anchor is the center of the screw hole location in the trap.  The trap width is
@@ -1453,7 +1485,9 @@ module nut(spec, shape, thickness, nutwidth, thread, tolerance, hole_oversize,
 //   trap_width = width of nut trap, measured from screw center, must be larger than half the nut width  (If spec is omitted this argument must be given by name.)
 //   spec = nut specification, e.g. "M5" or "#8".  See [screw naming](#subsection-screw-naming).  This can also be a screw or nut specification structure of the form produced by {{nut_info()}} or {{screw_info()}}.  
 //   shape = "hex" or "square" to specify the shape of the nut.   Default: "hex"
-//   --- 
+//   thickness = "thin", "normal", or "thick".  "DIN" or "undersized" for metric nuts.  See [nuts](#subsection-nuts). Default: "normal"
+//   ---
+//   nutwidth = width of the nut.  Default: determined from tables
 //   poke_len = length of poke hole.  Default: no poke hole
 //   poke_diam = diameter of poke hole.  Default: nut thickness
 //   $slop = extra space left to account for printing over-extrusion.  Default: 0
@@ -1497,8 +1531,8 @@ module nut_trap_side(trap_width, spec, shape, thickness, nutwidth, anchor=BOT, o
   dummy9=assert(is_num(trap_width), "trap_width is missing or the wrong type");
   tempspec = _get_spec(spec, "nut_info", "nut_trap", shape=shape, thickness=thickness);
   nutdata = _struct_reset(tempspec, [["width", nutwidth]]);
-  echo_struct(nutdata);
   $screw_spec = is_def(spec) ? nutdata : $screw_spec;
+  dummy8 = _validate_nut_spec(nutdata);
   nutwidth = struct_val(nutdata,"width")+2*get_slop();
   dummy = assert(is_num(poke_len) && poke_len>=0, "poke_len must be a nonnegative number")
           assert(is_undef(poke_diam) || (is_num(poke_diam) && poke_diam>0), "poke_diam must be a positive number")
@@ -1572,8 +1606,8 @@ module nut_trap_side(trap_width, spec, shape, thickness, nutwidth, anchor=BOT, o
 module nut_trap_inline(length, spec, shape, l, height, h, nutwidth, anchor, orient, spin) {
   tempspec = _get_spec(spec, "nut_info", "nut_trap", shape=shape, thickness=undef);
   nutdata = _struct_reset(tempspec, [["width", nutwidth]]);
-  echo_struct(nutdata);
   $screw_spec = is_def(spec) ? nutdata : $screw_spec;
+  dummy = _validate_nut_spec(nutdata);
   length = one_defined([l,length,h,height],"l,length,h,height");
   assert(is_num(length) && length>0, "length must be a positive number");
   nutwidth = struct_val(nutdata,"width")+2*get_slop();
@@ -1595,7 +1629,7 @@ module nut_trap_inline(length, spec, shape, l, height, h, nutwidth, anchor, orie
 //   info = screw_info(spec, [head], [drive], [thread=], [drive_size=], [oversize=], [head_oversize=])
 // Description:
 //   Look up screw characteristics for the specified screw type.
-//   See [screw parameters](#section-screw-parameters) for details on the parameters that define a screw.
+//   See [screw and nut parameters](#section-screw-and-nut-parameters) for details on the parameters that define a screw.
 //   .
 //   The `oversize=` parameter adds the specified amount to the screw and head diameter to make an
 //   oversized screw.  Does not affect length, thread pitch or head height.
@@ -1713,9 +1747,12 @@ function screw_info(spec, head, drive, thread, drive_size, threads_oversize=0, h
 //   hole_oversize = amount ot increase diameter of hole in nut.  Default: 0
 
 function nut_info(spec, shape, thickness, thread, hole_oversize=0, width, _origin) =
+  assert(is_undef(thickness) || (is_num(thickness) && thickness>0) ||
+           in_list(_downcase_if_str(thickness),["thin","normal","thick","undersized","din"]),
+          "thickness must be a positive number of one of \"thin\", \"thick\", \"normal\", \"undersized\", or \"DIN\"")
   let(
-      shape = default(shape,"hex"),
-      thickness = default(thickness, "normal")
+      shape = downcase(default(shape,"hex")),
+      thickness = _downcase_if_str(default(thickness, "normal"))
   )
   assert(is_string(spec), str("Nut specification must be a string ",spec))
   assert(in_list(shape, ["hex","square"]), "Nut shape must be \"hex\" or \"square\"")
@@ -1725,8 +1762,8 @@ function nut_info(spec, shape, thickness, thread, hole_oversize=0, width, _origi
       thread = is_undef(thread) || thread==true ? "coarse"
              : thread==false || thread=="none" ? 0
              : thread,
-      nutdata = type[0]=="english" ? _nut_info_english(type[1],type[2], thread, shape, thickness)
-              : type[0]=="metric" ?  _nut_info_metric(type[1],type[2], thread, shape, thickness)
+      nutdata = type[0]=="english" ? _nut_info_english(type[1],type[2], thread, shape, thickness, width)
+              : type[0]=="metric" ?  _nut_info_metric(type[1],type[2], thread, shape, thickness, width)
               : []
   )
   _struct_reset(nutdata, [["name", spec],
@@ -1738,6 +1775,8 @@ function nut_info(spec, shape, thickness, thread, hole_oversize=0, width, _origi
 
 // Nut data is from ASME B18.2.2, mostly Table A-1
 function _nut_info_english(diam, threadcount, thread, shape, thickness, width) =
+  assert(!is_string(thickness) || in_list(thickness,["normal","thin","thick"]),
+         "You cannot use thickness \"DIN\" or \"undersized\" with English nuts")
   let(
        screwspec=_screw_info_english(diam, threadcount, head="none", thread=thread),
        diameter = struct_val(screwspec,"diameter")/INCH,
@@ -1801,7 +1840,8 @@ function _nut_info_english(diam, threadcount, thread, shape, thickness, width) =
                 : diameter < 11/16 ? quantdn(7/8*diameter,1/64)
                 : diameter < 1+3/16 ? 7/8*diameter - 1/64
                 : 7/8 * diameter - 1/32, 
-      width = is_def(entry[1]) ? entry[1]
+      width = is_num(width) ? width/INCH
+            : is_def(entry[1]) ? entry[1]
             : shape=="square" ? (diameter<5/8 ? quantup(1.5*diameter,1/16)+1/16 : 1.5*diameter)
             : quantup(1.5*diameter,1/16)
   )
@@ -1814,42 +1854,123 @@ function _nut_info_english(diam, threadcount, thread, shape, thickness, width) =
    ["shape", shape]];
 
 
+function _downcase_if_str(s) = is_string(s) ? downcase(s) : s;
 
- /*
+function _nut_info_metric(diam, pitch, thread, shape, thickness, width) =
+  let(
+       screwspec=_screw_info_metric(diam, pitch, head="none", thread=thread),
+       diameter = struct_val(screwspec,"diameter"),
 
-   normal
-   1.6, [3.2
-   2,   [4    1.6
-   2.5, [5    2
-   3,   [5.5  2.4
-   4,   [7    3.2
-   5,   [8    4
-   6,   [10   
-   8,   [13   6.5
-   10,  [16   8
-   12,  [18   10
-   16,  [24   13
-   20,  [30   16
-   24,  [36   19
-   30,  [46   24
-   36,  [55   29
-   42,  [65   34
-   48,  [75   38
-   56,  [85
-   64,  [95
-
-   3.5, [6
-   14,  [21
-   18,  [27
-   22,  [34
-   27,  [41
-   33,  [50
-   39,  [60
-   45,  [70
-   52,  [80
-   60,  [90
-*/
-   
+       ISO_table =      //     - ASME B18.4.1M -    DIN 439
+          //                   --- ISO 4032 ----   ISO 4035   ISO 4033 
+          //                   normal     normal     thin       thick
+          // diam    width     midpt      max        (max)      (max)
+          // Preferred threads
+          [
+             [1.6,   [3.2 ,     1.2,       1.3,       1.0   ]],
+             [2,     [4   ,     1.5,       1.6,       1.2   ]],
+             [2.5,   [5   ,     1.875,     2,         1.6   ]],
+             [3,     [5.5 ,     2.25,      2.4,       1.8   ]],
+             [4,     [7   ,     3,         3.2,       2.2   ]],
+             [5,     [8   ,     4.5 ,      4.7,       2.7,      5.1]],
+             [6,     [10  ,     5,         5.2,       3.2,      5.7]],
+             [8,     [13  ,     6.675,     6.8,      undef,      7.5]],
+             [10,    [16  ,     8.25,      8.4,      undef,      9.3]],
+             [12,    [18  ,     10.5,     10.8,      undef,     12  ]],
+             [16,    [24  ,     14.5,     14.8,      undef,     16.4]],
+             [20,    [30  ,     17.5,     18,        undef,     20.3]],
+             [24,    [36  ,     21,       21.5,      undef,     23.9]],
+             [30,    [46  ,     25,       25.6,      undef,     28.6]],
+             [36,    [55  ,     30,       31,        undef,     34.7]],
+             [42,    [65  ,     33,       34,        undef      ]],
+             [48,    [75  ,     37,       38,        undef      ]],
+             [56,    [85  ,     44,       45,        undef      ]],
+             [64,    [95  ,     50,       51,        undef      ]],
+          // Non-preferred threads
+             [3.5,   [ 6,       2.675,     2.8,      2          ]],
+             [14,    [21,      12.5,      12.8,      undef,     14.1]],
+             [18,    [27,      15.5,      15.8,      undef,     17.6]],
+             [22,    [34,      19,        19.4,      undef,     21.8]],
+             [27,    [41,      23,        23.8,      undef,     26.7]],
+             [33,    [50,      28,        28.7,      undef,     32.5]],
+             [39,    [60,      33,        33.4,      undef      ]],
+             [45,    [70,      35,        36,        undef      ]],
+             [52,    [80,      41,        42,        undef      ]],
+             [60,    [90,      47,        48,        undef      ]]
+          ],
+       DIN_table =
+          [
+             //                  DIN 934   DIN 936  DIN 562     DIN 557
+             //diam      width   normal    thin    thin square   square
+             [   1,    [   2.5,    0.8,   undef]],
+             [   1.2,  [   3,      1  ,   undef]],
+             [   1.4,  [   3,      1.2,   undef]],
+             [   1.6,  [   3.2,    1.3,   undef,      1.0]],
+             [   2,    [   4,      1.6,   undef,      1.2]],
+             [   2.5,  [   5,      2  ,   undef,      1.6]],
+             [   3,    [   5.5,    2.4,   undef,      1.8]],
+             [   3.5,  [   6,      2.8,   undef,      2.0]],
+             [   4,    [   7,      3.2,     2.8,      2.2]],
+             [   5,    [   8,      4,       3.5,      2.7]],
+             [   6,    [  10,      5,       4  ,      3.2]],
+             [   7,    [  11,      5.5,     4  ]],
+             [   8,    [  13,      6.5,     5        ]],
+             [  10,    [  17,      8,       6        ]],     //
+             [  12,    [  19,     10,       7  ]],  //
+             [  14,    [  22,     11,       8  ]],  //
+             [  16,    [  24,     13,       8  ]],
+             [  18,    [  27,     15,       9  ]],
+             [  20,    [  30,     16,       9  ]],
+             [  22,    [  32,     18,      10  ]],  //
+             [  24,    [  36,     19,      10  ]],
+             [  27,    [  41,     22,      12  ]],
+             [  30,    [  46,     24,      12  ]],
+             [  33,    [  50,     26,      14  ]],
+             [  36,    [  55,     29,      14  ]],
+             [  39,    [  60,     31,      16  ]],
+             [  42,    [  65,     34,      16  ]],
+             [  45,    [  70,     36,      18  ]],
+             [  48,    [  75,     38,      18  ]],
+             [  52,    [  80,     42,      20  ]],
+             [  56,    [  85,     45]],
+             [  60,    [  90,     48]],
+             [  64,    [  95,     51]],
+             [  68,    [ 100,     54]],
+             [  72,    [ 105,     58]],
+             [  76,    [ 110,     61]],
+             [  80,    [ 115,     64]],
+             [  85,    [ 120,     68]],
+             [  90,    [ 130,     72]],
+             [ 100,    [ 145,     80]],
+             [ 110,    [ 155,     88]],
+             [ 125,    [ 180,    100]],
+             [ 140,    [ 200,    112]],
+             [ 160,    [ 230,    128]]
+          ],
+          useDIN = thickness=="din" || thickness=="undersized" || shape=="square", 
+          entry = struct_val(useDIN ? DIN_table : ISO_table, diameter),
+          width = is_def(width) ? width
+                : entry[0],
+          thickind = useDIN && thickness=="thin" ? 3
+                   : useDIN ? 1 
+                   : thickness=="normal" ? 2
+                   : thickness=="thin" ? 3
+                   : thickness=="thick" ? 4
+                   : undef,
+          thickness = is_num(thickness) ? thickness
+                    : is_def(entry[thickind]) ? entry[thickind]
+                    : thickness=="thin" && diameter > 8 ? diam/2
+                    : undef
+  )
+  assert(is_def(thickness) && is_def(width), "Unknown thickness, size and shape combination for nut")
+  [["type","nut_info"],
+   ["system", "ISO"],
+   ["diameter", struct_val(screwspec, "diameter")],
+   ["pitch", struct_val(screwspec,"pitch")],
+   ["width", width],
+   ["thickness", thickness],
+   ["shape", shape]];
+          
 
 function _screw_info_english(diam, threadcount, head, thread, drive) =
  let(
@@ -2574,8 +2695,30 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
 
 function _is_positive(x) = is_num(x) && x>0;
 
+
+function _validate_nut_spec(spec) =
+   let(
+       //dummy=echo_struct(spec,"Screw Specification"),
+       systemOK = in_list(struct_val(spec,"system"), ["UTS","ISO"]),
+       diamOK = _is_positive(struct_val(spec, "diameter")),
+       pitch = struct_val(spec,"pitch"),
+       pitchOK = is_undef(pitch) || (is_num(pitch) && pitch>=0),
+       shape = struct_val(spec, "shape"),
+       shapeOK = shape=="hex" || shape=="square",
+       thicknessOK = _is_positive(struct_val(spec, "thickness")),
+       widthOK = _is_positive(struct_val(spec, "width"))
+    )
+    assert(systemOK, str("Nut spec has invalid \"system\", ", struct_val(spec,"system"), ".  Must be \"ISO\" or \"UTS\""))
+    assert(diamOK, str("Nut spec has invalid \"diameter\", ", struct_val(spec,"diameter")))
+    assert(pitchOK, str("Nut spec has invalid \"pitch\", ", pitch))
+    assert(shapeOK, str("Nut spec has invalid \"shape\", ", shape, ".  Must be \"square\" or \"hex\""))
+    assert(thicknessOK, str("Nut spec thickness is not a postive number: ",struct_val(spec,"thickness")))
+    assert(widthOK, str("Nut spec width is not a postive number: ",struct_val(spec,"width")))
+    spec;
+
+    
 function _validate_screw_spec(spec) = let(
-    dummy=echo_struct(spec,"Screw Specification"),
+    //dummy=echo_struct(spec,"Screw Specification"),
     systemOK = in_list(struct_val(spec,"system"), ["UTS","ISO"]),
     diamOK = _is_positive(struct_val(spec, "diameter")),
     pitch = struct_val(spec,"pitch"),
diff --git a/threading.scad b/threading.scad
index 5a0356e..e0e982f 100644
--- a/threading.scad
+++ b/threading.scad
@@ -128,11 +128,11 @@ module threaded_rod(
 
 // Module: threaded_nut()
 // Usage:
-//   threaded_nut(od, id, h, pitch,...) [ATTACHMENTS];
+//   threaded_nut(nutwidth, id, h, pitch,...) [ATTACHMENTS];
 // Description:
 //   Constructs a hex nut or square nut for an ISO (metric) or UTS (English) threaded rod. 
 // Arguments:
-//   od = diameter of the nut.
+//   nutwidth = flat to flat width of nut
 //   id = diameter of threaded rod to screw onto.
 //   h = height/thickness of nut.
 //   pitch = Length between threads.
@@ -151,12 +151,12 @@ module threaded_rod(
 //   threaded_nut(od=16, id=8, h=8, pitch=1.25, $slop=0.05, $fa=1, $fs=1);
 //   threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, bevel=true, $slop=0.1, $fa=1, $fs=1);
 function threaded_nut(
-    od, id, h,
+    nutwidth, id, h,
     pitch, starts=1, shape, left_handed=false, bevel, bevel1, bevel2, id1,id2,
     anchor, spin, orient
 )=no_function("threaded_nut");
 module threaded_nut(
-    od, id, h,
+    nutwidth, id, h,
     pitch, starts=1, shape="hex", left_handed=false, bevel, bevel1, bevel2, id1,id2,
     anchor, spin, orient
 ) {
@@ -184,7 +184,7 @@ module threaded_nut(
         [ 6/16, -depth/pitch]
     ];
     generic_threaded_nut(
-        od=od,
+        nutwidth=nutwidth,
         id=basic ? id : id[2], id1=id1, id2=id2,
         h=h,
         pitch=pitch,
@@ -323,14 +323,14 @@ module trapezoidal_threaded_rod(
 
 // Module: trapezoidal_threaded_nut()
 // Usage:
-//   trapezoidal_threaded_nut(od, id, h, pitch, [thread_angle], [thread_depth], ...) [ATTACHMENTS];
+//   trapezoidal_threaded_nut(nutwidth, id, h, pitch, [thread_angle], [thread_depth], ...) [ATTACHMENTS];
 // Description:
 //   Constructs a hex nut or square nut for a symmetric trapzoidal threaded rod.
 //   By default produces the nominal dimensions
 //   for metric trapezoidal threads: a thread angle of 30 degrees and a depth set to half the pitch.
 //   You can also specify your own trapezoid parameters.  For ACME threads see acme_threaded_nut(). 
 // Arguments:
-//   od = diameter of the nut.
+//   nutwidth = flat to flat width of nut
 //   id = diameter of threaded rod to screw onto.
 //   h = height/thickness of nut.
 //   pitch = Thread spacing.
@@ -348,11 +348,11 @@ module trapezoidal_threaded_rod(
 //   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 //   $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
 // Examples(Med):
-//   trapezoidal_threaded_nut(od=16, id=8, h=8, pitch=2, $slop=0.1, anchor=UP);
-//   trapezoidal_threaded_nut(od=16, id=8, h=8, pitch=2, bevel=true, $slop=0.05, anchor=UP);
-//   trapezoidal_threaded_nut(od=17.4, id=10, h=10, pitch=2, $slop=0.1, left_handed=true);
-//   trapezoidal_threaded_nut(od=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15);
-function trapezoidal_threaded_rod(
+//   trapezoidal_threaded_nut(nutwidth=16, id=8, h=8, pitch=2, $slop=0.1, anchor=UP);
+//   trapezoidal_threaded_nut(nutwidth=16, id=8, h=8, pitch=2, bevel=true, $slop=0.05, anchor=UP);
+//   trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, $slop=0.1, left_handed=true);
+//   trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15);
+function trapezoidal_threaded_nut(
     d, l, pitch,
     thread_angle=30,
     thread_depth=undef, shape, 
@@ -364,7 +364,7 @@ function trapezoidal_threaded_rod(
     center, anchor, spin, orient
 ) = no_function("trapezoidal_threaded_nut");
 module trapezoidal_threaded_nut(
-    od,
+    nutwidth,
     id,
     h,
     pitch,
@@ -389,7 +389,7 @@ module trapezoidal_threaded_nut(
                [ z1,  0],
                [ z2, rr1],
               ];
-    generic_threaded_nut(od=od,id=id,h=h,pitch=pitch,profile=profile,id1=id1,id2=id2,
+    generic_threaded_nut(nutwidth=nutwidth,id=id,h=h,pitch=pitch,profile=profile,id1=id1,id2=id2,
                          shape=shape,left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts,
                          anchor=anchor,spin=spin,orient=orient)
       children();
@@ -465,11 +465,11 @@ module acme_threaded_rod(
 
 // Module: acme_threaded_nut()
 // Usage:
-//   acme_threaded_nut(od, id, h, tpi|pitch=, ...) [ATTACHMENTS];
+//   acme_threaded_nut(nutwidth, id, h, tpi|pitch=, [shape=], ...) [ATTACHMENTS];
 // Description:
-//   Constructs a hex nut for an ACME threaded screw rod. 
+//   Constructs a hexagonal or square nut for an ACME threaded screw rod. 
 // Arguments:
-//   od = diameter of the nut.
+//   nutwidth = flat to flat width of nut. 
 //   id = diameter of threaded rod to screw onto.
 //   h = height/thickness of nut.
 //   tpi = threads per inch
@@ -486,17 +486,17 @@ module acme_threaded_rod(
 //   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 //   $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
 // Examples(Med):
-//   acme_threaded_nut(od=16, id=3/8*INCH, h=8, tpi=8, $slop=0.05);
-//   acme_threaded_nut(od=16, id=1/2*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1);
+//   acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=8, tpi=8, $slop=0.05);
+//   acme_threaded_nut(nutwidth=16, id=1/2*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1);
 function acme_threaded_nut(
-    od, id, h, tpi, pitch,
+    nutwidth, id, h, tpi, pitch,
     starts=1,
     left_handed=false,shape, 
     bevel,bevel1,bevel2,
     anchor, spin, orient
 ) = no_function("acme_threaded_nut");
 module acme_threaded_nut(
-    od, id, h, tpi, pitch,
+    nutwidth, id, h, tpi, pitch,
     starts=1,
     left_handed=false,shape="hex",
     bevel,bevel1,bevel2,
@@ -506,7 +506,7 @@ module acme_threaded_nut(
     pitch = is_undef(pitch) ? INCH/tpi : pitch;
     dummy2=assert(is_num(pitch) && pitch>0);
     trapezoidal_threaded_nut(
-        od=od, id=id, h=h, pitch=pitch,
+        nutwidth=nutwidth, id=id, h=h, pitch=pitch,
         thread_depth = pitch/2, 
         thread_angle=29,shape=shape, 
         left_handed=left_handed,
@@ -725,11 +725,11 @@ module buttress_threaded_rod(
 
 // Module: buttress_threaded_nut()
 // Usage:
-//   buttress_threaded_nut(od, id, h, pitch, ...) [ATTACHMENTS];
+//   buttress_threaded_nut(nutwidth, id, h, pitch, ...) [ATTACHMENTS];
 // Description:
-//   Constructs a hex nut for a simple buttress threaded screw rod.  
+//   Constructs a hexagonal or square nut for a simple buttress threaded screw rod.  
 // Arguments:
-//   od = diameter of the nut.
+//   nutwidth = diameter of the nut.
 //   id = diameter of threaded rod to screw onto.
 //   h = height/thickness of nut.
 //   pitch = Thread spacing. 
@@ -745,15 +745,15 @@ module buttress_threaded_rod(
 //   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 //   $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
 // Examples(Med):
-//   buttress_threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.05, $fa=1, $fs=1);
+//   buttress_threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.05, $fa=1, $fs=1);
 function buttress_threaded_nut(
-    od=16, id=10, h=10,
+    nutwidth=16, id=10, h=10,
     pitch=2, shape, left_handed=false,
     bevel,bevel1,bevel2,starts,
     anchor, spin, orient
 ) = no_function("buttress_threaded_nut");
 module buttress_threaded_nut(
-    od=16, id=10, h=10,
+    nutwidth=16, id=10, h=10,
     pitch=2, shape="hex", left_handed=false,
     bevel,bevel1,bevel2,starts=1,
     anchor, spin, orient
@@ -767,7 +767,7 @@ module buttress_threaded_nut(
         [  1/ 2, -0.77],
     ];
     generic_threaded_nut(
-        od=od, id=id, h=h,
+        nutwidth=nutwidth, id=id, h=h,
         pitch=pitch,
         profile=profile,
         shape=shape,
@@ -857,13 +857,14 @@ module square_threaded_rod(
 // Usage:
 //   square_threaded_nut(od, id, h, pitch, ...) [ATTACHMENTS];
 // Description:
-//   Constructs a hex nut for a square profile threaded screw rod.  
+//   Constructs a hexagonal or square nut for a square profile threaded screw rod.  
 // Arguments:
-//   od = diameter of the nut.
+//   nutwidth = diameter of the nut.
 //   id = diameter of threaded rod to screw onto.
 //   h = height/thickness of nut.
 //   pitch = Length between threads.
 //   ---
+//   shape = specifies shape of nut, either "hex" or "square".  Default: "hex"
 //   left_handed = if true, create left-handed threads.  Default = false
 //   starts = The number of lead starts.  Default = 1
 //   bevel = if true, bevel the thread ends.  Default: false
@@ -874,10 +875,11 @@ module square_threaded_rod(
 //   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 //   $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
 // Examples(Med):
-//   square_threaded_nut(od=16, id=10, h=10, pitch=2, starts=2, $slop=0.1, $fn=32);
+//   square_threaded_nut(nutwidth=16, id=10, h=10, pitch=2, starts=2, $slop=0.1, $fn=32);
 function square_threaded_nut(
     od, id, h,
     pitch,
+    shape=shape,
     left_handed=false,
     bevel,bevel1,bevel2,
     starts=1,
@@ -893,7 +895,7 @@ module square_threaded_nut(
 ) {
     assert(is_num(pitch) && pitch>0)
     trapezoidal_threaded_nut(
-        od=od, id=id, h=h, pitch=pitch,
+        nutwidth=nutwidth, id=id, h=h, pitch=pitch,
         thread_angle=0,
         left_handed=left_handed,
         bevel=bevel,bevel1=bevel1,bevel2=bevel2,
@@ -1213,17 +1215,18 @@ module generic_threaded_rod(
 
 // Module: generic_threaded_nut()
 // Usage:
-//   generic_threaded_nut(od, id, h, pitch, profile, [$slop], ...) [ATTACHMENTS];
+//   generic_threaded_nut(nutwidth, id, h, pitch, profile, [$slop], ...) [ATTACHMENTS];
 // Description:
 //   Constructs a hexagonal or square nut for an generic threaded rod using a user-supplied thread profile.
 //   See generic_threaded_rod for details on the profile specification.  
 // Arguments:
-//   od = diameter of the nut.
+//   nutwidth = outer dimension of nut from flat to flat. 
 //   id = diameter of threaded rod to screw onto.
 //   h = height/thickness of nut.
 //   pitch = Thread spacing.
 //   profile = Thread profile.
 //   ---
+//   shape = specifies shape of nut, either "hex" or "square".  Default: "hex"
 //   left_handed = if true, create left-handed threads.  Default = false
 //   starts = The number of lead starts.  Default = 1
 //   bevel = if true, bevel the thread ends.  Default: false
@@ -1236,7 +1239,7 @@ module generic_threaded_rod(
 //   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 //   $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
 function generic_threaded_nut(
-    od,
+    nutwidth,
     id,
     h,
     pitch,
@@ -1244,12 +1247,12 @@ function generic_threaded_nut(
     shape,
     left_handed=false,
     starts=1,
-    bevel,bevel1,bevel2,bevang=30,
+    bevel,bevel1,bevel2,bevang=15,
     id1,id2,
     anchor, spin, orient
 ) = no_function("generic_threaded_nut");
 module generic_threaded_nut(
-    od,
+    nutwidth,
     id,
     h,
     pitch,
@@ -1257,7 +1260,7 @@ module generic_threaded_nut(
     shape="hex",
     left_handed=false,
     starts=1,
-    bevel,bevel1,bevel2,
+    bevel,bevel1,bevel2,bevang=15,
     id1,id2,
     anchor, spin, orient
 ) {
@@ -1273,12 +1276,18 @@ module generic_threaded_nut(
     bevel2 = first_defined([bevel2,bevel,false]);
     dummy1 = assert(is_num(pitch) && pitch>0);
     depth = -pitch*min(column(profile,1));
-    attachable(anchor,spin,orient, size=[od/cos(30),od,h]) {
+    bevel_d=.975;
+    vnf = linear_sweep(hexagon(id=nutwidth), height=h, center=true);
+    attachable(anchor,spin,orient, size=shape=="square" ? [nutwidth,nutwidth,h] : undef, vnf=shape=="hex" ? vnf : undef) {
         difference() {
-            if (shape=="hex")
-              cyl(d=od/cos(30), h=h, center=true, $fn=6,chamfer1=bevel1?depth:undef,chamfer2=bevel2?depth:undef);
-            else
-              cuboid([od,od,h]);
+            intersection(){
+                if (shape=="hex")
+                  vnf_polyhedron(vnf);
+                else
+                  cuboid([nutwidth,nutwidth,h]);
+                if (bevel2) cyl(h=h+.01, d2=nutwidth*bevel_d,d1=nutwidth*bevel_d+h/tan(bevang), $fn=64);
+                if (bevel1) down(.01) cyl(h=h+.01, d1=nutwidth*bevel_d,d2=nutwidth*bevel_d+h/tan(bevang), $fn=64);
+            }
             generic_threaded_rod(
                 d1=full_id1,d2=full_id2,
                 l=h+extra,