lakai_- Geschrieben September 28, 2016 at 10:12 Geschrieben September 28, 2016 at 10:12 Hallo zusammen, ich habe folgendes Problem bei der Programmierung eines Gaspedals mit C++: sobald meine Funktion über einen Callback (des Dual Button Bricklet) aufgerufen wird, möchte ich bei Betätigen eines Buttons jeweils einen bestimmten Wert auf eine Variable speichern. Wird der linke Buttons betätigt soll auf die Variable der Wert 1 und bei der rechten Taste der Wert 2 gespeichert werden. In der main-Funktion möchte ich nun den Wert der Variable abfragen und somit in bestimmte if-Schleifen übergehen. Mein Problem ist, dass der Wert der Variable nicht in der main-Funktion enthalten ist. Kann ich globale Variablen verwenden, damit ich der Variable in der Funktionen einen Wert zuweisen kann und diesen in der main-Funktion abfragen? Oder kann ich eine Variable mit der Funktion über zum Beispiel einen Zeiger mit zurück geben? Am Besten eine recht simple Lösung, die einfach der Funktionalität dient. Könnte mir jemand dabei ein Beispiel mit C++ geben bitte. Mein Code in der Funktion sieht ungefähr so aus (Dies sind nur Auszüge): void cb_state_changed(uint8_t button_l, uint8_t button_r, uint8_t led_l, uint8_t led_r, void *user_data) { (void)led_l; // avoid unused parameter warning (void)led_r; // avoid unused parameter warning (void)user_data; // avoid unused parameter warning if(button_l == DUAL_BUTTON_BUTTON_STATE_PRESSED) { printf("Left button pressed\n"); knopf = 1; } else { //printf("Left button released\n"); } Im Hauptprogramm sieht die if-Schleife wie folgt aus: if(knopf ==1){ rotary_poti_register_callback(&rp, ROTARY_POTI_CALLBACK_POSITION,(void *) cb_position, &servo); //Position-Callback für cb_funktion registrieren rotary_poti_set_position_callback_period(&rp, 50); //Periode für Positions-Callback auf 50ms setzen } Wäre echt super wenn mir jemand helfen könnte, da ich relativ schnell eine Lösung für das Problem benötige. Vielen Dank für eure Antworten! LG Max Zitieren
photron Geschrieben September 28, 2016 at 12:18 Geschrieben September 28, 2016 at 12:18 Du kannst das über einen globale Variable machen. Du kannst aber auch den User Data Pointer der Callbacks nutzen: #include <stdio.h> #include "ip_connection.h" #include "bricklet_dual_button.h" #define HOST "localhost" #define PORT 4223 #define UID "XYZ" // Change XYZ to the UID of your Dual Button Bricklet // Callback function for state changed callback void cb_state_changed(uint8_t button_l, uint8_t button_r, uint8_t led_l, uint8_t led_r, void *user_data) { (void)led_l; // avoid unused parameter warning (void)led_r; // avoid unused parameter warning // EDIT: Pointer auf lokale Variable in main() aus User Data Pointer casten int *knopf = (int *)user_data; if(button_l == DUAL_BUTTON_BUTTON_STATE_PRESSED) { printf("Left button pressed\n"); // EDIT: 1 an lokale Variable in main() zuweisen, dazu Pointer dereferenzineren *knopf = 1; } else { printf("Left button released\n"); // EDIT: 0 an lokale Variable in main() zuweisen, dazu Pointer dereferenzineren *knopf = 0; } if(button_r == DUAL_BUTTON_BUTTON_STATE_PRESSED) { printf("Right button pressed\n"); } else { printf("Right button released\n"); } printf("\n"); } int main(void) { // Create IP connection IPConnection ipcon; ipcon_create(&ipcon); // Create device object DualButton db; dual_button_create(&db, UID, &ipcon); // Connect to brickd if(ipcon_connect(&ipcon, HOST, PORT) < 0) { fprintf(stderr, "Could not connect\n"); return 1; } // Don't use device before ipcon is connected // EDIT: lokale Variable anlegen int knopf = 0; // Register state changed callback to function cb_state_changed dual_button_register_callback(&db, DUAL_BUTTON_CALLBACK_STATE_CHANGED, (void *)cb_state_changed, // EDIT: Pointer auf lokale Variable als User Data Pointer an den Callback geben (void *)&knopf); printf("Press key to exit\n"); getchar(); dual_button_destroy(&db); ipcon_destroy(&ipcon); // Calls ipcon_disconnect internally return 0; } Zitieren
lakai_- Geschrieben September 30, 2016 at 06:35 Autor Geschrieben September 30, 2016 at 06:35 Habe jetzt die Variante mit den User Data Pointer der Callbacks probiert, aber er übernimmt die Werte der Variable aus den Funktionen nicht in der main-Funktion. Habe meinen Code bis auf den If-Schleifen-Inhalt angefügt. Habe getestet die Variable Knopf auf den Wert 1 oder 2 zu initialisieren, dann wird die jeweilige Schleife durchlaufen. Somit muss der Fehler wohl bei der Übergabe des Wertes von der Callback-Funktion an die main-Funktion passieren. #include <stdio.h> #include "ip_connection.h" #include "bricklet_dual_button.h" #include "brick_servo.h" #include "bricklet_rotary_poti.h" #define HOST "localhost" #define PORT 4223 #define UID "mJ5" #define UID_Servo "6Jo3Pm" #define UID_Poti "y8F" int16_t servo_position; int16_t servo_overflow; void cb_position(int16_t position,void *user_data) { Servo *servo = (Servo *)user_data; servo_position = 9000*position/100; servo_set_position(servo, 1, servo_position); printf("%i", servo_position); } void cb_position1(int16_t position,void *user_data) { Servo *servo = (Servo *)user_data; servo_overflow = 0; servo_position = 9000*position/100; if (servo_position <= 50) { servo_set_position(servo, 1, servo_position); printf("%i", servo_position); } else { servo_set_position(servo, 1, servo_overflow); } } void cb_state_changed(uint8_t button_l, uint8_t button_r, uint8_t led_l, uint8_t led_r, void *user_data) { (void)led_l; (void)led_r; (void)user_data; int *knopf = (int *)user_data; if(button_l == DUAL_BUTTON_BUTTON_STATE_PRESSED) { printf("Left button pressed\n"); *knopf = 1; led_r = 2; led_r = 3; } else { //printf("Left button released\n"); } if(button_r == DUAL_BUTTON_BUTTON_STATE_PRESSED) { printf("Right button pressed\n"); *knopf = 2; led_r = 2; led_r = 3; } else { //printf("Right button released\n"); } printf("\n"); } int main(void) { // Create IP connection IPConnection ipcon; ipcon_create(&ipcon); // Create device object DualButton db; dual_button_create(&db, UID, &ipcon); Servo servo; //Device object für Servo erstellen servo_create(&servo, UID_Servo, &ipcon); RotaryPoti rp; //Device object für Drehpotentiometer erstellen rotary_poti_create(&rp, UID_Poti, &ipcon); // Connect to brickd if(ipcon_connect(&ipcon, HOST, PORT) < 0) { fprintf(stderr, "Could not connect\n"); return 1; } // Don't use device before ipcon is connected int knopf = 0; // Register state changed callback to function cb_state_changed dual_button_register_callback(&db, DUAL_BUTTON_CALLBACK_STATE_CHANGED, (void *)cb_state_changed, (void *)&knopf); if(knopf ==1){ ... } if(knopf ==2){ ... } servo_set_output_voltage(&servo, 7400); servo_set_velocity(&servo, 1, 65535); servo_set_acceleration(&servo,1, 65535); servo_set_position(&servo, 1, -9000); servo_enable(&servo, 1); printf("%i\n",knopf); printf("Press key to exit\n"); getchar(); dual_button_destroy(&db); servo_disable(&servo, 1); servo_destroy(&servo); ipcon_destroy(&ipcon); // Calls ipcon_disconnect internally return 0; } Ich wäre für jede Hilfe wirklich sehr dankbar!!! LG Max Zitieren
photron Geschrieben September 30, 2016 at 07:15 Geschrieben September 30, 2016 at 07:15 Das liegt daran, dass dual_button_register_callback() returned lange bevor du den Knopf wirklich drückst. dual_button_register_callback() legt nur fest welche Funktion aufgerufen werden soll, wenn ein bestimmter Callback auftritt. dual_button_register_callback() wartet nicht darauf, dass der Callback auftritt und deine Funktion aufgerufen wird. Die main() Funktion wartet in der getchar() Funktion während cb_state_changed() Aufgerufen wird. Du kannst getchar() durch ein while (true) Schleife ersetzen und dort regelmäßig alle 10 Millisekunden deine knopf Variable prüfen. while (true) { if (knopf == 1) { ... } if (knopf == 2) { ... } usleep(10000); // Warte 10 Millisekunden } Für usleep muss du noch unistd.h includen. Falls du auf Windows bist, musst du usleep(10000); durch Sleep(10); ersetzen und windows.h includen. Zitieren
markus5766h Geschrieben October 4, 2016 at 15:05 Geschrieben October 4, 2016 at 15:05 ... Du kannst getchar() durch ein while (true) Schleife ersetzen und dort regelmäßig alle 10 Millisekunden deine knopf Variable prüfen. ... Für usleep muss du noch unistd.h includen. Falls du auf Windows bist, musst du usleep(10000); durch Sleep(10); ersetzen und windows.h includen. wird aber nie wirklich 10ms sein : Windows selbst gibt eine min. Sleep-Step von 15..16ms an, da die Funktion Sleep nicht genau genug arbeitet, wer's genauer haben möchte muß auf den Performance Counter ausweichen. Zudem friert die Funktion Sleep in einer Schleife das Programm ein, daher sollte so eine Funktion dann in einem eigenen Thread eingebunden sein. ... nur so als Ergänzung 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.