Jump to content

Variable


Recommended Posts

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

Link zu diesem Kommentar
Share on other sites

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;
}

Link zu diesem Kommentar
Share on other sites

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

Link zu diesem Kommentar
Share on other sites

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.

Link zu diesem Kommentar
Share on other sites

...

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

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...