Custom Feeders

712 views
Skip to first unread message

Justin Rajewski

unread,
Jan 26, 2016, 12:50:22 PM1/26/16
to OpenPnP
I'm working on added an automatic feeder to the base version of the OpenPnp machine. I've extended it using the 1m bars instead of 0.5m to have more space for reels.

I wanted the feeders to be as thin as possible so I could pack as many different parts in as I can. The basic design is a tube that the tape goes into that is screwed onto the machine. There are two one-way bearings. The bottom one has a sprocket that locks into the holes in the tape and a gear that is used to connect it to the bearing above it as well as pull the covering off.

Each feeder doesn't have a motor. Instead there is one stepper motor on a linear rail. A servo can lift and lower the motor so that it can engage/disengage the different feeders.The V shaped gears help keep everything aligned and helps keep the covering centered in the gear.

Since the smoothie board is pretty much maxed out from the base machine, I'm using a Mojo with some extra hardware to drive the two steppers and the servo. I'm also planning to have a little micro switch on each feeder that will be able to detect the holes in the tape.

I have a simple serial interface that I can use to control everything and the hardware seems to be working decently. I now need to figure out how to add my feeder into the OpenPnp project.

I cloned the repo and started digging through and was able to get a new feeder to show up with little work (just copied the drag feeder). While I'm sure I can eventually get this to work, are there any pointers for adding my own feeder and driver to the project while still being able to easily pull updates?

Also once I get things a bit more ironed out, I'll be happy to share all my design files. I did all the CAD work in Blender.

Thanks,
Justin
2016-01-25.jpg
2016-01-25 (1).jpg
2016-01-25 (2).jpg

Rich Obermeyer

unread,
Jan 26, 2016, 12:58:35 PM1/26/16
to ope...@googlegroups.com
@Justin, Nice ideas.  What happens to the cover tape?

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/openpnp/2b28724e-b268-4a36-9e02-5ecb40382d9c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Rich

Jason von Nieda

unread,
Jan 26, 2016, 1:00:09 PM1/26/16
to OpenPnP
Hi Justin,

Really nice work! I like the looks of this and it's a very interesting design. Please keep us updated! :)

As for adding the feeder, here is the basic process:

1. Create a new class that extends ReferenceFeeder. You can do this by copying one of the existing classes, and it sounds like you already have. Copying ReferenceDragFeeder is a good choice since it already uses an Actuator and picks from a fixed location.
2. Add the new class to ReferenceMachine#getCompatibleFeederClasses(). This will make it show up in the UI when you want to add a feeder.
3. Modify the new feeder class to use the actuator to do whatever your feeder needs to advance. This will probably involve adding some configuration fields and using an index or something to choose the right actuator.
4. Add actuators as needed to your configuration file.
5. Modify your driver to respond to the actuator commands appropriately.
6. Profit!

The actuator is your interface into the driver. It's a very simple interface, but it should do the job. Using actuators allows you to keep the changes to the driver very minimal and it should remain easy to continue to merge features in. Once we get to the point of having a more generic driver it will be possible to implement this kind of new functionality without having to modify the driver, but for now that's the only way.

Let me know if this doesn't make sense, happy to provide more guidance.

Jason



--

Anthony Webb

unread,
Jan 26, 2016, 1:13:13 PM1/26/16
to ope...@googlegroups.com
Really nice machine Justin!  Awesome work with the feeder too.  Love to see the innovation coming from this group.

Justin Rajewski

unread,
Jan 26, 2016, 2:19:36 PM1/26/16
to OpenPnP
@Maddog, the covering is just pushed back towards the reels and towards the floor. The parts tape gets pushed down a slot that forces it under the machine and out the back. I originally was going to have it loop back towards the reels, but the added friction from the turn around was causing problems. I attached some more pictures to help explain. 

I wanted a feeder that could run basically forever. You can simply cut the extra off as it gets too long.

@Jason, thanks for the outline. I was thinking I need to make another driver class for my board. Is this correct, or should I modify the smoothie driver? I'll be using both at the same time and each will have it's own serial port. I'm not sure if this is supported/easy to do.

@Anthony, thanks but I can't take credit for most of it. It's basically an exact clone of the base OpenPnp machine (with the exception of extra width and my feeder mods). I actually wouldn't have even started this if I didn't meet Jason as Maker Faire.
IMG_20160126_120912.jpg
IMG_20160126_120919.jpg

Jason von Nieda

unread,
Jan 26, 2016, 2:28:45 PM1/26/16
to OpenPnP
Justin,

