1
0
mirror of https://github.com/rene-dev/stmbl.git synced 2024-12-24 17:42:10 +00:00
stmbl/sim/pwm.html
2015-08-27 12:25:12 +02:00

404 lines
8.5 KiB
HTML

<html>
<meta charset="utf-8">
<head><title>pwm</title>
<script type="text/javascript">
var isMouseDown = false;
document.onmousedown = function() { isMouseDown = true };
document.onmouseup = function() { isMouseDown = false };
function round(x, a){
return(Math.round(x * a) / a)
}
function clamp(x, a){
return((-a < x) ? ((a < x) ? (a) : (x)) : (-a));
}
function svm(u, v, w, mode, center){
switch(mode){
case "std":
u += 0.5;
v += 0.5;
w += 0.5;
break;
case "svm":
var uv = v - u;
var vw = w - v;
var wu = u - w;
if(Math.abs(uv) > Math.abs(vw)){
if(Math.abs(uv) > Math.abs(wu)){ // uv
u = -uv / 2.0;
v = uv / 2.0;
w = v + vw;
}
else{ // wu
u = wu / 2.0;
w = -wu / 2.0;
v = u + uv;
}
}
else{
if(Math.abs(vw) > Math.abs(wu)){ // vw
v = -vw / 2.0;
w = vw / 2.0;
u = w + wu;
}
else{ // wu
u = wu / 2.0;
w = -wu / 2.0;
v = u + uv;
}
}
u += 0.5;
v += 0.5;
w += 0.5;
break;
case "flat bottom svm":
if(u < v){
if(u < w){
v -= u;
w -= u;
u = 0.0;
}
else{
u -= w;
v -= w;
w = 0.0;
}
}
else{
if(v < w){
u -= v;
w -= v;
v = 0.0;
}
else{
u -= w;
v -= w;
w = 0.0;
}
}
}
var radio = document.getElementById('df');
if(radio){
radio.innerHTML += "<br>PWM_U = " + round(u, 100) + "<br>PWM_V = " + round(v, 100) + "<br>PWM_W = " + round(w, 100);
}
// var canvas = document.getElementById('canvas_plot');
// if (canvas.getContext){
// var ctx = canvas.getContext('2d');
//
//
// ctx.save();
// ctx.translate(canvas.width / 2, canvas.height / 2);
//
// ctx.moveTo(0, 0);
// ctx.lineTo(Math.cos(0 / 3 * 2 * Math.PI) * (u - 0.5) * canvas.width, Math.sin(0 / 3 * 2 * Math.PI) * (u - 0.5) * canvas.height);
// ctx.moveTo(0, 0);
// ctx.lineTo(Math.cos(1 / 3 * 2 * Math.PI) * (v - 0.5) * canvas.width, Math.sin(1 / 3 * 2 * Math.PI) * (v - 0.5) * canvas.height);
// ctx.moveTo(0, 0);
// ctx.lineTo(Math.cos(2 / 3 * 2 * Math.PI) * (w - 0.5) * canvas.width, Math.sin(2 / 3 * 2 * Math.PI) * (w - 0.5) * canvas.height);
//
//
// ctx.stroke();
// ctx.restore();
// }
draw(u, v, w, center);
}
function draw_vec(x, y){
y *= -1;
var canvas = document.getElementById('canvas_plot');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
//clear
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.save();
ctx.translate(w / 2, h / 2);
// limit circle
ctx.arc(0, 0, h / 2, 0, 2 * Math.PI);
ctx.arc(0, 0, h / 2 * 2 / Math.sqrt(3), 0, 2 * Math.PI);
// labels
ctx.font = "12px serif";
ctx.fillText("A", w / 2 - 24, 4);
ctx.fillText("B", -4, 10 - h / 2);
//ctx.fillText("V", Math.cos(1 / 3 * 2 * Math.PI) * w / 2, Math.sin(120 / 180 * Math.PI) * h / 2);
//ctx.fillText("W", Math.cos(2 / 3 * 2 *Math.PI) * w / 2, Math.sin(240 / 180 * Math.PI) * h / 2 + 10);
//ctx.fillText("W", -4, 10 - h / 2);
// vector
// voltage
ctx.moveTo(0, 0);
ctx.lineTo(x * w, y * h);
// a, b
ctx.moveTo(0, 0);
ctx.lineTo(x * w, 0);
ctx.moveTo(0, 0);
ctx.lineTo(0, y * h);
ctx.stroke();
ctx.restore();
}
}
function draw(u, v, w, align) {
u = round(1-u, 250) * 250;
v = round(1-v, 250) * 250;
w = round(1-w, 250) * 250;
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
//clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
// axis
ctx.moveTo(15,0);
ctx.lineTo(15, 100);
ctx.lineTo(515, 100);
// labels
ctx.font = "12px serif";
ctx.fillText("U", 0, 30);
ctx.fillText("V", 0, 60);
ctx.fillText("W", 0, 90);
// UVW waves
switch(align){
case "center":
ctx.moveTo(15,35);
ctx.lineTo(u + 15, 35);
ctx.lineTo(u + 15, 25);
ctx.lineTo(515 - u, 25);
ctx.lineTo(515 - u, 35);
ctx.lineTo(515, 35);
ctx.moveTo(15,65);
ctx.lineTo(v + 15, 65);
ctx.lineTo(v + 15, 55);
ctx.lineTo(515 - v, 55);
ctx.lineTo(515 - v, 65);
ctx.lineTo(515, 65);
ctx.moveTo(15,95);
ctx.lineTo(w + 15, 95);
ctx.lineTo(w + 15, 85);
ctx.lineTo(515 - w, 85);
ctx.lineTo(515 - w, 95);
ctx.lineTo(515, 95);
break;
case "right":
ctx.moveTo(15,35);
ctx.lineTo(u + 15, 35);
ctx.lineTo(u + 15, 25);
ctx.lineTo(265, 25);
ctx.lineTo(265, 35);
ctx.lineTo(u + 265, 35);
ctx.lineTo(u + 265, 25);
ctx.lineTo(515, 25);
ctx.moveTo(15,65);
ctx.lineTo(v + 15, 65);
ctx.lineTo(v + 15, 55);
ctx.lineTo(265, 55);
ctx.lineTo(265, 65);
ctx.lineTo(v + 265, 65);
ctx.lineTo(v + 265, 55);
ctx.lineTo(515, 55);
ctx.moveTo(15,95);
ctx.lineTo(w + 15, 95);
ctx.lineTo(w + 15, 85);
ctx.lineTo(265, 85);
ctx.lineTo(265, 95);
ctx.lineTo(w + 265, 95);
ctx.lineTo(w + 265, 85);
ctx.lineTo(515, 85);
break;
case "left":
ctx.moveTo(15, 25);
ctx.lineTo(265 - u, 25);
ctx.lineTo(265 - u, 35);
ctx.lineTo(265, 35);
ctx.lineTo(265, 25);
ctx.lineTo(515 - u, 25);
ctx.lineTo(515 - u, 35);
ctx.lineTo(515, 35);
ctx.moveTo(15, 55);
ctx.lineTo(265 - v, 55);
ctx.lineTo(265 - v, 65);
ctx.lineTo(265, 65);
ctx.lineTo(265, 55);
ctx.lineTo(515 - v, 55);
ctx.lineTo(515 - v, 65);
ctx.lineTo(515, 65);
ctx.moveTo(15, 85);
ctx.lineTo(265 - w, 85);
ctx.lineTo(265 - w, 95);
ctx.lineTo(265, 95);
ctx.lineTo(265, 85);
ctx.lineTo(515 - w, 85);
ctx.lineTo(515 - w, 95);
ctx.lineTo(515, 95);
}
ctx.stroke();
}
}
function update(){
var mode = "std";
var align = "left";
var a = 0.0;
var b = 0.0;
var u = 0.0;
var v = 0.0;
var w = 0.0;
var radio = document.getElementById('radio_std');
if(radio){
if(radio.checked){
mode = "std";
}
}
radio = document.getElementById('radio_svm');
if(radio){
if(radio.checked){
mode = "svm";
}
}
radio = document.getElementById('radio_fbsvm');
if(radio){
if(radio.checked){
mode = "flat bottom svm";
}
}
radio = document.getElementById('radio_left');
if(radio){
if(radio.checked){
align = "left";
}
}
radio = document.getElementById('radio_right');
if(radio){
if(radio.checked){
align = "right";
}
}
radio = document.getElementById('radio_center');
if(radio){
if(radio.checked){
align = "center";
}
}
radio = document.getElementById('range_a');
if(radio){
a = radio.value;
}
radio = document.getElementById('range_b');
if(radio){
b = radio.value;
}
u = a * 1.0; // inverse clarke
v = - a / 2.0 + b / 2.0 * Math.sqrt(3);
w = - a / 2.0 - b / 2.0 * Math.sqrt(3);
u = clamp(u, 0.5);
v = clamp(v, 0.5);
w = clamp(w, 0.5);
radio = document.getElementById('df');
if(radio){
radio.innerHTML = "A = " + round(a, 100) + "<br>B = " + round(b, 100) + "<br>U = " + round(u, 100) + "<br>V = " + round(v, 100) + "<br>W = " + round(w, 100);
}
draw_vec(a, b);
svm(u, v, w, mode, align);
}
function set_ab(e){
if(isMouseDown){
var mouseX, mouseY;
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
var canvas = document.getElementById('canvas_plot');
if (canvas.getContext){
var radio = document.getElementById('range_a');
if(radio){
radio.value = (mouseX - canvas.width / 2) / canvas.width;
}
radio = document.getElementById('range_b');
if(radio){
radio.value = -(mouseY - canvas.height / 2) / canvas.height;
}
}
update();
}
}
</script>
</head>
<style type="text/css">
input:button {width : 500px}
</style>
<body onload="update();">
<canvas id="canvas" width="550" height="100">
not supported
</canvas>
<canvas id="canvas_plot" width="200" height="200" onmousedown="isMouseDown = true; set_ab(event);" onmousemove="set_ab(event);">
not supported
</canvas><br>
<input type="radio" id="radio_std" name="mode" onclick="update();" checked="checked">std<br>
<input type="radio" id="radio_svm" name="mode" onclick="update();">SVM<br>
<input type="radio" id="radio_fbsvm" name="mode" onclick="update();">flat bottom SVM<br>
<input type="radio" id="radio_left" name="align" onclick="update();">left pwm<br>
<input type="radio" id="radio_right" name="align" onclick="update();">right pwm<br>
<input type="radio" id="radio_center" name="align" onclick="update();"" checked="checked">center pwm<br>
<input type="range" id="range_a" onchange="update();" oninput="update();" min="-0.5" max="0.5" step="0.01" value="0.0">A<br>
<input type="range" id="range_b" onchange="update();" oninput="update();" min="-0.5" max="0.5" step="0.01" value="0.0">B<br>
<a id="df"></a>
</body>
</html>