Jump to content

Callback in C++ für Mikrocontroller


fridolin11

Recommended Posts

Hallo zusammen

Bei der Verwendung der API Bindings mit C++ für Mikrocontroller sind einige Fragen aufgetaucht und ich hoffte, dass mit hier bitte jemand helfen könnte.

Ich verwende den ESP32 Brick im stand-alone Betrieb um ein Wegsensor via das Industrial Dual Analog In 2.1 Bricklet auszulesen, gebe den gemessenen Wert an ein PID-Algorithmus weiter um dann via Industrial Analog Out Bricklet 2.0 ein Ventil anzusteuern.

Als Vorlage verwende ich die "example_callback.c" Datei für das Industrial Dual Analog In 2.1 Bricklet. In Programm "example_driver.ino" rufe ich dann regelmässig den Wert des Bricklets ab:

//im Hauptprogramm:
//(...)
void loop() {
  example_loop(&hal);
}

//aus example_callback.c wird dann folgende Funktion aufgerufen
void example_loop(TF_HAL *hal) {
	// Poll for callbacks
    tf_hal_callback_tick(hal, 0);
}

Der ausgelesene Wert wird dann im Serial Monitor gezeigt, soweit so gut. Ich möchte nun jedoch den Wert in einer Variabel speichern und nicht im Serial Monitor ausgeben.

Kann mir bitte jemand helfen und zeigen welche Funktion ich benutzen soll um an den Messwert des Bricklets zu kommen? Oder welche Funktion ich anpassen soll, damit sie mir den Messwert zurückgibt?

Das simple Beispiel (nicht Callback) konnte ich soweit anpassen, damit es mir den Messwert in meine Variable zurück gibt und nicht im Serial Monitor. Allerdings kann ich diese Funktion nicht verwenden, da Sie zu langsam ist für meine Anwendung mit einer Datenrate von 150 Hz. Ich benötige mindestens eine Datenrate von 200 Hz, besser wäre 2kHz.

Für Inputs und Hilfe jeglicher Art bin ich sehr Dankbar!

Freundliche Grüsse

 

Edited by fridolin11
Schreibfehler
Link to comment
Share on other sites

2kHz bingen dir nichts, da das Bricklet bzw der ADC darauf maximal 976 Werte pro Sekunde messen kann. Das folgenden Beispiel schafft eine Abfragerate von 991 Hz, allerdings ohne jeglich Verarbeitung der Werte.

// This example is not self-contained.
// It requires usage of the example driver specific to your platform.
// See the HAL documentation.

#include <Arduino.h>
#include "src/bindings/hal_common.h"
#include "src/bindings/bricklet_industrial_dual_analog_in_v2.h"

void check(int rc, const char *msg);
void example_setup(TF_HAL *hal);
void example_loop(TF_HAL *hal);

static int32_t last_voltage;
static bool last_voltage_is_new = false;

// Callback function for voltage callback
static void voltage_handler(TF_IndustrialDualAnalogInV2 *device, uint8_t channel,
                            int32_t voltage, void *user_data) {
	(void)device; (void)user_data; // avoid unused parameter warning

	last_voltage = voltage;
	last_voltage_is_new = true;
}

static TF_IndustrialDualAnalogInV2 idai;

void example_setup(TF_HAL *hal) {
	// Create device object
	check(tf_industrial_dual_analog_in_v2_create(&idai, NULL, hal), "create device object");

	// Set sample rate to 976 samples per second
	check(tf_industrial_dual_analog_in_v2_set_sample_rate(&idai, TF_INDUSTRIAL_DUAL_ANALOG_IN_V2_SAMPLE_RATE_976_SPS), "set sample rate");

	// Register voltage callback to function voltage_handler
	tf_industrial_dual_analog_in_v2_register_voltage_callback(&idai, voltage_handler, NULL);

	// Set period for voltage (channel 0) callback to 1ms without a threshold
	tf_industrial_dual_analog_in_v2_set_voltage_callback_configuration(&idai, 0, 1, false, 'x', 0, 0);
}

static int start;
static int count = 0;

void example_loop(TF_HAL *hal) {
	// Poll for callbacks
	tf_hal_callback_tick(hal, 0);

	// Check for new value
	if (last_voltage_is_new) {
		if (count == 0) {
			start = millis();
		}

		count++;
      
		int32_t voltage = last_voltage;
		last_voltage_is_new = false;

		//tf_hal_printf("Voltage: %d 1/%d V\n", voltage, 1000);

		if (count % 1000 == 0) {
			int duration = millis() - start;
			tf_hal_printf("Got %d values in %d milliseconds (%d Hz)\n", count, duration, (duration * 1000) / count);
		}
	}
}

 

Link to comment
Share on other sites

Vielen Dank für deine Antwort! Das ist genau das was ich brauchte, mit deinem Code schaffe ich nun auch eine Abfragerate von über 990 Hz. Das Verarbeiten der Werte (Filter + PID Algorithmus) und das Setzen von einer Spannung auf einem Bricklet schafft das ESP32 locker ohne zu verlangsamen. Mein PID Loop läuft nun mit 991 Hz was etwa sechs mal schneller ist als was ich vorhin hatte und ausreichend ist für meine Anwendung :)

Noch ein kleiner Schönheitsfehler in deinem Code bei der Nachricht im Serialmonitor: Frequenz sollte folgend berechnet werden: count*1000/duration

Link to comment
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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...