There's not currently a good way to support two driver classes. This is probably something that needs some thought for a future API refactor since I suspect addon boards will start becoming much more popular.

In the meantime, what I would suggest is creating an extension of the OpenBuilds driver and in that class add your second serial connection. Then you can override the actuate() methods in your new class and have them call into your new serial port. This will make it easy to keep pulling in changes to the OpenBuilds driver without breaking your additions.

So, this would just look something like:

```
package org.openpnp.machine.openbuilds;

import java.io.OutputStream;

import org.openpnp.machine.reference.ReferenceActuator;
import org.simpleframework.xml.Attribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jssc.SerialPort;

public class JustinDriver extends OpenBuildsDriver {
    private static final Logger logger = LoggerFactory.getLogger(JustinDriver.class);
    
    @Attribute(required=false)
    protected String addonPortName;
    @Attribute(required=false)
    protected int addonBaud = 115200;
    
    protected SerialPort serialPort;
    protected SerialInputStream input;
    protected OutputStream output;

@Override
public void actuate(ReferenceActuator actuator, boolean on) throws Exception {
super.actuate(actuator, on);
// do actuator stuff for addon board here
}

@Override
public void actuate(ReferenceActuator actuator, double value) throws Exception {
super.actuate(actuator, value);
// do actuator stuff for addon board here
}
public synchronized void addonConnect() throws Exception {
// do addon connect stuff
}
public synchronized void addonDisconnect() {
// do addon disconnect stuff
}

@Override
public synchronized void connect() throws Exception {
// first connect to the main board
super.connect();
// then connect to the addon board
addonConnect();
}

@Override
public synchronized void disconnect() {
// first disconnect the main board
super.disconnect();
// then disconnect the addon board
addonDisconnect();
}
}
```


It may be easier to just copy and modify the driver but then you'll have a lot harder time merging in changes from the main codebase in the future. By extending it instead merges should be a breeze and it makes it much easier for you to contribute your new driver back to the project if you wish.

Jason


--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Anthony Webb

unread,
Jan 26, 2016, 2:35:58 PM1/26/16
to ope...@googlegroups.com
That is very clever.  Do you have any video of it running?  Are there any issues with re-engaging a sprocket that isnt well meshed? Meaning if it comes down and teeth are slightly off does it bind/bend?

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Justin Rajewski

unread,
Jan 26, 2016, 3:24:25 PM1/26/16
to OpenPnP
Thanks Jason for basically writing the class for me :P

Here are some crude videos.


On Tuesday, January 26, 2016 at 10:50:22 AM UTC-7, Justin Rajewski wrote:

Justin Rajewski

unread,
Jan 26, 2016, 3:26:54 PM1/26/16
to OpenPnP
Oh also there doesn't seem to be any issues with the gears meshing. It's really rare they don't mesh when it drops down, and in the case they don't, spinning the gear a tiny bit makes it drop down and mesh again. It doesn't seem like this will be an issue at all.

Jason von Nieda

unread,
Jan 26, 2016, 3:33:10 PM1/26/16
to OpenPnP
Really amazing work Justin, this looks awesome!

I bet you could skip the microswitch by using a bit of simple vision, too. You know how far the tape will advance per step, so you only need to compensate for any error created when the gears first mesh.

So, advance the tape by the amount you think you should, then go look for the hole with the camera. Record the offset from where you expected it to be and where it actually is and then adjust your next movement of that tape by the offset. It will always be a little off, but you just use the same offset when picking and it should work great.

That would, of course, be a lot slower but would keep the design nice and simple. 

Jason


--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Justin Rajewski

unread,
Jan 29, 2016, 2:11:34 PM1/29/16
to OpenPnP
I got some basic stuff written and I'm trying to get it to run on my PnP computer. I made the edits in Eclipse and can run it from there. However, I tried to export a runnable jar but get a bunch of exceptions like

java.lang.NullPointerException
at org.openpnp.gui.support.SvgIcon.<init>(SvgIcon.java:61)

However, I can see the resource folder was copied into the .jar so I'm not sure why it can't find the images.

Any ideas how to export the Eclipse project to a runnable version?

I'm going to try the vision idea out. The microswitches are kind of a pain to use and they add extra drag on the tape.

Jason von Nieda

unread,
Jan 29, 2016, 2:14:28 PM1/29/16
to OpenPnP
Justin,


This shows how to properly load the project into Eclipse so that Maven is setup and how to export a new jar using Maven. 

