• Hello ES! We could use some help to get us past the finish line on building the new knowledgebase for the forum.
    Can you donate? Please see our fundraising page. Thank you!

7070 Outboard project. ESC, BMS, logging...

I’ve also read that large capacitor banks on ESCs can cause very high inrush currents when the battery is connected, potentially triggering the BMS to shut down. While the ESC itself has an on/off switch, I’m not sure whether an additional anti-spark solution is still required. Would a XT90 anti-spark connector be sufficient, or would a dedicated anti-spark switch make more sense? I’ve seen XT90 connectors used as loop connectors, but I’m not sure if that’s actually a good approach.
I'd recommend looking up "precharge"; there's a lot of ways to do it, and what exactly you need to do depends on the total capacitance, the voltage, the resistance between the caps and the voltage source (cell block in the battery) and the current that results from the initial connection when caps start at 0V, and the max inrush current allowable for the device, and max allowable output spike current and duration for the supply (battery).

Unless you have a *huge* cap bank, like with large-EV controllers, I suspect that the antispark versions of connectors would be sufficient. Some hefty ebike/scooter/emoto controllers have had big enough banks that the antispark portion can be damaged or burn out, but mostly they work.
 
For the large cables (battery and motor leads), my idea was to use proper feedthroughs through the enclosure using bolts, with ring terminals on both sides, so the crimped cables are screwed on and there’s no direct opening through the housing.
that will probalby work fine.

The smaller signal wires are more challenging due to their size, but maybe there are sealed connectors that can be fully potted — I still need to look into that.

There are a bunch of panel-mount small-signal connectors available, some of them like HIgo and Julet are also "waterproof" and pigtails and/or extensions are available so you don't have to wire up the actual connector for the cable outside the enclosure.

One concern I have with fully potting the electronics is heat dissipation. I’m not sure how risky it is in terms of overheating if the entire ESC is encapsulated in resin.
The solid material will conduct heat better than air, so it will likely help, rather than hurt. Dpeends on your material.
 
Oh, and I almost forgot, regarding the lower voltage and higher torque, I actually asked ChatGPT about that, and it gave me a diagram, which is how I came to that conclusion.
file_00000000966471f4b02b2c7431e77afa.png
I wouldn't put trust in anyting any of the AIs tells you, unless you research it and verify it. They don't "understand" anything, and while they are often right, they are also often ridiculously wrong, or provide an answer that sounds perfectly logical but does not apply to the question you want answered...only the question it interpreted from your words. ;)

The graph doesn't label anything for the motor current line, but one must assume it goes up toward the right, because torque does, and torque is proportional to current. This graph thus shows you that motor torque goes up with motor current, which goes up with motor voltage (not down).

The duty cycle they're talking about is probalby for a brushed DC motor, which is directly controleld only by PWM. A multiphase BLDC motor is more complicated than that--voltage still increases current, but commutation (spinning) is done electronically, not simply by voltage applied (direct or average).

What the chart shows is that for a given *battery fvoltage*, less PWM duty cycle is needed to get the same motor current, and thus motor torque.

So...torque still goes up with voltage because current does.


I recommend strongly to go to the ebikes.ca motor simulator where you can experiment with many setups and see how they work under various "real" conditions.
 
As an alternative to the existing propeller i modified a OpenSCAD code i found on thingiverse.
prop1.jpg
 
////////////////////
// USER SETTINGS //
////////////////////

Clockwise = 0;
BladeNumber = 2;

PitchMM = 90;
DiameterMM = 250;

Sections = 100;

CenterlinePosition = 40;
BladeSweepFinalAngle = 3;

PitchAdjustmentHub = 1.05;
PitchAdjustmentTip = 0.95;

MaxChordLength = 40;
BladeTipHeight = 0;
BladeCurveHeight = 1;

ThicknessFactor = 0.85;
ThicknessFactorAtBase = 3.2;
BaseBladeThickeningLenght = 0.35;

