{"id":1928,"date":"2014-01-18T22:24:06","date_gmt":"2014-01-18T22:24:06","guid":{"rendered":"http:\/\/www.amzsaki.com\/?page_id=1928"},"modified":"2020-09-01T02:41:08","modified_gmt":"2020-09-01T02:41:08","slug":"rpm-meter-for-a-milling-machine","status":"publish","type":"page","link":"https:\/\/www.amzsaki.com\/?page_id=1928","title":{"rendered":"RPM meter for a milling machine"},"content":{"rendered":"<p><a href=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/CNCRPMMeter.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1941\" src=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/CNCRPMMeter.jpg\" alt=\"CNCRPMMeter\" width=\"850\" height=\"410\"><\/a><\/p>\n<p style=\"text-align: justify;\">My home workshop&#8217;s Milling machine now has a brand new rpm meter. Even though the machine has markings on the rpm adjustment dial, often it is hard to tell what is the actual rotation of the milling tool. Milling speeds and feed rates are important in obtaining a nice finish on the workpiece and prolonging tool life. The principle behind the rpm meters is quite simple; as the drawbar rotates, every revolution is counted by a Hall-effect sensor. The sensor is triggered by a small, yet strong magnet attached to the top of the drawbar via a custom 3D-printed holder. The counts from the sensor are transferred to a micro-controller, which displays it on a 4-digit LED screen.<\/p>\n<p style=\"text-align: justify;\">The meter was constructed using a PIC micro-controller and a &nbsp;<a href=\"http:\/\/www.melexis.com\/Hall-Effect-Sensor-ICs\/Special-Purpose-Hall-ICs\/MLX90217-3.aspx\">MELEXIS&nbsp;MLX90217<\/a> Hall-Effect Cam Sensor.&nbsp;The display is a&nbsp;<a href=\"http:\/\/ca.mouser.com\/ProductDetail\/Lite-On\/LTC-4727JS\/?qs=WxFF5lh7QM0cnidnffkAyA==\">Lite-On Elec. LTC-4727JS<\/a> 4 digit, 7-segment, common Cathode display driven by a&nbsp;<a href=\"http:\/\/www.maximintegrated.com\/datasheet\/index.mvp\/id\/1339\">MAX7221 LED Driver<\/a>.<\/p>\n<p style=\"text-align: justify;\">This short article concentrates on the rpm meter prope. Pretty much any PIC micro-controller can be used to run the device. Mine is a&nbsp;PIC16F876A on a home-brew printed circuit board.&nbsp;The schematics, and the PCB layout shown below along with the PIC BASIC Pro firmware source code should be sufficient to wire up the LED driver and the Hall-effect sensor to your particular flavour of micro-controller.<\/p>\n<p style=\"text-align: justify;\">The PCB containing the display and its driver and the PIC board are housed in a box made of 1\/8&#8243; thick MDF with custom milled cutout for the display. The box is attached to a 3D printed cylinder that sleeves over a protrusion on top the mill&#8217;s gearbox. Thus the rpm meter can be taken off with ease and replaced by the plastic cap that came with the mill.<\/p>\n<p style=\"text-align: justify;\">The following schematic illustrates the wiring between various components. Note that the PIC connects to the PCB board via four wires at JP1. The power to the board is supplied via the POWER connection and the Hall-effect sensor is labeled by&nbsp;MLX90217. The LED display, although missing a label (&#8230;my bad&#8230;) is the one in the upper right corner. Capacitor C1 and resistor R2 are per the MELEXIS data sheet (page 6, bottom left diagram), while resistor R1 and capacitors C2 and C3 follow the data sheet for the MAX7221 display driver (see page 10 for the capacitors and their types [C2 is a ceramic one and C3 is an electrolytic], place the capacitor as close as possible to the LED driver) .<\/p>\n<p><a href=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/Schematics.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1957\" src=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/Schematics.jpg\" alt=\"Schematics\" width=\"1\" height=\"1\"><\/a><a href=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/Schematics.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1959\" src=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/Schematics-1024x977.jpg\" alt=\"Schematics\" width=\"850\" height=\"596\"><\/a><\/p>\n<p style=\"text-align: justify;\">The matching PCB layout was created in EAGLE. Although I am attaching an image of it with the component placement, it is best to re-design it to suit your needs. My meager PCB making skills only cover one-sided PCBs, so I laid out the components and traces for a single-layer PCB. Of course, double-layer PCB could make the PCB much smaller.<\/p>\n<p><a href=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/PCBLayout.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1964\" src=\"https:\/\/www.amzsaki.com\/wp-content\/uploads\/2014\/01\/PCBLayout-1024x988.jpg\" alt=\"PCBLayout\" width=\"850\" height=\"603\"><\/a><\/p>\n<p style=\"text-align: justify;\">The firmware, which is responsible for polling the Hall-effect sensor and displaying the RPM is presented next. It was written in PIC BASIC Pro, but I am sure that any variant of a micro- controller programming language can be used to adapt the code. The source code is commented enough, I hope, that it is easy to follow what is going on. The Hall-effect sensor is accessed via port B.3 on the PIC, while the MAX7721 is communicated to via ports B.0 for clock (CLK), B.1 for data and B.2 for CS. The main program, after setting up and initializing the LED driver enters into an infinite loop. Within the loop the PIC polls the MELEXIS sensor and sends the rpm value as ones, tens, hundreds and thousands (the four digits) to the LED driver. A note on how the actual rpm value is computed. Revolutions or rotations per minute are displayed, but the number is arrived at by counting the pulses from the Hall-effect sensor for 4 seconds and multiplying this value by 15 to arrive at the number of revolutions per 60 seconds (or a minute). This is done so the display of the rpm is updated relative frequently, yet allowing enough time to sample the Hall-effect sensor&#8217;s output.<\/p>\n<pre class=\"pascal\"><span style=\"color: #ffffff;\">'****************************************************************\n'* Name : CNCRPM.BAS *\n'* Author : Dr. A.M. Zsaki *\n'* Notice : Copyright (c) 2012 All right reserved 2012 *\n'* : All Rights Reserved *\n'* Date : 12\/15\/2012 *\n'* Version : 1.0 *\n'* Notes : *\n'* : *\n'****************************************************************\n\n'****************************************************************\n'* *\n'* Equipment used: Homebrew PIC16F876A microcontroller *\n'* Melexis MLX90217 Hall-Effect Cam Sensor *\n'* MAX7221 LED Driver *\n'* Lite-On Elec. LTC-4727JS 4 digit, 7-segment *\n'* Common Cathode display *\n'* Misc. passive components; resistors, *\n'* capacitors, see datasheets and EAGLE *\n'* schematics *\n'* *\n'****************************************************************\n\nINCLUDE \"modedefs.bas\"\n\n' PIC16F876A is running at 4MHz\nDEFINE OSC 4\n\n' Serial port setup for debug\nDEFINE DEBUG_REG PORTC\nDEFINE DEBUG_BIT 6\nDEFINE DEBUG_BAUD 9600\nDefine DEBUG_MODE 0\n\n' Port and variable for communicating with the Hall effect sensor\n'HallPort var PORTC.3\nHallPort var PORTB.3\nHall_Counter VAR WORD\n\n' Ports for communicating with the MAX7221 LED driver\nMAX7221Data VAR PORTB.1\nCLK VAR PORTB.0\nCS VAR PORTB.2\n\n' Variables for the codes (bit serquences) for setting up and communicating\n' with MAX7221\nDisplayTestOpcode VAR WORD\nScanLimitEnableAllOpcode VAR WORD\nNoDecodeOpcode VAR WORD\nClearDigit1Opcode VAR WORD\nClearDigit2Opcode VAR WORD\nClearDigit3Opcode VAR WORD\nClearDigit4Opcode VAR WORD\nClearDigit5Opcode VAR WORD\nClearDigit6Opcode VAR WORD\nClearDigit7Opcode VAR WORD\nClearDigit8Opcode VAR WORD\nShutdownModeOffOpcode VAR WORD\nShutdownModeOnOpcode VAR WORD\nSetIntensity8Opcode VAR WORD\n\n' Variables for the current opcode, the current number to display and\n' the position (digit location) for display the number\n' NOTE: DigitPosition is counted left to right on the display (or as\n' wired between the MAX7221 and LTC-4727JS\nOpcode VAR WORD\nDigitPosition VAR BYTE\nDigitNumber VAR BYTE\n\n' Constants holding the on\/off bits for various numbers from 0 to 9\nNumbers VAR BYTE[10]\n\n' Constants holding the opcode for digit locations 0-7 on the display\nDigits VAR BYTE[8]\n\n' Counter\nCounter VAR BYTE\n\n' Variable holding the current number to display\nNumber VAR BYTE\n\n' Variable holding the current digit to display\nDigit VAR BYTE\n\n'****************************************************************\n'* *\n'* Initialize variables and constants *\n'* *\n'****************************************************************\n\n' Make the MAX7221 communication pins outputs\nTRISB.0=0\nTRISB.1=0\nTRISB.2=0\n\n' Initialize the Opcodes for MAX7221 communication\n' for the meaning of each see the MAX7221 datasheet\nDisplayTestOpcode=%000011110000000\nScanLimitEnableAllOpcode=%0000101100000111\nNoDecodeOpcode=%0000100100000000\nClearDigit1Opcode=%0000000100000000\nClearDigit2Opcode=%0000001000000000\nClearDigit3Opcode=%0000001100000000\nClearDigit4Opcode=%0000010000000000\nClearDigit5Opcode=%0000010100000000\nClearDigit6Opcode=%0000011000000000\nClearDigit7Opcode=%0000011100000000\nClearDigit8Opcode=%0000100000000000\nShutdownModeOffOpcode=%0000110000000000\nShutdownModeOnOpcode=%0000110000000001\nSetIntensity8Opcode=%0000101000000111\n\n' Definitions of numbers as displayed by segments\n' for the meaning of each see the MAX7221 datasheet\nNUMBERS[1]=%01111110 ' 0\nNUMBERS[2]=%00110000 ' 1\nNUMBERS[3]=%01101101 ' 2\nNUMBERS[4]=%01111001 ' 3\nNUMBERS[5]=%00110011 ' 4\nNUMBERS[6]=%01011011 ' 5\nNUMBERS[7]=%01011111 ' 6\nNUMBERS[8]=%01110000 ' 7\nNUMBERS[9]=%01111111 ' 8\nNUMBERS[10]=%01111011 ' 9\n\n' Definitions of opcodes for setting sigits on the LED display\n' for the meaning of each see the MAX7221 datasheet\nDIGITS[1]=%00000001 ' Position 0\nDIGITS[2]=%00000010 ' Position 1\nDIGITS[3]=%00000011 ' Position 2\nDIGITS[4]=%00000100 ' Position 3\nDIGITS[5]=%00000101 ' Position 4\nDIGITS[6]=%00000110 ' Position 5\nDIGITS[7]=%00000111 ' Position 6\nDIGITS[8]=%00001000 ' Position 7\n\n'****************************************************************\n'* *\n'* Main program starts here *\n'* *\n'****************************************************************\n\nmain:\n\n' Initialize the MAX7221 LED Driver\nGOSUB MAX7221Initialize\n\n' Shutdown Mode - Turn On\nOPCODE=ShutdownModeOnOpcode\nGOSUB SPICommand\n\n' Set Intensity to 8\nOPCODE=SetIntensity8Opcode\nGOSUB SPICommand\n\n' Display 0000 on the LED display\nDigitPosition=0\nDigitNumber=0\nGOSUB DisplayNumberAtDigit\n\nDigitPosition=1\nDigitNumber=0\nGOSUB DisplayNumberAtDigit\n\nDigitPosition=2\nDigitNumber=0\nGOSUB DisplayNumberAtDigit\n\nDigitPosition=3\nDigitNumber=0\nGOSUB DisplayNumberAtDigit\n\nloop:\n\n' Obtain reading for the Hall-effect device\n' by counting the number of crossings for 4 seconds\n' Multiply this value (Hall_Counter) by 15 to obtain\n' RPM\nHALL_COUNTER=0\nCOUNT HallPort,4000,HALL_COUNTER\nHALL_COUNTER=HALL_COUNTER*15\ndebug \"RPM:\",#HALL_COUNTER,\" \",10,13\n\n' Show the RPM count on the LED display\n' Rightmost digit (ones)\nDigitPosition=3\nDigitNumber=HALL_COUNTER DIG 0\nGOSUB DisplayNumberAtDigit\n\n' (tens)\nDigitPosition=2\nDigitNumber=HALL_COUNTER DIG 1\nGOSUB DisplayNumberAtDigit\n\n' (hundreds)\nDigitPosition=1\nDigitNumber=HALL_COUNTER DIG 2\nGOSUB DisplayNumberAtDigit\n\n' (thousands)\nDigitPosition=0\nDigitNumber=HALL_COUNTER DIG 3\nGOSUB DisplayNumberAtDigit\n\n' Loop back forever\ngoto loop\n\nEND\n\n'****************************************************************\n'* *\n'* Initialize the MAX7221 LED driver *\n'* *\n'* See the MAX7221 datasheet for the meaning of these codes *\n'* *\n'****************************************************************\nMAX7221Initialize\n\nHIGH CS\n\n' Set Display Test\nOPCODE=DisplayTestOpcode\nGOSUB SPICommand\n\n' Set Scan Limit - Enable All eight digits\nOPCODE=ScanLimitEnableAllOpcode\nGOSUB SPICommand\n\n' Set Decode Mode - No Decode\nOPCODE=NoDecodeOpcode\nGOSUB SPICommand\n\n' Set Clear Display 1\nOPCODE=ClearDigit1Opcode\nGOSUB SPICommand\n\n' Set Clear Display 2\nOPCODE=ClearDigit2Opcode\nGOSUB SPICommand\n\n' Set Clear Display 3\nOPCODE=ClearDigit3Opcode\nGOSUB SPICommand\n\n' Set Clear Display 4\nOPCODE=ClearDigit4Opcode\nGOSUB SPICommand\n\n' Set Clear Display 5\nOPCODE=ClearDigit5Opcode\nGOSUB SPICommand\n\n' Set Clear Display 6\nOPCODE=ClearDigit6Opcode\nGOSUB SPICommand\n\n' Set Clear Display 7\nOPCODE=ClearDigit7Opcode\nGOSUB SPICommand\n\n' Set Clear Display 8\nOPCODE=ClearDigit8Opcode\nGOSUB SPICommand\n\n' Set Shutdown Mode - Off\nOPCODE=ShutdownModeOffOpcode\nGOSUB SPICommand\n\nRETURN\n\n'****************************************************************\n'* *\n'* Send an SPI command to the MAX7221 *\n'* *\n'****************************************************************\nSPICommand\n\nlow CS\nShiftOut MAX7221Data,clk,MSBFIRST,[OPCODE\\16]\nHIGH CS\n\nRETURN\n\n'****************************************************************\n'* *\n'* Display a number at a 'digit' location *\n'* *\n'****************************************************************\nDisplayNumberAtDigit\n\nDIGIT=DIGITS[DigitPosition+1]\nNUMBER=NUMBERS[DigitNumber+1]\n\n' Lower byte of word - Number to display\nFOR COUNTER=0 TO 7\nOPCODE.0(COUNTER)=NUMBER.0(COUNTER)\nNEXT\n\n' Upper byte of word - Digit position\nFOR COUNTER=8 TO 15\nOPCODE.0(COUNTER)=DIGIT.0(COUNTER-8)\nNEXT\n\nGOSUB SPICommand\n\nRETURN<\/span><\/pre>\n<p style=\"text-align: justify;\"><script type=\"text\/javascript\" src=\"js\/shCore.js\" language=\"javascript\"><\/script><script type=\"text\/javascript\" src=\"js\/shBrushCSharp.js\" language=\"javascript\"><\/script>Well, there is nothing much else to it. Now it is relatively easy to add an RPM meter to any milling machine.<\/p>\n<p style=\"text-align: justify;\">Now, off to make more chips&#8230;<\/p>\n<p><script type=\"text\/javascript\" src=\"js\/shBrushXml.js\" language=\"javascript\"><\/script><script type=\"text\/javascript\" language=\"javascript\">\/\/ <![CDATA[\ndp.SyntaxHighlighter.ClipboardSwf = '\/flash\/clipboard.swf';\ndp.SyntaxHighlighter.HighlightAll('code');\n\/\/ ]]><\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>My home workshop&#8217;s Milling machine now has a brand new rpm meter. Even though the machine has markings on the<\/p>\n<p><a href=\"https:\/\/www.amzsaki.com\/?page_id=1928\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\">RPM meter for a milling machine<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":298,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1928","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/1928","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1928"}],"version-history":[{"count":45,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/1928\/revisions"}],"predecessor-version":[{"id":3308,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/1928\/revisions\/3308"}],"up":[{"embeddable":true,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/298"}],"wp:attachment":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1928"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}