• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[FRAGE] Kamera - Position anfahren

Tropaion

New member
Hallo Com,
ich habe wieder mal ein Problem mit JS. Ich auf einem RasPi eine Kamera, für die ich eine Websteuerung mache.
Die Schwenkweite der Kamera ist -90 - 90°. Die Position wird mit einem PWM-Signal zwischen 0 und 100 angegeben.
Ansteueren kann man sie mit der Tastatur oder Buttons: Rauf/Runter/Links/Rechts. Jedesmal wenn eine Ansteuerung gedrückt wird zur zugehörigen Richtung -1 oder +1 gerechnet.
Die aktuelle Position steht in einer Json-Datei. Bei einer Richtungsänderung wird per JS die PHP-Datei aufgerufen die die Position übernehmen soll.

Das Problem dabei ist, das sich der Positionwert wenn man auf einen Button klickt willkürlich ändert. Ich überlege jetzt schon seit Stunden wo der Fehler liegen könnte, finde ihn aber nicht.
Ich bin mir jedoch ziemlich sicher das es an JS liegt. Ich hoffe sehr das mir jemand bei meinem Problem helfen kann ;)

Programm im Anhang.

Danke und Mfg,
Tropaion
 

Anhänge

  • camera.zip
    106,4 KB · Aufrufe: 3
*freigeschaltet*

Willkommen Tropaion!

Nur als Hinweis: ZIP's werden ungern runtergeladen. Fiddle oder online wäre besser.
 
Ich hab mir das mal angeschaut, aber da steht fast immer "Verbindung wird hergestellt..."
Manchmal geht es aber.

du musst xy_axis und z_axis auch ausherhalb der function funcMovePosition definieren. Das kann ich nirgendwo finden.

Auch sagt er mir manchmal das einige Funktionen nicht definiert sind. Komisch mal so mal so. :confused:

PS.: auf dem RPi läuft nodejs. Da sparst du dir den weg über php. Nodejs kann direkt PWM modulieren https://www.npmjs.com/package/rpio
 
Die Varibalen sind global definiert:
function namePosition(jd) {
/** Pointer für einzulesende Variablen */
xy_axis = (jd.xy_axis);
z_axis = (jd.z_axis);
}


Der Weg über PHP ist aber sicherer oder?
Ich verstehe nicht ganz wie das mit Nodejs laufen soll.
 
Tropaion schrieb:
Die Varibalen sind global definiert:
Ja schon... aber nur weil du sie ohne das Schlüsselwort var deklarierst.
In JavaScript entstehen globale Variablen auf dreierlei Weise:

-wenn sie nicht durch var deklariert wurden,
-bei einer Deklaration außerhalb aller Funktionen,
-bei einer Wertzuweisung innerhalb einer Funktion, ohne dass die Variable zuvor durch das Schlüsselwort var deklariert wurde.
-In JavaScript entstehen durch das Vergessen des Schlüsselworts var vor einem Variablennamen ungewollt globale Variablen – ein unangenehmes Fehlerpotential. So überlebt die Variable auch nach dem Verlassen der Funktion und wenn die Funktion häufig aufgerufen wird, entsteht u.U. ein Speicherleck.
Javascript Globale und lokale Variablen


Erstell die Variablen doch mal außerhalb einer Funktion gleich ganz am Anfang vom Dokument. Ist zwar auch nicht schön aber fürs erste.

Tropaion schrieb:
Der Weg über PHP ist aber sicherer oder?
Ja warum nicht. Aber der Weg an sich ist doof wenn man andere Möglichkeiten hat. Du hast den Browser->dann php->dann komm ->/dev->dann erst die Ausgabe.
Mit nodejs fallen drei dinge weg. PHP, Apache und /dev/blablabla.
Mit nodejs erstellst dir einen http Server für die Webseite via express.js und zugleich kannst du via express.js die Ajax Requests verarbeiten. Dann läuft node-gpio los und fertig.
So ungefähr.
Was du nun in node-gpio einstellen musst gilt es auszuprobieren. Habe selber das Modul nicht installiert.


Tropaion schrieb:
Ich verstehe nicht ganz wie das mit Nodejs laufen soll.
Bevor du jetzt loslegst mit nodejs probiere erst mal den php weg.
 
Zuletzt bearbeitet:
Ok, das mit dem Speicherleck wusste ich nicht. Habe es bist jetzt immer so gemacht und es ging einwandfrei.
das speicherleck kann nur entstehen, wenn du jedesmal neue objekte erzeugst.
ob du die variable in der funktion ohne var deklarierst oder global mit var ist in beiden fällen das selbe, aber in beiden fällen nicht gut.