HubDiameter = 70;
HubThickness = 0;
HubScrewHoleDiameter = 10;
HubHeightFactor = 1;
RootInsetFactor = 12;

NACA1 = [4,4,12];
NACA2 = [2,4,08];

////////////////////
// AIRFOIL DATA //
////////////////////

AF_terms = [0.2969,-0.1260,-0.3516,0.2843];
a4 = -0.1036;
s = 30;
AirfoilWidth = 1000;
function AirfoilHeight(r) = AirfoilWidth * T_r(r);

Pitch = PitchMM;
Diameter = DiameterMM;

////////////////////
// HUB GEOMETRY //
////////////////////

HubRadius = HubDiameter / 2;
EffectiveHubThickness = max(HubThickness, MaxChordLength * HubHeightFactor);

module Hub() {
cylinder(r = HubRadius, h = EffectiveHubThickness, center = true, $fn = 100);
}

////////////////////////
// CENTERLINE LOGIC //
////////////////////////

function CenterlineAngle(r) = BladeSweepFinalAngle * r;
function CenterlineOffset(r) =
BladeSweepFinalAngle != 0
? -(ln(cos(BladeSweepFinalAngle*r))) / (BladeSweepFinalAngle*PI/180)
: 0;

CenterlineLength = sqrt(pow(.5*Diameter,2) / (pow(0.5*CenterlineOffset(1),2)+.25)) / 2;

///////////////////////
// BLADE GEOMETRY //
///////////////////////

function BaseThicknessAdjustment(r) =
1 - (20*(r-BaseBladeThickeningLenght+0.1) / (sqrt(pow(20*(r-BaseBladeThickeningLenght+0.1),2)+1))-1) * (ThicknessFactorAtBase-1);

function BladeThickness(r) = ThicknessFactor * BaseThicknessAdjustment(r) * AirfoilHeight(r) * (ChordLength(r)/AirfoilWidth);
function BladeHeight(r) = BladeTipHeight * pow(r, BladeCurveHeight) / CenterlineLength;
function RolAngle(r) = atan(BladeTipHeight/CenterlineLength * BladeCurveHeight * pow(r, BladeCurveHeight-1));
function ChordLength(r) = (1.392*pow(r,4)-1.570*pow(r,3)-2.46*pow(r,2)+3.012*r+0.215) * MaxChordLength;
function PitchAngleAdjustment(r) = (PitchAdjustmentTip-PitchAdjustmentHub)*r + PitchAdjustmentHub;
function PitchAngle(r) = atan(Pitch/(2*PI*r*CenterlineLength)) * PitchAngleAdjustment(r);

RootSweepAngle = CenterlineAngle(0);
ChordRoot = ChordLength(0);
LE_offset = CenterlinePosition/100 * ChordRoot;
TE_offset = (1-CenterlinePosition/100) * ChordRoot;
LE_radial = abs(LE_offset * cos(RootSweepAngle));
TE_radial = abs(TE_offset * cos(RootSweepAngle));
Gap_LE = HubRadius - sqrt(HubRadius*HubRadius - LE_radial*LE_radial);
Gap_TE = HubRadius - sqrt(HubRadius*HubRadius - TE_radial*TE_radial);
RequiredInset = max(Gap_LE, Gap_TE);
BladeRootRadius = (HubRadius - RequiredInset * RootInsetFactor) / CenterlineLength;

////////////////////
// AIRFOIL SHAPE //
////////////////////

function M_r(r)=((NACA2[0]-NACA1[0])*r+NACA1[0])/100;
function P_r(r)=((NACA2[1]-NACA1[1])*r+NACA1[1])/10;
function T_r(r)=((NACA2[2]-NACA1[2])*r+NACA1[2])/100;
AirfoilX=[for(i=[0:s])1-(1-cos(i*180/s))/2];
function yt(x,T)=(T/0.2)*(AF_terms[0]*sqrt(x)+AF_terms[1]*x+AF_terms[2]*x*x+AF_terms[3]*x*x*x+a4*x*x*x*x);

