Jump to content

Betaversion der C/C++ Bindings für Mikrocontroller


rtrbt

Recommended Posts

32 minutes ago, rtrbt said:

Das sieht aus als ob du das Programm nicht als Root startest. Die Root-Rechte brauchst du, damit du auf die SPI-Schnittstelle zugreifen darfst.

Komisch! Das mache ich auch nicht, wenn der Zugriff auf die SPI Schnittstelle (nach Deaktivierung des Brick Daemon) funktioniert.
Also ich lasse das Programm nie mit Root-Rechten laufen. Kann ich aber ab jetzt machen.

Quote

Falls du wirklich den vollen Durchsatz brauchst, sehe ich als Option nur noch, dass du einen ESP32 nimmst. Der ESP hat zwei benutzbare SPI-Einheiten, theoretisch könntest du einen HAL für jede SPI-Einheit anlegen und dann die HALs und deren zugeordnete Bricklets mit jeweils einem eigenen Thread auf einem der zwei Kerne des ESPs laufen lassen.

Stabile 12800 Hz reichen für mich erstmal aus. Aber die Option mit der Unterteilung in zwei Threads sehe ich mir definitiv genauer an.

Es ist auch so schon ein enormer Vorteil, wenn ich direkt mit den Bricklets sprechen kann. Denn jetzt (ohne Brick Daemon) wird auch das Raspberry Pi Zero wieder attraktiv für datenhungrige Anwendungen.

Ich werde weiter testen und Bescheid geben, was sich ergibt.

Besten Dank!

Link zu diesem Kommentar
Share on other sites

Bietet die API die Möglichkeit, die UIDs der angeschlossenen Bricklets zu erfragen? Ich habe im Code gesehen, dass es zumindest eine entsprechende Methode existiert.

bool tf_hal_enumerate_handler(TF_HalContext *hal, uint8_t port_id, TF_Packetbuffer *payload)

Bietet sie intern die gleichen Möglichkeiten wie in den normalen C/C++ Bindings?

Link zu diesem Kommentar
Share on other sites

17 minutes ago, cl- said:

Bietet die API die Möglichkeit, die UIDs der angeschlossenen Bricklets zu erfragen?

Ja, aber nicht mit dem enumerate_handler. Der ist nur für die interne erste Suche, was angeschlossen ist. Offiziell gibt es die Funktion

bool tf_hal_get_device_info(TF_HalContext *hal, size_t index, char ret_uid[7], char *ret_port_name, uint16_t *ret_device_id);

Die Funktion gibt dir zurück, ob der HAL das n-te Bricklet (index) kennt und falls ja schreibt sie in ret_uid, ret_port_name und ret_device_id die entsprechenden Informationen. Wenn die Funktion false zurückgibt ist der Index zu groß.