FYI, for my workflow I typically just have my PnP hooked up to my development machine so I can just hit the Run button in Eclipse and try changes without having to create a new jar and move it over. That process is documented in the first bullet on that link.

Jason

Justin Rajewski

unread,
Jan 29, 2016, 2:20:59 PM1/29/16
to OpenPnP
Awesome thanks! I missed the second link showing how to export it.

Justin Rajewski

unread,
Jan 29, 2016, 4:51:45 PM1/29/16
to OpenPnP
I have my driver working now but I'm a little confused on the best way to organize the new parts.

I setup the driver to control three new actuators that I identify by name. Should I add these actuators to the main head even though they aren't really part of it? Should I add a second head for the second slider instead and add two actuators to that (the servo and gear)?

The drag feeder uses the line

Actuator actuator = head.getActuatorByName(actuatorName);

to get the actuator. If I don't attach it to the head how do I get it?

It seems like the easiest route is to just add the actuators to the main head and just get them by name.

Thanks,
Justin


On Tuesday, January 26, 2016 at 10:50:22 AM UTC-7, Justin Rajewski wrote:

Jason von Nieda

unread,
Jan 29, 2016, 5:00:08 PM1/29/16
to OpenPnP
Hey Justin,

Yea, for now I'd suggest just putting them on the head. This is an API limitation. Machine should really also have Actuators. I do that for Cameras (there are Machine cameras and Head cameras) but I didn't do it for Actuators. There should be Machine actuators and Head actuators.

I've filed an issue for this (https://github.com/openpnp/openpnp/issues/203 ) , but for now just go ahead and attach them to the head.

Jason


--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Justin Rajewski

unread,
Jan 29, 2016, 6:12:45 PM1/29/16
to OpenPnP
Thanks, that's basically what I thought.

I got a basic feed operation to work. I just need to add the vision stuff now to compensate for tape alignment.

Jason von Nieda

unread,
Jan 29, 2016, 6:14:56 PM1/29/16
to OpenPnP
Nice work! Coming along quickly!

Justin Rajewski

unread,
Jan 29, 2016, 6:27:28 PM1/29/16
to OpenPnP
Honestly, I'm really impressed with the OpenPnp code. It's been really easy to add this with practically zero modifications to the core code.

Jason von Nieda

unread,
Jan 29, 2016, 6:29:39 PM1/29/16
to OpenPnP
Thanks, glad to hear that. I've designed it from the ground up to be extensible and modular for specifically this reason. I want to be able to support *any* pick and place, not just my pick and place. My secret (not secret) plan is for OpenPnP to someday be a better choice for pick and place manufacturers than writing their own software.

Jason


Anthony Webb

unread,
Jan 29, 2016, 9:09:10 PM1/29/16
to OpenPnP
Really enjoying following you progress Justin!  Keep the updates coming!

Hey I noticed an upward facing camera on your bed?  Are you playing with that?  I'm keen on doing that as well, I think Jason is tinkering with it as well.

Denis Seguin

unread,
Jan 29, 2016, 10:16:49 PM1/29/16
to ope...@googlegroups.com
Nice work



Bonne journée

Denis

Envoyé de mon iPhone

Richard Hornbaker

unread,
Jan 30, 2016, 5:11:45 PM1/30/16
to OpenPnP
Justin,
Clever design! I had a similar idea to use a single drive shaft for all the feeders, but with some differences. I'd be curious for your thoughts...
First, using a clutch solenoid per feeder to engage a roller/gear with the main shaft (like pressing a wheel into position). It looks like your plan is to move the motor on axis into position for each feeder?
What kind of feedback are you using to ensure the next part well is in position? Are you using friction to hold the position when the motor is not engaged?

Rich Obermeyer

unread,
Jan 30, 2016, 5:21:25 PM1/30/16
to ope...@googlegroups.com
I too think its clever.  However making the heavy stepper move around seems dangerous.
How about putting the large gear on the long shaft and just pressing down on a small gear to engage with the other gear.  That would be very simple servo action without all the weight.

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Rich

Justin Rajewski

unread,
Feb 1, 2016, 4:14:57 PM2/1/16
to OpenPnP
@Anthony, I added the camera for future use but I haven't used it at all yet.

@Richard, I thought of something like this at first too, but I didn't want to have to have an actuator per feeder. This way the single motor can servo all the feeders. The two gears are on one-way bearings to the tape can only go forward (unless you unclip them). I was originally going to use switches to detect the holes but now I'm going to use some machine vision.