module AirfoilGeneration(r) {
M=M_r(r); P=P_r(r); T=T_r(r);
polygon(points=1000*[for(i=[0:2*len(AirfoilX)-2])
let(j=i<len(AirfoilX)?i:2*len(AirfoilX)-2-i)
AirfoilX[j]<P ?
[AirfoilX[j]+(i<len(AirfoilX)?-1:1)*yt(AirfoilX[j],T)*sin(atan((2*M/(P*P))*(P-AirfoilX[j]))),
(M/(P*P))*(2*P*AirfoilX[j]-AirfoilX[j]*AirfoilX[j])+(i<len(AirfoilX)?1:-1)*yt(AirfoilX[j],T)*cos(atan((2*M/(P*P))*(P-AirfoilX[j])))]
:
[AirfoilX[j]+(i<len(AirfoilX)?-1:1)*yt(AirfoilX[j],T)*sin(atan((2*M/((1-P)*(1-P)))*(P-AirfoilX[j]))),
(M/((1-P)*(1-P)))*(1-2*P+2*P*AirfoilX[j]-AirfoilX[j]*AirfoilX[j])+(i<len(AirfoilX)?1:-1)*yt(AirfoilX[j],T)*cos(atan((2*M/((1-P)*(1-P)))*(P-AirfoilX[j])))]
]);
}

module BladeSlice(r) {
translate([CenterlineOffset(r)*CenterlineLength, BladeHeight(r)*CenterlineLength, r*CenterlineLength])
rotate([-RolAngle(r),CenterlineAngle(r),-PitchAngle(r)])
linear_extrude(height=0.00000001)
translate([-CenterlinePosition/100*ChordLength(r),0])
scale([ChordLength(r)/AirfoilWidth, BladeThickness(r)/AirfoilHeight(r)])
AirfoilGeneration(r);
}

module Blade() {
union() {
for(i=[0:Sections-1]) {
r1 = BladeRootRadius + (i/Sections)*(1-BladeRootRadius);
r2 = BladeRootRadius + ((i+1)/Sections)*(1-BladeRootRadius);
hull(){ BladeSlice(r1); BladeSlice(r2); }
}
}
}

module main() {
difference() {
union() {
Hub();
for(i=[0:BladeNumber-1]) {
rotate([90,0,i*360/BladeNumber]) Blade();
}
}
cylinder(r = HubScrewHoleDiameter/2, h = EffectiveHubThickness*4, center = true, $fn = 80);
}
}

if(!Clockwise) mirror([1,0,0]) main();
else main();
 
The last version...

