Здравствуйте меня зовут Дмитрий. Недавно мне попалась на глаза программа OpenSCAD и я хочу сделать небольшой обзор и ещё мы немного порисуем.
Итак OpenSCAD это как вы наверно догадались CAD программа но рисовать в ней нужно не мышкой, а по средствам встроенного скриптового языка. То есть проектирование в ней напоминает програмирование.
И вы спросите, а зачем это нужно не проще-ли рисовать по старинке мышкой. Но я похоже разгадал замысел авторов программы. Дело в том что существует определенный круг деталей внешняя форма которых определяется формулами. И как раз для проектирования подобных деталей OpenSCAD подходит как нельзя лучше.
Шестерня с внешним зацеплением.
И первой подобной деталью является шестерня. Вот пример который я написал:
Скрытый текст// To activate animation, select "View->Animate" from the
// menu; this will cause three fields to appear
// underneath the Preview console: Time, FPS & Steps.
// To commence animation, enter values into the FPS and Steps input
//Example FPS = 60 Steps = 120
// For set initial position uncomment
//$t=0;
//Fist gear...............................................
Teath = 20;
M = 1;
PressAng = 20;
C = 0.25;
DPeatch = Teath * M;
RPeatch = DPeatch/2;
DMain = DPeatch * cos(PressAng);
St = PI * M/2; // Teeth thickness by diameter
Stx = DPeatch * sin(St*(180/PI)/DPeatch); // Teeth thickness by chord
DIn = DPeatch - (2 + C)* M;
DOut = DPeatch + 2 * M;
ROut = DOut / 2;
d = sqrt(RPeatch^2 - (Stx/2)^2);
Steps = 90;
function ToRad(T) = T * (PI/180);
function Evolv_X(T, MD) = MD/2 * (cos(T) + ToRad(T) * sin(T));
function Evolv_Y(T, MD) = MD/2 * (sin(T) - ToRad(T) * cos(T));
FistEvolv_temp = [ for (a = [0 : Steps])
if (sqrt((Evolv_X(a, DMain) + RPeatch - Evolv_X(20, DMain))^2 + (Evolv_Y(a, DMain) - Evolv_Y(20, DMain) - Stx/2)^2) < ROut) // Cut pionts outside gear
[Evolv_X(a, DMain) + RPeatch - Evolv_X(20, DMain), Evolv_Y(a, DMain) - Evolv_Y(20, DMain) - Stx/2]];
FistEvolv = concat([[d - (2 + 2)* M/2 , - Stx/2]], FistEvolv_temp);
SecondEvolv = [ for(variable = FistEvolv) [variable.x, -variable.y]];
FistEvolvB = [ for(a =[0 : (len(FistEvolv) - 1)]) a];
SecondEvolvB = [ for(a =[0 : (len(SecondEvolv) - 1)])
2 * len(SecondEvolv) - a - 1];
rotate ([0, 0, $t*360])
linear_extrude(height = 2 * M, center = true, convexity = 10, twist = 0)
union()
{
for (i = [0 : (Teath - 1)])
rotate([0,0,(360/Teath) * i])
polygon(concat(FistEvolv, SecondEvolv),[concat(FistEvolvB, SecondEvolvB)]);
circle(d = DIn);
}
//Second Gear.........................................................
Teath_2 = 30;
DPeatch_2 = Teath_2 * M;
RPeatch_2 = DPeatch_2 / 2;
DMain_2 = DPeatch_2 * cos(PressAng);
Stx2 = DPeatch_2 * sin(St*(180/PI)/DPeatch_2); // Teeth thickness by chord
DIn2 = DPeatch_2 - (2 + C)* M;
DOut2 = DPeatch_2 + 2 * M;
d2 = sqrt(RPeatch_2^2 - (Stx2/2)^2);
FistEvolv_temp2 = [ for (a = [0 : Steps])
if (sqrt((Evolv_X(a, DMain_2)+ RPeatch_2 - Evolv_X(20, DMain_2))^2 + (Evolv_Y(a, DMain_2) - Evolv_Y(20, DMain_2) - Stx2/2)^2) < DOut2 / 2) // Cut pionts outside gear
[Evolv_X(a, DMain_2)+ RPeatch_2 - Evolv_X(20, DMain_2), Evolv_Y(a, DMain_2) - Evolv_Y(20, DMain_2) - Stx2/2]];
FistEvolv2 = concat([[d2 - (2 + 2)* M/2 , - Stx2/2]],FistEvolv_temp2);
SecondEvolv2 = [ for(variable = FistEvolv2)
[variable.x, -variable.y]];
FistEvolvB2 = [ for(a =[0 : (len(FistEvolv2) - 1)]) a];
SecondEvolvB2 = [ for(a =[0 : (len(SecondEvolv2) - 1)])
2 * len(SecondEvolv2) - a - 1];
k = Teath / Teath_2;
offset = (360/(2*Teath_2));
color( "Lime", 1.0 )
translate([DPeatch/2 + DPeatch_2/2, 0, 0])
rotate([0,0,k * (-$t*360) + offset])
linear_extrude(height = 2 * M, center = true, convexity = 10, twist = 0)
union()
{
for (i = [0 : (Teath_2 -1)])
rotate([0,0,(360/Teath_2) * i])
polygon(concat(FistEvolv2, SecondEvolv2),[concat(FistEvolvB2, SecondEvolvB2)]);
circle(d = DIn2);
}Код нужно вставить в программу. Если выбрать "View->Animate" то можно увидеть анимацию. Правда чтобы она запустилась нужно в поля FPS и Steps ввести значения.
Любую шестерню можно задать всего тремя параметрами это модуль, количество зубьев и угол контакта. Все остальные размеры выражаются через эти три.
Самая главная поверхность шестерни это конечно-же эвольвента, которая получается прокатыванием отрезка по цилиндру без скольжения. Вот её формула:
Steps = 90;
function ToRad(T) = T * (PI/180);
function Evolv_X(T, MD) = MD/2 * (cos(T) + ToRad(T) * sin(T));
function Evolv_Y(T, MD) = MD/2 * (sin(T) - ToRad(T) * cos(T));
FistEvolv_temp = [ for (a = [0 : Steps])
if (sqrt((Evolv_X(a, DMain) + RPeatch - Evolv_X(20, DMain))^2 + (Evolv_Y(a, DMain) - Evolv_Y(20, DMain) - Stx/2)^2) < ROut) // Cut pionts outside gear
[Evolv_X(a, DMain) + RPeatch - Evolv_X(20, DMain), Evolv_Y(a, DMain) - Evolv_Y(20, DMain) - Stx/2]];
FistEvolv = concat([[d - (2 + 2)* M/2 , - Stx/2]], FistEvolv_temp);Мы прокатываем наш воображаемый отрезок от нуля до 90. Чтобы избавится от лишней части эвольвенты. Я использую условный оператор который отсекает все точки, лежащие за внешним диаметром шестерни.
Эвольвента начинается от главного диаметра шестерни и уходит в бесконечность. Но нам нужно 2 эвольвенты, и чтобы получить вторую нужно отразить все точки. Но для этого нужно опустить эвольвенту вниз на половину толщины зуба по главному диаметру. А мы знаем толщину зуба только по делительному. И чтобы сдвинуть делительный диаметр эвольвенты в ноль я нахожу координаты эвольвенты при 20 градусах и вычитаю их. После этого остается только сдвинуть эвольвенту вниз на половину толшины зуба Stx.
Ну а вторую эвольвенту мы получаем просто изменив знак у координаты y.
SecondEvolv = [ for(variable = FistEvolv) [variable.x, -variable.y]];Шестерня с внутренним зацеплением.

