wirewinder/gcodegenerator/gcodegenerator.pas

816 lines
31 KiB
ObjectPascal

program gcodegenerator_v5;
uses
SysUtils, StrUtils, Math;
type
TPoint = record
X, Y: double;
end;
type
TStatorParams = record
StatorName: String;
BaseDiameter: Double;
BaseRadius: Double;
NumberOfRays: Integer;
RayShape: string;
RayDiameter: Double;
RayWidth: Double;
RayHeight: Double;
RayLength: Double;
RayTopShape: string;
RayTopDiameter: Double;
RayTopWidth: Double;
RayTopHeight: Double;
RayCenterOffset: Double;
WireDiameter: Double;
NeedleDiameter: Double;
NeedleRigidity: Double;
WorkSpeed :integer;
end;
type
TLayer = record
Turns: Integer; // Êîëè÷åñòâî âèòêîâ
StartZ: double; // Íà÷àëüíàÿ êîîðäèíàòà
EndZ: double; // Êîíå÷íàÿ êîîðäèíàòà
end;
var
StartTime, EndTime, ExecutionTime: TDateTime;
InputFileName, OutputFileName, CoilGeometryFileName: string;
StatorParams: TStatorParams;
InFile, OutFile, CoilGeometryFile: TextFile;
Line: string;
CoilRadius,CoilWidth,CoilHeight :double;
StartX: double;
StartY: double;
StartZ: double;
CurrentX: double;
CurrentY: double;
CurrentZ: double;
coords: TPoint;
normalizecoords: TPoint;
Layers: array[1..10] of TLayer;
i, j, k: Integer;
CoilLength :double;
CurrentCoilTurns, CoilTurnsSum :Integer;
AngleBetweenRays :double;
RequiredSpacing: Double;
LayerNumber :Integer;
MaxLayers :Integer;
angle :double;
MaxDepth,MaxPath :double;
MoveForward:boolean;
WindDirection:integer;
OperationMode:string;
xclearance,yclearance,zclearance: Double;
FixtureOffset: Double;
FixtureDiameter: Double;
FixtureTurns:integer;
function ParseLine(Line: string): Boolean;
var
Parts: array of string;
Value: string;
TrimmedLine: string;
begin
TrimmedLine := Trim(Line); // Óäàëÿåì ïðîáåëû â íà÷àëå è êîíöå ñòðîêè
if Length(TrimmedLine) = 0 then
begin
exit(true); // Ïóñòàÿ ñòðîêà - ïðîïóñêàåì
end
else if TrimmedLine[1] in [';','#'] then
begin
exit(true); // Ñòðîêà êîììåíòàðèÿ - ïðîïóñêàåì
end;
Parts := SplitString(TrimmedLine, '='); // Èñïîëüçóåì TrimmedLine
Result := Length(Parts) = 2;
if Result then
begin
Value := LowerCase(Trim(Parts[1])); // Ïðèâîäèì ê íèæíåìó ðåãèñòðó
case Trim(Parts[0]) of
'stator_name': begin
StatorParams.StatorName := Value;
writeln('StatorName: ', StatorParams.StatorName);
writeln();
end;
'Operation_Mode': begin
OperationMode := Value;
writeln('Operation Mode: ', OperationMode);
writeln();
end;
'base_dia': begin
StatorParams.BaseDiameter := StrToFloat(Value);
writeln('Base Diameter: ', StatorParams.BaseDiameter:8:2);
writeln();
StatorParams.BaseRadius := StatorParams.BaseDiameter/2;
writeln('Base Radius: ', StatorParams.BaseRadius:8:2);
writeln();
end;
'num_rays': begin
StatorParams.NumberOfRays := StrToInt(Value);
writeln('Number of Rays: ', StatorParams.NumberOfRays);
AngleBetweenRays := 360/StatorParams.NumberOfRays;
writeln('Angle Between Rays: ', AngleBetweenRays);
writeln();
end;
'ray_shape': begin
if Pos(Value, 'circle, rect, superellipse') = 0 then
raise Exception.Create('Invalid value for ray_shape: ' + Value);
StatorParams.RayShape := Value;
writeln('Ray Shape: ', StatorParams.RayShape);
writeln();
end;
'ray_dia': begin
StatorParams.RayDiameter := StrToFloat(Value);
writeln('Ray Diameter: ', StatorParams.RayDiameter:8:2);
writeln();
end;
'ray_w': begin
StatorParams.RayWidth := StrToFloat(Value);
writeln('Ray Width: ', StatorParams.RayWidth:8:2);
writeln();
end;
'ray_h': begin
StatorParams.RayHeight := StrToFloat(Value);
writeln('Ray Height: ', StatorParams.RayHeight:8:2);
writeln();
end;
'ray_len': begin
StatorParams.RayLength := StrToFloat(Value);
writeln('Ray Length: ', StatorParams.RayLength:8:2);
writeln();
end;
'raytop_shape': begin
if Pos(Value, 'circle, rect, superellipse') = 0 then
raise Exception.Create('Invalid value for ray_top: ' + Value);
StatorParams.RayTopShape := Value;
writeln('Ray Top Shape: ', StatorParams.RayTopShape);
end;
'raytop_dia': begin
StatorParams.RayTopDiameter := StrToFloat(Value);
writeln('Ray Top Diameter: ', StatorParams.RayTopDiameter:8:2);
writeln();
end;
'raytop_w': begin
StatorParams.RayTopWidth := StrToFloat(Value);
writeln('Ray Top Width: ', StatorParams.RayTopWidth:8:2);
writeln();
end;
'raytop_h': begin
StatorParams.RayTopHeight := StrToFloat(Value);
writeln('Ray Top Height: ', StatorParams.RayTopHeight:8:2);
writeln();
end;
'ray_offset': begin
StatorParams.RayCenterOffset := StrToFloat(Value);
writeln('Ray Center Offset: ', StatorParams.RayCenterOffset:8:2);
writeln();
end;
'wire_diameter': begin
StatorParams.WireDiameter := StrToFloat(Value);
writeln('Wire Diameter: ', StatorParams.WireDiameter:8:2);
writeln();
end;
'needle_diameter': begin
StatorParams.NeedleDiameter := StrToFloat(Value);
writeln('Needle Diameter: ', StatorParams.NeedleDiameter:8:2);
writeln();
end;
'needle_rigidity': begin
StatorParams.NeedleRigidity := StrToFloat(Value);
StatorParams.NeedleRigidity := StatorParams.NeedleRigidity/100;
writeln('Needle Rigidity: ', StatorParams.NeedleRigidity:8:2);
writeln();
end;
'x_clearance': begin
xclearance := StrToFloat(Value);
writeln('X Clearance: ', xclearance:8:2);
writeln();
end;
'y_clearance': begin
yclearance := StrToFloat(Value);
writeln('Y Clearance: ', yclearance:8:2);
writeln();
end;
'z_clearance': begin
zclearance := StrToFloat(Value);
writeln('Z Clearance: ', zclearance:8:2);
writeln();
end;
'fixture_offset': begin
FixtureOffset := StrToFloat(Value);
writeln('Fixture Offset: ', FixtureOffset:8:2);
writeln();
end;
'fixture_dia': begin
FixtureDiameter := StrToFloat(Value);
writeln('Fixture Diameter: ', FixtureDiameter:8:2);
writeln();
end;
'fixture_turns': begin
FixtureTurns := StrToInt(Value);
writeln('Fixture Turns: ', FixtureTurns);
writeln();
end;
'work_speed': begin
StatorParams.WorkSpeed := StrToInt(Value);
writeln('Work Speed: ', StatorParams.WorkSpeed);
writeln();
end;
else
Result := False;
end;
if not Result then
begin
writeln('Error: Unknown parameter: ', Parts[0]);
exit;
end;
end;
end;
procedure ReadInputFile();
Begin
// **Opening the input file**
AssignFile(InFile, InputFileName);
try
Reset(InFile); // **This line opens the file for reading**
while not EOF(InFile) do
begin
ReadLn(InFile, Line);
if Length(Line) > 0 then
if not ParseLine(Line) then
writeln('Error: Invalid line: ', Line);
end;
except
on E: Exception do
begin
writeln('Error opening or reading input file: ', E.Message);
Halt(1);
end;
end;
CloseFile(InFile);
end;
function CircleCoordinates(diameter, angleDegrees: Double): TPoint;
var
radius: Double;
angleRadians: Double;
begin
radius := diameter / 2;
// angleRadians := -1*angleDegrees * PI / 180; // Ïåðåâîä ãðàäóñîâ â ðàäèàíû
angleRadians := -1 * DegToRad(angleDegrees);
Result.X := radius * Cos(angleRadians);
Result.Y := radius * Sin(angleRadians);
end;
function CalculateAngle(opposite, adjacent: Double): Double;
begin
if adjacent = 0 then
raise Exception.Create('Adjacent side cannot be zero');
// CalculateAngle := ArcTan(opposite / adjacent) * 180 / PI;
CalculateAngle := RadToDeg(ArcTan(opposite / adjacent));
end;
function NormalizeZ(radius: Real; thetaDeg: Real): Real;
var
thetaRad, alphaRad, xKas, yKas, mTang, bTang: Real;
begin
// 1. Ïðåîáðàçîâàíèå óãëà èç ãðàäóñîâ â ðàäèàíû.
thetaRad := DegToRad(thetaDeg);
// 2. Âû÷èñëåíèå êîîðäèíàò òî÷êè êàñàíèÿ íà îêðóæíîñòè (îòíîñèòåëüíî öåíòðà 0,0).
xKas := radius * Cos(thetaRad);
yKas := radius * Sin(thetaRad);
// 3. Âû÷èñëåíèå óãëà, ïåðïåíäèêóëÿðíîãî ðàäèóñ-âåêòîðó (êàñàòåëüíîé).
alphaRad := thetaRad + PI / 2;
// 4. Âû÷èñëåíèå óãëîâîãî êîýôôèöèåíòà êàñàòåëüíîé.
mTang := Tan(alphaRad);
// 5. Âû÷èñëåíèå ñâîáîäíîãî ÷ëåíà óðàâíåíèÿ êàñàòåëüíîé (y = mTang * x + bTang).
bTang := yKas - mTang * xKas;
// 6. Âû÷èñëåíèå êîîðäèíàòû X òî÷êè ïåðåñå÷åíèÿ êàñàòåëüíîé ñ îñüþ X (y = 0).
// 0 = mTang * x + bTang
// x = -bTang / mTang
if mTang = 0 then
begin
// Êàñàòåëüíàÿ ïàðàëëåëüíà îñè X - íåò òî÷êè ïåðåñå÷åíèÿ. Âîçâðàùàåì NaN.
NormalizeZ := NaN;
end
else
begin
NormalizeZ := -bTang / mTang;
end;
end;
function DepthCheck(thickness, lineLength, angleDeg: double): double;
var
xIntersection, distanceToIntersection, radius: double;
begin
xIntersection := (thickness/2 + thickness/2 * cos(DegToRad(angleDeg)))/sin(DegToRad(angleDeg));
distanceToIntersection := sqrt(sqr(xIntersection) + sqr(1.2));
radius := lineLength / (2 * tan(DegToRad(angleDeg) / 2));
DepthCheck := distanceToIntersection + radius;
end;
function CalculateMaxPath(length, width, angleDegrees: double): double;
//ôóíêöèÿ âû÷èñëÿåò ìàêñèìàëüíîå ðàññòîÿíèå ìåæäó ëó÷àìè. Äëÿ ýòîãî îò öåíòðà ñòàòîðà äî
var
topLeftX, topLeftY, rotatedX, rotatedY, angleRadians, distance: double;
begin
// Âû÷èñëÿåì êîîðäèíàòû âåðõíåãî ëåâîãî óãëà ïðÿìîóãîëüíèêà
topLeftX := -length;
topLeftY := width / 2;
// Ïðåîáðàçóåì óãîë â ðàäèàíû (ñ ó÷åòîì âðàùåíèÿ ïî ÷àñîâîé ñòðåëêå)
angleRadians := degToRad(-angleDegrees);
// Âû÷èñëÿåì êîîðäèíàòû ïîâåðíóòîãî íèæíåãî ëåâîãî óãëà âòîðîãî ïðÿìîóãîëüíèêà
rotatedX := -length * cos(angleRadians) - (-width / 2) * sin(angleRadians);
rotatedY := -length * sin(angleRadians) + (-width / 2) * cos(angleRadians);
// Âû÷èñëÿåì ðàññòîÿíèå ìåæäó òî÷êàìè
distance := sqrt(sqr(rotatedX - topLeftX) + sqr(rotatedY - topLeftY));
// Âîçâðàùàåì ðåçóëüòàò
MaxPath := distance;
end;
procedure CalculateCoilGeometry();
var
StartZ, EndZ: double;
begin
writeln('CalculateCoilGeometry');
AssignFile(CoilGeometryFile, CoilGeometryFileName);
try
Rewrite(CoilGeometryFile);
//Ñ÷èòàåì, ñêîëüêî ñëî¸â ìîæåì íàìîòàòü.
MaxPath:=CalculateMaxPath((StatorParams.RayLength+StatorParams.BaseRadius), StatorParams.RayWidth, AngleBetweenRays);
//writeln(CoilGeometryFile, ';MaxPath:', MaxPath);
//MaxLayers :=trunc(((MaxPath-RequiredSpacing)/2/StatorParams.WireDiameter));
MaxLayers :=round((MaxPath-StatorParams.NeedleDiameter)/2/(StatorParams.WireDiameter+RequiredSpacing));
if (MaxLayers mod 2 = 0) then writeln(CoilGeometryFile, ';MaxLayers ', MaxLayers) else
begin
dec(MaxLayers);
writeln(CoilGeometryFile, ';Ñalculations resulted in MaxLayers=', MaxLayers+1, ' because it is even, MaxLayers=MaxLayers-1 and equal ',MaxLayers);
end;
MoveForward:=true;
for i := 1 to MaxLayers do
begin
write(CoilGeometryFile, ';Lair:', i, ' have ');
//Ñ÷èòàåì äëèíó êàòóøêè è êîëè÷åñòâî âèòêîâ
//Äëÿ ýòîãî ñ÷èòàåì íåîáõîäèìîå ðàññòîÿíèå ìåæäó ëó÷àìè. 2 äèàìåòðà ïðîâîäà + äèàìåòð èãëû + 2 çàçîðà áåçîïàñíîñòè
RequiredSpacing:=yclearance*2+(i-1)*StatorParams.WireDiameter*2+StatorParams.NeedleDiameter;
//Èñïîëüçóÿ íåîáõîäèìîå ðàññòîÿíèå, ðàññ÷èòûâàåì íà êàêóþ, ìàêñèìàëüíóþ ãëóáèíó ìîæåò ïîãðóçèòüñÿ èãîëêà. (ðàññòîÿíèå îò öåíòðà ñòàòîðà)
MaxDepth:=DepthCheck(StatorParams.RayWidth, RequiredSpacing, AngleBetweenRays);
//writeln(OutFile, ';RayWidth ', StatorParams.RayWidth:0:5);
//writeln(OutFile, ';RequiredSpacing ', RequiredSpacing:0:5);
//writeln(OutFile, ';AngleBetweenRays ', AngleBetweenRays:0:5);
//writeln(CoilGeometryFile, ';MaxDepth ', MaxDepth:0:5);
//writeln(OutFile);
//Åñëè äîïóñòèìàÿ ãëóáèíà ìåíüøå, ÷åì äèàìåòð îñíîâàíèÿ, òîãäà äëèíà êàòóøêè ðàâíà äëèíå ëó÷à.
//Åñëè äîïóñòèìàÿ ãëóáèíà áîëüøå, ÷åì äèàìåòð + äëèíà ëó÷à, ïðåêðàùàåì äâèæ.
//Èíà÷å äëèíà êàòóøêè ðàâíà "ðàäèóñ_îñíîâàíèÿ + äëèíà_ëó÷à - ãëóáèíà)
If (MaxDepth < (StatorParams.BaseRadius)) then CoilLength:=StatorParams.RayLength else if (MaxDepth > (StatorParams.RayLength+StatorParams.BaseRadius)) then break
else CoilLength:=StatorParams.RayLength+StatorParams.BaseRadius-MaxDepth;
//writeln(CoilGeometryFile, '!!!');
write(CoilGeometryFile, CoilLength:0:5, 'mm ');
//CurrentCoilTurns := ceil(CoilLength/StatorParams.WireDiameter);
//Èñõîäÿ èç äëèíû êàòóøêè ñ÷èòàåì êîëè÷åñòâî âèòêîâ. È ñêëàäûâàåì ñêîëüêî âñåãî âèòêîâ íà êàòóøêå.
CurrentCoilTurns := round(CoilLength/StatorParams.WireDiameter);
write(CoilGeometryFile, CurrentCoilTurns, ' Turns');
CoilTurnsSum := CoilTurnsSum+CurrentCoilTurns;
//Ïåðåä êàæäûì ñëîåì íóæíî ïåðåñ÷èòàòü êîîðäèíàòó Z
//writeln(CoilGeometryFile,' StartZ=',CurrentZ:0:5);
// if (MoveForward = false) then CurrentZ:=StatorParams.RayLength+StatorParams.BaseRadius-StatorParams.WireDiameter/2
// else CurrentZ:=StatorParams.RayLength+StatorParams.BaseRadius-StatorParams.WireDiameter*(CurrentCoilTurns-0.5);
if (MoveForward = false) then StartZ:=StatorParams.RayLength+StatorParams.BaseRadius-StatorParams.WireDiameter/2
else StartZ:=StatorParams.RayLength+StatorParams.BaseRadius-StatorParams.WireDiameter*(CurrentCoilTurns-0.5);
write(CoilGeometryFile,' NewStartZ=',StartZ:0:5);
if (MoveForward = true) then EndZ:=StartZ+StatorParams.WireDiameter*CurrentCoilTurns
else EndZ:=StartZ-StatorParams.WireDiameter*CurrentCoilTurns;
writeln(CoilGeometryFile,' EndZ=',EndZ:0:5);
//Inc(LayerNumber);
CoilWidth:=CoilWidth+StatorParams.WireDiameter*2;
MoveForward:= not MoveForward;
//writeln(CoilGeometryFile,';MoveForward: ', MoveForward);
//writeln(CoilGeometryFile);
writeln(CoilGeometryFile, CurrentCoilTurns, ' ',StartZ:0:5, ' ',EndZ:0:5);
Layers[i].Turns := CurrentCoilTurns;
Layers[i].StartZ := StartZ;
Layers[i].EndZ := EndZ;
end;
writeln(CoilGeometryFile);
writeln(CoilGeometryFile,';CoilTurnsSum: ', CoilTurnsSum);
except
on E: Exception do
begin
writeln('Error writing to coil_geometry file: ', E.Message);
Halt(1);
end;
end;
CloseFile(CoilGeometryFile);
end;
procedure ReadCoilGeometry();
var
// Parts: array of string;
// Value: string;
TrimmedLine: string;
line: string;
count, i, turns: Integer;
startZ: float;
endZ: float;
spacePos: Integer;
err: Integer;
begin
writeln('ReadCoilGeometry');
AssignFile(CoilGeometryFile, CoilGeometryFileName);
try
Reset(CoilGeometryFile); // **This line opens the file for reading**
i := 0;
while not EOF(CoilGeometryFile) do
begin
//writeln('!!!');
ReadLn(CoilGeometryFile, Line);
if Length(Line) > 0 then
begin
TrimmedLine := Trim(Line); // Óäàëÿåì ïðîáåëû â íà÷àëå è êîíöå ñòðîêè
if (Length(TrimmedLine) = 0) then continue //exit() // Ïóñòàÿ ñòðîêà - ïðîïóñêàåì
else if TrimmedLine[1] in [';','#'] then continue; // exit(); // Ñòðîêà êîììåíòàðèÿ - ïðîïóñêàåì
StringReplace(TrimmedLine, ',', '.', [rfReplaceAll]);
inc(i);
spacePos := Pos(' ', TrimmedLine);
//writeln(spacePos);
//writeln('!', TrimmedLine);
Val(Copy(TrimmedLine, 1, spacePos - 1), turns, err);
spacePos := 1 + spacePos;
//writeln('? ',spacePos);
//i:=1;
TrimmedLine:=Copy(TrimmedLine, spacePos, Length(TrimmedLine));
spacePos := Pos(' ',TrimmedLine);
//writeln(spacePos);
//writeln('!!', TrimmedLine);
Val(Copy(TrimmedLine, 1, spacePos - 1), startZ, err);
TrimmedLine:=Copy(TrimmedLine, spacePos, Length(TrimmedLine));
//writeln('!!!', TrimmedLine);
spacePos := Pos(' ',TrimmedLine);
//writeln(spacePos);
Val(Copy(TrimmedLine, 1, Length(TrimmedLine)), endZ, err);
writeln('layer:',i,' turns:', turns,' startX:', startZ:0:3,' endX:', endZ:0:3);
Layers[i].Turns := turns;
Layers[i].StartZ := StartZ;
Layers[i].EndZ := EndZ;
//for i := 1 to CurrentCoilTurns do
//begin
// writeln(Layers[i].Turns,Layers[i].StartZ,Layers[i].EndZ);
//end;
//MaxLayers
//writeln();
end;
//if not ParseLine(Line) then
// writeln('Error: Invalid line: ', Line);
end;
MaxLayers:=i;
except
on E: Exception do
begin
writeln('Error opening or reading Coil Geometry File: ', E.Message);
Halt(1);
end;
end;
CloseFile(CoilGeometryFile);
end;
procedure StartSequence();
begin
writeln(OutFile, ';Generate G-code file for ',StatorParams.StatorName,' stator. At ',FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz', StartTime));
writeln(OutFile, '; G-code for stator winding');
writeln(OutFile, 'G90 ; Absolute coordinate system');
//writeln(OutFile, 'G1 Y-10');
writeln(OutFile, 'G28 X Y Z');
writeln(OutFile, 'G1 X0 Y0');
writeln(OutFile);
// Move to center of ray along Y axis and reset coordinate
writeln(OutFile, 'G1 X', StatorParams.RayCenterOffset:0:2, ' Y0.0');
writeln(OutFile, 'G92 X0 Y0');
//îòâîäèì èãëó ëåâåå è âûøå âåðøèíû ëó÷à
CoilRadius:=(StatorParams.RayTopHeight/2+StatorParams.NeedleDiameter/2+yclearance);
CoilWidth:=(StatorParams.RayTopWidth+StatorParams.NeedleDiameter+yclearance*2);
CoilHeight:=(StatorParams.RayTopHeight+StatorParams.NeedleDiameter+xclearance*2);
writeln(OutFile, ';CoilRadius = ', CoilRadius:0:3);
writeln(OutFile, ';CoilWidth = ', CoilWidth:0:3);
writeln(OutFile, ';CoilHeight = ', CoilHeight:0:3);
StartX:=-1*CoilHeight/2;
StartY:=-1*AngleBetweenRays/2;
writeln(OutFile, 'G1 X', StartX:0:3, ' Y', StartY:0:3);
//ïðèáëèæàåìñÿ ê îñíîâàíèþ ñòàòîðà.
CurrentZ:=(StatorParams.BaseDiameter/2)+zclearance;
writeln(OutFile, 'G1 Z', CurrentZ:0:2, ' F', StatorParams.WorkSpeed);
//Âñòà¸ì íà ïàóçó äëÿ òîãî, ÷òîáû ïðèâÿçàòü êîíåö ïðîâîëîêè
writeln(OutFile, 'M0');
//Äâèæåíèå "ââåðõ" ïåðâîé êàòóøêè. Äåëàåòñÿ îäèí ðàç, ÷òîáû îáðàçîâàòü ïåòëþ îò êðþ÷êà.
writeln(OutFile, 'G1 X', StartX:0:3, ' Y', -1*StartY:0:3);
end;
procedure MakeCoil();
begin
for j := 1 to CurrentCoilTurns do
begin
writeln(OutFile,';Coil¹ = ',j);
writeln(OutFile,'M117 L',LayerNumber,'/C',j,'/S',CoilTurnsSum-CurrentCoilTurns+j);
//Move from -X,Y to X,Y
angle := WindDirection*AngleBetweenRays/2;
CurrentX :=CoilHeight/2+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity);
writeln(OutFile, 'G1 X', CurrentX:0:3, ' Y', angle:0:5,' Z', NormalizeZ(CurrentZ, angle):0:5,' F',StatorParams.WorkSpeed, ' ;Point 1 CurrentZ= ',CurrentZ:0:5, ' 2x_clear= ',+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity):0:3); // Top Right Corner
if MoveForward then CurrentZ:=CurrentZ+StatorParams.WireDiameter/4 else CurrentZ:=CurrentZ-StatorParams.WireDiameter/4;
//Divide the path into 100 points
//Move from X,Y to X,-Y
for k := 1 to 100 do
begin
angle := AngleBetweenRays/2;
angle := WindDirection*(angle-(2*(angle/100*k)));
CurrentX :=CoilHeight/2+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity);
writeln(OutFile, 'G1 X', CurrentX:0:3, ' Y', angle:0:5,' Z', NormalizeZ(CurrentZ, angle):0:5,' F',round(1.2*StatorParams.WorkSpeed/StatorParams.BaseRadius*CurrentZ), ' ;Point 2 CurrentZ= ',CurrentZ:0:5, ' 3x_clear= ',+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity):0:3); // Bottom Right Corner
end;
if MoveForward then CurrentZ:=CurrentZ+StatorParams.WireDiameter/4 else CurrentZ:=CurrentZ-StatorParams.WireDiameter/4;
//Move from X,-Y to -X,-Y
angle := -1*WindDirection*AngleBetweenRays/2;
CurrentX :=CoilHeight/2+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity);
writeln(OutFile, 'G1 X', -1*CurrentX:0:3, ' Y', angle:0:5,' Z', NormalizeZ(CurrentZ, angle):0:5,' F',StatorParams.WorkSpeed, ' ;Point 3 CurrentZ= ',CurrentZ:0:5, ' 4x_clear= ',+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity):0:3); // Bottom Left Corner
if MoveForward then CurrentZ:=CurrentZ+StatorParams.WireDiameter/4 else CurrentZ:=CurrentZ-StatorParams.WireDiameter/4;
//Move from -X,-Y to -X,Y
//Divide the path into 100 points
for k := 1 to 100 do
begin
angle := AngleBetweenRays/2;
angle := -1*WindDirection*(angle-(2*(angle/100*k)));
CurrentX :=CoilHeight/2+((CurrentZ-StatorParams.BaseRadius)*xclearance*StatorParams.NeedleRigidity);
writeln(OutFile, 'G1 X', -1*CurrentX:0:3, ' Y', angle:0:5,' Z', NormalizeZ(CurrentZ, angle):0:5,' F',round(1.2*StatorParams.WorkSpeed/StatorParams.BaseRadius*CurrentZ) , ' ;Point 4 CurrentZ= ',CurrentZ:0:5, ' 1x_clear= ',+((CurrentZ-StatorParams.BaseRadius*xclearance*StatorParams.NeedleRigidity)):0:3); // Top Left Corner
end;
if MoveForward then CurrentZ:=CurrentZ+StatorParams.WireDiameter/4 else CurrentZ:=CurrentZ-StatorParams.WireDiameter/4;
end;
end;
procedure PairCoilWind(mode: string);
begin
if ((mode = 'Aa') or (mode = 'Bb') or (mode = 'Cc')) then
begin
WindDirection:=1;
end
else if ((mode = 'aA') or (mode = 'bB') or (mode = 'cC')) then
begin
WindDirection:=-1;
end
else
begin
Writeln('Wrong Pair Coil Pattern. (Aa, aA, Bb, bB, Cc, cC');
Readln;
Halt(1);
end;
for LayerNumber := 1 to MaxLayers do
begin
writeln(OutFile, ';Layer ', LayerNumber);
if (Layers[LayerNumber].StartZ > Layers[LayerNumber].EndZ) then CoilLength:=Layers[LayerNumber].StartZ-Layers[LayerNumber].EndZ
else CoilLength:=Layers[LayerNumber].EndZ-Layers[LayerNumber].StartZ;
writeln(OutFile, ';CoilLength ', CoilLength:0:5);
CurrentCoilTurns:=Layers[LayerNumber].Turns;
//writeln(OutFile, ';CurrentCoilTurns ', CurrentCoilTurns);
CoilTurnsSum := CoilTurnsSum+CurrentCoilTurns;
writeln(OutFile, ';CoilTurnsSum ', CoilTurnsSum);
CurrentZ:=Layers[LayerNumber].StartZ;
writeln(OutFile,'; NewZ=',CurrentZ:0:5);
//Íà÷èíàåì ìîòàòü.
writeln(OutFile, ';We make ',CurrentCoilTurns, ' turns on ', LayerNumber, ' layer.' );
writeln(OutFile);
WindDirection := 1;
MakeCoil();
writeln(OutFile, 'M300 S2500 P100');
CoilWidth:=CoilWidth+StatorParams.WireDiameter*2;
MoveForward:= not MoveForward;
writeln(OutFile,';MoveForward: ', MoveForward);
end;
writeln(OutFile, 'M300 S2500 P100');
writeln(OutFile, 'G4 P100');
writeln(OutFile, 'M300 S2500 P100');
writeln(OutFile, 'G4 P100');
writeln(OutFile, 'M300 S2500 P100');
writeln(OutFile, ';Coil Complete.');
writeln(OutFile, ';Changing coords.');
writeln(OutFile, 'G92 Y', -1*angle:0:5);
writeln(OutFile, ';Second coil');
for LayerNumber := 1 to MaxLayers do
begin
writeln(OutFile, ';Layer ', LayerNumber);
if (Layers[LayerNumber].StartZ > Layers[LayerNumber].EndZ) then CoilLength:=Layers[LayerNumber].StartZ-Layers[LayerNumber].EndZ
else CoilLength:=Layers[LayerNumber].EndZ-Layers[LayerNumber].StartZ;
writeln(OutFile, ';CoilLength ', CoilLength:0:5);
CurrentCoilTurns:=Layers[LayerNumber].Turns;
//writeln(OutFile, ';CurrentCoilTurns ', CurrentCoilTurns);
CoilTurnsSum := CoilTurnsSum+CurrentCoilTurns;
writeln(OutFile, ';CoilTurnsSum ', CoilTurnsSum);
CurrentZ:=Layers[LayerNumber].StartZ;
writeln(OutFile,'; NewZ=',CurrentZ:0:5);
//Íà÷èíàåì ìîòàòü.
writeln(OutFile, ';We make ',CurrentCoilTurns, ' turns on ', LayerNumber, ' layer.' );
writeln(OutFile);
WindDirection := -1;
MakeCoil();
writeln(OutFile, 'M300 S2500 P100');
CoilWidth:=CoilWidth+StatorParams.WireDiameter*2;
MoveForward:= not MoveForward;
writeln(OutFile,';MoveForward: ', MoveForward);
end;
writeln(OutFile, 'M300 S2500 P100');
writeln(OutFile, 'G4 P50');
writeln(OutFile, 'M300 S2500 P100');
writeln(OutFile, 'G4 P50');
writeln(OutFile, 'M300 S2500 P100');
writeln(OutFile, ';Coil Complete.');
end;
procedure MoveToNextPair();
begin
writeln(OutFile, ';Move To Next Pair');
writeln(OutFile, 'G92 Y0');
writeln(OutFile, 'G1 Y', 360/(StatorParams.NumberOfRays/3/2):0:5 ); // Top Left Corner
writeln(OutFile, ';Turn to next pair with ',360/(StatorParams.NumberOfRays/3/2):0:5,'°.' );
writeln(OutFile, 'G92 Y',StartY:0:5);
end;
procedure CreateMotorPhase(pattern:string);
begin
PairCoilWind(pattern);
MoveToNextPair();
PairCoilWind(pattern);
MoveToNextPair();
PairCoilWind(pattern);
MoveToNextPair();
PairCoilWind(pattern);
end;
procedure MoveToFixture();
begin
writeln(OutFile, ';Move To Fixture');
writeln(OutFile, 'G1 X', FixtureOffset:0:3);
writeln(OutFile, 'M0'); //Ïàóçà
end;
procedure AttachToFixture();
begin
writeln(OutFile, ';Attach To Fixture');
for j := 0 to FixtureTurns do
begin
for i := 0 to 360 do
begin
coords := CircleCoordinates(FixtureDiameter/2+xclearance, i+180);
angle := CalculateAngle(coords.Y, CurrentZ);
writeln(OutFile, 'G1 X', coords.X:0:3, ' Y', angle:0:5,' Z', NormalizeZ(CurrentZ, angle):0:5);
CurrentZ:=CurrentZ+StatorParams.WireDiameter/360;
end;
end;
end;
begin //Start Programm
// Command line argument handling
StartTime := Now;
if ParamCount < 3 then
begin
Writeln('Usage: GCodeGenerator <input_file.txt> <output_file.gcode> <coil_geometry.txt>');
Halt(1);
end;
InputFileName := ParamStr(1);
OutputFileName := ParamStr(2);
CoilGeometryFileName := ParamStr(3);
ReadInputFile();
// G-code generation
AssignFile(OutFile, OutputFileName);
try
Rewrite(OutFile);
StartSequence();
// *** Your G-code generation logic here ***
if (OperationMode = 'auto') then CalculateCoilGeometry() else
if (OperationMode = 'manual') then ReadCoilGeometry() else
begin
writeln('Error determining operation mode.');
writeln('You should use auto or manual.');
Readln;
Halt(1);
end;
writeln();
writeln(OutFile, ';Information about layers');
writeln(OutFile, ';MaxLayers: ', MaxLayers);
for i := 1 to MaxLayers do
begin
writeln(OutFile, ';', i, ' ',Layers[i].Turns,' ',Layers[i].StartZ:0:5,' ',Layers[i].EndZ:0:5);
end;
Inc(LayerNumber);
//Íà÷èíàåì ìîòàòü êàòóøêó.
writeln(OutFile);
writeln(OutFile, ';Start winding');
//Äâèãàåìñÿ îò öåíòðà ê êðàþ
MoveForward:=true;
if (StatorParams.RayShape = 'circle') then
begin
for j := 0 to CurrentCoilTurns do
begin
for i := 0 to 360 do
begin
coords := CircleCoordinates(CoilRadius*2, i+180);
// writeln(OutFile,'CoilRadius*2= ',CoilRadius*2:0:5,' X=', coords.X:0:3, ' Y=', coords.Y:0:5);
angle := CalculateAngle(coords.Y, CurrentZ);
// writeln(OutFile, ';G1 X', coords.X:0:3, ' Y', angle:0:5,' Z', CurrentZ:0:5);
writeln(OutFile, 'G1 X', coords.X:0:3, ' Y', angle:0:5,' Z', NormalizeZ(CurrentZ, angle):0:5);
// writeln(OutFile);
CurrentZ:=CurrentZ+StatorParams.WireDiameter/360;
end;
writeln(OutFile, ';Next coil.');
end;
writeln(OutFile, ';Second coil');
Inc(LayerNumber);
// RequiredSpacing:=StatorParams.RayWidth+StatorParams.NeedleDiameter+StatorParams.PathClearance*2+LayerNumber*StatorParams.WireDiameter*2;
// writeln(OutFile, ';RequiredSpacing = ',RequiredSpacing:0:5);
RequiredSpacing:=StatorParams.RayTopWidth;
writeln(OutFile, ';RequiredSpacing = ',RequiredSpacing:0:5);
RequiredSpacing:=RequiredSpacing+StatorParams.NeedleDiameter;
writeln(OutFile, ';RequiredSpacing = ',RequiredSpacing:0:5);
RequiredSpacing:=RequiredSpacing+yclearance*2+LayerNumber*StatorParams.WireDiameter*2;
writeln(OutFile, ';RequiredSpacing = ',RequiredSpacing:0:5);
CurrentZ:=RequiredSpacing/(2 * tan(AngleBetweenRays*PI/180/2));
writeln(OutFile, ';CurrentZ = ',CurrentZ:0:3);
end
else if (StatorParams.RayShape = 'rect') then
begin
// writeln(OutFile, ';Rect? ');
CreateMotorPhase('Aa');
MoveToFixture();
AttachToFixture();
end;
except
on E: Exception do
begin
writeln('Error writing to output file: ', E.Message);
Halt(1);
end;
end;
CloseFile(OutFile);
EndTime := Now;
ExecutionTime := EndTime - StartTime;
writeln('G-code generated to: ', OutputFileName, ' in ', FormatFloat('0.000', ExecutionTime * 86400), ' seconds.');
writeln('Press Enter... ');
Readln;
end.