/*

[Project Goal]

Autonomous Solar Canoe for long distance (Germany, May-Aug)

Target Speed = 5km/h

Daily Range = Solar supported only

Propulsion = Efficient outboarder, minimal Wh/km across the entire drivetrain

Lifespan = high

Continuous Operation = yes

Operation = efficiency comes before silence!



[Boat & Mission Profile]

5m * 0.85m Canoe with 4.5m * 0.2m outrigger

Weight = 200 kg

Type = Displacement hull

Inland shipping canal = calm water



[Motor & Drive Concept]

Motor = FlipSky 7070

kv = 110kv

Outrunner = yes

Waterproof = yes

Voltage = 6-20S

Max Power = 4300W

Continuous Power = 2200W

Max Current = 100A

Continuous Current = 45A

Max Torque = 9.5Nm

Continuous Torque = 3.8Nm

Weight = 1.08KG

Resistance(R) = 64.5mΩ

Motor Structure = 12N/14P

HousingDiameter * HousingLength = 70mm * 70mm

Shaft = 10mm round

Motor Wire = 12AWG

Protection Class = IP58

Cable Length = max. 1.3m

Drive = direct



[Battery]

Cell = VC-32 LiFePO4

Capacity = 32Ah

Internal resistance = 3

Discharge current = 3C

Configuration = 6S2P (19.2V Nominal Voltage)

Energy = ~1200 Wh

Charging = Victron 100/20 MPPT

Discharge Cutoff Voltage = 3V

Charge Cutoff Voltage = 3.55V

BMS = JK-B1A8S10P

Vesc = directly to battery



[Solar]

Flexible Solar Panels = 4x 125W

Material = Monocrystalline silicon

Maximum Power(Pmax) = 125W±3%

Maximum Power Voltage(Vmp) = 19.8V

Maximum Power Current (Imp) = 6.3A

Open-Circuit Voltage (Voc) = 23.76V

Short-Circuit Current (Isc) = 6.85A

Nominal Operating Cell Temp.(NOCT) = -45 to 80℃

Maximum System Voltage = DC1000V

Maximum Series Fuse = 15A

Dimension = 1055MM(L)*569MM(W)*2.5mm(H)

Orientation = 0°/0°

Wiring = 2s2p



[Control / Regulation]

ESC = Flipsky VESC 75100 Pro V2

Drive Start = 75°C

Drive End = 85°C

Control Mode = Current Control

Motor Poles = 14

ERPM = 12000

FOC-Regulation = ON

FOC Id Current = 0.0A

FOC Id Current Offspeed = 0A

FOC Switching Frequency = 25kHz

Deadtime Compensation = ON

Field Weakening Current = 0A

Maximum Input Voltage = 32V

Maximum Operating Voltage = 29.5

Motor Current Max = 30A

Motor Current Max Brake = -3A

Absolute Maximum Current = 50A

Battery Current Max = 25A

Battery Current Regen = -5A

Wattage Limit = ON

Wattage Limit = 350W

Positive Ramp = 2.0s

Positive Ramping Time = 3.5s

Negative Ramping Time = 3s

Max Current Ramp Step = 0.02

Max Duty Cycle = 0.85

Minimum Duty Cycle 0.02

Stator Saturation Compensation = 3%

Motor Temperature Compensation 3.8%/°C

Battery Cutoff Limit = Yes

Open Loop ERPM = 900

Open Loop Current = 3A.

Observer Gain = low

Interpolation = ON

Battery Cutoff Start = 18.6V

Battery Cutoff End = 18V



[Sensor]

Encoder = AS5048A

Sensor Mode = Encoder



[Propeller]

Diameter = ~250 mm

Blades = 2-3

Propeller Efficiency = high

Material = Resin printed

Material = 80% Elegoo ABS-Like V3 / 20% Siraya Tech Tenacious



[Daggerboard & Hydrodynamics]

Daggerboard

Profile = NACA 0014

Profile Length (chord) = 180 mm

Distance DaggerboardTrailingEdge to PropellerLeadingEdge = 100mm



*/



///////////////////////////////

//////Settings/////////////////

///////////////////////////////



/* [Project Configuration] */

Clockwise = 1; // Rotation direction, [0 for Left, 1 for Right]

BladeNumber = 2; // Number of blades

ShowSingleBlade = 0; // Render single blade; [0=false, 1=true]

ShowBlades = 1; // Show/Hide blades; [0=false, 1=true]

ShowHub = 1; // Show/Hide HUB; [0=false, 1=true]

CutHub = 0; // Cuts HUB along Z axis; [0=false, 1=true]

CutSide = 1; // Which side remains; [1,0]



/* [Performance Parameters] */

PitchMM = 130; // Optimized for (x) km/h

DiameterMM = 255; // Total diameter in mm

Sections = 150; // Level of detail



/* [PITCH DISTRIBUTION] */

PitchRootFactor = 1.10; // Factor at the root (1.0 = Linear): [1.1 - 1.2 improves startup current]

PitchTipFactor = 0.70; // Reduces tip vortices at low pitch; [0.7 - 0.9]



