Skip to content

Commit

Permalink
Enhanced configuration options
Browse files Browse the repository at this point in the history
Added configuration settings in PCBLaser.config for default emulsion
types used (Negative or Positive) and file endings for autodetecting
image inversion and mirroring.
  • Loading branch information
terjeio committed Jan 19, 2018
1 parent a226703 commit a334450
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 21 deletions.
4 changes: 2 additions & 2 deletions PCB Laser/About.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion PCB Laser/PCB Laser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
Expand Down
8 changes: 8 additions & 0 deletions PCB Laser/PCBLaser.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@
<DefaultPower>3800</DefaultPower>
<BacklashCompensation>9</BacklashCompensation>
<XOffset>89</XOffset>
<EtchMaskEmulsion>Negative</EtchMaskEmulsion>
<SolderMaskEmulsion>Negative</SolderMaskEmulsion>
<FileNameEnding>
<TopCopper>F.Cu</TopCopper>
<BottomCopper>B.Cu</BottomCopper>
<TopMask>F.Mask</TopMask>
<BottomMask>B.Mask</BottomMask>
</FileNameEnding>
</PCBConfig>
58 changes: 57 additions & 1 deletion PCB Laser/UserUI.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 98 additions & 16 deletions PCB Laser/UserUI.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* UserUI.cs - PCB Laser Printer
*
* v1.03 / 2017-08-13 / Io Engineering (Terje Io)
* v1.04 / 2018-01-19 / Io Engineering (Terje Io)
*
*/

Expand Down Expand Up @@ -53,6 +53,11 @@ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
namespace PCB_Laser
{

public struct FileEndings
{
public string topCopper, bottomCopper, topMask, bottomMask;
}

public partial class UserUI : Form
{

Expand All @@ -61,15 +66,23 @@ public partial class UserUI : Form
const int TXBUFFERSIZE = 4096;
const double PIXELSIZE = 25.4 / 1200;

private string PortParams = "com14:38400,N,8,1,P";
enum EmulsionType {
Negative = 0,
Positive
}

private string PortParams = "com15:38400,N,8,1,P";
private int PollInterval = 50, y = 0, z = 50, Xoffset = 0, XBacklashComp = -1;
private bool zFocusClicked = false, mirrored = false, started = false, cancel = false;
private bool zFocusClicked = false, mirrored = false, started = false, cancel = false, solderMask = false, uknownFileEnding = true;
private byte[] rowBuffer = null;
private Bitmap layout = null, board = null;
private Graphics gr = null;
private Graphics gr = null;
private System.Timers.Timer pollTimer = null;
private StringBuilder input = new StringBuilder(100);
private Rectangle rect;
private EmulsionType emulsionEtchMask = EmulsionType.Negative;
private EmulsionType emulsionSolderMask = EmulsionType.Negative;
private FileEndings fileEnding;

#if USEELTIMA
private SPortLib.SPortAx SerialPort;
Expand Down Expand Up @@ -100,6 +113,12 @@ public UserUI()
this.aboutMenuItem.Click += new EventHandler(aboutMenuItem_Click);
this.exitMenuItem.Click += new EventHandler(exitMenuItem_Click);

// default to KiCad file name endings
this.fileEnding.topCopper = "F.Cu";
this.fileEnding.bottomCopper = "B.Cu";
this.fileEnding.topMask = "F.Mask";
this.fileEnding.bottomMask = "B.Mask";

try
{
XmlDocument config = new XmlDocument();
Expand All @@ -124,6 +143,14 @@ public UserUI()
this.Xoffset = int.Parse(N.InnerText);
break;

case "EtchMaskEmulsion":
this.emulsionEtchMask = this.parseEmulsionType(N.InnerText);
break;

case "SolderMaskEmulsion":
this.emulsionSolderMask = this.parseEmulsionType(N.InnerText);
break;

case "BacklashCompensation":
this.XBacklashComp = int.Parse(N.InnerText);
break;
Expand All @@ -132,10 +159,32 @@ public UserUI()

}

foreach (XmlNode N in config.SelectNodes("PCBConfig/FileNameEnding/*"))
{
switch (N.Name)
{
case "TopCopper":
this.fileEnding.topCopper = N.InnerText;
break;

case "BottomCopper":
this.fileEnding.bottomCopper = N.InnerText;
break;

case "TopMask":
this.fileEnding.topMask = N.InnerText;
break;

case "BottomMask":
this.fileEnding.bottomMask = N.InnerText;
break;
}
}

}
catch
{
MessageBox.Show("Config file not found.", this.Text);
MessageBox.Show("Config file not found or invalid.", this.Text);
System.Environment.Exit(1);
}

Expand Down Expand Up @@ -205,9 +254,17 @@ public UserUI()
this.enableUI();

this.zFocus.Value = this.z;
this.cbxEtchEmulsion.SelectedIndex = (int)this.emulsionEtchMask;
this.cbxSolderEmulsion.SelectedIndex = (int)this.emulsionSolderMask;
this.chkInvert.Checked = solderMask ? this.emulsionSolderMask == EmulsionType.Negative : this.emulsionEtchMask == EmulsionType.Positive;

this.cbxEtchEmulsion.SelectedIndexChanged += new EventHandler(cbxEtchEmulsion_SelectedIndexChanged);
this.cbxSolderEmulsion.SelectedIndexChanged += new EventHandler(cbxSolderEmulsion_SelectedIndexChanged);

this.Visible = true;

}