@Maddog, I don't see the problem with the stepper moving around. The servo has way more than enough torque to lift it. It's really not that heavy.

I've run into a problem with trying to get the machine vision to work. It keeps crashing in locateTemplateMatches(). It seems like BufferedImage cameraImage_ = camera.capture(); (line 178 in OpenVcVisionProvider.java) is returning null causing it to crash at line 183, cameraImage_ = ImageUtils.convertBufferedImage(cameraImage_, BufferedImage.TYPE_INT_ARGB);

Any ideas why this would be the case? I can see the camera feed in the preview window so my camera is clearly working.

Jason von Nieda

unread,
Feb 1, 2016, 4:20:23 PM2/1/16
to OpenPnP
Hey Justin,

Can you send or paste your machine.xml? I suspect there's not vision provider registered on the camera instance and that will help me confirm. It would also help if you send the code where you are calling locateTemplateMatches.

Jason


Justin Rajewski

unread,
Feb 1, 2016, 4:36:05 PM2/1/16
to OpenPnP
<openpnp-machine>
   <machine class="org.openpnp.machine.reference.ReferenceMachine">
      <heads>
         <head class="org.openpnp.machine.reference.ReferenceHead" id="22964dce-252a-453e-8106-65db104a0763" name="H1">
            <nozzles>
               <nozzle class="org.openpnp.machine.reference.ReferenceNozzle" id="69edd567-df6c-495a-9b30-2fcbf5c9742f" name="N1" pick-dwell-milliseconds="250" place-dwell-milliseconds="250" current-nozzle-tip-id="e092921a-2eef-449b-b340-aa3f40d8d791" changer-enabled="false" limit-rotation="false">
                  <nozzle-tips>
                     <nozzle-tip class="org.openpnp.machine.reference.ReferenceNozzleTip" id="e092921a-2eef-449b-b340-aa3f40d8d791" name="NT1" allow-incompatible-packages="false">
                        <compatible-package-ids class="java.util.HashSet">
                           <id>LED-1</id>
                           <id>rcl-C0603K</id>
                           <id>TAC-1</id>
                           <id>transistor-power-SUPER-SOT3</id>
                           <id>resistor-net-CTS743C163</id>
                        </compatible-package-ids>
                        <changer-start-location units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                        <changer-mid-location units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                        <changer-end-location units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                     </nozzle-tip>
                  </nozzle-tips>
                  <head-offsets units="Millimeters" x="41.95" y="-10.9" z="0.0" rotation="0.0"/>
                  <safe-z value="12.0" units="Millimeters"/>
               </nozzle>
               <nozzle class="org.openpnp.machine.reference.ReferenceNozzle" id="269edd567-df6c-495a-9b30-2fcbf5c9742f" name="N2" pick-dwell-milliseconds="250" place-dwell-milliseconds="250" current-nozzle-tip-id="2e092921a-2eef-449b-b340-aa3f40d8d791" changer-enabled="false" limit-rotation="false">
                  <nozzle-tips>
                     <nozzle-tip class="org.openpnp.machine.reference.ReferenceNozzleTip" id="2e092921a-2eef-449b-b340-aa3f40d8d791" name="NT1" allow-incompatible-packages="false">
                        <compatible-package-ids class="java.util.HashSet">
                           <id>LED-1</id>
                           <id>LED-0</id>
                           <id>TAC-1</id>
                           <id>SparkFun-Electromechanical-TACTILE_SWITCH_SMD</id>
                           <id>embeddedmicro-MAXIM_TSSOP20</id>
                           <id>TAC-0</id>
                           <id>resistor-net-CTS743C163</id>
                        </compatible-package-ids>
                        <changer-start-location units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                        <changer-mid-location units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                        <changer-end-location units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                     </nozzle-tip>
                  </nozzle-tips>
                  <head-offsets units="Millimeters" x="71.8" y="-11.0" z="0.0" rotation="0.0"/>
                  <safe-z value="11.0" units="Millimeters"/>
               </nozzle>
            </nozzles>
            <actuators>
               <actuator class="org.openpnp.machine.reference.ReferenceActuator" id="5b8a8cbd-d6c1-4324-af8b-eba5f0444622" name="Servo" index="0">
                  <head-offsets units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                  <safe-z value="0.0" units="Millimeters"/>
               </actuator>
               <actuator class="org.openpnp.machine.reference.ReferenceActuator" id="5b8a8cbd-d6c1-4324-af8b-eba5f0444621" name="Wheel" index="0">
                  <head-offsets units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                  <safe-z value="0.0" units="Millimeters"/>
               </actuator>
               <actuator class="org.openpnp.machine.reference.ReferenceActuator" id="5b8a8cbd-d6c1-4324-af8b-eba5f0444624" name="Cart" index="0">
                  <head-offsets units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                  <safe-z value="0.0" units="Millimeters"/>
               </actuator>
            </actuators>
            <cameras>
               <camera class="org.openpnp.machine.reference.camera.OpenCvCamera" id="90b848bc-8946-4823-abd3-1b6cb09391fe" name="OpenCvCamera" looking="Down" settle-time-ms="250" rotation="180.0" flip-x="false" flip-y="false" offset-x="0" offset-y="0" device-index="0" preferred-width="0" preferred-height="0">
                  <units-per-pixel units="Millimeters" x="0.059" y="0.059" z="0.0" rotation="0.0"/>
                  <vision-provider class="org.openpnp.machine.reference.vision.OpenCvVisionProvider"/>
                  <head-offsets units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
                  <safe-z value="0.0" units="Millimeters"/>
                  <calibration enabled="false">
                     <camera-matrix length="9">0.0, 0.0, 6.9151234118009E-310, 6.9151234118009E-310, 0.0, 0.0, 5.716612348656109E-262, 1.6131867801013524E-307, 1.3499293480135045E-308</camera-matrix>
                     <distortion-coefficients length="5">2.2680464761193897E223, 4.262343313801839E180, 3.1465022599774634E161, 2.075912757417795E243, 1.7136589314178146E262</distortion-coefficients>
                  </calibration>
               </camera>
            </cameras>
            <paste-dispensers/>
         </head>
      </heads>
      <feeders>
         <feeder class="com.embeddedmicro.feeder.AutoFeeder" id="14ce4e29-9dc4-4bcf-b757-fcf8e5f95254" name="AutoFeeder" enabled="false" part-id="0603 0.1uf" cart-actuator-name="Cart" wheel-actuator-name="Wheel" servo-actuator-name="Servo">
            <location units="Millimeters" x="345.8" y="-76.9" z="26.4" rotation="0.0"/>
            <feed-location units="Millimeters" x="4040.0" y="0.0" z="100.0" rotation="0.0"/>
            <feed-speed>1.0</feed-speed>
            <steps-per-part>39</steps-per-part>
            <vision enabled="false">
               <area-of-interest x="0" y="0" width="0" height="0"/>
               <template-image-top-left units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
               <template-image-bottom-right units="Millimeters" x="0.0" y="0.0" z="0.0" rotation="0.0"/>
            </vision>
         </feeder>
      </feeders>
      <cameras/>
      <job-processors class="java.util.HashMap">
         <job-processor type="PickAndPlace">
            <job-processor class="org.openpnp.machine.reference.ReferenceJobProcessor" demo-mode="false">
               <job-planner class="org.openpnp.planner.SimpleJobPlanner"/>
            </job-processor>
         </job-processor>
      </job-processors>
      <driver class="com.embeddedmicro.driver.EmbeddedMicroDriver" port-name="/dev/ttyACM0" baud="115200" feed-rate-mm-per-minute="50000.0" z-cam-radius="24.0" z-cam-wheel-radius="9.5" z-gap="2.0" addon-port-name="/dev/ttyACM1" addon-baud="115200" cart-steps="4" wheel-steps="8" cart-actuator-name="Cart" wheel-actuator-name="Wheel" servo-actuator-name="Servo"/>
   </machine>
