Windroos – deel 2

De windrichtingmeter in testopstelling

Het was/is echt stoeien met Annex32 om op een visueel aantrekkelijke manier de resultaten van mijn windrichtingmeter te tonen. Daarvoor is een mix van BASIC, HTML en JavaScript nodig. In deel 1 van deze serie had ik het pure Annex32 BASIC programma aan de praat. De windrichtingmeter draait in het rond en geeft netjes de waardes als tekst aan: Noord, Noordoost, Oost, enzovoorts. Maar ik wil dus een visuele weergave: een naald die in een kompas/ windroos ronddraait en zodoende toont waar de wind vandaan komt. En dat blijkt een stuk lastiger! Na lang rondzoeken op internet besloot ik Gemini te raadplegen en verzocht om een voorzet te doen. Ik heb trouwens het idee dat sinds AI ons helpt met onze zoektochten maar hulp de Google-zoekopdrachten steeds beroerde werken.

Mijn vraag was dat ik een webpagina aan het maken was in HTML met JavaScript en SVG (Scaleable Vector Graphics) waarin een polygon (250,50 270,250 230,250) afhankelijk van een variabele met een bepaalde hoek roteert om het punt 250, 250 (de basis van de polygon). De precieze vraag kan ik me niet meer herinneren, maar terugzoekend wat mijn vraag precies was, zag ik dat Gemini er het volgende van had gemaakt.

Ik heb een webpagina aan het maken HTML met javascript en SVG. Ik heb een en afhankelijk van een variabel wil ik deze polygon laten roteren om punt 250,250. Hoe doe ik dat?

Een redelijk verminkte vraag! Vreemd dat de exacte vraag niet bewaard is gebleven! Dit is in ieder geval waar Gemini mee kwam …

<!DOCTYPE html>
<html lang="nl">
<head>
    <title>SVG Polygon Rotatie</title>
    <style>
        svg {
            border: 1px solid black;
        }
    </style>
</head>
<body>

    <h1>Roteren van een SVG Polygon</h1>

    <svg width="500" height="500">
        <polygon id="mijnPolygon" points="250,50 270,250 230,250" style="fill:red;stroke:black;stroke-width:1" />
        
        <circle cx="250" cy="250" r="5" fill="blue" />
        
    </svg>

    <p>
        <button onclick="rotatePolygonByVariable()">Roteer de polygon</button>
    </p>

    <script>
        // De variabele die de rotatiehoek bepaalt
        let rotatieHoek = 0;

        // De functie om de polygon te roteren
        function rotatePolygonByVariable() {
            // Verhoog de hoek met 45 graden bij elke klik
            rotatieHoek = (rotatieHoek + 45) % 360; 

            const polygon = document.getElementById('mijnPolygon');
            const cx = 250; // x-coördinaat van het rotatiepunt
            const cy = 250; // y-coördinaat van het rotatiepunt

            // De transform-string: 'rotate(hoek, cx, cy)'
            const transformString = `rotate(${rotatieHoek}, ${cx}, ${cy})`;

            // Pas de transform-attribuut toe
            polygon.setAttribute('transform', transformString);
        }
    </script>

</body>
</html>

… en onderstaand het resultaat.

