Rotary Encoder Generator
Outputs angle as gray code using desired number of bits.
by Santiago J
HTML
<img id="encoder">
JavaScript
// Important parameters
var nbits = 7; // number of bits used by the encoder
var radius = 100; // radius of circle in pixels
var startAt = 1 / nbits; // fraction of radius that defines inner radius
var padding = 20; // padding between circumference and edge of canvas
// "validation"
startAt = Math.min(Math.max(startAt, 0), 1); // startAt must be between 0 and 1
nbits = Math.max(nbits, 1); // nbits must be positive
// Canvas and variables
var canvas = document.createElement("canvas");
var img = document.querySelector("#encoder");
var ctx = canvas.getContext("2d");
var xyc = radius + padding;
var n = 1 << nbits;
var K = 2 * Math.PI / n;
var HOLE_COLOR = "#fff";
var NOHOLE_COLOR = "#000";
// Get m-th of n-th number in Gray Code sequence
function isHigh(n,m) {
return Math.floor(n / (1 << (m+1)) - 0.5) % 2 == 0;
}
// Paint background
canvas.width = canvas.height = 2 * xyc;
ctx.fillStyle = HOLE_COLOR;
ctx.fillRect(0, 0, 2*xyc, 2*xyc);
// Pre-fill circle
ctx.fillStyle = NOHOLE_COLOR;
ctx.beginPath();
ctx.arc(xyc, xyc, radius, 0, 2*Math.PI, false);
ctx.fill();
// Draw code
ctx.fillStyle = ctx.strokeStyle = HOLE_COLOR;
for (var i = 0; i < n; i++) {
for (var j = 0; j < nbits; j++) {
if (isHigh(i,j)) {
ctx.beginPath();
ctx.arc(xyc, xyc,
(startAt + (1 - startAt) * (1 - (j+1) / nbits)) * radius,
i*K, (i+1)*K, false);
ctx.arc(xyc, xyc,
(startAt + (1 - startAt) * (1 - j / nbits)) * radius,
(i+1)*K, i*K, true);
ctx.fill();
ctx.stroke();
}
}
}
// Draw lines between bits for clarity
ctx.strokeStyle = NOHOLE_COLOR;
ctx.lineWidth = 3;
for (var j = 0; j <= nbits; j++) {
ctx.beginPath();
ctx.arc(xyc, xyc,
(startAt + (1 - startAt) * j / nbits) * radius,
0, 2*Math.PI, false);
ctx.stroke();
}
img.src = canvas.toDataURL("image/png");