du hast mit deiner globalen variable aber ein problem in funcCurrentPosition(); im onload. dort wird in den meisten fällen xy_axis und z_axis nicht definiert sein, da der request von funcUpdatePosition() zwar vor onload gestartet wird, aber vermutlich erst nach onload eintrifft, da deine seite ja sonst nichts zu laden hat. in jedem fall ist es aber immer möglich, daß dieses irgendwann mal passiert.

etwas ähnliches dürfte auch dein eigentliches problem sein.
in funcMovePosition rufst du wieder als erstes funcUpdatePosition() welche einen request startet und die position ausliesst.
dann setzt du xy_axis und z_axis
und startest einen weiteren request, welcher die position setzt

welcher request hier wann auf dem server ankommt ist schon mal nicht definiert. wann die antwort von funcUpdatePosition kommt auch nicht.

der rest ist jetzt nur eine nebenbemerkung, die nicht stimmen muss, da ich deinen aufbau nicht kenne.
aber da du die kamera ja vermutlich mit einem servo steuerst, und Pi-blaster (hab mir das nicht genau angesehen) bei einem wert vom 1 den ausgang immer auf high zieht, bei 0 immer auf low, ist das was du da generierst kein brauchbares signal für einen standardservo.
um auf nummer sicher zu gehen solltest du signale mit 20ms periodendauer erzeugen. dann entspricht ein high-puls von 1ms dem servo-min und einer von 2ms dem servo-max.
damit sollte dein wert den du Pi-blaster übergibst sich zw. 0,05 und 0,1 bewegen. also 0,05 sind -90° und 0,1 sind 90°.
du übergibst aber einen wert zw 0 und 1. ich denke das ist falsch, kann mich aber auch irren.
 
Ok, ich denke das mit den Variablen habe ich so halbwegs verstanden.
Jedoch weis ich trotzdem nicht wie ich das am besten lösen kann.
Hast du vll dazu ein paar Vorschläge?

Und der Wert muss zwischen 0 und 1 sein, das stimmt schon, funktioniert ja auch wenn ich es in der Shell eingebe ;)
 
Jedoch weis ich trotzdem nicht wie ich das am besten lösen kann.
pack den code, der auf funcUpdatePosition() warten muss in ein callback welches du an funcUpdatePosition() übergibst und im onreadystatechanged aufrufst


Und der Wert muss zwischen 0 und 1 sein, das stimmt schon, funktioniert ja auch wenn ich es in der Shell eingebe ;)
wenn du 1 übergibst und dann 0,5 ändert sich die position?
 
tsseh schrieb:
um auf nummer sicher zu gehen solltest du signale mit 20ms periodendauer erzeugen. dann entspricht ein high-puls von 1ms dem servo-min und einer von 2ms dem servo-max.
Um auf Nummer sicher zu gehen würde ich erst mal das Oszilloskop anwerfen:p

Meinst du Tropaion hat verstanden was du da redest?

Hm "ascii art" funzt nicht im Forum mist.
dann doch ein video:
https://www.youtube.com/watch?v=xwZyfOnS8dk

Das was du da bei ca. 1:50min siehst ist das was tsseh mein mit " high-puls von 1ms zu high-puls von 2ms".

tsseh schrieb:
umdas speicherleck kann nur entstehen, wenn du jedesmal neue objekte erzeugst.
Das würde ja bedeuten wenn man im requestAnimationframe oder web audio Scriptprocessor alle x sec ein TypedArray erzeugt ensteht ein speicherleck. Ja oder nein?
Ich hab aktuell das Problem das das 4te TypedArray im onaudioprocess Event nicht mehr leer ist, da sind beim erstellen schon Werte drinnen [0.9998888,0.99914879, usw] meist 0.99 irgendwas.
Hat das damit zutun? Das Problem ist bei allen Browsern, selbst bei Windows 10 EDGE. Selbst der Arraybuffer+DataView selbes Problem. Array nicht leer.
 
Zuletzt bearbeitet:
Das würde ja bedeuten wenn man im requestAnimationframe oder web audio Scriptprocessor alle x sec ein TypedArray erzeugt ensteht ein speicherleck. Ja oder nein?
jein, kommt darauf an, wer alles eine referenz auf das objekt hält.

Ich hab aktuell das Problem das das 4te TypedArray im onaudioprocess Event nicht mehr leer ist, da sind beim erstellen schon Werte drinnen [0.9998888,0.99914879, usw] meist 0.99 irgendwas.
Hat das damit zutun?
nee, dann wäre irgendwann dein speicher voll und der konstrucktor schmeissst eine exception
 
Es ist bei mir so(wenn wir schon mal dabei sind):
Ich habe ein Ringbuffer im scriprocessor oder eher ein Jitterbuffer. Vom Scriprocessor der durch 2048 Samples läuft gehe ich in einen Resampler und danach in die Fensterfunktion, das Ende ist die FFT+Visualisierung.

Die pcm Daten kommen von einer websocket Verbindung. Wenn ich allerdings gar keine Daten bringe steht im Ringbuffer überall [0,0,0,0,0,]. Der Resampler macht sein dienst, Array größer oder kleiner auch danach überall [0,0,0,0,]. Jetzt komme die Samples zu den Fensterfunktionen und da ergibt eine Multiplikation mit 0 eben das von mir zuvor erwähnte (0.9998888,0.99914879, usw] )
Hier das Hamming Fenster
Code:
function windowHamming(sampleBuffer){
	var l = sampleBuffer.length;
	for(var i=0; i<l;i++){
		sampleBuffer[i] *= 0.54 - 0.46 * Math.cos(Math.PI*2 * i / (l - 1));
	}
	self.postMessage({ "buffer" : sampleBuffer });
};
Vor der for Schleife ist sampleBuffer noch 0,0,0,0 danach zeugs (anders kann man es nicht ausdrücken). eine Multiplikation mit 0 kann nur 0 ergeben.
Wie du an self.postMessage erkennst läuft das ganze im WebWorker ab. Es spielt keine Rolle ob Webwoker oder nicht, Ergebnis ist immer das gleiche.
Das sieht visuell so aus:
Zwischenablage01.png
Das Ergebnis ist auf Allen Rechnern mit allen Browsern, mit allen Fensterfunktion immer das gleiche!
Das ganze macht mich alle.

Später viel später werde ich noch einen eigenen Thread dazu aufmachen. Ohne Test link kann man das sowieso nicht nachvollziehen.

Hast du ein Vermutung was das Problem verursacht? Ist ECMA am ende mit zuviel DSP?

Ich möchte ja auch nicht so sehr von Tropaion's Thema abschweifen.. hätte ja was mit dem Speicherleck zutun haben können.
 
Zuletzt bearbeitet:
Da steht ganz sicher 0 drinnen wenn ich ein console.log vor der for schleife mache und danach ein console.log...
Das Rechteck Fenster mit *= 1, geht ja komischer weiße. Bei Linux Rechnern habe ich die Beobachtung gemacht das der Ominöse Träger bei 10Hz anfängt bei Windows 50Hz.
mac not tested. Auch sieht der Ominöse 50Hz Träger unterm Oszilloskop nicht aus wie ein Sinus, sondern wie ein 5 die man 90° nach links gekippt hat. Das erklärt die Oberwellen.
Erinnert mich ein Softstarter: https://www.youtube.com/watch?v=6bTHTuJ45Bs
 
Zuletzt bearbeitet:
Noch mal zu meinem Problem ;)
Ich kenne callback mit onclick und so, also wenn der User eine Eingabe macht.
Aber wie soll das mit eine Funktion gehen? Ich komme nicht dahinter :D
Das ich callback richtig verstehe:
Wenn eine Funktion fertig ist, wird ein Wert zurückgegeben der irgendetwas auslöst, stimmt das?

Danke und Mfg,
Tropaion
 
also 1. denke ich, dass es (so wie es jetzt ist) sowiso keine gute idee ist funcUpdatePosition in funcMovePosition aufzurufen.
das ganze ist ja nur für denn fall notwendig, dass mindestens 2 leute parallel an der position rumspielen. dass sollte meiner meinung nach ganz verhindert werden.
selbst, wenn du es nicht verhindern willst, ist es so eigenartig,
angenommen 2 user sind mit dem server verbunden.
beide sehen beim öffnen der seite durch das funcUpdatePosition im onload eine position 0°
user 1 dreht die kamera auf position -90°
user 2 dreht irgendwann später um +2°
er sieht immer noch die position 0° aus onload und erwartet eigentlich, dass sich die kamera auf position +2° bewegt, wenn er 0° in der anzeige sieht und einmal den button + drückt
tatsächlich aber dreht sich die kamera aber auf -88°, da du in funcMovePosition erst die aktuelle position vom server liest(also -90°) und dann deine +2° damit verrechnest
Ich kenne callback mit onclick und so, also wenn der User eine Eingabe macht.
in funcUpdatePosition ist namePosition ein callback
in funcMovePosition kannst du am ende dem xmlhttp-objekt ein callback mitgeben https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/onreadystatechange.

Aber wie soll das mit eine Funktion gehen?
ein callback ist eine eine funktion, welche aufgerufen wird, wenn ein event gefeuert wird. z.b. wenn kannst du auf button klickst wird das click-event gefeuert. hast du dem button vorher ein callback als eventhandler zugewiesen(button.onclick = function(){...}) wird dieses callback dann aufgerufen. bei deinem xmlhttp-objekt ist es das gleiche. dessen onreadystatechange wird immer aufgerufen, wenn sich der state des objektes ändert. bei readyState 4 ist die antwort vom server eingetroffen. in funcUpdatePosition machst du das über jquery, welches auch nichts anderes macht, als dein callback namePosition ganz am ende an seinem xmlhttp-objekt an onreadystatechange zuzuweisen.

du müsstest also etwas machen wie:
Code:
function funcUpdatePosition(cb)
{
  $.getJSON(urlPosition, function (data)
  {
    namePosition(data);
    cb(data);
  });
}
funcUpdatePosition müsstest du dann mit callback aufrufen
im index.html
Code:
<script>
  window.onload = function()
  {
     funcUpdatePosition(funcCurrentPosition);
  };
</script>
in funcMovePosition
Code:
function funcMovePosition(varDirection, varValue)
{
  var getCB = function(varDirection, varValue)
  {
    return function ()
    {
      calcPosition(varDirection, varValue);
    };
  };
  funcUpdatePosition(getCB(varDirection, varValue));
}
// den rest deiner funcMovePosition packst du in die funktion calcPosition
function calcPosition(varDirection, varValue)
{
  varValue = Math.abs(varValue);
  switch(varDirection) {
  ...
  /** Ausgabe aktualisieren */  
  funcCurrentPosition();
}
dann musst du noch dafür sorgen, dass solange funcMovePosition (asynchron)läuft der links/rechts/hoch/runter button nicht nochmals gedrückt wird
das kannst du machen, indem du in funcMovePosition als 1. die buttons disablest und diese erst wieder enablest, wenn die daten am server angekommen sind also im onreadystatechange deines xmlhttp-objektes
 
"pack den code, der auf funcUpdatePosition() warten muss in ein callback welches du an funcUpdatePosition() übergibst und im onreadystatechanged aufrufst"

Jetzt muss ich nochmal nachfragen. Habe ich mit der Aussage jetzt ein weilchen beschäftigt.
Im Grunde sieht ja so aus?
onreadystatechanged gibt irgendwas zurück und löst funcUpdate aus.

Jedoch habe ich ehrlich gesagt keine Ahnung wie das aussehen soll. Kann mir das bitte jemand etwas genauer erläutern?

Mfg und vielen Dank,
Tropaion
 
Jetzt muss ich nochmal nachfragen. Habe ich mit der Aussage jetzt ein weilchen beschäftigt.
dann sieh dir den code aus #17 dazu an, wenn es dann nicht klar wird, kann ich dir auch nicht weiter helfen

onreadystatechanged gibt irgendwas zurück und löst funcUpdate aus.
onreadystatechanged gibt nichts zurück, sondern ist eine eigenschaft an deinem XmlHttpRequest-objekt, wo man ein callback hinterlegen kann.
wenn man das macht, ruft das XmlHttpRequest-objekt dieses callback auf.
funcUpdatePosition ruft getJSON auf. das ist eine jquery-funktion, die auch ein XmlHttpRequest-objekt nutzt um einen request zu starten. getJSON übergibst du das callback als 2. parameter. du musst also den code, der darauf wartet, dass die aktuelle position gelesen wurde als 2. parameter an getJSON übergeben.
in #17
Code:
$.getJSON(urlPosition, function (data)
  {
    namePosition(data);
    cb(data);
  });
hier wird getJSON eine funktion übergeben, die namePosition aufruft und dein callback
jetzt musst du nur noch funcUpdatePosition jedesmal mit dem callback als parameter aufrufen

Jedoch habe ich ehrlich gesagt keine Ahnung wie das aussehen soll. Kann mir das bitte jemand etwas genauer erläutern?
#17
 
Zurück
Oben