Ну а если мы создали шестерню с внешним зацепление. То сделать шестерню с внутренним зацеплением не представляет большого труда. Надо просто из цилиндра вырезать форму шестерни. Вот код:
Скрытый текст// To activate animation, select "View->Animate" from the
// menu; this will cause three fields to appear
// underneath the Preview console: Time, FPS & Steps.
// To commence animation, enter values into the FPS and Steps input
//Example FPS = 60 Steps = 120
// For set initial position uncomment
//$t=0;
//Fist gear...............................................
Teath = 30;
M = 1;
PressAng = 20;
C = 0.25;
DPeatch = Teath * M;
RPeatch = DPeatch/2;
DMain = DPeatch * cos(PressAng);
St = PI * M/2; // Teeth thickness by diameter
Stx = DPeatch * sin(St*(180/PI)/DPeatch); // Teeth thickness by chord
DIn = DPeatch - 1 * M;
DOut = DPeatch + (2 + C) * M;
ROut = DOut / 2;
d = sqrt((DPeatch/2)^2 - (Stx/2)^2);
steps = 90;
function ToRad(T) = T * (PI/180);
function Evolv_X(T, MD) = MD/2 * (cos(T) + ToRad(T) * sin(T));
function Evolv_Y(T, MD) = MD/2 * (sin(T) - ToRad(T) * cos(T));
FistEvolv_temp = [ for (a = [0 : steps])
if (sqrt((Evolv_X(a, DMain) + RPeatch - Evolv_X(20, DMain))^2 + (Evolv_Y(a, DMain) - Evolv_Y(20, DMain) - Stx/2)^2) < ROut) // Cut pionts outside gear
[Evolv_X(a, DMain)+ RPeatch - Evolv_X(20, DMain),
Evolv_Y(a, DMain) - Evolv_Y(20, DMain) - Stx/2]];
FistEvolv = concat([[d - (2 + 2)* M/2 , - Stx/2]],FistEvolv_temp);
SecondEvolv = [ for(variable = FistEvolv)
[variable.x, -variable.y]];
FistEvolvB = [ for(a =[0 : (len(FistEvolv) - 1)]) a];
SecondEvolvB = [ for(a =[0 : (len(SecondEvolv) - 1)])
len(SecondEvolv) - a - 1 + len(SecondEvolv)];
rotate ([0, 0, $t*360])
linear_extrude(height = 2 * M, center = true, convexity = 10, twist = 0)
difference()
{
circle(d = DPeatch + 5 * M);
for (i = [0 : (Teath -1)])
rotate([0,0,(360/Teath) * i])
polygon(concat(FistEvolv, SecondEvolv),[concat(FistEvolvB, SecondEvolvB)]);
circle(d = DIn);
}
//Second Gear.........................................................
Teath_2 = 10;
DPeatch_2 = Teath_2 * M;
RPeatch_2 = DPeatch_2 / 2;
DMain2 = DPeatch_2 * cos(PressAng);
Stx_2 = DPeatch_2 * sin(St*(180/PI)/DPeatch_2); // Teeth thickness by chord
DIn_2 = DPeatch_2 - (2 + C)* M;
DOut_2 = DPeatch_2 + 2 * M;
ROut_2 = DOut_2 / 2;
d2 = sqrt((DPeatch_2/2)^2 - (Stx_2/2)^2);
FistEvolv_temp_2 = [ for (a = [0 : steps])
if (sqrt((Evolv_X(a, DMain2)+ (DPeatch_2/ 2) - Evolv_X(20, DMain2))^2 + (Evolv_Y(a, DMain2) - Evolv_Y(20, DMain2) - Stx_2/2)^2) < DOut_2 / 2) // Cut pionts outside gear
[Evolv_X(a, DMain2)+ (DPeatch_2/ 2) - Evolv_X(20, DMain2), Evolv_Y(a, DMain2) - Evolv_Y(20, DMain2) - Stx_2/2]];
FistEvolv_2 = concat([[d2 - (2 + 2)* M/2 , - Stx_2/2]],FistEvolv_temp_2);
SecondEvolv_2 = [ for(variable = FistEvolv_2)
[variable.x, -variable.y]];
FistEvolvB_2 = [ for(a =[0 : (len(FistEvolv_2) - 1)]) a];
SecondEvolvB_2 = [ for(a =[0 : (len(SecondEvolv_2) - 1)])
2 * len(SecondEvolv_2) - a - 1];
k = Teath / Teath_2;
offset = 0;
color( "Lime", 1.0 )
translate([DPeatch/2 - DPeatch_2/2, 0, 0])
rotate([0,0,k * ($t*360) + offset])
linear_extrude(height = 2 * M, center = true, convexity = 10, twist = 0)
union()
{
for (i = [0 : (Teath_2 -1)])
rotate([0,0,(360/Teath_2) * i])
polygon(concat(FistEvolv_2, SecondEvolv_2),[concat(FistEvolvB_2, SecondEvolvB_2)]);
circle(d = DIn_2);
}
Циклоидный редуктор