/* [Blade Geometry] */

MaxChordLength = 45; // Maximun chord length

BladeFormSymmetry = 0.60; // Widest point; [0.5 = Center, 0.7 = Outer]

RootWidthRatio = 0.75; // Width at the hub relative to MaxChordLength; [0.6-0.8]

TipRoundness = 0.98; // Tip roundness; [0.85-0.95]

TipStartPoint = 0.72; // Start of tapering; [0.75 - 0.95]

TipCurveShape = 4; // Shape of tip curve (Higher = More aggressive taper); [2-6]

TipThicknessFactor = 0.8; // Thickness of tip relative to profile; [0.5-0.9]



/* [Anti-Flex & Smoothness] */

BladeSweepFinalAngle = 32; // Increase for smoothness and weed shedding; [>=0.5-40]

SweepCurvature = 1.8; // Curvature of sweep (1.0 = Linear, 2.0+ = Sickle shape); [1-3]

BladeTipHeight = -12; // Axial tilt (Rake) in mm; [8-15]

BladeCurveHeight = 3; // Offset of blade tip relative to root (1=linear, 2=parabolic); [2-4]

CenterlinePosition = 40; // Position of rotation axis in profile; [25-45]



/* [Material Strength & Root Optimization] */

ThicknessFactor = 1.15; // Increase for stiffness; [1-1.5]

ThicknessFactorAtBase = 35; // Reinforcement at the root; [3-6]

BaseBladeThickeningLength = 0.33; // Length of root reinforcement in % of r; [0.2-0.4]

ThicknessFadePower = 1.8; // Curve shape of transition (1=Linear, 2-3=Smooth/Organic); [1-5]

RootAsymmetry = 0.3; // Asymmetric thickness (0.1=Massive nose, 0.5=uniform); [0.1-0.5]

ChordFactorAtBase = 2.5; // Factor for chord length at the root (1.3 = 30% wider); [1-2]

BaseChordThickeningLength = 0.35; // How far the widening extends radially (in % of r); [0.1-0.5]

ChordFadePower = 2.5; // Curve shape of widening (2.0 = S-Curve); [1-4]

MinEdgeThickness = 0.7; // Minimum thickness of trailing edge; [0.2-0.4]

MinEdgeThicknessRoot = 1.2; // Minimum thickness of trailing edge at root;

EdgeThicknessFadePower = 2.2; // Decay rate of root trailing edge; [1-3]

RootInsetFactor = 0.28; // Immersion depth into HUB; [1-20]



/* [Hub & Nose Cone] */

HubDiameter = 70; // Hub diameter;

HubThickness = 130; // Hub length;

HubOgiveZOffset = -105; // Shifts Hub on Z; [-50--70]

OgiveFlip = 1; // Rotates Ogive by 180°; [0=false, 1=true]

OgiveShapePower = 2.8; // Shape of the Ogive; [1.5-3]

ShaftDiameter = 0; // 0 = solid



/* [Profiles] */

NACA1 = [4,4,13]; // Profile at the root; [thicker]

NACA2 = [2,3,9]; // Profile at the tip; [thinner]

MaxThicknessPosRoot = 0.35; // Location of thickest point at root (0.3 = 30%)

MaxThicknessPosTip = 0.45; // At the tip (0.4-0.5 is good for efficiency)

CamberFadePower = 1.5; // 1.0 = Linear, 2.0 = Camber remains high longer on the inside







/////////////////////////////////////////////////////////////////////////////////

// LOGIC-CORE

////////////////////////////////////////////////////////////////////////////////

$fn = $preview ? 32 : 128;





Diameter = DiameterMM;

HubRadius = HubDiameter / 2;

EffectiveHubThickness = max(HubThickness, MaxChordLength * 1.0);



AF_terms = [0.2969,-0.1260,-0.3516,0.2843];

a4 = -0.1036;

s = 30;

AirfoilWidth = 1000;





