IC Programming Rig

Exemplarily an IC programming rig is depicted. The rig is used to program ICs with SOIC8 footprint while being assembled by the pick and place machine. The script calls avrdude to program the IC. The programming task is kept in the script. Do program a part, just define it's description as “prog-TASK” where TASK is the identifier that the script will check for.

under development

1. Setup Script

Where is the Location of the Rig?

Location ProgrammingRigLocation = new Location(LengthUnit.Millimeters, 362.373, 100.07, -23.5, 270);
                                                                   //  X        Y       Z     Rotation

Download AVRdude and put the path to the executable here:

String avrdudeLocation="C:\\Users\\buero\\Downloads\\avrdude-6.3-mingw32\\avrdude.exe";

2. Define Programming Task in the Script

new String []	{
	"-c stk500v2 command 1",
	"command line 2 if needed",
} );

3. Setup Part in OpenPnP to be Programmed

The part to be programmed has to have a description like prog-EXAMPLEprogTASK, whereas prog- is the keyword for the script and the latter the task defined above.


If programming fails, there is an error message. Assembly continues after confirming as usual.


import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.HashMap;
import java.util.Arrays;
import com.Ostermiller.util.ExecHelper;
import com.Ostermiller.util.UberProperties;
import org.pmw.tinylog.Logger;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Location;
import org.openpnp.util.MovableUtils;
Location ProgrammingRigLocation = new Location(LengthUnit.Millimeters, 354.822, 105.382, -24.7, 270);
String avrdudeLocation="\"C:\\Program Files\\avrdude-6.3-mingw32\\avrdude.exe\"";
programmingTasks = new java.util.HashMap();
new String []	{
	"-c usbasp -P usb -B 20.96 -p t13 -U lfuse:w:0x7A:m -U hfuse:w:0xF9:m",
	"-c usbasp -P usb -B 0.5   -p t13 -U flash:w:\"M:\\v2\\touchdim.elf\":a -U eeprom:w:\"M:\\v2\\touchdim.elf\":a -U lock:w:0x3C:m",
} );
	"example prog task",
new String []	{
	"-c stk500v2 command 1",
	"command line 2 if needed",
} );
/* examples to program ATTiny13a:
ISP fast: disable prescaler via fuses, program afterwards with high frequency:
-c usbasp -P usb -B 20.96 -p t13 -U lfuse:w:0x7A:m -U hfuse:w:0xF9:m
-c usbasp -P usb -B 0.5   -p t13 -U flash:w:"target_firmware.hex":a -U eeprom:w:"target_firmware.eep":a
ISP slow: do all in one command (prescaler enabled by default on most atmel chips, so frequency is reduced):
-c usbasp -P usb -B 8 -p t13 -U flash:w:"target_firmware.hex":a -U eeprom:w:"target_firmware.eep":a -U lfuse:w:0x7A:m -U hfuse:w:0xF9:m -U lock:w:0x3C:m 
boolean program(Location ProgrammingRigLocation,String[] commands) {
    boolean programmingSuccessfull=true;
	//do dedicated vision for programming rig
	aligner=jobProcessor.findPartAligner(machine, part);
	if( aligner == null )
		throw new Exception("Unable to find part aligner");
    alignmentOffsetsProgrammingRig=aligner.findOffsets(part, null, ProgrammingRigLocation, nozzle);		//call findOffsets directly instead of findPartAlignmentOffsets, which would trigger PartAlignment.before/after
	if( alignmentOffsetsProgrammingRig == null )
		throw new Exception("Unable to find part offset");	
	//move to rig
	//take alignment offsets into consideration
	if (alignmentOffsetsProgrammingRig.getPreRotated()) 
			ProgrammingRigLocation = ProgrammingRigLocation.subtractWithRotation(alignmentOffsetsProgrammingRig.getLocation());
		ProgrammingRigLocation = new Location(LengthUnit.Millimeters)
		.rotateXyCenterPoint(alignmentOffsetsProgrammingRig.getLocation(),ProgrammingRigLocation.getRotation() - alignmentOffsetsProgrammingRig.getLocation().getRotation())
		.derive(null, null, null, ProgrammingRigLocation.getRotation() - alignmentOffsetsProgrammingRig.getLocation().getRotation())
	//add part's height
	ProgrammingRigLocation = ProgrammingRigLocation.add(new Location(part.getHeight().getUnits(), 0,0, part.getHeight().getValue(), 0));
	MovableUtils.moveToLocationAtSafeZ(nozzle, ProgrammingRigLocation);
	try{ Thread.sleep(200); } catch(Exception e) {} // wait for stabilisation
	for(command:commands) {
		String cmd=avrdudeLocation + " " + command;
		Logger.debug("ISP CMD: "+cmd);
		exec = ExecHelper.execUsingShell(cmd);
		Logger.debug("ISP CMD STATUS: " +exec.getStatus());
		Logger.debug("ISP stdout output: " +exec.getOutput());
		Logger.debug("ISP stderr output: "+exec.getError());
		if(exec.getStatus()!=0) {
			programmingSuccessfull = false;
	// Retract
	return programmingSuccessfull;
try {
	if( part.getName() != null && part.getName().contains("prog-") ) {
		Logger.debug("checking for right arguments (should be 2): " + numberOfArguments );
		if (numberOfArguments!=2 ) {
			throw new Exception("insufficient/too many arguments");
		} else {
			Logger.debug("arguments ok");
		Logger.debug("checking for programming task " + taskDescription[1] + " being defined" );
		if ( !programmingTasks.containsKey( taskDescription[1] ) ) {
			throw new Exception("task not defined");
		} else {
			Logger.debug("task defined");
		// backup nozzle position
		success=program( ProgrammingRigLocation, programmingTasks.get(taskDescription[1]) );
		// restore old nozzle position
		MovableUtils.moveToLocationAtSafeZ(nozzle, nozzle.getLocation().derive(null,null,null,backupNozzleLocation.getRotation() ) );
		if(success) {
			Logger.debug("programming successful");
		} else {
			throw new Exception("programming failed");
} catch(e) {
	javax.swing.JOptionPane.showMessageDialog(gui, "Programming Part failed", "Error Programming", JOptionPane.ERROR_MESSAGE);
	//howto pause job?
  • maschine/pickandplace/ic_programming.txt
  • Last modified: 2018/09/09 12:06
  • by michael