Benutzen kannst du die Funktion dann z.b. so um das erste Device mit einer Device-ID zu finden. (Wie bei den normalen C-Bindings gibt es im entsprechenden Header ein define für die Device-ID, z.b. TF_ACCELEROMETER_V2_DEVICE_IDENTIFIER

bool find_first_uid_by_did(uint16_t device_id, char uid[7]) {
    char pos;
    uint16_t did;
    for (size_t i = 0; tf_hal_get_device_info(&hal, i, uid, &pos, &did); ++i) {
        if (did == device_id) {
            return true;
        }
    }
    return false;
}

Wenn du alle Bricklets sehen willst, die angeschlossen sind, kannst du folgendes machen:

int i = 0;
char uid[7] = {0};
char port_name;
uint16_t device_id;
while(tf_hal_get_device_info(&hal, i, uid, &port_name, &device_id)) {
    printf("Device %d: %s of type %d at port %c\n", i, uid, device_id, port_name);
    ++i;
}

 

Link zu diesem Kommentar
Share on other sites

Sehr cool. Genau das habe ich gesucht! Habs direkt getestet und es läuft.

Kurzes Feedback noch zum Raspberry Pi Zero (mit HAT Brick). Ich kriege mit drei angeschlossenen Accelerometer V2 Bricklets mit den Defaulteinstellungen der Bindings und einem 16 Bit Continuous Callback (eine Achse) ca. 11000 Werte die Sekunde pro Bricklet.

Link zu diesem Kommentar
Share on other sites

43 minutes ago, cl- said:

Ich kriege mit drei angeschlossenen Accelerometer V2 Bricklets mit den Defaulteinstellungen der Bindings und einem 16 Bit Continuous Callback (eine Achse) ca. 11000 Werte die Sekunde pro Bricklet.

Teste das nochmal mit Beta 3, die ich gerade in den Post oben eingefügt habe: Du kannst jetzt den Tick-Funktionen 0 als Timeout mitgeben, dann versuchen sie nur ein Callback zu empfangen, dass sofort gelesen werden kann, aber blockieren nicht weiter.

Außerdem kannst du jetzt Callbacks z.b. so für 5 Sekunden ticken:

uint32_t bench_start = tf_hal_current_time_us(&hal);

while (tf_hal_current_time_us(&hal) - bench_start < 5000000) {
  tf_hal_callback_tick(&hal, 0);
}

Bei meinen Messungen war das praktisch genauso schnell, wie das Ticken von Hand auf die vier Bricklets zu verteilen. (Ich habe aber nur mit einem Pi 3 getestet, nicht einem Zero)

Link zu diesem Kommentar
Share on other sites

28 minutes ago, rtrbt said:

 


uint32_t bench_start = tf_hal_current_time_us(&hal);

while (tf_hal_current_time_us(&hal) - bench_start < 5000000) {
  tf_hal_callback_tick(&hal, 0);
}

 

Das geht bei mir nicht. Wenn ich auf das Hal ticke, passiert nichts (also ich bekomme keine Ausgaben aus meinen Callbacks).
Muss das vielleicht außerhalb der demo_loop() aufgerufen werden (was aber ja eigentlich keinen Unterschied machen dürfte)?

Ich bekomme jetzt mit der Beta3 ca. 12000 Werte pro Bricklet, das sind in etwa 1000 mehr als bei der Beta2 🙂

Link zu diesem Kommentar
Share on other sites

Noch was: Wenn ich die BRICKLET_STACK_SPI_CONFIG_MAX_SPEED_HZ in hal_linux.c auf 2000000 setze, sorgt das bei der Beta3 dafür, dass die Anzahl der empfangenen Werte stark schwangt. Während es bei 1400000 stabile Werte zwischen 12000 und 12300 pro Bricklet gibt, schwankt bei 2000000 die Anzahl der empfangenen Werte zwischen 11000 und 13000.

Das mag aber auch an einer Raspberry Pi Zero spezifischen SPI Implementierung liegen? Ich habe irgendwo in den Bindings gesehen, dass man bei den Raspberry 3 Modellen irgendwas ändern soll?

Link zu diesem Kommentar
Share on other sites

18 hours ago, cl- said:

Das geht bei mir nicht. Wenn ich auf das Hal ticke, passiert nichts

*hust* nimm mal Beta 4.

18 hours ago, cl- said:

Noch was: Wenn ich die BRICKLET_STACK_SPI_CONFIG_MAX_SPEED_HZ in hal_linux.c auf 2000000 setze, sorgt das bei der Beta3 dafür, dass die Anzahl der empfangenen Werte stark schwangt. Während es bei 1400000 stabile Werte zwischen 12000 und 12300 pro Bricklet gibt, schwankt bei 2000000 die Anzahl der empfangenen Werte zwischen 11000 und 13000.

Das liegt vermutlich daran, dass der Pi Zero die Timings dann nicht ganz schafft. Ich bin hier mal auch auf einen Zero umgestiegen, am besten läufts bei mir im Bereich 1950000 bis 1960000. Ich komme aber trotzdem nicht auf deine Werte. Kannst du mal das angehangene Programm testen und mir im Gegenzug dein aktuelles Testprogramm schicken? Außerdem folgende Fragen:

  • Welchen Compiler und welche Flags benutzt du? (Ich im Moment arm-linux-gnueabihf-gcc (GCC) 10.1.0 mit -Ofast -std=gnu99 )
  • Welchen Kernel hast du auf dem Pi und hast du einen core_freq- oder arm_freq-Eintrag in der /boot/config.txt? (Ich im Moment Linux 4.19.97+ #1294 und core_freq=250)

main.c

Link zu diesem Kommentar
Share on other sites

On 7/22/2020 at 11:47 AM, rtrbt said:
  • Welchen Compiler und welche Flags benutzt du? (Ich im Moment arm-linux-gnueabihf-gcc (GCC) 10.1.0 mit -Ofast -std=gnu99 )
  • Welchen Kernel hast du auf dem Pi und hast du einen core_freq- oder arm_freq-Eintrag in der /boot/config.txt? (Ich im Moment Linux 4.19.97+ #1294 und core_freq=250)

Ich nutze momentan auf dem Pi Zero gcc version 8.3.0 (Raspbian 8.3.0-6+rpi1) mit den gleichen Flags wie du (-Ofast -std=gnu99)
Die Kernel Version ist 5.4.51+ und der arm_freq=800 Eintrag ist nicht aktiv.

Mit deinem Testprogramm und vier Accelerometer V2 Bricklets komme ich auf kombinierte 867 Pakete pro Sekunde.

Channel 0: Packet counter is 1095 after 5.000120 seconds.
Channel 1: Packet counter is 1081 after 5.000120 seconds.
Channel 2: Packet counter is 1080 after 5.000120 seconds.
Channel 3: Packet counter is 1080 after 5.000120 seconds.
Combined: 867.179138 packets per second
6503.843536 samples per channel per second

BRICKLET_STACK_SPI_CONFIG_MAX_SPEED_HZ habe ich hierbei nicht verändert (ist ja im Default auf 1400000 gesetzt).

Link zu diesem Kommentar
Share on other sites

Hat jemand dies mit einem ir Temperatur v2 Bricklet implementiert?
Ich kann es nicht zum Laufen bringen. Es schlägt fehl, wenn ich versuche, das Objekt mit tf_temperature_ir_v2_get_object_temperature zu erstellen. Es gibt einen Fehlercode zurück: -10

I'm using an arduino uno.

bearbeitet von Daniel Navarrete
Link zu diesem Kommentar
Share on other sites

Hi,

9 hours ago, Daniel Navarrete said:

I'm using an arduino uno.

Are you using some kind of level shifter between the Uno and the bricklet? This is required as the Uno (and all other AVR based Arduinos) have a logic level of 5V, but the bricklets only work with 3.3V. Some Unos seem to understand the 3.3V high level as a 5V high level, but some don't.

The error code -10 indicates that the bindings can't find the bricklet (see errors.h), so you either have the logic level problem from above, or you use the wrong UID. The bindings will print all found devices to the serial console when tf_hal_arduino_init runs. You can connect to the serial console (maybe add a delay(5000) at the top of your setup-function, so you don't miss the output) and check if the bindings see the bricklet under another UID.

Link zu diesem Kommentar
Share on other sites

On 7/27/2020 at 5:28 AM, rtrbt said:

Hi,

Are you using some kind of level shifter between the Uno and the bricklet? This is required as the Uno (and all other AVR based Arduinos) have a logic level of 5V, but the bricklets only work with 3.3V. Some Unos seem to understand the 3.3V high level as a 5V high level, but some don't.

The error code -10 indicates that the bindings can't find the bricklet (see errors.h), so you either have the logic level problem from above, or you use the wrong UID. The bindings will print all found devices to the serial console when tf_hal_arduino_init runs. You can connect to the serial console (maybe add a delay(5000) at the top of your setup-function, so you don't miss the output) and check if the bindings see the bricklet under another UID.

Hello, I'm actually not using any level shifter I figured that 3.3 would be enough for the arduino to get a HIGH level, I'll try with a level shifter,

Regarding the UID, how can I get the UID of my bricklet?

Thanks for your support,

 

Hallo, ich benutze eigentlich keinen Level Shifter. Ich dachte mir, dass 3.3 ausreichen würde, damit der Arduino einen HIGH Level erreicht. Ich werde es mit einem Level Shifter versuchen.

Wie kann ich die UID meines Bricklets in Bezug auf die UID ermitteln?

Danke für deine Unterstützung,

Link zu diesem Kommentar
Share on other sites

3 hours ago, Daniel Navarrete said:

Regarding the UID, how can I get the UID of my bricklet?

You could connect your Bricklet to a PC over a Brick. Then you can check the UID with Brick Viewer.

Also the bindings print the UID of all attached Bricklets to the serial console when calling tf_hal_arduino_init(). (This only works if the Bricklet is detected, so only with a level shifter in your case)

Link zu diesem Kommentar
Share on other sites

Sorry, dass die Antwort etwas gedauert hat.

On 7/25/2020 at 4:37 PM, cl- said:

Mit deinem Testprogramm und vier Accelerometer V2 Bricklets komme ich auf kombinierte 867 Pakete pro Sekunde.

Das hat mich erst sehr verwirrt. Anscheinend bricht die Performance mit dem 5.4er Kernel ziemlich ein, obwohl das Kernelupdate eigentlich den gegenteiligen Effekt haben sollte (siehe z.b. hier)

Ich habe deshalb (und weil es mit HAT und Brick Daemon Probleme mit dem neuen Kernel gibt) einen neuen HAL geschrieben, der direkt mit dem BCM2835-Chip spricht, der die GPIOs steuert. Falls du den HAL testen möchtest, habe ich ihn mal angehangen. Die Init-Funktion heißt noch tf_hal_linux_init und nimmt den spidev-Pfad, das wird aber ignoriert, ich habe das Interface noch nicht verändert, damit man einfacher hin und her wechseln kann. Du musst dann im Makefile folgende Änderung machen:

SOURCES_HAL_LINUX := hal_linux/hal_linux.c \
					 hal_linux/gpio_sysfs.c \
					 hal_linux/utils.c \

ersetzen durch

SOURCES_HAL_LINUX := hal_bcm2835/hal_linux.c \
 					 hal_bcm2835/bcm2835.c \

Bei meinen Tests läuft der HAL bisher deutlich besser: ich komme auf 2000 PPS bei 1,4MHz und 2650 PPS bei 1,95MHz.

hal_bcm2835.zip

Link zu diesem Kommentar
Share on other sites

Ich habe noch eine andere Frage.

Es ist statistisch erkennbar, dass ich nie eine identische Anzahl von Nachrichten für die verschiedenen Kanäle bekomme.
Das ist erstmal nicht so schlimm, da die 5 Sekunden halt irgendwann vorbei sind und dann einige Pakete nicht mehr mit gezählt werden.

Es ist aber so, dass ich für das Bricklet an port a immer mit Abstand die meisten Pakete bekomme. Im Schnitt sind das 15 mehr als Kanäle b, c, und d.
Das kann ich mir nicht erklären. Auch deckt sich das mit Beobachtungen meiner anderen Programme, bei denen ich den Brick Daemon nutze.
Wenn ich beispielsweise eine Minute lang Messwerte abfrage (Continuous Callback mit den Accelerometer V2 Bricklets) und sekündliche Statistiken ausgebe, dann sehe ich diesen Sachverhalt in jeder einzelnen Sekunde. Auf Dauer führt das dann dazu, dass die Kanäle sich relativ zueinander verschieben.

Gibt es hierfür eine technische Erklärung? Mache ich was falsch?

Besten Dank!

 

pi@raspberrypi:~/tf $ sudo ./linux_demo 
Hello World!
Found device 2kAkfr of type 2130 at port A
Found device 2kBkGe of type 2130 at port B
Found device 2uvASe of type 2130 at port C
Found device Wdm9R of type 2130 at port D
Found device JUj of type 112 at port E
Channel 0: Packet counter is 1094 after 5.000550 seconds.
Channel 1: Packet counter is 1079 after 5.000550 seconds.
Channel 2: Packet counter is 1080 after 5.000550 seconds.
Channel 3: Packet counter is 1079 after 5.000550 seconds.
Combined: 866.304749 packets per second
6497.285614 samples per channel per second
pi@raspberrypi:~/tf $ sudo ./linux_demo 
Hello World!
Found device 2kAkfr of type 2130 at port A
Found device 2kBkGe of type 2130 at port B
Found device 2uvASe of type 2130 at port C
Found device Wdm9R of type 2130 at port D
Found device JUj of type 112 at port E
Channel 0: Packet counter is 1095 after 5.000013 seconds.
Channel 1: Packet counter is 1081 after 5.000013 seconds.
Channel 2: Packet counter is 1081 after 5.000013 seconds.
Channel 3: Packet counter is 1079 after 5.000013 seconds.
Combined: 867.197754 packets per second
6503.983154 samples per channel per second

 

bearbeitet von cl-
Link zu diesem Kommentar
Share on other sites

Das hängt vermutlich davon ab wie du die Callbacks tickst. Was benutzt du dafür im Moment?

Abgesehen davon ist das vermutlich ein Effekt, den du nur beobachten kannst, weil das Programm praktisch permanent überlastet ist. Wenn du es schaffst alle Pakete die die Bricklets erzeugen zu verarbeiten, sollte das nicht mehr auftreten. Die Bricklets generieren Pakete ja mit einer festen Frequenz.

Link zu diesem Kommentar
Share on other sites

Ok. Ich habe jetzt die Beta 5 getestet. Es kommt dazu, dass ich nicht immer alle Bricklets ansprechen kann. Es sind aber immer andere, die das Hal nicht finden kann.

Die Anzahl der Pakete (max. 85) erscheint mir als ein wenig gering. Ich werde mal schauen, wodran das liegt. Es müssten aber mindestens 867 sein, wie im oberen Beispiel.

pi@raspberrypi:~/tf/source $ sudo ./linux_demo 
Found device 2kAkfr of type 2130 at port A
Found device 2kBkGe of type 2130 at port B
Found device Wdm9R of type 2130 at port D
Found device JUj of type 112 at port E
Failed to create acc: no device with the given UID is reachable (return code -10, errno 0)
Segmentation fault
pi@raspberrypi:~/tf/source $ sudo ./linux_demo 
Found device 2kBkGe of type 2130 at port B
Found device 2uvASe of type 2130 at port C
Found device Wdm9R of type 2130 at port D
Found device JUj of type 112 at port E
Failed to create acc: no device with the given UID is reachable (return code -10, errno 0)
Segmentation fault
pi@raspberrypi:~/tf/source $ sudo ./linux_demo 
Found device 2kAkfr of type 2130 at port A
Found device 2kBkGe of type 2130 at port B
Found device 2uvASe of type 2130 at port C
Found device Wdm9R of type 2130 at port D
Found device JUj of type 112 at port E
Channel 0: Packet counter is 48 after 5.000009 seconds.
Channel 1: Packet counter is 85 after 5.000009 seconds.
Channel 2: Packet counter is 77 after 5.000009 seconds.
Channel 3: Packet counter is 81 after 5.000009 seconds.
Combined: 58.199894 packets per second
436.499205 samples per channel per second
pi@raspberrypi:~/tf/source $ sudo ./linux_demo 
Found device 2kAkfr of type 2130 at port A
Found device 2kBkGe of type 2130 at port B
Found device Wdm9R of type 2130 at port D
Found device JUj of type 112 at port E
Failed to create acc: no device with the given UID is reachable (return code -10, errno 0)
Segmentation fault

 

bearbeitet von cl-
Link zu diesem Kommentar
Share on other sites

19 minutes ago, rtrbt said:

Das hängt vermutlich davon ab wie du die Callbacks tickst. Was benutzt du dafür im Moment?

Abgesehen davon ist das vermutlich ein Effekt, den du nur beobachten kannst, weil das Programm praktisch permanent überlastet ist. Wenn du es schaffst alle Pakete die die Bricklets erzeugen zu verarbeiten, sollte das nicht mehr auftreten. Die Bricklets generieren Pakete ja mit einer festen Frequenz.

Das passiert in angehangenem Programm auf dem Pi Zero. Ich nutze dein

tf_hal_callback_tick(&hal, 5000000);

dafür.

main.c

Link zu diesem Kommentar
Share on other sites

5 minutes ago, rtrbt said:

Im Demo-Programm sehe ich spontan, dass du den hal_raspberry_pi includest, aber noch tf_hal_linux_init aufrufst. Das musst du mal anpassen und vermutlich auch dein Makefile.

Sorry mein Fehler, das war das falsche main.c, was angehangen habe. Lokal auf dem Pi lag aber das Richtige (siehe neuer Anhang).

Auszug aus meinem Makefile:

# Executable name
TARGET := linux_demo

CC = $(CROSS_COMPILE)gcc

CFLAGS += -std=gnu99 -Ofast -Wall -Wextra -Wno-padded -I..
LDFLAGS += -pthread
LIBS += -lrt -ldl

WITH_DEBUG ?= yes

ifeq ($(WITH_DEBUG),yes)
	CFLAGS += -g -ggdb
endif

# These files are always required when using the bindings
SOURCES_BINDINGS := bindings/base58.c \
					bindings/bricklet_unknown.c \
					bindings/endian_convert.c \
					bindings/errors.c \
					bindings/hal_common.c \
					bindings/packetbuffer.c \
					bindings/pearson_hash.c \
					bindings/spitfp.c \
					bindings/tfp.c \

# HAL specific files
#SOURCES_HAL_LINUX := hal_linux/hal_linux.c \
#					 hal_linux/gpio_sysfs.c \
#					 hal_linux/utils.c \

SOURCES_HAL_LINUX := hal_raspberry_pi/hal_raspberry_pi.c \
 					 hal_raspberry_pi/bcm2835.c \

# List your used devices here
SOURCES_DEVICES :=  bindings/bricklet_accelerometer_v2.c

main.c

bearbeitet von cl-
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...