Sunday, October 25, 2020

Raspberry Pi Bridge eth0 to wlan0 with wlan_kabel

I spent a ridiculous amount of time trying to persuade native Raspberry Pi OS to bridge the local ethernet port onto the WiFi segment. (turns out it is apparently not possible) 

My intention is having a remote device such as my Envox BB3 programmable power supply with only a wired ethernet connection, connect to my WiFi segment so that I can use EEZ Studio without needing to plug the BB3 into a wired ethernet port. The connection is the same as before:



In my prior blog, I came up with a somewhat brute-force method of setting up a local DHCP server and using dnsmasq. However, as brute force methods go, it was also neither a very graceful nor flexible solution.

While surfing the internet looking for alternatives, there was one person that casually mentioned "you can also try wlan_kabel". This turned out to be a ridiculously cool solution!

Starting with my default headless Raspberry Pi setup, install git and clone escitalopram's wlan_kabel. You'll need the MAC address of the device to use; the BB3 shows this on the ethernet settings screen:




sudo apt-get install git
git clone https://github.com/escitalopram/wlan_kabel.git
cd wlan_kabel
make

# the magic (showing the example MAC address from the docs)
# you'll need to put your own address here:
sudo ./wlan_kabel wlan0 eth0 74:69:69:2d:30:11

That's it! It just works. There are of course limitations (one device connected to Raspberry Pi eth0 port).

To run wlan_kabel at boot time, put this in /etc/rc.local :
(/home/pi/wlan_kabel/wlan_kabel wlan0 eth0 74:69:69:2d:30:11 > /dev/null 2>&1) &
Don't forget to use your own MAC address, and be sure to include the training ampersand.

This is a vastly more graceful solution. Just plug in the RPi and connect to the IP address shown, in my case 192.168.1.114 then connect:


  Et voilĂ !


Note the hard-wired ethernet port of the BB3 on the other wise of the Raspberry Pi has an IP address from the WiFi.

Raspberry Pi Network eth0 to wlan0 Router

Connecting ethernet wired-only equipment to WiFi.

TL;DR install dnsmasq, edit /etc/dnsmasq.conf to setup DHCP server and /etc/dhcpcd.conf to configure eth0, enable forwarding then manually set default routes.

There are lots of articles on using a Raspberry Pi as a WiFi AP (Access Point, aka "hotspot") and routing that traffic onto a wired eth0 connection: wlan0 to eth0. I want the opposite: take a Raspberry Pi STA (Station aka "client", already connected to some other WiFi) and route the local eth0 traffic into the wireless wlan0. Ideally, I'd like that eth0 to be bridged onto the WiFi network (DHCP relay onto eth0). Turns out that's not so easy. Google "can't add wlan0 to bridge br0: Operation not supported"

Why do this? Well, I started with my new Envox BB3 programmable power supply that has only a wired ethernet connection. What would it take to connect it via a Raspberry Pi to WiFi? Not as trivial of a matter as I had expected. 


To get started, see my prior blog on setting up a headless Raspberry Pi

This first operational example below uses somewhat of a brute-force method in using dhcpcd to manually configure the eth0 interface, and dnsmasq as a DHCP server. 

First, install dnsmasq
sudo apt-get install dnsmasq --assume-yes                               

