3D printing NACA airfoil profiles

12 Jun 2020 - tsp
Last update 05 Jul 2020
Reading time 4 mins

Note: This blog post is the product of a 3 AM idea. If you spot any errors comments are welcome.

What are NACA profiles?

Example of NACA 5614 profile

NACA profiles are well known airfoil shapes for wings. They’ve been developed by the National Advisory Committee for Aeronautics in the United States. All NACA profiles are identified either by 4 or 5 digits - called 4 or 5 digit series.

The four digit series identifies:

An NACA 4318 profile would have a maximum camber of 4% located at 30% from the leading edge with a maximum thickness of 18% of the chord.

Are 3D printed wings flyable?

I’m going to do some experiments on this but currently it seems that they normally require some additional post processing to get a smooth surface if one uses FDM printing - for example sanding or painting. This seems to reduces vortexes on the surface of the wings and produce much more laminar flow till the tail edge (where vortexes of course occur and provide a major contribution to lift)

Basic symmetric profiles (00xx series)

The basic symmetric 00xx airfoil is generated by

[ y_t = 5*t*(0.2969*\sqrt(x) - 0.1260*x - 0.3516*x^2 + 0.2843*x^3 - 0.1015*x^4) \\ x \in (0;1) ]

The variable $x$ is the position along the chord and runs from zero to one, $y_t$ is the half thickness at the given center-line position - to generate a symmetric airfoil this can simply be extended in both directions of the $z$ axis. The $t$ value is the maximum thickness in relation to the chord (i.e. the last two digits divided by hundred)

As one can see this has been derived as a polynomial fit.

To generate such a profile using OpenJSCAD we can simply use a polynomial and extrude from that shape:


function naca00_YT(maxThickness, x) {
	return 5 * (maxThickness/100.0) * (0.2969*Math.sqrt(x) - 0.1260*x - 0.3516*x*x + 0.2843*x*x*x - 0.1015*x*x*x*x);
}

function naca00_CAG(length, maxThickness, fn) {
	let pnts = [];
	let step = length / fn;

	// Leading edge
	pnts.push([0,0]);

	// Upper half
	for(let i = 1; i < fn; i++) {
		pnts.push([i*step, naca00_YT(maxThickness, (i*step)/length)]);
	}

	// Trailing edge
	pnts.push([length, 0]);

	// Lower half
	for(let i = fn-1; i > 0; i--) {
		pnts.push([i*step, -1*naca00_YT(maxThickness, (i*step)/length)]);
	}

	return CAG.fromPoints(pnts);
}

function naca00(length, width, maxThickness, fn) {
	return linear_extrude({ height : width }, naca00_CAG(length, maxThickness, fn));
}

function main() {
    return naca00(5, 10, 60, 100);
}

These airfoils have their maximum thickness at about 30% of the airfoil.

Cambered airfoils

If one wants a cambered airfoil one has to modify the equation a little bit. First one has to calculate the mean camber, then profile thickness as well as the direction of thickness measurement due to bent camber line:

function nacaYC(x, maxCamber, maxPosition, maxThickness) {
	let m = (maxCamber / 100.0);
	let p = (maxPosition / 10.0);
	let t = (maxThickness / 100.0);

	if(x < p) {
		return m / (p*p) * (2 * p * x - x * x);
	} else {
		return m / ((1-p)*(1-p)) * ((1-2*p) + 2*p*x - x*x);
	}
}

function nacaYCDiff(x, maxCamber, maxPosition, maxThickness) {
	let m = (maxCamber / 100.0);
	let p = (maxPosition / 10.0);
	let t = (maxThickness / 100.0);

	if(x < p) {
		return m / (p*p) * (2 * p - 2 * x);
	} else {
		return m / ((1-p)*(1-p)) * (2*p - 2 * x);
	}
}

function nacaYT(x, maxThickness) {
	let t = (maxThickness / 100.0);

	return t / 0.2 * (0.2969 * Math.sqrt(x) - 0.1260 * x - 0.3516 * x * x + 0.2843 * x * x * x - 0.1015 * x * x * x * x);
}

function nacaCAG(length, maxCamber, maxPositon, maxThickness, fn) {
	let pnts = [];
	let step = length / fn;

	for(let i = 0; i <= fn; i=i+1) {
		let x = (i*step) / length;
		let yt = nacaYT(x, maxThickness);

		let theta = Math.atan(nacaYCDiff(x, maxCamber, maxPositon, maxThickness));

		let xu = x - yt * Math.sin(theta);
		let yu = nacaYC(x, maxCamber, maxPositon, maxThickness) + yt * Math.cos(theta);

		pnts.push([xu*length, yu*length]);
	}

	for(let i = fn-1; i > 0; i--) {
		let x = (i*step) / length;
		let yt = nacaYT(x, maxThickness);
		let theta = Math.atan(nacaYCDiff(x, maxCamber, maxPositon, maxThickness));

		let xl = x + yt * Math.sin(theta);
		let yl = nacaYC(x, maxCamber, maxPositon, maxThickness) - yt * Math.cos(theta);

		pnts.push([xl*length, yl*length]);
	}

	return CAG.fromPoints(pnts);
}

function naca(length, width, maxCamber, maxPositon, maxThickness, fn) {
	return linear_extrude({ height : width }, nacaCAG(length, maxCamber, maxPositon, maxThickness, fn));
}

function main() {
	return naca(5, 10, 2, 4, 15, 100);
}

OpenJSCAD library

To make life way easier I’ve implemented (as usual) an OpenJSCAD library that’s available at GitHub.

This article is tagged: Airfoil, 3D printing, OpenJSCAD


Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support