function T_r(r)=((NACA2[2]-NACA1[2])*r+ NACA1[2])/100;

function AirfoilHeight(r) = AirfoilWidth * T_r(r);

function GetLocalPitch(r) = PitchMM * ( PitchRootFactor + (PitchTipFactor - PitchRootFactor) * r);

function CenterlineAngle(r) = BladeSweepFinalAngle * pow(max(0.0001, r), SweepCurvature);



function CenterlineOffset(r) = let(ang = CenterlineAngle(r)) BladeSweepFinalAngle != 0 ? -(ln(max(0.0001, cos(ang)))) / (BladeSweepFinalAngle * PI / 180) : 0;



CenterlineLength = sqrt(pow(.5*Diameter,2) / (pow(0.5*CenterlineOffset(1),2)+.25)) / 2;



function BladeThickness(r) =

let(

baseT = ThicknessFactor * AirfoilHeight(r) * (ChordLength(r)/AirfoilWidth),

tipTaper = (r < 0.7) ? 1 : 1 - ( (1 - TipThicknessFactor) * (r - 0.7) / 0.3 )

)

baseT * tipTaper;



function BladeHeight(r) = BladeTipHeight * pow(max(0, r), BladeCurveHeight) / CenterlineLength;



function RollAngle(r) = atan( (BladeTipHeight/CenterlineLength) * BladeCurveHeight * pow(max(0, r), max(0.01, BladeCurveHeight-1)));



function ChordLength(r) =

let(



baseShape = RootWidthRatio + (1 - RootWidthRatio) * sin(r * 180),

distortedShape = pow(max(0.01, baseShape), BladeFormSymmetry),

standardChord = distortedShape * MaxChordLength,





chordBoost = (r < BaseChordThickeningLength)

? 1 + (ChordFactorAtBase - 1) * pow(1 - (r/BaseChordThickeningLength), ChordFadePower)

: 1,



boostedChord = standardChord * chordBoost,





safeR = max(TipStartPoint, r),

taper = (r < TipStartPoint) ? 1 : 1 - (TipRoundness * pow((safeR - TipStartPoint) / (1 - TipStartPoint + 0.0001), TipCurveShape))

)

max(0.1, boostedChord * taper);



function PitchAngle(r) = atan(GetLocalPitch(r)/(2*PI*max(0.0001, r)*CenterlineLength));



module AirfoilGeneration(r) {

camberFade = 1.5;

M = (NACA1[0] + (NACA2[0] - NACA1[0]) * pow(r, camberFade)) / 100;

P = (NACA1[1] + (NACA2[1] - NACA1[1]) * r) / 10;

T = T_r(r);

localChord = ChordLength(r);



mTP_Root = 0.35;

mTP_Tip = 0.45;

currentMaxPos = mTP_Root + (mTP_Tip - mTP_Root) * r;

p = ln(0.3) / ln(currentMaxPos);



rootBoostRange = BaseBladeThickeningLength;

localRootBoost = (r < rootBoostRange)

? pow(1 - (r/rootBoostRange), ThicknessFadePower) * (ThicknessFactorAtBase - 1)

: 0;



currentMinEdge = (r < rootBoostRange)

? MinEdgeThickness + (MinEdgeThicknessRoot - MinEdgeThickness) * pow(1 - (r/rootBoostRange), EdgeThicknessFadePower)

: MinEdgeThickness;



actualMinEdge = min(currentMinEdge, localChord * 0.05);





AirfoilX = [for(i=[0:s]) 1 - (1 - cos(i * 180 / s)) / 2];



polygon(points=1000 * [for(i=[0:2 * len(AirfoilX) - 1])

let(

isUpper = (i < len(AirfoilX)),

idx_real = isUpper ? i : (2 * len(AirfoilX) - 1 - i),

x_orig = AirfoilX[idx_real],





x = pow(x_orig, p),



xWeight = pow(1 - x, 1 / RootAsymmetry),

currentBoost = 1 + (localRootBoost * xWeight),



yc = (x < P) ? (M / (P * P)) * (2 * P * x - x * x) : (M / ((1 - P) * (1 - P))) * (1 - 2 * P + 2 * P * x - x * x),

dyc_dx = (x < P) ? (2 * M / (P * P)) * (P - x) : (2 * M / ((1 - P) * (1 - P))) * (P - x),

theta = atan(dyc_dx),





thickness = (T / 0.2) * (AF_terms[0] * sqrt(x) + AF_terms[1] * x + AF_terms[2] * x * x + AF_terms[3] * pow(x, 3) + a4 * pow(x, 4)),



finalThick = (thickness * currentBoost) + (x * (actualMinEdge / max(0.1, localChord)) / 2) / (T / 0.2)

)

isUpper

? [ x_orig - finalThick * sin(theta), yc + finalThick * cos(theta) ]

: [ x_orig + finalThick * sin(theta), yc - finalThick * cos(theta) ]

]);

}