Essential to the RPi acting as a forwarding router, edit the /proc/sys/net/ipv4/ip_forward file and ensure a value of 1 is there. Note that the change is immediate, although perhaps not permanent. Thanks to a comment on stackexchange, I found this to be very helpful:
grep -rn net.ipv4.ip_forward /etc/*                                  

In my case: /etc/sysctl.conf:28:#net.ipv4.ip_forward=1

Note the line is commented out. To make IP forwarding permanent, edit the /etc/sysctl.conf file to uncomment the net.ipv4.ip_forward=1 line.

Edit /etc/dnsmasq.conf and add these lines at the end to serve as a DHCP server on the RPi ethernet port:
#configure the eth0 interface
interface=eth0

# The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
bind-dynamic

# Never forward plain names (without a dot or domain part)
domain-needed

# Never forward addresses in the non-routed address spaces.
bogus-priv

# Set the NTP time server address to be the same machine as is running dnsmasq
dhcp-option=42,0.0.0.0

# enable the integrated DHCP server, you need to supply the range of 
# addresses available for lease and optionally a lease time
dhcp-range=192.168.42.50,192.168.42.59,255.255.255.0,12h

Edit /etc/dhcpcd.conf (see RPi docs and man page) and add these lines to assigned a fixed IP address to the RPi ethernet port:
interface eth0
static ip_address=192.168.42.10/24

# add the default route on the RPi on the line below. See command: 
# ip route | grep default
# static routers=192.168.42.10
static routers=192.168.42.10, 192.168.1.10

# Don't solicit or accept IPv6 Router Advertisements and DHCPv6
noipv6

# Don't solicit or accept IPv6 Router Advertisements.
noipv6rs

# ensure this route has a high metric to not use it for regular traffic
metric 900

Reboot the RPi.

Once everything is setup, a tiny bit of attention is needed to get routing working properly. This is because your default router does not "know" that a new network exists and is routed through a specific device interface. We need to know the IP address of the RPi that is now acting as router, shown here using the ifconfigcommand:

pi@raspberrypi:~$ ifconfig -a wlan0
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.110  netmask 255.255.255.0  broadcast 192.168.1.255
My IP address in this case is 192.168.1.110, other WiFi IP addresses will likely be different.

The best way to set the new default route is at the WiFi router itself. Given the many different types of routers, there are as many methods of setting a new route. For dd-wrt, see static routing.

Alternatively, this can be done on a local workstation (in my case the one running EEZ Studio that I want to connect to the BB3); On Windows in an administrative privileges DOS command prompt. connected to the same network WiFi as the RPi configured above, we need to manually tell Windows how to find the new Raspberry Pi routed subnet with the DOS route command:

ROUTE [-f] [-p] [-4|-6] command [destination] [MASK netmask] [gateway] [METRIC metric] [IF interface]

In our case: route add [destination network] mask 255.255.255.0 [RPi address]:

route add 192.168.42.0 mask 255.255.255.0 192.168.1.110
  
This basically tells windows: hey, to find the 192.168.42.0 network, route via the address of our Raspberry Pi at 192.168.1.110

To confirm operation:
pi@raspberrypi:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.42.10  netmask 255.255.255.0  broadcast 192.168.42.255

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.110  netmask 255.255.255.0  broadcast 192.168.1.255

pi@raspberrypi:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.1.10    0.0.0.0         UG    303    0        0 wlan0
192.168.1.0     0.0.0.0         255.255.255.0   U     303    0        0 wlan0
192.168.42.0    0.0.0.0         255.255.255.0   U     900    0        0 eth0
And on Windows with the route print command (edited here, as I have VM's cluttering up the list):
C:\>route print
  
IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0     192.168.1.10    192.168.1.140     50
      192.168.1.0    255.255.255.0         On-link     192.168.1.140    306
    192.168.1.140  255.255.255.255         On-link     192.168.1.140    306
    192.168.1.255  255.255.255.255         On-link     192.168.1.140    306
     192.168.42.0    255.255.255.0    192.168.1.110    192.168.1.140     51
  255.255.255.255  255.255.255.255         On-link     192.168.1.140    306
===========================================================================
Persistent Routes:
  None
 
If you see an error "Timeout (no response to IDN query)" in EEZ Studio, try rebooting the BB3



In the end, although this technically works - it is still not the simple solution I am looking forward. It is too annoying to find DHCP address (or manually configure a static one), and the fuss with manual routes. In my next blog, I test drive wan_kabel. It is pretty cool!


Resources, Inspiration, Credits, and Other Links:







Saturday, October 24, 2020

Raspberry Pi Headless Setup

Some notes on setting up a fresh Raspberry Pi.

TL;DR Edit 4 files on the SD card before initial powerup:
  • ssh (just create a blank one)
  • cmdline.txt (add option to disabled IPv6)
  • config.txt (edit to enable UART)
  • wpa_supplicant.conf (config to boot with WiFi working)

Newer versions of Raspian (now called Raspberry Pi OS) come with the Serial UART TTL and SSH disabled by default. Enable SSH by adding a file called SSH to the root directory. The Serial UART can be enabled as described in the Adafruit Headless Quick Start by adding a line to the config.txt file on the SD card before inserting into the RPi:

#enable pins 8 (TxD) and 10 (RxD) as serial TTY                               
enable_uart=1                                   

Reminder for Windows users: Microsoft continues to try to out-think you by automatically adding a ".txt" to files created when right-clicking in Explorer. Check the box "View - File name extensions" in Explorer or use the copy con: ssh command from a DOS prompt (Ctrl-Z to write the file)

The network can be configured in the wpa_supplicant.conf (new file created on SD card) as described in Setting up a wireless LAN via the command line by creating a file called wpa_supplicant.conf: (see docs)
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev                       
update_config=1
country=US
 
network={
    ssid="YOURSSID"
    psk=YOURPASSWORD
    scan_ssid=1
}

Some places will claim to not use quotes. I needed to use them around ssid, but not on psk.

The wpa_supplicant.conf file will be copied to /etc/wpa_supplicant/wpa_supplicant.conf and the removed from the boot directory at RPi startup time. cmdline.txt file and add ipv6.disable=1

If you want to use a psk instead of a plain text password, and for some reason don't have a linux box or WSL to run wpa_passphrase "YOURSSID" (installed with sudo apt install wpasupplicant) there's a Wireshark page that will do the conversion.

We'll also (optionally) install log2ram as described in my prior blog on the Pi-Hole notes.
sudo rfkill unblock wlan
sudo apt-get update
sudo-apt-get upgrade --assume-yes
sudo apt-get install fail2ban --assume-yes


# log2ram install (optional)
cd ~/
curl -Lo log2ram.tar.gz https://github.com/azlux/log2ram/archive/master.tar.gz
tar xf log2ram.tar.gz
cd log2ram-master
chmod +x install.sh && sudo ./install.sh
# REBOOT BEFORE INSTALLING ANYTHING ELSE

I saved these 4 files and simply copy them to the root of the CD card when burning a new image for a fresh Raspberry Pi setup.

Sunday, October 18, 2020

Envox EEZ Bench Box 3 Ground Modification - BB3 Safety Upgrade

Over the weekend, I received my EEZ Bench Box 3 that I backed on Crowd Supply. The assembly instructions are quite straightforward and easy to follow and I had it working fairly quickly:


Shortly after assembly however, I noticed the case was not properly grounded. I think this was on my mind, as my recent reflow oven retrofit had this exact same problem. And that's a commercial product by a much larger company!

I mentioned this over on the Envox Discord Channel;  I started the discord discussion on this topic in the #eez-bb3 channel, but it was suggested that I move it to the #crowdsupply channel. So the discussion continues there.

Sure enough: although there was an excellent paint job on the enclosure, there was not supposed to be paint where the standoffs meet the case:
"The fact is that one of the AUX-PS stand-off has connection to PE but enclosure maker didn't leave a part of bottom plate unpainted to make electrical contact" --prasimix (eez admin)
My initial solution was to scrape off the paint on the inside bevel of the screw holes. Done carefully, and there will be minimal to no visibility once the screws are re-inserted:


Note the screws are black (painted!) so for a good electrical contact, the undersides of the screws should *also* be scraped.  



Initially I used a hand-turned, over-sized drill bit to scratch off the paint in the holes:


Really on the back and bottom, I think plain silver, unpainted screws would be best, however I don't have any on hand. Even on the sides this might be a good idea, although admittedly the black screws on the nice blue case is quite aesthetically impressive. Still, safety should always take priority.

My next modification was to actually hardwire the ground connection to the case. Fortunately there's even a space lug awaiting the connector. Here the blue end is on the screw holding the power connecting to the case (also scraped off paint on case, see above) and the bare connector is attached to the extra lug on the auxiliary power supply:



Although my initial solution worked, it was admittedly lazy. The right way to do this would have been during assembly, to clean up all the paint around all of the standoffs. But I didn't really want to completely disassemble everything just to do this. 

I started with just the removal of the cover, and the side screws holding the auxiliary power supply:



I then scraped off the paint in a little perimeter around the holes to ensure the standoffs would make electrical contact:


The two holes closest to the rear of the unit (near the power cable) have standoffs that are in direct contact with the incoming earth ground on the power supply connector mounted on the PCB, so it would probably be a good idea to ensure these are in good contact with the case.



The red square to the left is the most important This one is closest to the inbound ground from the power connector (the ground pin in the small red square in the middle). Note the PCB trace. The connector to the right is not connected to anything.

I ended up removing all of the screws from the bottom case:


This allowed removing the bottom cover, without having to disassemble the entire front panel, display, PCBs, etc:


The paint is fairly durable, some sandpaper on the end of a pencil or small nut driver might work. I used a Dremel tool on lowest speed setting to gently clean off the paint around all of the standoff connectors in the bottom panel:


Note the two screws that connect the front panel two the base should also conduct. Pay extra attention to these to ensure the best contact. It is really quite surprising just how well the painted case acts as an insulator. But with quality paint, and even painted screws - that's exactly what happens. Even upon assembly, the screws do not scratch the paint enough to make an electrical connection.

Edit: it's really great when a lot of people participate! All sorts of great ideas come about. @timonsku has an excellent suggestion of using those toothed lock washers to help make contact!


When re-assembling, but sure to connect the wires FIRST, before moving everything into place. Otherwise it will be difficult to reattach them. (yes, I learned this the hard way and removed all the screws in the auxiliary power supply a second time)


Afterwards, simply replace the bottom plate.

Really what I need to do is order some longer screws, and connect the front panel to case ground with wires, and not rely only on the (painted) screws to make a good electrical contact. Note the screws holding the display plate are apparently built-in to the case (my unit arrived with the display already mounted, and the screws to not come through to the front panel). This would be an excellent place for a wired ground connection:


When reassembling, be sure to check to top lid as well. Mine is completely insulated from the power supplies (not good).


Really, I think this is the best suggestion: to have welded posts on all 4 case parts. Thanks [timonsku] :


Hopefully the EEZ folks will mention this early on in their assembly instructions, as this whole process would certainly be easier before the unit is assembled.

See also a discussion of the BB3 on eevblog and the eez-open releases, and firmware releases.


Monday, October 12, 2020

CNC3018 Woodpecker Grbl Firmware Notes


The Woodpecker boards shares the USB 5VDC line with the power input. I use a non-powered USB hub between my computer and the CNC machine. Honestly I'm not sure if it actually does anything to isolate or perhaps I'm just lucky. (probably the latter) TODO: find and buy a good isolated USB, such as the Adafruit USB Isolator - 100mA Isolated Low/Full Speed USB.

For reference, my current firmware version is Grbl 1.1f, or more specifically $I result:

[VER:1.1f.20170801:]
[OPT:V,15,128]

The Woodpecker board has a CH340 serial chip and is accessible via the usual putty 8N1/115200:

"Help" $$ is simply this one line:

[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]

That's not very helpful, but according to the documentation, newer versions will apparently provide more details:

$$ (view Grbl settings)
$# (view # parameters)
$G (view parser state)
$I (view build info)
$N (view startup blocks)
$x=value (save Grbl setting)
$Nx=line (save startup block)
$C (check gcode mode)
$X (kill alarm lock)
$H (run homing cycle)
~ (cycle start)
! (feed hold)
? (current status)
ctrl-x (reset Grbl)

My settings via $$ (always a good idea to save these BEFORE upgrading firmware):

$0=10                                                           
$1=25
$2=0
$3=5
$4=0
$5=0
$6=0
$10=1
$11=0.010
$12=0.002
$13=0
$20=0
$21=0
$22=0
$23=0
$24=25.000
$25=500.000
$26=250
$27=1.000
$30=1000
$31=0
$32=0
$100=800.000
$101=800.000
$102=800.000
$110=800.000
$111=800.000
$112=600.000
$120=10.000
$121=10.000
$122=10.000
$130=200.000
$131=200.000
$132=200.000
The Grbl Default Settings:
$0=10 (step pulse, usec)                                          
$1=25 (step idle delay, msec)
$2=0 (step port invert mask:00000000)
$3=6 (dir port invert mask:00000110)
$4=0 (step enable invert, bool)
$5=0 (limit pins invert, bool)
$6=0 (probe pin invert, bool)
$10=3 (status report mask:00000011)
$11=0.020 (junction deviation, mm)
$12=0.002 (arc tolerance, mm)
$13=0 (report inches, bool)
$20=0 (soft limits, bool)
$21=0 (hard limits, bool)
$22=0 (homing cycle, bool)
$23=1 (homing dir invert mask:00000001)
$24=50.000 (homing feed, mm/min)
$25=635.000 (homing seek, mm/min)
$26=250 (homing debounce, msec)
$27=1.000 (homing pull-off, mm)
$100=314.961 (x, step/mm)
$101=314.961 (y, step/mm)
$102=314.961 (z, step/mm)
$110=635.000 (x max rate, mm/min)
$111=635.000 (y max rate, mm/min)
$112=635.000 (z max rate, mm/min)
$120=50.000 (x accel, mm/sec^2)
$121=50.000 (y accel, mm/sec^2)
$122=50.000 (z accel, mm/sec^2)
$130=225.000 (x max travel, mm)
$131=125.000 (y max travel, mm)
$132=170.000 (z max travel, mm)


My $# result:
[G54:0.000,0.000,0.000]                                          
[G55:0.000,0.000,0.000]
[G56:0.000,0.000,0.000]
[G57:0.000,0.000,0.000]
[G58:0.000,0.000,0.000]
[G59:0.000,0.000,0.000]
[G28:0.000,0.000,0.000]
[G30:0.000,0.000,0.000]
[G92:0.000,0.000,0.000]
[TLO:0.000]
[PRB:0.000,0.000,0.000:0]


Whistling sound? Thanks chamnit:

The PWM frequency changed from 7.8 kHz to 1kHz in Grbl v1.1. To change back, edit the cpu_map.h file and look for the SPINDLE_TCCRB_INIT_MASK macros. There are several commented, including the one for 1kHz. Just swap them and recompile


If for some reason I ever need to replace the controller board, I'll probably try the SAINSMART Controller Board for Genmtisu CNC Router 3018, 3018-PRO, 1810-RP and the Offline Controller Module (although need to determine if there's anything hardware specific to their Genmtisu)


Resources, Inspiration, Credits, and Other Links:




CNC 3018 Limit Switch End Stop Mounts (3DPrinted)

This is a continuation of my prior blog: The road to CNC3018 Limit Switches

Update: I've migrated my blog to GitHub pages, here and posted the STL files here.

These parts that I custom designed are for the CNC3018 (specifically the CNC3-3018Pro) Desktop CNC Engraving Router such as the one I purchased from Twowin Tools on AliExpress. Some of these mounts may be applicable to other CNC Routers as well. ymmv.


All of the designs here are for the relatively common Makerbot limit switch available on Amazon, eBay, AliExpress, etc...

There are certainly less complex implementations of limit switches.

WARNING: CNC Machining, even on a small desktop unit is inherently DANGEROUS.

I'm a software engineer at the Day Job, with relatively minimal mechanical engineering experience. This project is also my first experience with Fusion360. Although I've gone through (an embarrassingly large number of) iterations trying to take into account a surprising number of factors - there are probably still problems. DO NOT RELY ON THESE MOUNTS FOR PERSONAL SAFETY. There is no guarantee of proper operation or reliability. 

WEAR EYE PROTECTION AT ALL TIMES.

For installation, I wanted to minimize any additional machine tooling: no drilling, cutting, or other modifications are needed to mount these switches.

Parts Needed:

  • 6x Switches: a pair for each axis end limit: X, Y, Z.
  • M3 x 8mm screws.

Optional:
  • Assembly tools such as a quite handy 2.5 MM Ball-Hex (allen) driver. The ball-end is just too cool for screwing in M3 nuts from an angle.

  • Opto-isolator, such as the CNC Optical Limit Switch Isolator - GRBL on Tindie. Note that TWO of these boards may be needed to cover both end limits for some machines. This is clearly illustrated in the schematic that I should have studied more closely (but who would want a limit in only one direction?). As it turns out, I was "lucky" in that both ends of each axis are tied together on the PCB anyhow. So one board should work just fine for my desktop CNC:

 

Axis Designation

The notation in Fusion360 XYZ, Red Green Blue is followed:




These parts are all printed with Prusament PLA (silver) on a Prusa I3 MK3S kit with the Double-sided Textured PEI Powder-coated Spring Steel Sheet using mostly default settings for 0.15mm Quality, 15% infill and the "brim" checkbox in the PrusaSlicer with the exception that I increase the bed temperature to 65C for the first layer: 

X-Axis (red)

The X-Axis on the CNC3018 is the left-right worm gear holding the engraver motor. Thus the motor moves in the X and Z directions.

My final design for the X-Axis end-stops uses the black Bakelite sides as the stop for the actuator.

The switches are mounted on a pair of symmetric clip-on brackets. One is as shown: 

X-Axis Switch Mount

  1. The wrap-around clip that holds the bracket in place.

  2. Holes for 5.5mm nuts. The fit is a bit tight to make assembly easier. It may be useful to first thread a screw to pull the nut into the hole.

  3. Wire routing channel.

  4. Alignment holes for the "chimney" portion of the wire routing channel extension.



  5. Continued wire routing channel.

  6. Cutout for wire exit.

  7. Nubs to snap into pre-existing hold in the side of the motor mount.


Here's the as-seen, design view of one of the mounting clips with the chimney:

With an additional X-Axis Clip-on Bracket, the actual assembly looks like this:


Y-Axis (green)

The Y-Axis end-stops are located underneath the plan of the the moving table. Two assemblies are used: one on each side of the router table. The design is such that the switch is positioned underneath the table to minimize debris dropping into what could have otherwise been considered a bucket in earlier designs. This was one of the many things not considered during design, but abundantly obvious once viewed in place.

There are a total 7 parts for each of the Y-Axis mounts. Although one could certainly buy mounting hardware, 4 of the printed parts are the pair of nuts and bolts:


Printing nuts and bolts is a learning opportunity (including paying attention to left or right-hand threading). The fit is not super great as-printed. I used this as an excuse to buy a metric tap and die set. These specific ones are designed as M8X1.25

Other than the 4 parts for nuts and bolts, the remaining 3 parts for the Y-Axis are the actual switch mount, lid and limit stop. The stop is a vertical thin tab designed to be break-away in case of mishap, instead of destroying the bracket housing the Y-Axis electronics:

The vertical tab stop is not only thin, but it is also printed parallel to the print bed, making it even more weak. It should only be strong enough to trigger the switch.

The body of the Y-Axis switch mount Body is considerably more complex:


  1. Through-holes for mounting the PCB for the switch.
    (2x) 10mm M3 screw and (2x) 5.5mm nuts.

  2. Posts with a snap-in nub for the other 2 holes in the switch PCB.

  3. Bumps to help catch and hold the lid from the sides.

  4. Another bump to hold the lid in place.

  5. Opening for wire exit.

  6. Narrow channel for wire routing.

  7. Mounting holes to mount to side rail. 
    (2x) 8mm M3 screw and (2x) T-Slot nuts.


    The final part of the Y-Axis end-stop is the Lid:


  8. Catch for the bumps on the base, (#3) above.
    s
  9. Rear catch for #4 bump from above.

  10. Wire hold-downs.

  11. Window for switch trigger arm.
The complete, rendered Y-Axis mount Body and Lid:


A complete set of the above Y-Axis parts is used both on the left and right sides for min / max limits.

(TODO: which is which?)

It's probably best to mount the PCB inside the switch housing and install the lid before mounting to the side rail with (2x) 8mm M3 screw and (2x) 5.5mm nuts.





Z-Axis (blue)

There are 4 main components for the Z-Axis: an upper and lower end limit clip, and a 2-part switch mount. All attach to the motor mount with snap-on, press-fit.

The first part is this lower limit clip:



  1. The sides extend back fairly far. They are thin here to minimize any wasted travel distance range in the X direction (the motor mount otherwise travels right up flush with the Bakelite sides.

  2. Little round nubs catch in pre-existing holes on the motor mount.

  3. An extension is providing to distance the clip from the actual switch lever.

    The next part is the upper clip used for the vertical limit:


  4. Mounting brackets to snap onto the vertical Z-Axis motor spacers.

  5. Spare cutting bit holder. (beware the bits are extremely sharp: the protective cover for them typically protects the bit, not your fingers. Yes, I learned this the hard way. Twice. The first time, I didn't even know how I cut my finger!)  TODO: design a cover.

  6. Not visible in this photo is a little bump that hits the upper Z-Axis switch.

    Switches are mounted with this two part assembly. The first part snaps onto the motor mount:



  7. Mounting Holes to attach the second part that has switches mounted. (see below)

  8. Clearance for the upper clip.

  9. Clearance for the lower clip.

  10. Upper nub to latch housing onto motor mount.

  11. Part of housing "wraps around" front of motor mount here.

  12. Unnecessary material removed.





  13. Posts with a snap-in nub for the other 2 holes in the switch PCB. (upper limit)

  14. Posts with a snap-in nub for the other 2 holes in the switch PCB.(lower limit)

  15. Through-holes for mounting the PCB for the switch. Aligns with holes in first part, the inner housing described above. This is for the lower limit switch.
    (2x) 10mm M3 screw and (2x) 5.5mm nuts.

  16. Through-holes for mounting the PCB for the switch. Aligns with holes in first part, the inner housing described above. This is for the upper limit switch.
    (2x) 10mm M3 screw and (2x) 5.5mm nuts.

  17. Unnecessary material removed.

  18. Ridge to hold snap-on cover (TODO: design Z-Axis switch cover)

Both Z-Housing Mounts, rendered together as a single assembly:



And so I guess in the end, yes: this is a rather overly complex design for something as (seemingly) simple as CNC limit switches. Alas this is 2020 and I have plenty of time at home to learn all these things that I've wanted for so long. For a software guy like me - it is really quite amazing to draw something and have it actually end up as a physical thing, all from the comfort of my home.



If you've read along this far (hey! thank you, I'm glad someone is interested) ... and if you have a CNC machine like the one described above but do not have a 3D printer, I have a bunch of initial prototype parts that with a bit of TLC (read: they don't fully work; time needed to sand, cut, or otherwise modify and adjust) ... that could probably be adapted to function. I'm willing to ship them anywhere in the USA for free, and perhaps anywhere in the world, depending on actual destination and cost. It's a shame to throw them away and I don't know what I would do with them otherwise. So if the prototypes can go to a good home, let me know. My blog name at gmail works.

See my next blog post on CNC 3018 Makerbot Limit Switch Wiring.

As always: I am not specifically recommending or endorsing any of the product links in this blog. None are ads, or "affiliate" links. These links are included from my personal experience, "notes to self" and for reader convenience only. If you, too, are ridiculously tired of excessive ads, check out The pi-hole.



CNC 3018 Makerbot Limit Switch Wiring

This is a continuation of my prior blog on limit switch mounting hardware design for the CNC3018.

There are plenty of resources on various limit switch wiring. As with most information on the internet: some is good, some not so good. One place to start for the desktop CNC is the gnea/grbl wiki: Wiring Limit Switches.

One of the first things to note is the Woodpecker board is designed such the the default switches are expected to be NO (Normally Open, High); The limit is triggered by pulling the signal low (short to ground).  This is unfortunate, as switches will typically fail in the open position. Worse: Perhaps they even become disconnected and stay apparently open during a limit-exceeded condition.

I ordered these switches from ebay. There are similar ones on Amazon. Here's a switch installed in the Y-Axis mount that I designed in Fusion360:


Although there's a wiki link on the board schematic, it has long since disappeared from the internet. Fortunately I was able to recover some key files from the wayback machine, and copied them here for reference (next 5 images credit: Makerbot):


Interface description:



The PCB layout:


Bill of materials:

PCB Render; "The Mechanical Endstop v1.2 is Open Source Hardware and is licensed under the GNU GPLv3":


I needed to measure and create my own mechanical drawing with dimensions:
The PCB supports are 5mm in diameter extrusions, 2.1mm high; The 2 holes are 3.1mm diameter (snug fit). The little nubs on the posts at the end near the connector are an addition 1mm high, 2.9mm diameter. 

I also ordered this Eccentric Work shop CNC optical limit switch isolator. Keep in mind that optical isolation does only that: isolate. This is not a switch debouncer. But then, we'll never need to debounce: the first limit trigger will freeze the controller board. All future signals, limit, G-Code, serial or otherwise will be ignored until the board is reset. 

See the EccentricWorkShop schematic:

At one point, I thought I might need two of these isolator boards, as there is a connection for only 1 wire for each axis. However when looking at the schematic, it appears the limit switch detection is also tied together on the PCB:

And sure enough:




So it appears that when limits are detected, there's no way for the software to determine which limit switch was triggered for a given axis. Although the software would of course know which direction it last send a g-code, so perhaps it could be inferred. Still, if there was a malfunction, it might be nice to know which switch actually triggered.


2* Limit-X-Axis
2* Limit-Y-Axis
2* Limit-Z-Axis
A5 = Probe
A4 =
A3 = Coolant Enable
A2 = Cycle Start/Resume
A1 = Feed Hold
A0 = Reset/About
A7 =
A6 =
D13 = Spindle Direction
RST
5V

And from electrokean:

X = D9 = PB1 = pin 13 via R20
Y = D10 = PB2 = pin 14 via R21
Z = D12 = PB4 = pin 16 via R22

My first test drive was rather disappointing. After all that design work for the limit switch mounts, when using the stand-alone controller, nothing happened when running the sample G-Code and the limit switches were manually pressed. I would have hoped the woodpecker board would be interrupt-driven to detect the switch closures regardless of how the g-code arrived. There's a GitHub discussion where rseijo claimed "Zen, Yen & Xen had no connection points to the Atmega328" (confirmed to not be the case for me) and posted this useful header diagram:



As it turns out, the switches are not enabled by default! Thanks Anyzy for this useful tidbit:


Reading the fine print in the text block, we see that hard limits are enabled with $21=1 (of course they are). My $21 was found to be set to zero. Manually setting this to a value of 1 and tada! Upon pressing the limit switch while even manually moving the axis with the external controller, and the motion immediately stopped! See also the grbl documentation wiki.

Of course, there's probably a reason for having the feature disabled by default. Once triggered, all bets are off and the machine can only continue by pressing reset. Any work in progress is lost. Thus if any sort of stray noise or interference triggers the signal, well - that would certainly fall into the "undesired features" category; for example:
The machine stop working randomly with the spindle still running
And sure enough, if you see the settings posted, the $21 is already set on! So stray noise triggering these limit switches is definitely undesired.

I sure wish I had first found the Hackaday article that referred to an informative blog by Shahada Abubakar. One of the things I learned there: the reset switch is only one option to restart after a limit switch has been triggered. The other option:
 "This can be done by sending Control-X followed by $X"
There are additional tips on GRBL setting there, too.


Resources, Inspiration, Credits, and Other Links:

 


















Find gojimmypi at gojimmypi.github.io

I'm currently working on my new blog home at  gojimmypi.github.io After implementing a variety of features such as dark mode , syntax hi...