Controller / Firmware

M-Code steered Arduino Mega Shield to control servos in 3d printed feeder. Additionally firmware has capabilities to read some analog channels (e.g. for vacuum sensors) and switch some mosfets to power some peripherials. Used in combination with 3d printed 0816-automatic feeder.

  • two alternative shields, one firmware ready for both
  • firmware for Arduino Mega
  • handles up to 24 feeder (native shield) resp. 48 feeder (sensor shield)
  • advance tape 2 mm and multiples of that
  • interfaces via G-Codes received per serial communication
  • seamless integration into OpenPnP via G-Code-Driver and it's actuator system
  • controller checks status of feeder and passes an occuring error to host (e.g. feeder not loaded, cover tape tension insufficient) (native shield only)
  • Manual feed: Press on cover tape tensioner for a short time to feed. Useful to setup feeder. (native shield only)
  • Additional Non-Feeder related features (native shield only):
    • read up to 8 analog channels and report it's value to OpenPnP
    • scaling and offsetting raw analog values to real units
    • up to 4 power output
    • 2 special analog channels prepared to read NXP vacuum sensors

Controller-Shield for Arduino Mega

Native Shield Arduino Mega Sensor Shield v2.0
0816 automatic smt feeder arduino native shield MNS G54.2 IN10 N10 RN8 O0.40 Y264.00 C198.00 YT1 CT3 s0 sY8.00 S300 C50 NRThrd6
needASF1  FM0 CR1.04 FC111111111: bfalic 0000X:zzzzzH87010tzzzzzz1
d1aa5305c04388505801761941040 c30 be2a0  0  0365116287  0  0  0  0 0 0 0 0296
1e1f1ca  4 2 02ca 1a4f195  4 2 02fe 14cf12f  4 2 0365  fbf0cc  4 2 0293  c6f091 
4 2 0262 16bf14e  4 2 0231 1c9f1b5  4 2 0200 1bcf1a9  4 2 023c 171f156  4 2 024f
1c9f1b9  4 2 0262 1cff1be  4 2 0275 1caf1b4  4 2 024f 1c7f1af  4 2 0252f7f2f 2
c87 c 02d 02d 0 a 0 94d294a2746 942 b19 415 5 9 4 8 514 611 4 7 5 7 412 5 f 5 7
4 5 5 5 4 6 5 5 5 4 5 4 4 4 4 4 5 5 4 4 5 4 4 4 5 4...
supported by firmware out of the box
Number of feeder 24 48
Manual feed by tapping on tape tensioner -
Check feedback line for sufficient tape tension -
2 optional vacuum sensors -
4 optional power output -
power from arduino or external
enable/disable power for all feeder via g-code -
where to get? OSHpark and co. and others

Choose how to supply power to the feeder:

type source how to activate that type? useful for precaution
internally powered arduino 5v line set a jumper on the pinheader INT_PWR (native shield) resp. PWR_SEL (sensor shield) prototyping don't connect external power
externally powered external 5V power supply remove jumper from INT_PWR (native shield) resp. PWR_SEL (sensor shield) and
connect supply to FEEDER_PWR resp. the only screw block (sensor shield)

Get the currentmost firmware at

Configure and Build

Use Arduino IDE to build and upload to microcontroller. Precompiled files are not available. Adapt firmware to your needs by modifying config.h. Most of the settings should not need to be touched as they are preconfigured properly already.

Anyway there is a config.h to enable/disable debugging, change serial baud rate and choose the controller shield.

#define DEBUG  // disabled (commented) by default. uncomment to get some debug data printed via serial
#define CONTROLLER_SHIELD NATIVE_SHIELD  //compile for native shield (NATIVE_SHIELD) or sensor shield (SENSOR_SHIELD)
#define SERIAL_BAUD 115200  //set speed of serial communication

Install the following libraries via Arduino Library Manager:

  • EEpromEx
  • Servo

Test Firmware

Open serial monitor within Arduino IDE and see whether the controller works. There should be messages on startup that inform about the settings hold in eeprom. Test some commands in the serial monitor to see whether communication works as expected before setting up in OpenPnP.

In combination with the native shield all 4 pin connect to the controller. If you chose to use the sensor shield, the feedback line is left unconnected.

The native shield has the maptable printed on. For the sensor shield the maptable is as the image depicts:

The following commands should work if everything is setup properly. A full list of available commands is listed below.

M610 S1 ; enable feeder
M600 N0 F4 ; feeder N0 advance tape 4mm
M601 N0 ; retract advancing lever (next time feed is faster, this command is a post-pick command)
M600 N0 F2 ; feeder N0 advance tape 2mm
M600 N0 F2 ; feeder N0 advance tape 2mm
M600 N0 F12 ; feeder N0 advance tape 12mm
M610 S0 ; disable feeder

If the feeder doesn't move and an error pops up on the console, check the feeder status with

M602 N0 ; print N0 feeder status

If it reports an error, the feedback-line might not setup properly. Fix it by checking the cabling. Temporarily the error check can be overridden by adding X1 to the feed command:

M600 N0 F4 X1 ; feeder N0 advance tape 4mm ignoring errors

The firmware comes preset for the feeders mechanics. But it may be the case, that the servo angle is a little different from manufacturer and how the servo controller handles the incoming PWM signal. For this reason every feeder has a configuration set. Adapt it so that commanding the servo to 0°/90° indeed makes the servo go to 0°/90°. The current configuration setting per feeder is printed with

M620 N0 ; display settings for feeder N0