Мне так понравилось проектировать в этой программе, что я начал искать другие детали которые тоже как и шестерни строятся по формулам. И одним из подобных примеров является циклоидный редуктор. Вот код:
Скрытый текст// To activate animation, select "View->Animate" from the
// menu; this will cause three fields to appear
// underneath the Preview console: Time, FPS & Steps.
// To commence animation, enter values into the FPS and Steps input
//Example FPS = 60 Steps = 120
// For set initial position uncomment
//$t=0;
D = 100;
R = D/2;
Dout = 5;
Drol = 5;
Rrol = Drol/2;
E = 0.75;
I = 39;
N = I + 1;
DHols = 65;
H = 5;
Steps = 360;
function Cycloyd_X(T) = (R * cos(T)) - (Rrol * cos(T + atan(sin((1 - N) * T) / ((R / (E * N)) - cos((1 - N) * T))))) - (E * cos(N * T));
function Cycloyd_Y(T) = (-R * sin(T)) + (Rrol * sin(T + atan(sin((1 - N) * T) / ((R / (E * N)) - cos((1 - N) * T))))) + (E * sin(N * T));
//Cycloyd body.........................................
Cycloyd = [ for (a = [0 : Steps])
[Cycloyd_X(a), Cycloyd_Y(a)]];
translate([E, 0, 0])
rotate([0,0,($t*360)])
linear_extrude(height = H, center = true, convexity = 10, twist = 0)
difference()
{
polygon(Cycloyd);
circle(d = 20);
translate([DHols/2, 0, 0])
circle(d = Dout + 2 * E);
rotate([0,0,120])
translate([DHols/2, 0, 0])
circle(d = Dout + 2 * E);
rotate([0,0,240])
translate([DHols/2, 0, 0])
circle(d = Dout + 2 * E);
}
//Rollers body.............................................................
k = I/N;
rotate([0,0, k * ($t*360)])
color( "Lime", 1.0 )
linear_extrude(height = H, center = true, convexity = 10, twist = 0)
union()
{
difference()
{
circle(d = D + 20);
circle(d = D);
}
for (i = [0 : I])
rotate([0,0,i * 360/N])
translate([D/2, 0, 0])
circle(d = Drol);
};
//Vodilo........................................
color( "Aqua", 1.0 )
rotate([0,0,($t*360)])
union()
{
hull()
{
translate([0,0,-20]) cylinder(h = 5, d= 15);
translate([DHols/2,0,-20])cylinder(h = 5, d= 15);
}
rotate([0,0,120])
hull()
{
translate([0,0,-20]) cylinder(h = 5, d= 15);
translate([DHols/2,0,-20])cylinder(h = 5, d= 15);
}
rotate([0,0,240])
hull()
{
translate([0,0,-20]) cylinder(h = 5, d= 15);
translate([DHols/2,0,-20])cylinder(h = 5, d= 15);
}
translate([DHols/2, 0, -20])
cylinder(h = 20 + H,d = Dout);
rotate([0,0,120])
translate([DHols/2, 0, -20])
cylinder(h = 20 + H,d = Dout );
rotate([0,0,240])
translate([DHols/2, 0, -20])
cylinder(h = 20 + H ,d = Dout);
}Здесь необходимо создать циклоиду. В обычной CAD программе это было-бы сделать очень проблематично, а в OpenSCAD нет никаких проблем.
Циклойдный редуктор с промежуточными телами качения.