</openpnp-machine>

Justin Rajewski

unread,
Feb 1, 2016, 4:53:02 PM2/1/16
to OpenPnP
I just realized you asked for the code making the call too. It's just the stock code in ReferenceDragFeeder in the getVisionOffsets() function. For what it's worth, I'm pretty sure I had this problem before I started making mods. I just never used vision for anything other than setting locations before. 

Jason von Nieda

unread,
Feb 1, 2016, 5:04:44 PM2/1/16
to OpenPnP
Hey Justin,

I'm not sure what the deal with this is, so I can't give a quick answer. I'll take a look at it tonight and see what I can come up with.

Jason


--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Justin Rajewski

unread,
Feb 1, 2016, 5:18:19 PM2/1/16
to OpenPnP
Thanks for looking into it.

For what it's worth, I tracked down the problem to line 89 in OpenCvCamera.java.

if (!fg.read(mat)) {
       return null;
   }
fg.read(mat) is false so it returns null here.

Jason von Nieda

unread,
Feb 1, 2016, 5:23:30 PM2/1/16
to OpenPnP
Are you getting trash in your console about camera errors? The only time that should ever return null is if the camera fails to send a frame.

Jason


Justin Rajewski

unread,
Feb 1, 2016, 5:31:29 PM2/1/16
to OpenPnP
I get a ton of "Corrupt JPEG data: xxx extraneous bytes before marker 0xd9" where xxx is a varying number. 