#if USEELTIMA
bool SerialOpen { get { return this.SerialPort.IsOpened; } }
int SerialOutCount { get { return this.SerialPort.OutCount; } }
Expand Down Expand Up @@ -274,6 +331,8 @@ void disableUI () {
this.zPower.Enabled = false;
this.chkInvert.Enabled = false;
this.chkMirror.Enabled = false;
this.cbxEtchEmulsion.Enabled = false;
this.cbxSolderEmulsion.Enabled = false;
this.aboutMenuItem.Enabled = false;
}

Expand All @@ -287,6 +346,8 @@ void enableUI () {
this.zPower.Enabled = true;
this.chkInvert.Enabled = true;
this.chkMirror.Enabled = true;
this.cbxEtchEmulsion.Enabled = !this.solderMask || this.uknownFileEnding;
this.cbxSolderEmulsion.Enabled = this.solderMask || this.uknownFileEnding;
this.aboutMenuItem.Enabled = true;
}

Expand Down Expand Up @@ -341,6 +402,20 @@ void chkMirror_CheckedChanged(object sender, EventArgs e)
ShowBoard();
}

void cbxSolderEmulsion_SelectedIndexChanged(object sender, EventArgs e)
{
this.emulsionSolderMask = (EmulsionType)this.cbxSolderEmulsion.SelectedIndex;
if (this.solderMask)
this.chkInvert.Checked = !this.chkInvert.Checked;
}

void cbxEtchEmulsion_SelectedIndexChanged(object sender, EventArgs e)
{
this.emulsionEtchMask = (EmulsionType)this.cbxEtchEmulsion.SelectedIndex;
if (!this.solderMask)
this.chkInvert.Checked = !this.chkInvert.Checked;;
}