En dat deed precies wat ik wilde! Wanneer je op de knop klikt draait de driehoek (poligon) om het punt 250, 250 (het kleine, blauwe cirkeltje. Makkelijk zat! Nu nog zorgen dat de rotatie gedaan wordt op basis van de waardes die uit de windrichtingmeter komen! Het pure BASIC programma moest dus gemengd worden met het HTML/SVG/JavaScript-programma. Vele varianten volgde. Hieronder een aantal van de meest belovenden!

'Windroos_2_test3.bas

PIN.MODE 0, INPUT, PULLUP
PIN.MODE 1, INPUT, PULLUP
PIN.MODE 2, INPUT, PULLUP
PIN.MODE 3, INPUT, PULLUP

onhtmlreload WEBPAGE

gosub   WEBPAGE
timer0 500, RICHTING 'meet richting elke 500 miliseconde
wait


'#########################
WEBPAGE:
'#########################

cls
A$ = ||
A$ = A$ + |<!DOCTYPE html>|
A$ = A$ + |<html lang="nl">|
A$ = A$ + |<head>|
A$ = A$ + |    <title>SVG Polygon Rotatie</title>|
A$ = A$ + |    <style>|
A$ = A$ + |        svg {|
A$ = A$ + |            border: 1px solid black;|
A$ = A$ + |        }|
A$ = A$ + |    </style>|
A$ = A$ + |</head>|
A$ = A$ + |<body>|
A$ = A$ + ||
A$ = A$ + |    <h1>Roteren van een SVG Polygon</h1>|
A$ = A$ + ||
A$ = A$ + |     <script>|
A$ = A$ + |         document.write(<p>'Text'</p>);|
A$ = A$ + |     </script>|
A$ = A$ + ||
A$ = A$ + |    <svg width="500" height="500">|
A$ = A$ + |        <polygon id="mijnNaald" points="250,50 270,250 230,250" style="fill:red;stroke:black;stroke-width:1" />|
A$ = A$ + |        |
A$ = A$ + |        <circle cx="250" cy="250" r="5" fill="blue" />|
A$ = A$ + |        |
A$ = A$ + |    </svg>|
A$ = A$ + ||
A$ = A$ + |    <p>|
A$ = A$ + |        <button onclick="rotatePolygonByVariable()">Roteer de polygon</button>|
A$ = A$ + |    </p>|
A$ = A$ + ||
A$ = A$ + |</body>|
A$ = A$ + |</html>|

html A$

A$ = ""
A$ = A$ + |        let rotatieHoek = 0;|
A$ = A$ + |        function rotatePolygonByVariable() {|
A$ = A$ + |            rotatieHoek = (rotatieHoek + 45) % 360;|
A$ = A$ + |            const polygon = document.getElementById('mijnNaald');|
A$ = A$ + |            const cx = 250;|
A$ = A$ + |            const cy = 250;|
A$ = A$ + |            const transformString = `rotate(${rotatieHoek}, ${cx}, ${cy})`;|
A$ = A$ + |            polygon.setAttribute('transform', transformString);|
A$ = A$ + |        }|

A$ = A$ + |        function rotateMe(rotatieHoek) {|
A$ = A$ + |            const polygon = document.getElementById('mijnPolygon');|
A$ = A$ + |            const cx = 250;|
A$ = A$ + |            const cy = 250; |
A$ = A$ + |            const transformString = `rotate(${rotatieHoek}, ${cx}, ${cy})`;|
A$ = A$ + |            polygon.setAttribute('transform', transformString);|
A$ = A$ + |        }|


jscript A$
return

'#########################
RICHTING:
'#########################

A = pin(0)
B = pin(1)
C = pin(2)
D = pin(3)

IF (A = 0) AND (B = 1) AND (C = 1) AND (D = 1) THEN
  wlog "Noord"
  direction = 0
END IF
IF (A = 0) AND (B = 0) AND (C = 1) AND (D = 1) THEN
  wlog "Noord-Oost"
  direction = 45
END IF
IF (A = 1) AND (B = 0) AND (C = 1) AND (D = 1) THEN
  wlog "Oost"
  direction = 90
END IF
IF (A = 1) AND (B = 0) AND (C = 0) AND (D = 1) THEN
  wlog "Zuid-Oost"
  direction = 135
END IF
IF (A = 1) AND (B = 1) AND (C = 0) AND (D = 1) THEN
  wlog "Zuid"
  direction = 180
END IF
IF (A = 1) AND (B = 1) AND (C = 0) AND (D = 0) THEN
  wlog "Zuid-West"
  direction = 225
END IF
IF (A = 1) AND (B = 1) AND (C = 1) AND (D = 0) THEN
  wlog "West"
  direction = 270
END IF
IF (A = 0) AND (B = 1) AND (C = 1) AND (D = 0) THEN
  wlog "Noord-West"
  direction = 315
END IF

return

De driehoek verschijnt keurig in beeld, maar doet het niet??? Ik kwam erachter dat wanneer er ergens in het script en fout staat, de uitvoer van de rest van de pagina stokt, zonder dat je daar perse een melding van krijgt. Het is dus niet altijd duidelijk of het gehele script überhaupt uitgevoerd wordt. Ik moet onthouden hiervoor aan het einde van een script een soort test in te bouwen. Is dat laatste stukje script uitgevoerd? Dan pas is het gehele script doorlopen.
Op het forum van Annex RDS hulp gezocht en gekregen! O.a. van Peter Neufeld die me ook al had geholpen met mijn radar-experiment. Hieronder het script dat gebruik maakt van een extern JavaScript bibliotheek: “gauge.min.js” dat als bestand op de root van de ESP gezet moet worden. Het doet wat ik wil, maar niet met MIJN windroos. 🙁

'Gauge_minimaal_1.bas

PIN.MODE 0, INPUT, PULLUP
PIN.MODE 1, INPUT, PULLUP
PIN.MODE 2, INPUT, PULLUP
PIN.MODE 3, INPUT, PULLUP

dir = 0

onhtmlreload WEBPAGE

gosub   WEBPAGE
timer0 1000, RICHTING 'meet richting elke seconde
wait


'#########################
WEBPAGE:
'#########################
cls
jsexternal "/gauge.min.js" ' load javascript library for gauges
pause 500 ' gives time to the browser to import the library

A$ = ""
A$ = A$ + textbox$(dir)  + "<br>"      ' textbox
A$ = A$ + meter$(dir, 0, 360)+ "<br>"  ' meter

A$ = A$ + |<canvas id="gauge2" data-type="linear-gauge"|
A$ = A$ + |        data-width="200"|
A$ = A$ + |        data-height="600"|
A$ = A$ + |        data-min-value="0"|
A$ = A$ + |        data-max-value="360"|
A$ = A$ + |        data-animation-rule="linear"|
A$ = A$ + |        data-animation-duration="100"|
A$ = A$ + |        data-var="dir"|  ' this is where the variable is defined (dir in this case)
A$ = A$ + |></canvas>|

html A$
a$ = "" ' clear a little bit of memory
return


'#########################
RICHTING:
'#########################

A = pin(0)
B = pin(1)
C = pin(2)
D = pin(3)

IF (A = 0) AND (B = 1) AND (C = 1) AND (D = 1) THEN
  wlog "Noord"
  dir = 0
END IF
IF (A = 0) AND (B = 0) AND (C = 1) AND (D = 1) THEN
  wlog "Noord-Oost"
  dir = 45
END IF
IF (A = 1) AND (B = 0) AND (C = 1) AND (D = 1) THEN
  wlog "Oost"
  dir = 90
END IF
IF (A = 1) AND (B = 0) AND (C = 0) AND (D = 1) THEN
  wlog "Zuid-Oost"
  dir = 135
END IF
IF (A = 1) AND (B = 1) AND (C = 0) AND (D = 1) THEN
  wlog "Zuid"
  dir = 180
END IF
IF (A = 1) AND (B = 1) AND (C = 0) AND (D = 0) THEN
  wlog "Zuid-West"
  dir = 225
END IF
IF (A = 1) AND (B = 1) AND (C = 1) AND (D = 0) THEN
  wlog "West"
  dir = 270
END IF
IF (A = 0) AND (B = 1) AND (C = 1) AND (D = 0) THEN
  wlog "Noord-West"
  dir = 315
END IF

refresh
return

Nog een andere poging: werkt ook.

'Gauge_minimaal_2.bas

PIN.MODE 0, INPUT, PULLUP
PIN.MODE 1, INPUT, PULLUP
PIN.MODE 2, INPUT, PULLUP
PIN.MODE 3, INPUT, PULLUP

dir = 0

onhtmlreload WEBPAGE

gosub   WEBPAGE
timer0 1000, RICHTING 'meet richting elke seconde
wait


'#########################
WEBPAGE:
'#########################
cls
jsexternal "/gauge.min.js" ' load javascript library for gauges
pause 500 ' gives time to the browser to import the library

A$ = ""
A$ = A$ + textbox$(dir)  + "<br>"      ' textbox
A$ = A$ + meter$(dir, 0, 360)+ "<br>"  ' meter

A$ = A$ + |<canvas data-type="radial-gauge"|
A$ = A$ + |        data-width="300"|
A$ = A$ + |        data-height="300"|
A$ = A$ + |        data-min-value="0"|
A$ = A$ + |        data-max-value="360"|
A$ = A$ + |        data-major-ticks="N,NE,E,SE,S,SW,W,NW,N"|
A$ = A$ + |        data-minor-ticks="22"|
A$ = A$ + |        data-ticks-angle="360"|
A$ = A$ + |        data-start-angle="180"|
A$ = A$ + |        data-stroke-ticks="false"|
A$ = A$ + |        data-highlights="false"|
A$ = A$ + |        data-color-plate="#33a"|
A$ = A$ + |        data-color-major-ticks="#f5f5f5"|
A$ = A$ + |        data-color-minor-ticks="#ddd"|
A$ = A$ + |        data-color-numbers="#ccc"|
A$ = A$ + |        data-color-needle="rgba(240, 128, 128, 1)"|
A$ = A$ + |        data-color-needle-end="rgba(255, 160, 122, .9)"|
A$ = A$ + |        data-value-box="true"|
A$ = A$ + |        data-animated-value="true"|
A$ = A$ + |        data-value-text-shadow="false"|
A$ = A$ + |        data-color-circle-inner="#fff"|
A$ = A$ + |        data-color-needle-circle-outer="#ccc"|
A$ = A$ + |        data-needle-circle-size="15"|
A$ = A$ + |        data-needle-circle-outer="false"|
A$ = A$ + |        data-animation-rule="linear"|
A$ = A$ + |        data-needle-type="line"|
A$ = A$ + |        data-needle-start="75"|
A$ = A$ + |        data-needle-end="99"|
A$ = A$ + |        data-needle-width="3"|
A$ = A$ + |        data-borders="true"|
A$ = A$ + |        data-border-inner-width="0"|
A$ = A$ + |        data-border-middle-width="0"|
A$ = A$ + |        data-border-outer-width="10"|
A$ = A$ + |        data-color-border-outer="#ccc"|
A$ = A$ + |        data-color-border-outer-end="#ccc"|
A$ = A$ + |        data-color-needle-shadow-down="#222"|
A$ = A$ + |        data-border-shadow-width="0"|
A$ = A$ + |        data-animation-target="plate"|
A$ = A$ + |        data-units="deg"|
A$ = A$ + |        data-title="DIRECTION"|
A$ = A$ + |        data-font-title-size="19"|
A$ = A$ + |        data-color-title="#f5f5f5"|
A$ = A$ + |        data-animation-duration="1500"|
A$ = A$ + |        data-var="dir"|  ' this is where the variable is defined (dir in this case)
A$ = A$ + |></canvas>|

html A$
a$ = "" ' clear a little bit of memory
return


'#########################
RICHTING:
'#########################

A = pin(0)
B = pin(1)
C = pin(2)
D = pin(3)

IF (A = 0) AND (B = 1) AND (C = 1) AND (D = 1) THEN
  wlog "Noord"
  dir = 0
END IF
IF (A = 0) AND (B = 0) AND (C = 1) AND (D = 1) THEN
  wlog "Noord-Oost"
  dir = 45
END IF
IF (A = 1) AND (B = 0) AND (C = 1) AND (D = 1) THEN
  wlog "Oost"
  dir = 90
END IF
IF (A = 1) AND (B = 0) AND (C = 0) AND (D = 1) THEN
  wlog "Zuid-Oost"
  dir = 135
END IF
IF (A = 1) AND (B = 1) AND (C = 0) AND (D = 1) THEN
  wlog "Zuid"
  dir = 180
END IF
IF (A = 1) AND (B = 1) AND (C = 0) AND (D = 0) THEN
  wlog "Zuid-West"
  dir = 225
END IF
IF (A = 1) AND (B = 1) AND (C = 1) AND (D = 0) THEN
  wlog "West"
  dir = 270
END IF
IF (A = 0) AND (B = 1) AND (C = 1) AND (D = 0) THEN
  wlog "Noord-West"
  dir = 315
END IF

refresh
return

Uiteindelijk krijg ik hulp van de grote Annex RDS chef cicciocb oftewel Francesco Ceccarella, de ontwikkelaar van Annex RDS. Dat resulteerde in onderstaand script. Het werkt, maar waarom het een wel en het ander niet werkt heb ik nog niet achterhaald. Ciccocb heeft trouwens nog een aantal aardige websites: o.a. hier en hier een YouTube kanaal.

'Windroos_test_ciccioB_1.bas

cls

A$ = ||
A$ = A$ + |<!DOCTYPE html>|
A$ = A$ + |<html lang="nl">|
A$ = A$ + |<head>|
A$ = A$ + |    <title>SVG Polygon Rotatie</title>|
A$ = A$ + |    <style>|
A$ = A$ + |        svg {|
A$ = A$ + |            border: 1px solid black;|
A$ = A$ + |        }|
A$ = A$ + |    </style>|
A$ = A$ + |</head>|
A$ = A$ + |<body>|
A$ = A$ + ||
A$ = A$ + |    <h1>Roteren van een SVG Polygon</h1>|
A$ = A$ + ||
A$ = A$ + |    <svg width="500" height="500">|
A$ = A$ + |        <polygon id="mijnPolygon" points="250,50 270,250 230,250" style="fill:red;stroke:black;stroke-width:1" />|
A$ = A$ + |        |
A$ = A$ + |        <circle cx="250" cy="250" r="5" fill="blue" />|
A$ = A$ + |        |
A$ = A$ + |    </svg>|
A$ = A$ + ||
A$ = A$ + |    <p>|
A$ = A$ + |        <button onclick="rotatePolygonByVariable()">Roteer de polygon</button>|
A$ = A$ + |    </p>|
A$ = A$ + ||
A$ = A$ + |</body>|
A$ = A$ + |</html>|

html A$

a$ = ""
A$ = A$ + |        let rotatieHoek = 0;|
A$ = A$ + |        function rotatePolygonByVariable() {|
A$ = A$ + |            rotatieHoek = (rotatieHoek + 45) % 360; |
A$ = A$ + |            const polygon = document.getElementById('mijnPolygon');|
A$ = A$ + |            const cx = 250;|
A$ = A$ + |            const cy = 250; |
A$ = A$ + |            const transformString = `rotate(${rotatieHoek}, ${cx}, ${cy})`;|
A$ = A$ + |            polygon.setAttribute('transform', transformString);|
A$ = A$ + |        }|

A$ = A$ + |        function rotateMe(rotatieHoek) {|
A$ = A$ + |            const polygon = document.getElementById('mijnPolygon');|
A$ = A$ + |            const cx = 250;|
A$ = A$ + |            const cy = 250; |
A$ = A$ + |            const transformString = `rotate(${rotatieHoek}, ${cx}, ${cy})`;|
A$ = A$ + |            polygon.setAttribute('transform', transformString);|
A$ = A$ + |        }|

jscript a$


' you can now control the position of the needle
'using jscall
pause 1000
jscall "rotateMe(30)"
pause 500
jscall "rotateMe(60)"
pause 500
jscall "rotateMe(90)"
pause 500
jscall "rotateMe(120)"
pause 500
jscall "rotateMe(150)"

Het advies dat ik gekregen heb, wat mij zeer aanspreekt omdat ik het zo ook wilde aanpakken, is om alles onder te brengen in aparte scripts. Een BASIC-script, een html-script, en een JavaScript-script. Dus daar ga ik vervolgens mee aan de slag.

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Deze site gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie gegevens worden verwerkt.