I changed the if to a while and it works now! https://www.youtube.com/watch?v=EaJjHEBQDXU

Any ideas about those errors?

Jason von Nieda

unread,
Feb 1, 2016, 5:34:49 PM2/1/16
to OpenPnP
Glad to hear it's working! I'll have to think on how to best handle that.

What camera are you using? 

I get a lot of errors on my ELP camera, and I suspect it's due to too long of a low quality cable. I recently read that the transfer mode that USB uses for cameras allows for errors to be sent and it's supposed to be up to the application to handle them, so I may need to make this a bit more robust. Possibly just a while loop with a timeout or something.

Jason


Justin Rajewski

unread,
Feb 1, 2016, 5:51:55 PM2/1/16
to OpenPnP
I'm using the camera in your BOM http://www.ebay.com/itm/221448995232

I have a long janky USB cable (like 10ft made of two cables soldered together) so it wouldn't surprise me if that wasn't helping...

Jason von Nieda

unread,
Feb 1, 2016, 6:29:08 PM2/1/16
to OpenPnP
Yep, that's probably it. I filed an issue to track this: https://github.com/openpnp/openpnp/issues/204

Jason


Message has been deleted

Justin Rajewski

unread,
Feb 3, 2016, 5:31:59 PM2/3/16
to OpenPnP
Just realized I typed my other message in the wrong spot...

I'm trying to add a button in the feeder wizard so that when you click it, it moves the feeder head to the set position so I can fine tune the position without performing a full feed command. The problem is I don't have a way to get access to the actuators in the wizard. Is there an easy way to do this?

On Wednesday, February 3, 2016 at 3:31:28 PM UTC-7, Justin Rajewski wrote:


On Monday, February 1, 2016 at 4:29:08 PM UTC-7, Jason von Nieda wrote:
Yep, that's probably it. I filed an issue to track this: https://github.com/openpnp/openpnp/issues/204

Jason
I'm trying to add a button in the feeder wizard so that when you click it, it moves the feeder head to the set position so I can fine tune the position without performing a full feed command. The problem is I don't have a way to get access to the actuators in the wizard. Is there an easy way to do this?

Jason von Nieda

unread,
Feb 3, 2016, 5:35:53 PM2/3/16
to OpenPnP
Justin,

You can always get access to the full machine from Configuration.get().getMachine(). From there you can getHeads().getActuators(), or getDefaultHead().getActuators(). Is that what you mean, or am I missing the question?

Jason


Justin Rajewski

unread,
Feb 3, 2016, 8:45:14 PM2/3/16
to OpenPnP
Thanks Jason! That was exactly what I was looking for.

I got four feeders setup for different parts. Tomorrow I'm going to try and make some boards using them.

I have two 8mm strips with 4mm spacing. The feeders are basically the same but the channel for one was too narrow for most parts but it fits the NMOSs I'm using (hence the "transistors" label on it). There are two 12mm feeders, one with a shallow channel and one with a deeper channel.

I didn't have full reels for the LEDs and NMOSs so I fed the covering through the first hole to preserve parts. However, for the buttons and resistor networks, I have full reels with the extra empty lead tape. That allowed me to feed the covering through the pick window so that there's less of a chance of parts popping out from vibration. Once I use enough of the LEDs and transistors I'll probably refeed the covering through the pick window instead.
IMG_20160203_183839.jpg
IMG_20160203_183845.jpg
IMG_20160203_183903.jpg
IMG_20160203_183911.jpg

Jason von Nieda

unread,
Feb 4, 2016, 1:19:00 AM2/4/16
to OpenPnP
Looks great Justin! Lets see it in action! :)

Jason


Justin Rajewski

unread,
Feb 4, 2016, 7:31:08 PM2/4/16
to OpenPnP
https://www.youtube.com/watch?v=i685qnvw-IQ

I changed the vision stuff a bit since that video so that it tries to use the match with the highest Y value. You can see in the video towards the end it skipped a few LEDs.