Ну и конечно-же после того как мы создали редуктор с внешней циклоидой. Возникает вопрос. А существуют-ли редукторы с внутренней циклоидой. И на удивление я нашел такой редуктор, называется он циклоидный редуктор с промежуточными телами качения. Вот видео, там автор подробно расписывает все преимущества этого редуктора над просто циклоидным. Ну а мы приступаем к рисованию:
Скрытый текст// To activate animation, select "View->Animate" from the
// menu; this will cause three fields to appear
// underneath the Preview console: Time, FPS & Steps.
// To commence animation, enter values into the FPS and Steps input
//Example FPS = 60 Steps = 120
// For set initial position uncomment
//$t=0;
Dball = 6;
Rball = Dball/2;
I = 17;
Rout = 38;
E = 0.2 * Dball;
ZG = I + 1; //gear ratio
Rin = Rout - 2 * E;
HC = 2.2 * E; //Separator thickness
Dex = (Rin + E - Dball) * 2;
Dsep = Dex + Dball; //Separator diameter
Dcyclbody = 2 * Rout + 20;
Dsepm = Dex + Dball;
k = (I + 1)/I;
H = 5;
function S(T) = sqrt((Rball + Dex/2) ^ 2 - (E * cos(ZG * T)) ^ 2);
function L(T) = E * cos(ZG * T) + S(T);
function XI(T) = atan2(E * ZG * sin(ZG *T),S(T));
function Cycloyd_X(T) = L(T) * sin(T) + Rball * sin(T + XI(T));
function Cycloyd_Y(T) = L(T) * cos(T) + Rball * cos(T + XI(T));
//Cycloyd body.........................................
Steps = 360;
Cycloyd = [ for (a = [0 : Steps])
[Cycloyd_X(a), Cycloyd_Y(a)]];
rotate([0,0,($t*360)])
linear_extrude(height = H, center = true, convexity = 10, twist = 0)
difference()
{
circle(d = Dcyclbody);
polygon(Cycloyd);
}
//Excenric...................................................
color( "Blue", 1.0 )
translate([0, E, 0])
rotate([0,0, k * ($t*360)])
cylinder( h = H, d = Dex);
//Balls...................................................
color( "Aqua", 1.0 )
translate([0, E, 0])
rotate([0,0, k * ($t*360)])
for (i = [0 : I - 1])
rotate([0,0,i * 360/I])
translate([0, Dsepm/2, 0])
sphere(d = Dball);
//Seporator.........................................................
color( "Lime", 1.0 )
translate([0, E, 0])
rotate([0,0, k * ($t*360)])
linear_extrude(height = H, center = true, convexity = 10, twist = 0)
difference()
{
circle(d = Dsep + HC);
circle(d = Dsep - HC);
for (i = [0 : I - 1])
rotate([0,0,i * 360/I])
translate([0, Dsepm/2 , 0])
square(Dball,true);
}Вывод
Конечно есть за что программу поругать. У неё ужасный текстовый редактор. Из-за окна предпросмотра для него остается только пол экрана, поэтому работать в нем невозможно. Я все скрипты писал в VSCodium. Кроме того неудобная работа с массивами. Это проявилось при создании шестерни. Чтобы добавить точку с координатой основания зуба в начало массива пришлось создать новый массив. Кроме того хотелось-бы иметь инструмент для измерения размеров, но все что есть это сетка с координатами.
Но если не смотреть на эти недостатки, то программа просто огонь. Если вас утомили однообразные CAD программы похожие друг на друга как две капли, рекомендую попробовать. Это как глоток свежего воздуха.

Комментарии 0