void btnHome_Click(object sender, EventArgs e)
{
this.SerialOut("HomeXY");
Expand Down Expand Up @@ -385,7 +460,6 @@ void zPower_MouseUp(object sender, MouseEventArgs e)

void btnStart_Click(object sender, EventArgs e)
{

if(this.started)
this.ShowBoard();

Expand All @@ -404,7 +478,6 @@ void btnStart_Click(object sender, EventArgs e)
this.pollTimer.Start();

disableUI();

}

void btnCancel_Click (object sender, EventArgs e) {
Expand All @@ -430,7 +503,7 @@ void UserUI_DragEnter (object sender, DragEventArgs e) {

void UserUI_DragDrop (object sender, DragEventArgs e) {

string filetype;
string filename;
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, false);

Bitmap image = null;
Expand All @@ -453,13 +526,17 @@ void UserUI_DragDrop (object sender, DragEventArgs e) {
}

this.mirrored = false;
filetype = files[0].Substring(files[0].LastIndexOf('.'));
this.chkInvert.Checked = files[0].EndsWith("smask" + filetype) ||
files[0].EndsWith("Mask" + filetype);
this.chkMirror.Checked = files[0].EndsWith("B_Cu" + filetype) ||
files[0].EndsWith("B_Mask" + filetype) ||
files[0].EndsWith("B.Cu" + filetype) ||
files[0].EndsWith("B.Mask" + filetype);
filename = files[0].Substring(0, files[0].LastIndexOf('.'));

if ((solderMask = filename.EndsWith(this.fileEnding.topMask) || filename.EndsWith(this.fileEnding.bottomMask)))
this.chkInvert.Checked = this.emulsionSolderMask == EmulsionType.Negative;
else
this.chkInvert.Checked = this.emulsionEtchMask == EmulsionType.Positive;

this.chkMirror.Checked = filename.EndsWith(this.fileEnding.bottomCopper) ||
filename.EndsWith(this.fileEnding.bottomMask);

this.uknownFileEnding = !(solderMask || this.chkMirror.Checked || filename.EndsWith(this.fileEnding.topCopper));

image = new Bitmap(files[0]);
this.rect = GetPCBSize(image);
Expand All @@ -482,8 +559,9 @@ void UserUI_DragDrop (object sender, DragEventArgs e) {

this.enableUI();

if (this.uknownFileEnding)
MessageBox.Show("File ending not recognized, set image inversion and mirroring manually!", this.Text);
}

}

#endregion
Expand Down Expand Up @@ -660,6 +738,10 @@ private Rectangle GetPCBSize (Bitmap b) {

}

private EmulsionType parseEmulsionType (string type) {
return type == EmulsionType.Positive.ToString() ? EmulsionType.Positive : EmulsionType.Negative;
}

private void SetStatus (string s) {

if (this.txtStatus.InvokeRequired)
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ Desktop application for rendering PCB designs on the PCB Laser Exposer, written

Laser PCB Exposer is blu-ray laser "printer" for exposing photo-sensitive PCBs at 1200 dpi resolution by raster-rendering.

A typical workflow is to "print" the PCB artwork to a bitmap, BMP or PNG are supported, then drop the image onto the desktop application for exposing the PCB. I am using the [KiCad EDA](http://kicad-pcb.org/) for my designs, from that "plotting" to PDF and printing the resulting file to a PNG-file via the [PDFCreator](http://www.pdfforge.org/pdfcreator) printer-driver. I prefer to crop the PNG-files before using them for exposing the PCBs, this is not necesseary to do as the exposer software wil automatically do that - but it will speed up the process.
A typical workflow is to "print" the PCB artwork to a bitmap, BMP or PNG are supported, then drop the image onto the desktop application for exposing the PCB. I am using the [KiCad EDA](http://kicad-pcb.org/) for my designs, from that "plotting" to PDF and printing the resulting file to a PNG-file via the [PDFCreator](http://www.pdfforge.org/pdfcreator) printer-driver. I prefer to crop the PNG-files before using them for exposing the PCBs, this is not necesseary to do as the exposer software will automatically do that - but it will speed up the process.

It is possible to have a drill-ready PCB with solder mask in just two hours from outputting the artwork, this includes about one hour for "hardening" the solder mask.

Related projects are for [schematics, PCB](https://github.com/terjeio/PCBLaserSchematics) and [firmware](https://github.com/terjeio/PCBLaserFirmvare) for the controller. A [new design](https://github.com/terjeio/PCBLaserMkII) is in development which will make it simpler and cheaper to build.

---
Release notes:

1.04 - 2018-01-19:

Added configuration settings in PCBLaser.config for default emulsion types used \(Negative or Positive\) and file endings for autodetecting image inversion and mirroring. File endings defaults to those used by KiCad. Emulsion type can also be selected from the UI - note that the "Invert" checkbox will toggle on emulsion type change if a PCB image is loaded!
---

Further information and some images can be found over at [43oh.com](http://forum.43oh.com/topic/9645-pcb-laser-exposerprinter/#comment-72756)

0 comments on commit a334450

Please sign in to comment.