I'm using the getTemplateMatches() function instead of locateTemplateMatches() as locateTemplateMatches() only every returns the single "best" match. I'm having a bit of trouble picking the best match though. It sometimes misses the second or third part and will skip it because it doesn't "see" it. I tried tweaking the threshold and corr values in the function but have had limited success. When I make these too low, it picks the match with the highest Y which might be a pretty bad match.

Any ideas for getting this to work? It works really well with the LEDs, MOSFETs, and buttons right now. The resistor networks are having a hard time being detected I think due to their shininess.

Michael Anton

unread,
Feb 5, 2016, 12:14:50 AM2/5/16
to OpenPnP
Looks good!!

You might be able to run a little faster if you advanced a feeder after picking a part, without waiting for it, rather than advancing it before picking, which you have to wait for.

Mike

Anthony Webb

unread,
Feb 5, 2016, 1:08:24 AM2/5/16
to OpenPnP
Amazing work Justin!  Not sure if you will be sharing the design, but if so do you have any of the models/code up on the web somewhere?  Are there other challenges with the design you are seeing issues with?  I'd love a solid feeder solution long term, your design checks a lot of the boxes.

Jason von Nieda

unread,
Feb 5, 2016, 2:01:36 AM2/5/16
to ope...@googlegroups.com
Hey Justin,

Really nice work! Thanks for posting the video. It's really fun to see something go from idea to working prototype, and in a really short time!

For your vision issue, best bet would be to capture some images and show them to the group. That will make it easier for us to give recommendations. 

To do that, just enable debug logging on org.openpnp.machine.reference.vision.OpenCvVisionProvider. A guide to doing that is here: https://github.com/openpnp/openpnp/wiki/FAQ#how-do-i-turn-on-debug-logging

Once you do that, every time getTemplateMatches() is called it will store several images showing a bunch of useful stuff related to the operation. These will be stored in your .openpnp directory under the class name.

I suggest running your feeder until you get a failure like you described above and then find the images corresponding to that event and send them over.

Jason

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Anthony Webb

unread,
Feb 5, 2016, 2:29:16 AM2/5/16
to OpenPnP
I'd also be curious to know what you are doing for the secondary board.  Is it just another smoothieboard that you are sending GCODE commands to?  I have been contemplating how to control a secondary serial device in openpnp, seems like you have a pretty decent implementation here.

Cri S

unread,
Feb 5, 2016, 8:50:19 AM2/5/16
to OpenPnP
can you share pictures of strep and picture of template and the machine.xml part of that feeder.
One reason can be template is too small.

Justin Rajewski

unread,
Feb 6, 2016, 4:48:05 PM2/6/16
to OpenPnP
@Mike, yea there's a lot that could be sped up. I'm not sure how to hook into the existing code to get notified for something being picked besides the feed() call. It would be nice in this case to get a startFeed() and finishFeed() calls for when the feeder can start loading a part and finishFeed() to make sure the feeder is done before the head tries to pick it. In my case startFeed() could move the tape the estimated amount and in finishFeed() it would wait for the tape to finish moving and then do the vision stuff.

@Anthony, I'll definitely share everything I've done. I just uploaded the modified OpenPnp code here https://github.com/embmicro/openpnp/tree/auto-feeders . I'll post the .stl files soon along with the Blender source. The biggest problems I've run into are sizing the sprocket and gear spacers just right. People will likely have to tweak the models a bit depending on their 3D printers.

My second board is the Mojo with some extras added on. I'm using a simple register based interface that allows the PC to read/write addresses over serial. The addresses map to motor movements, servo position, motor speeds, and step settings. I'm the guy who makes these so it was convenient to use. The Mojo is an FPGA dev board so it's a bit different to work with than writing software.

@Jason, I've actually been working on this a lot longer than I've been posting about it. My original idea was to use two one-way bearings with plasti-dip to pull the covering off which would force the tape forward. There were a lot of problems with that so I ended up using gears to make things mesh better. The gears didn't really work and then I realized I could use the same bearing to push the tape and pull off the covering. That worked alright but the ratio of push-pull was impossible to get perfect so it would end up jamming or not pulling the tape off. My breakthrough was when I made gear spacers to keep the gears a little apart. This, with a push-pull ratio slightly in favor of pulling the covering, make it work smoothly because the tape would be pulled off but could slip if it got too tight.


@Cri, I attached some images of weird cases and my machine.xml file. Most of the parts are detected well, but the resistor network continues to be missed and/or over seen by the vision software. I've tried changing the template size to include more of the tape but that seems to make things worse. I think the big problem with the resistor network is that it can rotate in the pocket making it match poorly (and pick poorly). It would be great to get rotation with the template detection. 
debugging.zip

