Just commit

This commit is contained in:
VladimirLatukhin 2025-02-26 21:50:32 +03:00
parent 62a95eddde
commit aa5693dd09
18 changed files with 1032 additions and 0 deletions

View file

@ -0,0 +1,13 @@
# Change Log
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## 2025-01-05
### Добавлено
### Изменено
### Исправлено

16
gcodegenerator/TODO.md Normal file
View file

@ -0,0 +1,16 @@
This file contains a list of tasks that need to be completed.
# TODO
## CRITICAL
## HIGH
## MEDIUM
## LOW
1. Íàïèñàòü ïîäðîáíûé àëãîðèòì ðàáîòû ñòàíêà.
2. Íàïèñàòü ïîäðîáíóþ èíñòðóêöèþ ïî ðàáîòå.
# IN PROGRESS
# DONE

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<PathDelim Value="\"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="gcodegenerator_v5"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<Units>
<Unit>
<Filename Value="gcodegenerator_v5.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="gcodegenerator_v5"/>
</Target>
<SearchPaths>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf3"/>
</Debugging>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectSession>
<PathDelim Value="\"/>
<Version Value="12"/>
<BuildModes Active="Default"/>
<Units>
<Unit>
<Filename Value="gcodegenerator_v5.pas"/>
<IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/>
<TopLine Value="648"/>
<CursorPos X="25" Y="668"/>
<FoldState Value=" TC6B22 PPTB T3iV2{#5 piZmf2L1123]Rl3pQ2 T0yU4U0"/>
<UsageCount Value="220"/>
<Loaded Value="True"/>
</Unit>
</Units>
<JumpHistory HistoryIndex="19">
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="191" Column="51" TopLine="158"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="351" Column="28" TopLine="333"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="518" Column="74" TopLine="496"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="524" Column="47" TopLine="504"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="181" Column="56" TopLine="166"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="651" Column="71" TopLine="625"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="604" Column="42" TopLine="587"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="612" Column="91" TopLine="590"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="506" Column="32" TopLine="245"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="657" Column="139" TopLine="621"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="630" Column="26" TopLine="246"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="632" TopLine="610"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="671" Column="7" TopLine="615"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="532" Column="51" TopLine="493"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="542" Column="49" TopLine="515"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="580" Column="67" TopLine="313"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="507" Column="66" TopLine="72"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="222" Column="64" TopLine="198"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Column="11"/>
</Position>
<Position>
<Filename Value="gcodegenerator_v5.pas"/>
<Caret Line="668" Column="25" TopLine="636"/>
</Position>
</JumpHistory>
<RunParams>
<FormatVersion Value="2"/>
<Modes ActiveMode="default">
<Mode Name="default">
<local>
<CommandLineParams Value="input.txt output.gcode"/>
</local>
</Mode>
</Modes>
</RunParams>
<HistoryLists>
<List Name="LaunchingApplication" Type="File" Count="1">
<Item1 Value="C:\Windows\system32\cmd.exe /C ${TargetCmdLine}"/>
</List>
<List Name="CommandLineParameters" Count="1">
<Item1 Value="input.txt output.gcode"/>
</List>
</HistoryLists>
</ProjectSession>
</CONFIG>

Binary file not shown.

View file

@ -0,0 +1,816 @@
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.

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Compiler Value="C:\lazarus\fpc\3.2.2\bin\x86_64-win64\fpc.exe" Date="1497193866"/>
<Params Value=" -MObjFPC -Scghi -O1 -gw3 -gl -l -vewnhibq -FuD:\Documents\GitHub\motor-wire-winder\gcodegenerator\ -FUD:\Documents\GitHub\motor-wire-winder\gcodegenerator\lib\x86_64-win64\ -FED:\Documents\GitHub\motor-wire-winder\gcodegenerator\ -oD:\Documents\GitHub\motor-wire-winder\gcodegenerator\gcodegenerator.exe gcodegenerator.pas"/>
</CONFIG>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.