
Здравствуйте меня зовут Дмитрий. Недавно мне попалась на глаза программа 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 программы похожие друг на друга как две капли, рекомендую попробовать. Это как глоток свежего воздуха.
