Electronics > Manufacturing & Assembly

Neoden3V | KiCad Pos to Neoden CSV - Python Script


Hey all,

I just picked up a Neoden3V and was using femtodev's script to convert a KiCad .pos file to a .csv for the Neoden. I wanted to be able to launch the script without the command line so with the help of OpenAI's GPT3 I modified the code to launch it as a gui that also shows the output directory.

I'm no coder and it's still a work in progress to please feel free to let me know if you have anything to add or that should be fixed.

Python script below:

--- Code: ---# Ash's GPT3 KiCad to Neoden3V file conversion code | 5/12/2022

# This script is a modified version of femtodev's version of szczys's python script. It was edited (sucessfully)
# by OpenAI's GPT3 Chat dialog in around 5 minutes. This script remains a perpetual work in progress.

# Original script: https://git.femtostar.com/femtodev/kicad_to_neoden/-/blob/master/readme.md

from __future__ import print_function

#Translator for converting KiCAD .pos files to .csv files for a NEODEN pick and place machine
#Paste relevant rows of the .pos files below and chance the trailing_letter
#to be "T" for top or "B" for bottom

import fileinput
import tkinter as tk
from tkinter import filedialog
import os
import sys

def main(file_path):
    # Open the .pos file using the file path
    with open(file_path, 'r') as f:
        pos_lines = []
        for line in f:

    # Get the directory containing the input file
    file_dir = os.path.dirname(file_path)

    filename = os.path.basename(file_path)
    if filename[-4:] != ".pos":
            print("WARNING: Input file doesn't have expected '.pos' extension")
    print("Parsing " + filename)

    # get the minimum Y coordinate on the board, to shift components up later
    min_y = find_min_y(pos_lines)
    print("Minimum Y coordinate on board: " + str(min_y))

    neoden_format = process_pos_lines(pos_lines, min_y)
    #Strip trailing newline character
    if neoden_format[-2:] == '\n':
            neoden_format = neoden_format[:-2]

    print("Writing CSV file")
    # Create the output file path by joining the input file directory with the output file name
    output_file = os.path.splitext(os.path.join(file_dir, filename))[0] + "_neoden.csv"

    with open(output_file, 'w') as g:

    print("Conversion complete!")

# Print the output file's path
    print("Output file saved as", os.path.abspath(output_file))

def select_file():
    # Create a file selection dialog that only allows the user to select .csv files
    file_path = filedialog.askopenfilename(filetypes=(("KiCad Position Files", "*.pos"), ("All files", "*.*")))
    # Convert the file using the main function

class StdoutRedirector(object):
    def __init__(self, widget):
        self.widget = widget

    def write(self, string):
        self.widget.insert("end", string)

def transrotate(value):
if value <= 180:
return int(value)
value -= 180
return int(0-(180-value))

def process_pos_lines(pos_lists, min_y):
        output_string = "Designator,Footprint,Mid X,Mid Y,Layer,Rotation,Comment\n"
        output_string += ",,,,,,\n"
        for line in pos_lists:
                if line[0][0] == '#':

                # fix to output package instead of value, matching order expected by machine
                outline = line[0] + "," + line[2] + ","
                outline += line[3].split('.')[0] + "." + line[3].split('.')[1][:2] + "mm,"

# fix to force all Y coordinates to be above zero
                line[4] = str(float(line[4]) + abs(min_y) + 1)

                outline += line[4].split('.')[0] + "." + line[4].split('.')[1][:2] + "mm,"
                if line[-1] == "top":
                        outline += "T,"
                        outline += "B,"

                # fix to output value instead of package, matching order expected by machine
                outline += str(transrotate(float(line[5]))) + "," + line[1]
                output_string += outline + '\n'
        return output_string

# for above fix
def find_min_y(pos_lines):
        min_y = 0
        for line in pos_lines:
                if line[0][0] == '#':
                if float(line[4]) < min_y:
                        min_y = float(line[4])

        return min_y

# Create the main window
root = tk.Tk()

# Set the text displayed in the title bar of the window
root.title("KiCad to Neoden 3V File Converter")

# Add a button that allows the user to select a file
select_button = tk.Button(root, text="Select file", command=select_file)

# Add a text box to display the output from the script
text_box = tk.Text(root)

# Redirect the print statements from the main function to the text box
sys.stdout = StdoutRedirector(text_box)

# Start the main loop

--- End code ---

Code updated as of 12/12/2022

I thought this might be handy for the few other Neoden3V owners out there. Please let me know if posting this is not allowed.

Just adding to this thread that this is also the script I use to go from KiCad to Neoden 3V.


[0] Message Index

There was an error while thanking
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod