MasT3r-A Geschrieben February 10, 2015 at 11:31 Geschrieben February 10, 2015 at 11:31 Hallo Tinkerfreunde! Entweder bin ich zu doof oder ich bekomme es einfach nicht hin. Leider habe ich auch noch keinen Eintrag dazu gefunden. Ich möchte einen Kreuztisch mit 2 Achsen (X und Y) aufbauen. Dafür habe ich einen Master und 2x den StepperBrick. Meine Problem ist, ich bekomme es nicht hin es so zu programmieren (C#) das ich beide Stepper separat ansteuern kann. Irgendwas mache ich falsch bzw. hab keine Ahnung wie ich es richtig machen soll. StepperBrick 1 hängt an Position 1 und StepperBrick 2 hängt an Position 2 im Stack (Pos. 0 ist der Master) Kann mir jemand weiterhelfen? Würde mich über jeden Beitrag freuen! Danke Artur Zitieren
Nic Geschrieben February 10, 2015 at 11:53 Geschrieben February 10, 2015 at 11:53 Das sind zu wenige Informationen. Als Einstieg würde ich erstmal die Beispiele zum Stepper aus der API/Doku ausprobieren, später erst die eigene Anwendung, anschl. poste hier deinen Source-Code. Und prüfe ob jeder Stepper-Brick einzeln (und mal mit Master) funktioniert um Hardware Versagen einer oder mehr Teile auszuschließen. Dann den kompletten Stack Aufbau beschreiben einschl. Stromversorgung etc.. Es wurde hier im Forum schon eine mehrachsige CNC Fräse vorgestellt: http://www.tinkerunity.org/forum/index.php/topic,863.0.html Zitieren
MasT3r-A Geschrieben February 10, 2015 at 11:59 Autor Geschrieben February 10, 2015 at 11:59 Also die StepperBricks funktionieren einzeln wunderbar.. Achsen verfahren. Der Aufbau ist nicht das Problem! Stromversorgung auch nicht. Ich habe nach dem Robusten Ansatz programmiert mit der [EnumerateCB]-Funktion. Die Schwierigkeiten sind aufgetreten als ich dann auf einmal 2xStepperbricks am Master habe. Die Zuordnung kann dann ja nur über die Abfrage der Position im Stack stattfinden.. dies habe aber noch nicht im Griff .. ich denke da liegt auch das Problem! =( Zitieren
remotecontrol Geschrieben February 10, 2015 at 13:04 Geschrieben February 10, 2015 at 13:04 Dein konkretes Problem hast Du aber immernoch nicht genauer beschrieben. Wenn Du den Enumerate verwendest, dann bekommst Du darüber doch die Position im Stack (0,1,2) und UID und den Typ (Master, Stepper) etc.. Damit kannst Du doch alles zuordnen was Du brauchst und mit der richtigen UID den einen oder anderen Stepper steuern. Und Dein Problem ist ... ? Zitieren
Nic Geschrieben February 10, 2015 at 13:08 Geschrieben February 10, 2015 at 13:08 Wenn dein Source-Code geheim bleiben soll können wir dir nicht helfen. Die Schwierigkeiten sind aufgetreten als ich dann auf einmal 2xStepperbricks am Master habe. Die Zuordnung kann dann ja nur über die Abfrage der Position im Stack stattfinden.. dies habe aber noch nicht im Griff .. ich denke da liegt auch das Problem! Ich verstehe nur Bahnhof. Kannst du das folgende Beispiel ausführen, Parameter wie Uid, port etc. deiner Umgebung angepasst ? http://www.tinkerforge.com/de/doc/Software/Bricks/Stepper_Brick_CSharp.html#callback Warum sollte es ein Problem sein, da noch eine 2.Stepper Instanz zu erzeugen ? Zitieren
MasT3r-A Geschrieben February 10, 2015 at 13:17 Autor Geschrieben February 10, 2015 at 13:17 Also mein Sourcecode ist nicht geheim.. namespace CrazyStuff { public partial class Form1 : Form { private static string HOST = "localhost"; private static int PORT = 4223; private static IPConnection ipcon = null; private static BrickStepper X_Achse = null; private static BrickStepper Y_Achse = null; private delegate void SetuidTextBoxCallback(string value); private delegate void SetconnectedUIDTextBoxCallback(string value); private delegate void SetpositionTextBoxCallback(string value); private delegate void SetdeviceidentifierTextBoxCallback(string value); private delegate void GetStackVoltageLabelCallback(string value); private delegate void GetRemainingStepsLabelCallback(string value); private delegate void GetActualPositionLabelCallback(string value); private delegate void GetCurrentConsumptionLabelCallback(string value); public Form1() { InitializeComponent(); // Create IP Connection ipcon = new IPConnection(); // Register IP Connection callbacks ipcon.EnumerateCallback += EnumerateCB; ipcon.Connected += ConnectedCB; // Connect to brickd, will trigger cb_connected ipcon.Connect(HOST, PORT); ipcon.Enumerate(); } // Callback handles device connections and configures possibly lost // configuration of lcd and temperature callbacks, backlight etc. private void EnumerateCB(IPConnection sender, string UID, string connectedUID, char position, short[] hardwareVersion, short[] firmwareVersion, int deviceIdentifier, short enumerationType) { if (enumerationType == IPConnection.ENUMERATION_TYPE_CONNECTED || enumerationType == IPConnection.ENUMERATION_TYPE_AVAILABLE) { SetdeviceidentifierTextBox(Convert.ToString(deviceIdentifier)); SetpositionTextBox(Convert.ToString(position)); SetconnectedUIDTextBox(Convert.ToString(connectedUID)); SetuidTextBox(Convert.ToString(UID)); if (deviceIdentifier == BrickStepper.DEVICE_IDENTIFIER) { if (position == 1) { X_Achse = new BrickStepper(UID, ipcon); X_Achse.AllData += AllDataX; } else if (position == 2) { Y_Achse = new BrickStepper(UID, ipcon); //Y_Achse.AllData += AllDataY; noch nicht programmiert } } } } private void AllDataX(BrickStepper sender, int currentVelocity, int currentPosition, int remainingSteps, int stackVoltage, int externalVoltage, int currentConsumption) { GetStackVoltageLabel(Convert.ToString(externalVoltage / 1000) + "V"); GetRemainingStepsLabel(Convert.ToString(remainingSteps)); GetActualPositionLabel(Convert.ToString(currentPosition)); GetCurrentConsumptionLabel(Convert.ToString(currentConsumption) + "mA"); } //############################################################################################################ Callback handles reconnection of IP Connection private void ConnectedCB(IPConnection sender, short connectReason) { // Enumerate devices again. If we reconnected, the Bricks/Bricklets // may have been offline and the configuration may be lost. // In this case we don't care for the reason of the connection ipcon.Enumerate(); } //############################################################################################# private void SetdeviceidentifierTextBox(string value) { // Invoke nötig? if (deviceIdentifier.InvokeRequired) { // Invoke nötig deviceIdentifier.Invoke((MethodInvoker)delegate { deviceIdentifier.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar deviceIdentifier.Text = value; } } //############################################################################################# private void SetpositionTextBox(string value) { // Invoke nötig? if (position.InvokeRequired) { // Invoke nötig position.Invoke((MethodInvoker)delegate { position.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar position.Text = value; } } //############################################################################################# private void SetconnectedUIDTextBox(string value) { // Invoke nötig? if (connected_uid.InvokeRequired) { // Invoke nötig connected_uid.Invoke((MethodInvoker)delegate { connected_uid.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar connected_uid.Text = value; } } //############################################################################################# private void SetuidTextBox(string value) { // Invoke nötig? if (uid.InvokeRequired) { // Invoke nötig uid.Invoke((MethodInvoker)delegate { uid.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar uid.Text = value; } } //############################################################################################# private void GetCurrentConsumptionLabel(string value) { // Invoke nötig? if (lbl_current_consumption.InvokeRequired) { // Invoke nötig lbl_current_consumption.Invoke((MethodInvoker)delegate { lbl_current_consumption.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar lbl_current_consumption.Text = value; } } //############################################################################################# private void GetActualPositionLabel(string value) { // Invoke nötig? if (lbl_akt_position.InvokeRequired) { // Invoke nötig lbl_akt_position.Invoke((MethodInvoker)delegate { lbl_akt_position.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar lbl_akt_position.Text = value; } } //############################################################################################# private void GetRemainingStepsLabel(string value) { // Invoke nötig? if (lbl_rem_steps.InvokeRequired) { // Invoke nötig lbl_rem_steps.Invoke((MethodInvoker)delegate { lbl_rem_steps.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar lbl_rem_steps.Text = value; } } //############################################################################################# private void GetStackVoltageLabel(string value) { // Invoke nötig? if (lbl_ext_voltage.InvokeRequired) { // Invoke nötig lbl_ext_voltage.Invoke((MethodInvoker)delegate { lbl_ext_voltage.Text = value; }); } else { // Kein Invoke nötig - Vorgang sicher durchführbar lbl_ext_voltage.Text = value; } } } } Also wenn ich das Programm starte dann wird in meiner Windows Form in den Invoked-Textboxen angezeigt: Connected_UID UID Position deviceIdentifier Mein Problem ist einfach (denke ich) das ich die Position nicht korrekt abfrage und dann den Stepper nicht richtig zuweise. Danke schonmal für eure Mühe. Zitieren
MasT3r-A Geschrieben February 10, 2015 at 13:39 Autor Geschrieben February 10, 2015 at 13:39 Ist dieser Teil überhaupt richtig so? // Callback handles device connections and configures possibly lost // configuration of lcd and temperature callbacks, backlight etc. private void EnumerateCB(IPConnection sender, string UID, string connectedUID, char position, short[] hardwareVersion, short[] firmwareVersion, int deviceIdentifier, short enumerationType) { if (enumerationType == IPConnection.ENUMERATION_TYPE_CONNECTED || enumerationType == IPConnection.ENUMERATION_TYPE_AVAILABLE) { if (deviceIdentifier == BrickStepper.DEVICE_IDENTIFIER) { if (position == 1) { X_Achse = new BrickStepper(UID, ipcon); X_Achse.AllData += AllDataX; } else if (position == 2) { Y_Achse = new BrickStepper(UID, ipcon); Y_Achse.AllData += AllDataY; } } } } Zitieren
Nic Geschrieben February 10, 2015 at 13:51 Geschrieben February 10, 2015 at 13:51 Nicht über Position fragen, sondern der Enum Callback gibt dir auch die Uid zurück, nur diese beschreibt eindeutig ob es um den Stepper Brick für X- oder Y-Achse geht. Schau mal was dir der BrickV zurückgibt, so prüfe ich immer ob die Uid "c3po" Stepper 1 oder "r2d2" Stepper 2 ist usw. Zitieren
MasT3r-A Geschrieben February 10, 2015 at 13:59 Autor Geschrieben February 10, 2015 at 13:59 ok .... hab das nu mit der abfrage der UID gemacht.. und jetzt klappt es .. unglaublich... hmm großes Dankeschön! Grüße Zitieren
photron Geschrieben February 10, 2015 at 14:02 Geschrieben February 10, 2015 at 14:02 MasT3r-A, dein Problem ist, dass position vom Typ char ist. Du musst also nicht mit 1 und 2, sondern mit '1' und '2' vergleichen musst. Zitieren
MasT3r-A Geschrieben February 10, 2015 at 14:14 Autor Geschrieben February 10, 2015 at 14:14 Das mit '1' und '2' hab ich probiert .. hab irgendwie nicht funktioniert.. habs nur so gemacht.. und siehe da Alldata wird für beide Achsen alle 500ms angezeigt.. if (deviceIdentifier == BrickStepper.DEVICE_IDENTIFIER) { if (UID == "69imVq") { X_Achse = new BrickStepper(UID, ipcon); X_Achse.AllData += AllDataX; X_Achse.SetAllDataPeriod(500); } else if (UID == "6dLjnF") { Y_Achse = new BrickStepper(UID, ipcon); Y_Achse.AllData += AllDataY; Y_Achse.SetAllDataPeriod(500); } } Zitieren
Nic Geschrieben February 10, 2015 at 14:32 Geschrieben February 10, 2015 at 14:32 Dann lass es so, wenn es jetzt klappt. Über die Uid ist der generelle Weg, da jedes Bauteil seine eigene Identifikation Nr hat, unabh. welche Pos. es im Stack einnimmt. Und das interessiert i.d.R. nicht. ich prüfe immer über die Uid und device Type. Zitieren
remotecontrol Geschrieben February 10, 2015 at 18:59 Geschrieben February 10, 2015 at 18:59 Den Ansatz, das in diesem Fall über die Position im Stack zu machen finde ich eigentlich gut. Die Brick Reihenfolge im Stack kann man leicht erkennen (leichter als die Bricklet Ports) und wenn man den Stack zerlegt, um z.B. neue Firmware draufzuspielen, muss man nicht drauf achten, ob man danach den richtigen Stepper an Anschluss X oder Y hat. Mich wundert nur, dass die Abfrage nicht funktioniert hat, sollte eigentlich gehen. Zitieren
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.