BME280, Raspberry, Programmieren in C

Webdesign, Programmierung, PC-Hardware und allgemeine Computerprobleme.

Moderatoren: MaxZ, ebastler, SeriousD

Antworten

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

Moin, ich weiss nicht so recht ob ich hier richtig bin - mal sehen:

Ich versuche den BME280-Sensor unter C auf dem Raspberry zum laufen zu bringen und mir dabei auch ein wenig C beizubringen.

(Unter Python läuft er übrigends, Quelle: wget https://bitbucket.org/MattHawkinsUK/rpi ... /bme280.py python bme280.py von der Seite https://sebastianhemel.blogspot.com/2019/08/)

Ich verwende linux_userspace.c und bme280.c von https://github.com/BoschSensortec/BME28 ... serspace.c


Wer kann mir eine funktionierende Alternative nennen (ohne dass ich 100 Varianten von Github testen muss) ?


Eine Frage zu C:

Wie kann es sein, dass "int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);" zwei mal (einmal mit, einmal ohne Body) in der gleichen Datei definiert wird? ( und der Compiler mir das nicht um die Ohren haut)

Dass ich mich bei C (ich bin Java gewöhnt) auf einiges gefasst machen musste, war mir ja klar (Achtung, wer nicht gerne Flüche lesen möchte, sollte folgendes nicht markieren:
Wer zum Teufel hat diese Sprache erfunden?? Dateien werden einfach mal in per include verbunden, so dass man suchen muss, wo denn diese Funktion jetzt gerade herkommt - aaargh.
struct mit a->b und namespaces mit a::b anstatt schöne eindeutige Objekte auf deren Bestandteile man einfach mit einem Punkt zugreift und das auch tun muss, so dass man immer weiss wo die Definition zu der Funktion zu finden ist!
Aber das beste kommt ja noch: Zeiger-Arithmetik! Eine Funktion wird als Teil einer struct deklariert, aber die eigentliche Definition wird dann einfach später an ganz anderer Stelle zugewiesen!!
Ganz zu schweigen von Compilier-Anweisungen mit mehreren Source-Dateien, die auch noch in der Richtigen Reihenfolge stehen müssen, die dann so kompliziert werden, das man Makefiles braucht!
Benutzeravatar

VDX
Beiträge: 2175
Registriert: Fr 13. Jul 2018, 18:23
Spezialgebiet: Laser und Mikro-/Nanotechnik
Hat sich bedankt: 14 Mal
Danksagung erhalten: 237 Mal

Re: BME280, Raspberry, Programmieren in C

Beitrag von VDX »

... ja, du kannst den gleichen Methodennamen mit unterschiedlichen Parametern und Rückgabewerten definieren -- später wird anhand der Parameter die "richtige" Methode ausgewählt ...

Viktor
Aufruf zum Projekt "Müll-freie Meere" - https://reprap.org/forum/list.php?426 -- Facebook-Gruppe - https://www.facebook.com/groups/383822522290730
Call for the project "garbage-free seas" - https://reprap.org/forum/list.php?425
Benutzeravatar

Eddy Wirbelstrom
Beiträge: 255
Registriert: Di 19. Jun 2012, 23:02
Spezialgebiet: Marxgeneratoren, Capbanks, alte Quacksalbereien
Wohnort: Erlangen
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: BME280, Raspberry, Programmieren in C

Beitrag von Eddy Wirbelstrom »

VDX hat geschrieben: Di 26. Mai 2020, 22:48 ... ja, du kannst den gleichen Methodennamen mit unterschiedlichen Parametern und Rückgabewerten definieren -- später wird anhand der Parameter die "richtige" Methode ausgewählt ...
äh nee, Overloading geht in C nur mit Plusplus.

Ging ja auch um was anderes:
RaspKiller hat geschrieben: Di 26. Mai 2020, 22:24 Wie kann es sein, dass "int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);" zwei mal (einmal mit, einmal ohne Body) in der gleichen Datei definiert wird? ( und der Compiler mir das nicht um die Ohren haut)
Das kann sein, weil es gar nicht zwei mal in der gleichen Datei definiert wird. Beim ersten Mal wird es nur deklariert (wie im Headerfile).

Code: Alles auswählen

1	int two_times(int x); //ohne das gäb’s Error in Zeile 4
2
3	int answer() {
4		return two_times(21);
5	}
6
7	int two_times(int x) {
8		return 2 * x;
9	}
Grüße
Claus
[ externes Bild ]Der Außerirdische mit Tentakelarmen hat es schwer, einen Lötkolben zu halten“ – Harald Lesch
Benutzeravatar

SeriousD
Beiträge: 427
Registriert: Mi 26. Aug 2009, 22:16
Spezialgebiet: Handwerkliche Improvisationen
Wohnort: Kiel
Hat sich bedankt: 19 Mal
Danksagung erhalten: 41 Mal

Re: BME280, Raspberry, Programmieren in C

Beitrag von SeriousD »

Moin,

um das XY Problem zu vermeiden:
Was hast Du denn genau vor?
Warum reicht Deine python Lösung nicht?


Um Dir irgendwie weiterhelfen zu können:
Was funktioniert nicht?
Was hast Du bisher probiert?
Welches Fehlerbild zeichnet sich ab?
Wie ist dein Systemaufbau?

OT Spoiler:
Spoiler:
RaspKiller hat geschrieben: Di 26. Mai 2020, 22:24 Wer zum Teufel hat diese Sprache erfunden??
Dennis Ritchie.
RaspKiller hat geschrieben: Di 26. Mai 2020, 22:24 Dateien werden einfach mal in per include verbunden, so dass man suchen muss, wo denn diese Funktion jetzt gerade herkommt - aaargh.
Wie bei sehr vielen anderen Programmiersprachen auch. Das hat nichts mit C zu tun, sondern mit Deiner Entwicklungsumgebung.
Ich verwende VS Code mit der C Extension und kann wunderbar zwischen Files navgieren, Defintionen ansehen etc.
RaspKiller hat geschrieben: Di 26. Mai 2020, 22:24 struct mit a->b und namespaces mit a::b anstatt schöne eindeutige Objekte auf deren Bestandteile man einfach mit einem Punkt zugreift und das auch tun muss, so dass man immer weiss wo die Definition zu der Funktion zu finden ist!
Aber das beste kommt ja noch: Zeiger-Arithmetik! Eine Funktion wird als Teil einer struct deklariert, aber die eigentliche Definition wird dann einfach später an ganz anderer Stelle zugewiesen!!
Nun ich denke Du musst da noch einiges lernen, Du wirfst Da vieles durcheinander was nicht zusammengehört. C bildet nur bedingt objektorientierte Paradigmen ab. Es ist recht hardwarenah, Du arbeitest quasi direkt auf dem Speicher, arbeitest direkt mit Zeigern und musst dich um dessen Handling selber kümmern im Gegensatz zu Java. Ich möchte Dir nicht zu Nahe treten aber ich hab ein wenig das Gefühl, dass Du auch noch nicht so lange Java programmierst, ansonsten wäre Dir das Pattern von seperaten Definitionen und Deklarationen ja durch die in Java gegebenen Interfaces bekannt.

Mach doch mal ein zwei C Tutorials - Du solltest mindestens schonmal ne linked List gebaut haben um ein wenig ein Gefühl für die Sprache zu haben.
Beste Grüße
SeriousD
Hey Sigma, ist noch Lambda? - Ja aber das Phi ist noch Rho.
Benutzeravatar

Heisath
Beiträge: 539
Registriert: Mi 26. Jun 2013, 15:44
Hat sich bedankt: 33 Mal
Danksagung erhalten: 81 Mal
Kontaktdaten:

Re: BME280, Raspberry, Programmieren in C

Beitrag von Heisath »

Hi,

für den BME280 (und viele andere Sensoren) gibt es im Linux Kernel bereits Module / Treiber. Wenn du also nicht selber schreiben willst, findest du im Kernel unter drivers/iio/pressure/bmp280 das was du suchst. Ich weiß nicht, ob das Modul in Raspbian (oder welches OS du auch immer nutzt) bereits aktiviert ist, sonst musst du evtl. den Kernel neu bauen und/oder mit modprobe das Modul laden. Nachdem du das Modul geladen hast, kannst du mittels "echo 'bmp280 0x76' > /sys/bus/i2c/devices/i2c-1/new_device" das Modul aktivieren, danach stehen im Dateisystem dann entsprechende Dateien bereit um Temp etc. zu lesen. (Natürlich bei 0x76 die I2C Adresse einsetzen und bei i2c-1 deinen I2C Bus).

Willst du das selbst machen, beschreibe uns doch bitte, was mit der Bosch Library nicht geht. Sie sollte es eigentlich tun. Zeig uns evtl. deinen Code, und beschreibe die Konfiguration und das System, was auf dem Raspberry Pi läuft.

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

Re: BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

Woah, hier wird schnell und gut geantwortet und das auf so nervige Anfänger-Fragen - danke schon mal.

Ich experimentiere nur privat - im Wesentlichen geht es für mich um das Lernen von C.
Davon abgesehen habe ich einen Rasp Zero und da ist die Geschwindigkeit von Python unschön. (Ich hab für später noch Pläne, die schnelleres Reaktionsvermögen voraussetzen)

Das mit "echo 'bmp280 0x76' > /sys/bus/i2c/devices/i2c-1/new_device" werde ich probieren.


Also ( ich musste erst wieder alles neu machen, weil ich so viel experimentiert hatte) :
1. Ich habe "linux_userspace.c" aus "examples/" neben "bme280.c" kopiert, weil ich mit "gcc -o bmetest bme280.c bme280.h examples/linux_userspace.c" (oder "gcc -o bmetest bme280.c examples/linux_userspace.c bme280.h ") nur "bme280.h: Datei oder Verzeichnis nicht gefunden" erhalte - also wohl was falsch mache.

2. Nach dem Kopieren und "gcc -o bmetest bme280.c linux_userspace.c" und "./bmetest /dev/i2c-1" erhalte ich "Failed to initialize the device (code -2)."

3. Das Experimentieren ergab, dass die Chip-ID als falsch erkannt wurde.

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

Re: BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

PS: So was wie einmal deklariert und einmal definiert , hatte ich mir schon gedacht - kennt man ja von Header-Dateien - aber wieso soll das in einer einzigen .c-Datei Sinn ergeben?
Benutzeravatar

Thunderbolt
Beiträge: 2907
Registriert: Fr 7. Apr 2006, 14:05
Spezialgebiet: Physik,Elektronik,Blender
Schule/Uni/Arbeit: M.Sc ET, Hardwareentwickler
Wohnort: 65366 Geisenheim (Hessen)
Hat sich bedankt: 1 Mal
Danksagung erhalten: 83 Mal
Kontaktdaten:

Re: BME280, Raspberry, Programmieren in C

Beitrag von Thunderbolt »

RaspKiller hat geschrieben: Mi 27. Mai 2020, 10:56 Woah, hier wird schnell und gut geantwortet und das auf so nervige Anfänger-Fragen - danke schon mal.

Ich experimentiere nur privat - im Wesentlichen geht es für mich um das Lernen von C.
Davon abgesehen habe ich einen Rasp Zero und da ist die Geschwindigkeit von Python unschön. (Ich hab für später noch Pläne, die schnelleres Reaktionsvermögen voraussetzen)

Das mit "echo 'bmp280 0x76' > /sys/bus/i2c/devices/i2c-1/new_device" werde ich probieren.


Also ( ich musste erst wieder alles neu machen, weil ich so viel experimentiert hatte) :
1. Ich habe "linux_userspace.c" aus "examples/" neben "bme280.c" kopiert, weil ich mit "gcc -o bmetest bme280.c bme280.h examples/linux_userspace.c" (oder "gcc -o bmetest bme280.c examples/linux_userspace.c bme280.h ") nur "bme280.h: Datei oder Verzeichnis nicht gefunden" erhalte - also wohl was falsch mache.

2. Nach dem Kopieren und "gcc -o bmetest bme280.c linux_userspace.c" und "./bmetest /dev/i2c-1" erhalte ich "Failed to initialize the device (code -2)."

3. Das Experimentieren ergab, dass die Chip-ID als falsch erkannt wurde.

der compiler bekommt im normalfall nur C files, keine header-dateien (die kommen ja in den C-Files per include rein)

evtl. musst du dem compiler not mit

Code: Alles auswählen

-I ./examples
sagen, dass er in "examples" auch header findet, wenn du die nicht mit vollem pfad angibst

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

Re: BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

mh

Ich arbeite im Verzeichnis "../BME280_driver-master/" , da sind "bme280.c" und "bme280.h" drin ;
"linux_userspace.c" ist in "../BME280_driver-master/examples/" - "bme280.h" wird also gesehen.
("-I ./examples" habe ich natürlich getestet - tatsächlich kein Unterschied)
Allerdings meckert er über "#include "bme280.h" " in "linux_userspace.c", was ich sogar verstehe - ich würde so was wie "#include "../bme280.h" erwarten.
Benutzeravatar

SeriousD
Beiträge: 427
Registriert: Mi 26. Aug 2009, 22:16
Spezialgebiet: Handwerkliche Improvisationen
Wohnort: Kiel
Hat sich bedankt: 19 Mal
Danksagung erhalten: 41 Mal

Re: BME280, Raspberry, Programmieren in C

Beitrag von SeriousD »

Moin,
RaspKiller hat geschrieben: Mi 27. Mai 2020, 10:56 Davon abgesehen habe ich einen Rasp Zero und da ist die Geschwindigkeit von Python unschön. (Ich hab für später noch Pläne, die schnelleres Reaktionsvermögen voraussetzen)
Ah okay, Du willst also Performance, jop kenn ich. War bei mir auch nen Unterschied um den Faktor 10 an CPU Last als ich ein wenig Wifi im Monitormodus gelauscht habe.

RaspKiller hat geschrieben: Mi 27. Mai 2020, 10:56 1. Ich habe "linux_userspace.c" aus "examples/" neben "bme280.c" kopiert, weil ich mit "gcc -o bmetest bme280.c bme280.h examples/linux_userspace.c" (oder "gcc -o bmetest bme280.c examples/linux_userspace.c bme280.h ") nur "bme280.h: Datei oder Verzeichnis nicht gefunden" erhalte - also wohl was falsch mache.

2. Nach dem Kopieren und "gcc -o bmetest bme280.c linux_userspace.c" und "./bmetest /dev/i2c-1" erhalte ich "Failed to initialize the device (code -2)."
Hast Du in die in linux_userspace.c angegebene Variante zum kompilieren probiert?

Code: Alles auswählen

compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280
Da die Files nun im gleichen Ordner liegen, kompiliert er aber offensichtlich doch schon. Wird also vermutlich kein wirkliches C Problem sein.

Hast Du den in linux_userspace.c angegebenen Aufruf probiert?

Code: Alles auswählen

Use like: ./bme280 /dev/i2c-0
Spannend ist, dass dort i2c-0 als Bus genannt ist, Du irgendwo aber vorher von i2c-1 als Bus sprichst.

Mit welchen Pins am Raspi hast Du den Sensor angeschlossen?
Wie sieht deine /etc/modules aus?
Wie sieht deine //boot/config.txt aus?
Was liefert ls /dev | grep i2c ?
RaspKiller hat geschrieben: Mi 27. Mai 2020, 10:56 Das Experimentieren ergab, dass die Chip-ID als falsch erkannt wurde.
Wie bist Du zu diesem Schluss gekommen?
Was liefert i2cdetect -y 1 und i2cdetect -y 0 ?
RaspKiller hat geschrieben: Mi 27. Mai 2020, 12:05 Allerdings meckert er über "#include "bme280.h" " in "linux_userspace.c", was ich sogar verstehe - ich würde so was wie "#include "../bme280.h" erwarten.
Ja, siehe:

Code: Alles auswählen

compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280
OT Spoiler:
Spoiler:
RaspKiller hat geschrieben: Mi 27. Mai 2020, 11:02 PS: So was wie einmal deklariert und einmal definiert , hatte ich mir schon gedacht - kennt man ja von Header-Dateien - aber wieso soll das in einer einzigen .c-Datei Sinn ergeben?
Damit Du Deinen Code vernünftig strukturierst zum Beispiel da kannst Du zu beginn alle in der source Datei befindlichen Funktionen deklarieren und später definieren. Hat den Vorteil, dass diese dann auch nur in dieser Source Datei "sichtbar" sind, sprich nicht aus anderen C-Files aufgerufen werden können. So lässt sich ein wenig ein objektorinetiertes Pattern abdecken.

Außerdem wirds gebraucht, wenn Du zB von Funktion A aus Funktion B und Funkltion B aus Funktion A aurufen möchtest,

Code: Alles auswählen

void bar(void);

void foo(){
	bar(); //Hier wäre bar noch nicht bekannt, wenn es nicht deklariert wäre. 
}

void bar(){
	foo();
}
Ist natürlich ein stark simplifiziertes Beispiel Du musst Dir den Kram dann noch mit vielen if abfragen und so vorstellen, sodass die sich nich einfach stumpf gegenseitig aufrufen.
Beste Grüße
SeriousD
Hey Sigma, ist noch Lambda? - Ja aber das Phi ist noch Rho.
Benutzeravatar

Thunderbolt
Beiträge: 2907
Registriert: Fr 7. Apr 2006, 14:05
Spezialgebiet: Physik,Elektronik,Blender
Schule/Uni/Arbeit: M.Sc ET, Hardwareentwickler
Wohnort: 65366 Geisenheim (Hessen)
Hat sich bedankt: 1 Mal
Danksagung erhalten: 83 Mal
Kontaktdaten:

Re: BME280, Raspberry, Programmieren in C

Beitrag von Thunderbolt »

RaspKiller hat geschrieben: Mi 27. Mai 2020, 12:05 mh

Ich arbeite im Verzeichnis "../BME280_driver-master/" , da sind "bme280.c" und "bme280.h" drin ;
"linux_userspace.c" ist in "../BME280_driver-master/examples/" - "bme280.h" wird also gesehen.
("-I ./examples" habe ich natürlich getestet - tatsächlich kein Unterschied)
Allerdings meckert er über "#include "bme280.h" " in "linux_userspace.c", was ich sogar verstehe - ich würde so was wie "#include "../bme280.h" erwarten.
zum debuggen kannst du gcc auch mit -v (oder auch -vv oder vvv wenn mich nicht alles täuscht) aufrufen, dann verrät er dir auch, wo er nach headern sucht

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

Re: BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

hmpf: es compiliert á la linuxuserspace-Kommentar (hatte ich ganz am anfang mal bemerkt, aber durch 10 Baustellen wieder vergessen)
Ist ja eigentlich auch logisch, da ist main() drin und linuxuserspace included bme280 und nicht umgekehrt.

Laufen tut's aber genauso wenig.

i2cdetect -y 1 gibt adresse 76 an, sonst nix -y 0 überhaupt nix. Das hatte ich auch vorher schon probiert und es stimmt ja auch mit bme280_defs:

Code: Alles auswählen

#define BME280_I2C_ADDR_PRIM    UINT8_C(0x76) 
überein.

So, damit ich das auch wirklich richtig nachvollzogen habe:
linux_userspace:main(): dev wird als struct vom Typ bme280_dev initiert. Dann wird dev.dev_id auf BME280_I2C_ADDR_PRIM, also 76Hex gesetzt. (wieso wird hier ein Punkt statt -> verwendet?)
Und dev.read = user_i2c_read; , also das read von Zeile 175
In Zeile 155 wird dev an bme280.init() übergeben, dass wiederum bme280_get_regs() aufruft. (wie gesagt, das Problem ist vorgeblich, dass die chip-Id als falsch erkannt wird)
Dort wird in Zeile 417 rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); (jetzt wieder mit -> ..... Punkt zum setzten, -> zum lesen ??)
aufgerufen also linux_userspace Zeile 175 user_i2c_read(uint8_t id,...)
Genau diese id wird in der Funktion aber gar nicht verwendet - wie soll so ein bestimmtes Gerät angesprochen werden ? - fd ist ja bloß der Filehandle für den i2c-1-Bus.
Benutzeravatar

SeriousD
Beiträge: 427
Registriert: Mi 26. Aug 2009, 22:16
Spezialgebiet: Handwerkliche Improvisationen
Wohnort: Kiel
Hat sich bedankt: 19 Mal
Danksagung erhalten: 41 Mal

Re: BME280, Raspberry, Programmieren in C

Beitrag von SeriousD »

Moin,

also bevor ich Dir helfe vermutlich funktionierenden Code nachzuvollziehen(mach ich später wirklich gerne), wäre es ganz nett, wenn Du uns hilfst Dein Problem nachzuvollziehen, dafür ist immerhin der Thread da und nicht für ein C-Tutorial.

Also beantworte mal die vorangegangenen Fragen, sonst können wir auch nur die in Glaskugel gucken.

Außerdem:
RaspKiller hat geschrieben: Mi 27. Mai 2020, 19:05 Laufen tut's aber genauso wenig.
Wie kommst Du zu dem Schluss?
Hast Du irgendwas verändert?
Wie hast Du das Programm aufgerufen?
Was ist die Fehlermeldung?

Grüße
SeriousD
Hey Sigma, ist noch Lambda? - Ja aber das Phi ist noch Rho.

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

Re: BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

Ok, also:

Mit
gcc linux_userspace.c ../bme280.c -I ../ -o bme280
und
./bme280 /dev/i2c-1
erhalte ich
Failed to initialize the device (code -2).


In meinem Experimentier-Order habe ich in bme280.c hinter Zeile 365 - in der der Aufruf

Code: Alles auswählen

 rslt = bme280_get_regs(BME280_CHIP_ID_ADDR, &chip_id, 1, dev); 
zu finden ist - eine Ausgabe gebastelt:

Code: Alles auswählen

printf("in bme280_init() : rslt= %i , should be: %i ; chipID is: %u , should be: %u\n", BME280_OK, rslt, chip_id,BME280_CHIP_ID);
welche mir :
in bme280_init() : rslt= 0 , should be: 0 ; chipID is: 0 , should be: 96
ausgibt - bei allen 5 Aufrufen der while-Schleife.

Was innerhalb von bme280_get_regs() beim Aufruf (Zeile 417)

Code: Alles auswählen

 rslt = dev->read(dev->dev_id, reg_addr, reg_data, len);
passieren soll, versteh ich eben nicht.

Thread-Ersteller
RaspKiller
Beiträge: 7
Registriert: Di 26. Mai 2020, 20:22
Spezialgebiet: Raspberry

Re: BME280, Raspberry, Programmieren in C

Beitrag von RaspKiller »

Danke auch für die den Tipp mit gcc -v

In gdb wollte ich mich eh einarbeiten.
Antworten