Я в одной из предыдущих статей писал — я, фактически, безработный. Юридически — нет, во-первых я пенсионер, но вполне мог бы и работать. Во-вторых, вроде как и работаю в одной маленькой фирме из двух человек, но последний год у нас с контрактами напряженка. С голоду не умираем, пенсии вполне достаточно на жизнь, но ведь развлекаться как-то надо?
Время от времени от скуки публикую статьи-обзоры на сайте шопоголиков, администрация сайта даже денег довольно-таки регулярно за это дает. Очень хорошая отмазка для супруги — нет, я не шопоголик, это я, вроде как, при деле. И вот здесь взялся публиковать статейки — если на том сайте такие публиковать, только минусов нахватаешь — типа ты что, слишком умный, что ли? — а вот на тебе минус и не балуй. И в следующий раз пиши про какую-нибудь мыльницу.
В одной из предыдущих своих статей я рассказывал о дисплее на базе адресуемых светодиодов. Сейчас расскажу, как проектировались последние варианты плат для них.
Самих светодиодов было довольно-таки много — 1296 штук, плюс в плате должны быть вырезы. Дисплей, размещенный в окне, не должен полностью заслонять свет. А дисплей, предназначенный для замораживания, если его сделать сплошным, и порвать при заморозке может. Или компоненты оторвать. А может и еще что — специально обученный товарищ рассказывал, что случается при заморозке печатных плат во льду, но у меня в одно ухо влетело, во второе — вылетело.
Плата здесь приведена только для примера — реальная структура была чуть сложнее и были еще компоненты, которые надо было втолкать на эту же плату — но по сравнению с матрицей светодиодов это были совсем мелочи и окончательная разводка была сделана вручную.
Сразу предупреждаю, что я не большой специалист ни в Python, ни в KiCAD — для меня это лишь инструменты, которыми я пользуюсь время от времени. Наверное, я вообще во всем по жизни чайник — но зато медный и со свистком.
Первое дело — конечно, схема. Ее нужно нарисовать так, чтобы компоненты, расположенные рядом, имели и соответствующие номера.
Готовим форму платы — у нее множество отверстий, руками делать вспотеешь. Эта процедура вообще сделана по сермяге. Нарисовал пустую плату с одним только контуром и сделал генерацию более сложного контура по образу и подобию. Потом уже обнаружил, что в KiCAD есть библиотека pcbnew, предназначенная для разработки своих скриптов, но переделывать уже не хотелось, работает — не трогай.
Итак, создаем пустую плату и запускаем
panel_rows = 36
panel_lines = 36
deltaX = 10.0
deltaY = 10.0
holeX = 7.0
holeY = 7.0
hole_cut = 1.0
panel_gap = 2
origin=[0,0]
pcb_name = 'habr_dummy.kicad_pcb'
pcb_name2 = 'habr_edges.kicad_pcb'
def Create_edges():
try:
pcb_file = open(pcb_name, 'r')
#pcb_data = pcb_file.read()
lineList = pcb_file.readlines()
#pos = pcb_data.find(')')
pcb_file.close()
except IOError:
print("Cannot open file '%s'." % pcb_name)
return
panel_size=[0,0]
panel_size[0]= deltaX * panel_rows - panel_gap
panel_size[1]= deltaY * panel_lines - panel_gap
#print(panel_size)
corners=[]
corners.append([origin[0] - panel_size[0]/2, origin[1] - panel_size[1]/2])
corners.append([origin[0] + panel_size[0]/2, origin[1] - panel_size[1]/2])
corners.append([origin[0] + panel_size[0]/2, origin[1] + panel_size[1]/2])
corners.append([origin[0] - panel_size[0]/2, origin[1] + panel_size[1]/2])
#print(corners)
holes=[]
for x in range(panel_rows-1):
for y in range(panel_lines-1):
hole_orig =[0,0]
hole_orig [0] = origin[0] - (deltaX * (panel_rows-1))/2 + x*deltaX + deltaX/2
hole_orig [1] = origin[1] - (deltaY * (panel_lines-1))/2 + y*deltaY + deltaY/2
hole_corners=[]
hole_corners.append([hole_orig[0] - holeX/2 + hole_cut, hole_orig[1] - holeY/2]) # left down
hole_corners.append([hole_orig[0] + holeX/2 - hole_cut, hole_orig[1] - holeY/2 ])
hole_corners.append([hole_orig[0] + holeX/2, hole_orig[1] - holeY/2 + hole_cut])
hole_corners.append([hole_orig[0] + holeX/2 , hole_orig[1] + holeY/2 - hole_cut])
hole_corners.append([hole_orig[0] + holeX/2 - hole_cut, hole_orig[1] + holeY/2])
hole_corners.append([hole_orig[0] - holeX/2 + hole_cut, hole_orig[1] + holeY/2])
hole_corners.append([hole_orig[0] - holeX/2, hole_orig[1] + holeY/2 - hole_cut])
hole_corners.append([hole_orig[0] - holeX/2, hole_orig[1] - holeY/2 + hole_cut])
holes.append(hole_corners)
pos = len(lineList)-1
# build board edge
for i in range(len(corners)):
k = i+1
if k==len(corners):
k=0;
new_line = ' (gr_line (start '
new_line += str(corners[i][0]) + ' '
new_line += str(corners[i][1]) + ') (end '
new_line += str(corners[k][0]) + ' '
new_line += str(corners[k][1])
new_line += ') (layer Edge.Cuts) (width 0.05))\n'
#print(new_line)
lineList.insert(pos, new_line)
pos += 1
# build holes
for hole in holes:
for i in range(len(hole)):
k = i+1
if k==len(hole):
k=0;
new_line = ' (gr_line (start '
new_line += str(hole[i][0]) + ' '
new_line += str(hole[i][1]) + ') (end '
new_line += str(hole[k][0]) + ' '
new_line += str(hole[k][1])
new_line += ') (layer Edge.Cuts) (width 0.05))\n'
#print(new_line)
lineList.insert(pos, new_line)
pos += 1
lineList.insert(pos, '\n')
try:
pcb_file = open(pcb_name2, 'w')
for line in lineList:
#pcb_file.write(line.decode('utf-8'))
pcb_file.write(line)
pcb_file.close()
except IOError:
print("Cannot write file '%s'." % pcb_name2)
Create_edges()
Сразу сделана хорошая часть работы:
Монтажных отверстий всего 6, но уж поставим их тоже сразу. Эти же отверстия будут служить и для подвода напряжения.
import pcbnew
panel_rows = 36
panel_lines = 36
deltaX = 10.0
deltaY = 10.0
pcb_name2 = 'habr_edges.kicad_pcb'
def MountHoles(pcb):
libpath = "/usr/share/kicad/modules/MountingHole.pretty"
for i in range (2):
x = panel_rows/4 * deltaX + deltaX/2
if i==0:
x = -x
for j in range (3):
y = panel_lines/3 * deltaY
if j==1:
y = 0
elif j==2:
y = -y
print(x,y)
footprint = pcbnew.FootprintLoad(libpath, "MountingHole_3.2mm_M3_DIN965_Pad")
pcb.Add(footprint)
footprint.SetPosition(pcbnew.wxPoint(pcbnew.Millimeter2iu(x),pcbnew.Millimeter2iu(y)))
footprint.Reference().SetVisible(False)
def Convert():
print("start")
pcb = pcbnew.LoadBoard(pcb_name2)
MountHoles(pcb)
pcb.Save(pcb_name2)
print("created!")
Convert()
Вырезы около монтажных отверстий получаются слишком большими — поправим их в конце, не все же автоматизировать, что-то и руками сделать надо.
Теперь на получившуюся плату загружаем список компонентов.
Мой компьютер после этого практически прекращает шевелиться — я его покупал несколько лет назад и основным критерием было отсутствие любых вентиляторов и шума соответственно. И должна быть возможность подключения двух, а лучше трех дисплеев. Цель была достигнута — и, кроме всего, системный блок потребляет всего 1 ампер от 12-Вольтового источника питания. Есть задачи, когда его быстродействия начинает не хватать, но их не так уж и много.
Размещаем светодиоды
import pcbnew
panel_rows = 36
panel_lines = 36
deltaX = 10.0
deltaY = 10.0
holeX = 7.0
holeY = 7.0
hole_cut = 1.0
panel_gap = 2
origin=[0,0]
pcb_name = 'habr_populated.kicad_pcb'
pcb_name2 = 'habr_layout.kicad_pcb'
def LED_placement(pcb):
led_position=[]
for y in range (panel_lines):
line_pos=[]
for x in range (panel_rows):
diode_ref = y*panel_rows + x +1
# Find the component
c = pcb.FindModuleByReference("D"+str(diode_ref))
# Place it somewhere
pos = [0.0,0.0]
rot =0;
pos[1] = origin[1] + (deltaY * (panel_lines-1))/2 - y*deltaY
if y%2==0:
pos[0] = origin[0] - (deltaX * (panel_rows-1))/2 + x*deltaX
#rot = (-45+180)*10
rot = (270+180)*10
else:
pos[0] = origin[0] + (deltaX * (panel_rows-1))/2 - x*deltaX
#rot = -45 *10
rot = 270 *10
line_pos.append(pos)
c.SetPosition(pcbnew.wxPointMM(pos[0], pos[1]))
# Rotate it (angle in 1/10 degreee)
c.SetOrientation(rot)
c.Reference().SetVisible(False)
led_position.append(line_pos)
return led_position
def Convert():
print("start")
pcb = pcbnew.LoadBoard(pcb_name)
led_position = LED_placement(pcb)
pcb.Save(pcb_name2)
print("created!")
Convert()
теперь конденсаторы
def Cap_placement(pcb):
cap_position=[]
for y in range (panel_lines-1):
line_pos=[]
for x in range (panel_rows):
cap_ref = y*panel_rows + x +1
# Find the component
c = pcb.FindModuleByReference("C"+str(cap_ref))
# Place it somewhere
pos = [0.0,0.0]
rot =0;
pos[1] = origin[1] + (deltaY * (panel_lines-1))/2 - y*deltaY - deltaY/2
if y%2==0:
pos[0] = origin[0] - (deltaX * (panel_rows-1))/2 + x*deltaX
rot = (270+180)*10
else:
pos[0] = origin[0] + (deltaX * (panel_rows-1))/2 - x*deltaX
rot = 270 *10
line_pos.append(pos)
c.SetPosition(pcbnew.wxPointMM(pos[0], pos[1]))
# Rotate it (angle in 1/10 degreee)
c.SetOrientation(rot)
c.Reference().SetVisible(False)
cap_position.append(line_pos)
return cap_position
На стороне компонентов у нас будет положительное напряжение питания, на обратной — земля.
Проведем короткие проводочки от светодиодов и конденсаторов и установим проходные отверстия.
def AddTrack(pcb, track, netCode, width, layer):
for i in range (len(track)-1):
t = pcbnew.TRACK(pcb)
pcb.Add(t)
t.SetStart(pcbnew.wxPoint(track[i][0], track[i][1]))
t.SetEnd(pcbnew.wxPoint(track[i+1][0], track[i+1][1]))
t.SetWidth(pcbnew.Millimeter2iu(width))
t.SetNetCode(netCode)
t.SetLayer(layer)
def AddVia(pcb, pos, netCode, dia, drill):
v = pcbnew.VIA(pcb)
pcb.Add(v)
v.SetViaType(pcbnew.VIA_THROUGH)
v.SetWidth(pcbnew.Millimeter2iu(dia))
v.SetNetCode(netCode)
v.SetPosition(pcbnew.wxPoint(pos[0],pos[1]))
#v.SetLayerPair(0,31)
v.SetDrill(pcbnew.Millimeter2iu(drill))
def LedGroundViaTrace(pcb, led_position, netCode):
#ground vias
for y in range (panel_lines):
for x in range (panel_rows):
v = pcbnew.VIA(pcb)
pcb.Add(v)
v.SetViaType(pcbnew.VIA_THROUGH)
v.SetWidth(pcbnew.Millimeter2iu(0.8)) # 1mm
v.SetNetCode(netCode)
pos = led_position[y][x]
x0=pos[0]
if y%2==0:
y0 = pos[1]-1.5-0.65
else:
y0 = pos[1]+1.5+0.65
v.SetPosition(pcbnew.wxPointMM(x0,y0))
v.SetLayerPair(0,31)
v.SetDrill(pcbnew.Millimeter2iu(0.4))
#line to via
for y in range (panel_lines):
for x in range (panel_rows):
pos = led_position[y][x]
if y%2==0:
x0=pos[0]+1
y0 = pos[1]-0.65
y1=y0-0.5
x1=pos[0]
y2=y1-1
else:
x0=pos[0]-1
y0 = pos[1]+0.65
y1=y0+0.5
x1=pos[0]
y2=y1+1
t = pcbnew.TRACK(pcb)
pcb.Add(t)
t.SetStart(pcbnew.wxPointMM(x0,y0))
t.SetEnd(pcbnew.wxPointMM(x0, y1))
t.SetWidth(pcbnew.Millimeter2iu(0.25))
t.SetNetCode(netCode)
t = pcbnew.TRACK(pcb)
pcb.Add(t)
t.SetStart(pcbnew.wxPointMM(x0,y1))
t.SetEnd(pcbnew.wxPointMM(x1, y2))
t.SetWidth(pcbnew.Millimeter2iu(0.25))
t.SetNetCode(netCode)
def CapGroundViaTrace(pcb, cap_position, netCode):
#ground vias
for y in range (panel_lines-1):
for x in range (panel_rows):
v = pcbnew.VIA(pcb)
pcb.Add(v)
v.SetViaType(pcbnew.VIA_THROUGH)
v.SetWidth(pcbnew.Millimeter2iu(0.8)) # 1mm
v.SetNetCode(netCode)
pos = cap_position[y][x]
x0=pos[0];
if y%2==0:
y0 = pos[1]-1.5
else:
y0 = pos[1]+1.5
v.SetPosition(pcbnew.wxPointMM(x0,y0))
v.SetLayerPair(0,31)
v.SetDrill(pcbnew.Millimeter2iu(0.4))
#line to via
for y in range (panel_lines-1):
for x in range (panel_rows):
t = pcbnew.TRACK(pcb)
pcb.Add(t)
pos = cap_position[y][x]
if y%2==0:
y0 = pos[1]-0.485
y1 = pos[1]-1.5
else:
y0 = pos[1]+0.485
y1 = pos[1]+1.5
t.SetStart(pcbnew.wxPointMM(pos[0],y0))
t.SetEnd(pcbnew.wxPointMM(pos[0], y1))
t.SetWidth(pcbnew.Millimeter2iu(0.25))
t.SetNetCode(netCode)
По сути дела остались только линии данных. Не забываем, что в сумме ток у нас приличный и линии тока лучше не разрывать, поэтому линия данных идет не по прямой, а по другой стороне платы.
def DataLines(pcb):
for y in range (panel_lines):
for x in range (panel_rows-1):
diode_ref = "D"+str(y*panel_rows+x+1)
diode = pcb.FindModuleByReference(diode_ref)
for pad in diode.Pads():
if pad.GetPadName()=='1':
#PIN1 DOUT
netCode = pad.GetNet().GetNet()
x0 = pad.GetPosition().x
y0 = pad.GetPosition().y
if y%2==0:
x1 = x0 + pcbnew.Millimeter2iu(0.8)
x2 = x1 + pcbnew.Millimeter2iu(0.65)
y1 = y0 - pcbnew.Millimeter2iu(0.65)
x3 = x2 + pcbnew.Millimeter2iu(5.1)
x4 = x3 + pcbnew.Millimeter2iu(0.65)
y2 = y1 - pcbnew.Millimeter2iu(0.65)
x5 = x4 + pcbnew.Millimeter2iu(0.8)
else:
x1 = x0 - pcbnew.Millimeter2iu(0.8)
x2 = x1 - pcbnew.Millimeter2iu(0.65)
y1 = y0 + pcbnew.Millimeter2iu(0.65)
x3 = x2 - pcbnew.Millimeter2iu(5.1)
x4 = x3 - pcbnew.Millimeter2iu(0.65)
y2 = y1 + pcbnew.Millimeter2iu(0.65)
x5 = x4 - pcbnew.Millimeter2iu(0.8)
# top
track=[]
track.append([x0, y0])
track.append([x1, y0])
track.append([x2, y1])
AddTrack(pcb, track, netCode, 0.25, 0)
AddVia(pcb, [x2, y1], netCode, 0.8, 0.4)
#bottom
track=[]
track.append([x2, y1])
track.append([x3, y1])
AddTrack(pcb, track, netCode, 0.25, 31)
AddVia(pcb, [x3, y1], netCode, 0.8, 0.4)
# top
track=[]
track.append([x3, y1])
track.append([x4, y2])
track.append([x5, y2])
AddTrack(pcb, track, netCode, 0.25, 0)
def CrossLines(pcb):
for y in range (panel_lines-1): #panel_rows
diode_ref = "D"+str((y+1)*panel_rows )
diode = pcb.FindModuleByReference(diode_ref)
for pad in diode.Pads():
if pad.GetPadName()=='1':
#PIN1 DOUT
netCode = pad.GetNet().GetNet()
x0 = pad.GetPosition().x
y0 = pad.GetPosition().y
if y%2==0:
x1 = x0 + pcbnew.Millimeter2iu(0.8)
x2 = x1 + pcbnew.Millimeter2iu(0.65)
y1 = y0 - pcbnew.Millimeter2iu(0.65)
y2 = y1 - pcbnew.Millimeter2iu(deltaY - 1.3)
y3 = y2 - pcbnew.Millimeter2iu(0.65)
else:
x1 = x0 - pcbnew.Millimeter2iu(0.8)
x2 = x1 - pcbnew.Millimeter2iu(0.65)
y1 = y0 - pcbnew.Millimeter2iu(0.65)
y2 = y1 - pcbnew.Millimeter2iu(deltaY - 1.3)
y3 = y2 - pcbnew.Millimeter2iu(0.65)
# top
track=[]
track.append([x0, y0])
track.append([x1, y0])
track.append([x2, y1])
track.append([x2, y2])
track.append([x1, y3])
track.append([x0, y3])
AddTrack(pcb, track, netCode, 0.25, 0)
Полигоны, конечно, и ручкам сделать несложно, да уж ладно, раз взялись писать подпрограммы, то доделаем и это
def DrawPolygons(pcb):
# grownd plane DrawPolygons(pcb)
plane_size=[0,0]
plane_size[0]= deltaX * panel_rows/2 - panel_gap/2 - 0.5
plane_size[1]= deltaY * panel_lines/2 - panel_gap/2 - 0.5
Contour=[]
Contour.append( [pcbnew.Millimeter2iu(plane_size[0]), pcbnew.Millimeter2iu(plane_size[1]) ])
Contour.append( [pcbnew.Millimeter2iu(plane_size[0]), -pcbnew.Millimeter2iu(plane_size[1]) ])
Contour.append( [-pcbnew.Millimeter2iu(plane_size[0]), -pcbnew.Millimeter2iu(plane_size[1]) ])
Contour.append( [-pcbnew.Millimeter2iu(plane_size[0]), pcbnew.Millimeter2iu(plane_size[1]) ])
nets = pcb.GetNetsByName()
net = nets.find("GND").value()[1]
netCode = net.GetNet()
newarea = pcb.InsertArea(netCode, pcbnew.B_Cu, pcbnew.B_Cu, Contour[0][0], Contour[0][1], pcbnew.ZONE_CONTAINER.DIAGONAL_EDGE)
newoutline = newarea.Outline()
for i in range (1,4):
newoutline.Append(Contour[i][0],Contour[i][1]);
poly_set = pcbnew.SHAPE_POLY_SET()
poly_set.NewOutline()
for i in range (0,4):
poly_set.Append(Contour[i][0],Contour[i][1])
newarea.SetFilledPolysList(poly_set)
nets = pcb.GetNetsByName()
net = nets.find("+5V").value()[1]
netCode = net.GetNet()
newarea = pcb.InsertArea(netCode, pcbnew.F_Cu, pcbnew.F_Cu, Contour[0][0], Contour[0][1], pcbnew.ZONE_CONTAINER.DIAGONAL_EDGE)
newoutline = newarea.Outline()
for i in range (1,4):
newoutline.Append(Contour[i][0],Contour[i][1]);
poly_set = pcbnew.SHAPE_POLY_SET()
poly_set.NewOutline()
for i in range (0,4):
poly_set.Append(Contour[i][0],Contour[i][1])
newarea.SetFilledPolysList(poly_set)
И суммарная процедура теперь выглядит так
def Convert():
print("start")
pcb = pcbnew.LoadBoard(pcb_name)
led_position = LED_placement(pcb)
cap_position = Cap_placement(pcb)
nets = pcb.GetNetsByName()
net = nets.find("GND").value()[1]
netCode = net.GetNet()
CapGroundViaTrace(pcb, cap_position, netCode)
LedGroundViaTrace(pcb, led_position, netCode)
DataLines(pcb)
CrossLines(pcb)
DrawPolygons(pcb)
pcb.Save(pcb_name2)
print("created!")
Convert()
Когда все функции написаны, уже легко менять размеры, формы, количество пикселей, добавлять перламутровые пуговицы и потакать любым прихотям заказчика, если плата делается на заказ. Хотя, наверно, заказчику лучше рассказать, как употел разработчик этой платы рисуя бесконечные соединения, а то ведь не оценит.
В заключение на жизнь пожаловаться, что ли. Хотя Остап Бендер советовал с этим обращаться во всемирную лигу сексуальных реформ (смех смехом, а она действительно существовала в то время).
Отвечайте нам, а то,
Если вы не отзовётесь,
мы напишем в «Спортлото» ©
В Финляндии вовсю кричат о нехватке рабочей силы, особенно квалифицированной в области IT. Но о чем крик — я не понимаю.
Мой случай несколько не входит в общие рамки — пенсионер по инвалидности мало кому нужен. Да, в офис приходить каждый день мне сложно. Но ведь сейчас все топят за дистанционную работу.
А тут-то мне равных немного — мало у кого дома есть столько оборудования, как у меня. И опыт работы в фирмах, круче которых, наверно, только яйца вкрутую, и то не факт.
И знакомых полно — руководителей среднего звена. Но они работают в крупных фирмах и кадровиков не могут убедить никак, всем нужны молодые работники на постоянную работу.
А пенсионера со странными требованиями (например, зарплата не должна быть больше определенного уровня), всерьез никто не воспринимает. Типа, иди, кури. А я ищу не денег, а просто применения сил — потому, наверно, и не хотят связываться.
Остаются мелкие фирмы, хозяева которых рисковать с персоналом не могут и берут хороших знакомых, если они идут, конечно. У мелких фирм, как правило, и зарплата мелкая.
Но в такой мелкой фирме я и так работаю — мой друг, владелец и тоже пенсионер, и я. Но последний год у нас контрактов нет.
В нашем переулке, в двух соседних от меня домах, живут инженеры по электронике, были далеко не последними специалистами. С коллапсом Nokia многие фирмы, которые работали с ней, тоже позакрывали свои подразделения. Много народа осталось без работы, и они тоже.
Ладно, один из них не молодой, а второй через какое-то время тяжело заболел. Но у меня есть и несколько знакомых инженеров, в самом расцвете сил — но перебиваются случайными заработками. Я с ними сталкивался как раз, когда у них была такая временная работа, большинство из них очень квалифицированные специалисты.
Комментарии (11)
slovak
11.12.2021 20:57+1Статья на самом деле интересная, но для Kicad есть плагин replicate layout. Пользуюсь им для разводки многоканальных схем. Можно конечно и самому скриптить, но автор плагина и его пользователи уже прошли по большинству граблей.
AlexanderS
11.12.2021 21:27+3Похоже, пост оказался неинтересным.
Извините.
Прошлые ваши статьи набрали дикие плюсы из-за научно-популярного стиля изложения, охватив максимуму аудитории. Там не было перегрузки всяким матаном, спецификациями и прочей «техничкой». А эта статья — очень узконаправленная, специализированная, детализированная. Естественно, что у неё охват гораздо меньше -> оценивать её будет потребность у гораздо меньшего количества людей -> не будет рейтинга за сотню. Но это не значит, что статья неинтересна. Просто не всем подряд. Новичку в Kiсad — самое то будет. Так что не стоит извиняться и считать статью бесполезной — это не так. Вы просто кому-то в будущем, возможно, помогли в разбирательстве с скриптами. И для человека это будет весьма полезно. Спасибо вам кто-то скажет просто в воздух, а не плюсиком сейчас ;)DustyZebra Автор
11.12.2021 21:49+1Спасибо, пусть живет, как есть :) А то я уже, после чьего-то минуса, чуть не снес ее совсем.
monane
11.12.2021 23:26+1Простите что влез, не надо сносить если выпустили редакторы пусть живет. Хабр давно не место где можно получить минус за профессионализм или его отсутвие, чаще тут минус просто так. Или стадность, к сожалению. Как правило если есть претензии к оформлению или что важнее к содержанию то от настоящих оппонентов вы увидите посты, что именно не нравится или неверно.
belav
11.12.2021 22:28Спасибо. Полезный скрипт. У меня так и не дошли руки, обычно разводил один модуль, потом редактировал net лист в notepad++, прописывал координаты элементов с помощью поиска и замены.
engine9
12.12.2021 11:18Друзья, буду признателен, если кто поделится русскоязычным руководством по кикаду. В общих чертах освоил, но как подключать сторонние ресурсы или создавать свои компоненты (или просто изменять существующие) до сих пор не осилил. Там так запутанно и не логично сделана система управления ресурсами, что мозг закипает...
DustyZebra Автор
12.12.2021 11:46+1гугл говорит, что тут или пдф https://docs.kicad.org/4.0/ru/getting_started_in_kicad/getting_started_in_kicad.pdf
lukan
спаасибо автору за статтю, очень понятно и доходчиво обяснено