mojalovaa1

unread,
Feb 6, 2016, 5:48:19 PM2/6/16
to OpenPnP
One  question for all who work with feeders and openpnp , and maybe is good  suggestion for this feeders all so  , why  you not add on feeder options  max speed for place travel for  that feeder , because cant make place with same  speed for all components  , if component is bigger  need  be lower speed ?
Something like on tape feeder for actuate  feed .
On all this feeder work same speed  with all components , and then you need move resistor  with same speed like some bigger IC or TQFP package and maybe resistor can move 3x bigger speed  .
That is only suggestion .

Jason von Nieda

unread,
Feb 6, 2016, 6:15:25 PM2/6/16
to OpenPnP
Hi Moja,

I had previously considered this and I felt that I didn't want to clutter the parts database with this kind of data, but I have since reconsidered and I will be adding this to Part in the near future.

I've logged an issue to track this feature: https://github.com/openpnp/openpnp/issues/211

Jason


--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Jason von Nieda

unread,
Feb 6, 2016, 7:03:55 PM2/6/16
to OpenPnP
Okay, that one was actually easy enough I just went ahead and implemented it. You can set speed on the Parts table now and it will be respected for movements between the pick and the place.

Jason

Justin Rajewski

unread,
Feb 6, 2016, 7:24:07 PM2/6/16
to OpenPnP
I also have a speed setting for the feeder but I haven't figured out a clean way to tell the actuator what speed to use. It's simple enough to change the stepper motor speed.

I played with the vision stuff and added +/-5 degrees of rotation detection by rotating the camera image in 0.5 degree increments. I then do the match on each of those then rotate them back. 

Since there will be a lot of overlapping matches, I added a "mergeNearbyMatches()" function that merges any matches within 1mm of each other to simply the best match. This will select the best rotation match.

I then use the rotation from the image as a pick offset.

This doesn't seem to make much of a difference for picking, but for the resistor pack recognition it seems to help a lot.

Jason von Nieda

unread,
Feb 6, 2016, 7:26:05 PM2/6/16
to OpenPnP
Hey Justin,

If you look at the ReferenceDragFeeder you can see an example of how to use speed for the actuator. It's just a parameter you pass to moveTo(). If you mean something other than movement you'd probably have to include that in your actuate()  method, maybe by overloading the double if you are already using it.

Jason


--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

Michael Anton

unread,
Feb 7, 2016, 4:24:50 AM2/7/16
to OpenPnP
I agree, that this is pretty important to have, so it is great that Jason has implemented it already!!!

Mike

Justin Rajewski

unread,
Feb 11, 2016, 8:07:20 PM2/11/16
to OpenPnP
Just an update. https://www.youtube.com/watch?v=k4B8w6jdJR8

I now have the feeder working independently from the pick head. I'm still having a little trouble with a few tape feeders getting stuck. You can see the stepper driving the gear skip a little in the video.

Rich Obermeyer

unread,
Feb 11, 2016, 8:13:24 PM2/11/16
to ope...@googlegroups.com
Nice work Justin!
What is that clicking sound when the motor gear engages with other gears below? 

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Rich

Jason von Nieda

unread,
Feb 11, 2016, 8:47:39 PM2/11/16
to ope...@googlegroups.com
Justin,

Looking really good! Are you planning to open source / document this build? I'd love to link to it on the OpenPnP hardware page, if so.

Jason


Justin Rajewski

unread,
Feb 11, 2016, 9:44:05 PM2/11/16
to OpenPnP
@maddog, that's the stepper motor skipping because of excessive force on some tape. I'm trying to work that out still.

@Jason It's all free to use as far as I'm concerned. I attached the blender source and some stl exports for what I have right now. Also my code is here https://github.com/embmicro/openpnp/tree/auto-feeders but I haven't pushed the latest stuff yet (with working multi-threaded feeder). I had to add preFeed() and postFeed() function calls for feeders so that I can get it to properly run independently. I set up my feeder so that you can either just call feed() for a full feed, or preFeed(), feed(), postFeed() in the order to perform a feed. preFeed() should be called asap, feed() gets the location set with the camera and pushes the tape more if it can't find a part. postFeed() release a lock that keeps the feeding thread from moving the tape before it is picked.

I'm not sure when I'll have time to write up some formal stuff and clean up the blender/stl files.
stl.zip
Reply all
Reply to author
Forward
0 new messages