The meaning of each argument is to be seen in the detailed list.

  • Check whether the PWM signal timing arguments suit your servo
  • Check whether the servo settles within settle time, otherwise raise it
  • Check for correct angles
M603 N0 A55; set servo on feeder N0 to angle 55°

Once found a proper configuration, set the values globally in config.h or issue an M620 command with correct values for every feeder.

→ see next chapter

The feeder and its controller are designed to suit well to OpenPnP, so nothing special is required to get them to work with OpenPnP. To set up one or more feeder follow the next three steps.

  • add GCode-Driver
  • set port and baud rate (default 115200)
  • set timeout to 10000 ms
  • add command COMMAND_CONFIRM_REGEX and COMMAND_ERROR_REGEX (see below)
parts for the controller's gcode-driver in machine.xml
<gcode-driver port-name="COM15" baud="115200" flow-control="Off" data-bits="Eight" stop-bits="One" parity="None" set-dtr="false" set-rts="false" units="Millimeters" max-feed-rate="1000" backlash-offset-x="-1.0" backlash-offset-y="-1.0" non-squareness-factor="0.0" backlash-feed-rate-factor="0.1" timeout-milliseconds="10000" connect-wait-time-milliseconds="1000" visual-homing-enabled="false" name="0816 feeder controller">
  <command type="COMMAND_CONFIRM_REGEX">
  <command type="COMMAND_ERROR_REGEX">

In general, there are as many actuators needed as feed lengths are desired. Example: The feeder shall be able to feed 4mm (0805 resistors), 8mm (some ICs) and 12mm there will be 3 actuators to be created, each for one feed length. Every feed-length has to be setup only once, not per feeder. See machine.xml regarding the actuator elements:

parts for actuators in machine.xml
<actuator class="org.openpnp.machine.reference.ReferenceActuator" id="actAutoFeeder4mm" name="AutoFeeder_4mmAdvance" index="0">
<actuator class="org.openpnp.machine.reference.ReferenceActuator" id="actAutoFeeder8mm" name="AutoFeeder_8mmAdvance" index="1">
<actuator class="org.openpnp.machine.reference.ReferenceActuator" id="actAutoFeeder12mm" name="AutoFeeder_12mmAdvance" index="2">
<actuator class="org.openpnp.machine.reference.ReferenceActuator" id="actAutoFeederPostPick" name="AutoFeeder_PostPick" index="3">
<actuator class="org.openpnp.machine.reference.ReferenceActuator" id="actAutoFeederEnable" name="AutoFeeder_Enable" index="4">

For each actuator the G-Code passed to the 0816-controller when a feed command is issued has to be added (example below). The feed command is M600 per default. The Parameter N is the index of the feeder (zero based) and F the feed length in millimeter. Please note that the actuator's name and the value for the parameter F correspond each other. So actAutoFeeder4mm will have the command M600 N{IntegerValue} F4.

parts for the actuator's gcodes in machine.xml
<command head-mountable-id="actAutoFeeder4mm" type="ACTUATE_DOUBLE_COMMAND">
  <text><![CDATA[M600 N{IntegerValue} F4]]></text>
<command head-mountable-id="actAutoFeeder8mm" type="ACTUATE_DOUBLE_COMMAND">
  <text><![CDATA[M600 N{IntegerValue} F8]]></text>
<command head-mountable-id="actAutoFeeder12mm" type="ACTUATE_DOUBLE_COMMAND">
  <text><![CDATA[M600 N{IntegerValue} F12]]></text>
<command head-mountable-id="actAutoFeederPostPick" type="ACTUATE_DOUBLE_COMMAND">
  <text><![CDATA[M601 N{IntegerValue}]]></text>
<command head-mountable-id="actAutoFeederEnable" type="ACTUATE_BOOLEAN_COMMAND">
  <text><![CDATA[M610 S{True:1}{False:0}]]></text>

Do a Test Feed

In the actuators tab click one of the actuators just setup. Put a “0” into “Set Double” to issue a feed command on the first feeder. Click “Set” fires the G-Code to be sent off to the controller and makes the feeder advance the desired length.

Add a ReferenceAutoFeeder in the feeder tab for every physically existing feeder lane. In the field “actuator-name” fill in one of the actuators created in step 2. Example: If the feeder shall advance 8mm, set the actuator-name to “AutoFeeder_8mmAdvance”. In field “actuator-value” the ID of the feeder comes into. The index is 0 based, so 0 will be the first feeder, 23/47 the last. The PostPick actuator is optional but useful to speed up feeding. After a pick, the feeder retracts if needed and gets ready for next feed.

parts for the feeder in machine.xml
<feeder class="org.openpnp.machine.reference.feeder.ReferenceAutoFeeder" id="autofeeder0" name="auto_id0_8mm" enabled="false" part-id="R0805" retry-count="3" actuator-name="AutoFeeder_4mmAdvance" actuator-type="Double" actuator-value="0.0" post-pick-actuator-name="AutoFeeder_PostPick" post-pick-actuator-type="Double" post-pick-actuator-value="0.0">
<feeder class="org.openpnp.machine.reference.feeder.ReferenceAutoFeeder" id="autofeeder1" name="auto_id1_8mm" enabled="false" part-id="R0603-1K" retry-count="3" actuator-name="AutoFeeder_4mmAdvance" actuator-type="Double" actuator-value="1.0" post-pick-actuator-name="AutoFeeder_PostPick" post-pick-actuator-type="Double" post-pick-actuator-value="1">

  • maschine/pickandplace/feeder/0816feeder/controller.txt
  • Last modified: 2019/01/04 00:00
  • (external edit)