module HubOgiveBody(L) {

rotate_extrude($fn=100) polygon(concat([[0,0], [HubRadius,0]], [for(i=[1:40]) let(t = i / 40, r = HubRadius * (1 - pow(t, OgiveShapePower)), z = L * t) [ r, z ]], [[0,L]]));

}



module HubSelector() {

L = EffectiveHubThickness;

translate([0,0,HubOgiveZOffset])

if (OgiveFlip == 1) rotate([180,0,0]) translate([0,0,-L]) HubOgiveBody(L);

else HubOgiveBody(L);

}



module BladeSlice(r) {

chord = ChordLength(r);

translate([CenterlineOffset(r)*CenterlineLength, BladeHeight(r)*CenterlineLength, r*CenterlineLength])

rotate([-RollAngle(r),CenterlineAngle(r),-PitchAngle(r)])

linear_extrude(height=0.05) translate([-CenterlinePosition/100*chord,0])

scale([chord/AirfoilWidth, BladeThickness(r)/AirfoilHeight(r)]) AirfoilGeneration(r);

}



module Blade() {

ChordRoot = ChordLength(0);

RootSweepAngle = CenterlineAngle(0);

LE_radial = abs((CenterlinePosition/100 * ChordRoot) * cos(RootSweepAngle));

Gap_LE = HubRadius - sqrt(max(0, HubRadius*HubRadius - LE_radial*LE_radial));

TE_radial = abs(((1-CenterlinePosition/100) * ChordRoot) * cos(RootSweepAngle));

Gap_TE = HubRadius - sqrt(max(0, HubRadius*HubRadius - TE_radial*TE_radial));

localRoot = (HubRadius - (max(Gap_LE, Gap_TE) * RootInsetFactor)) / CenterlineLength * 0.98;

for(i=[0:Sections-1]) {

r1 = max(0, localRoot) + (i/Sections)*(1-max(0, localRoot));

r2 = max(0, localRoot) + ((i+1)/Sections)*(1-max(0, localRoot));

hull(){ BladeSlice(r1); BladeSlice(r2); }

}

}



module main() {



BladeInstances = (ShowSingleBlade == 1) ? 1 : BladeNumber;



difference() {



union() {



if (ShowBlades == 1) {

for(i=[0:BladeInstances-1]) {

rotate([90, 0, i * 360 / BladeNumber]) Blade();

}

}





if (ShowHub == 1) {

HubSelector();

}

}





union() {



if (CutHub == 1) {

translate([500 * (CutSide == 1 ? -1 : 0), -500, -500])

cube([500, 1000, 1000]);

}





if (ShaftDiameter > 0) {



translate([0,0,-500])

cylinder(h=1000, d=ShaftDiameter, center=false, $fn=50);

}

}

}

}



if(Clockwise != 1) mirror([1,0,0]) main(); else main();


Greetings from Germany
 
Back
Top