Guten Tag liebe Community,
dies ist mein erster Post, deswegen entschuldige ich mich vorab bei
falscher Formatierung.
Für die Universität muss ich folgendes Projekt fertig kriegen. Da wegen
der Coronapandemie die praktische Seite des Projekts weggefallen ist und
ich somit große Probleme mit dem Code habe, bitte ich hier um Hilfe.
Hier habe ich nochmal den zu vervollständigenden Code reinkopiert.
Danke im Voraus
Tareq
#define F_CPU 16000000
//Nachfolgend müssen vier Bibliotheks-Dateien eingebunden werden (bitte
Punkte passend ersetzen)
#include ...
#include ...
#include ...
#include ...
// MAX30102 I2C device ID & Konfigurationsregister Adressen
#define MAX30102_ID 0xAE
#define MAX30102_REG_INT_STATUS 0x00
#define MAX30102_REG_INT_EN 0x02
#define MAX30102_REG_FIFO_DATA 0x07
#define MAX30102_REG_FIFO_CONFIG 0x08
#define MAX30102_REG_MODE_CONFIG 0x09
#define MAX30102_REG_SPO2_CONFIG 0x0A
#define MAX30102_REG_LED1_PA 0x0C
// Ring Puffer für gleitende Mittelwertbildung
#define BUFFER_SIZE 128 // Mittelwertbildung über
128 Werte ...
#define BUFFER_BITS 7 // ... entsprechend 2^7
(=128)
#define BUFFER_MASK 0x7F // Maskierwort für das
Überlauf-Handling von 127 --> 0
uint16_t buffer[BUFFER_SIZE]; // Enthält letzte 128
PPG-Werte für die Mittelwertbildung
uint8_t buffer_index = 0; // Index-Nummer des
nächsten Eintragselements im Array
uint32_t buffer_sum = 0; // Laufende Summe über alle
Array-Werte
// Weitere globale Variablen und Felder
uint8_t i2c_data[3]; // Array für neu ausgelesene
FIFO-Werte
uint16_t ppg_raw; // Enthält Höchstwertige 16
Bits des 18-Bit FIFO-Werts
uint16_t ppg_avg; // Enthält den aus buffer_sum
berechneten Mittelwert
int16_t ppg_ac; // Enthält Wechselanteil des
PPG-Wertes
// (aus Differenz zum Mittelwert)
uint8_t graph; // Enthält Anzahl der Zeichen je
Zeile für den Text-Graph
void sensor_init(void)
{ // Initialisierungssequenz für die
Pulsmessung
// (nicht genannte Parameter auf "0"
setzen!)
i2c_write_byte(MAX30102_ID, MAX30102_REG_MODE_CONFIG, ...); //
Heart-Rate Modus (nur rote LED)
i2c_write_byte(MAX30102_ID, MAX30102_REG_FIFO_CONFIG, ...); //
FIFO-Rollover aktiviert, chipinterne Mittelwert-
// bildung über 8 Werte je FIFO Wert
i2c_write_byte(MAX30102_ID, MAX30102_REG_SPO2_CONFIG, ...); // 18
Bit Auflösung, 400 samples/s
// (Mittelwert über 8 Werte entspricht
50 FIFO Werte/s)
i2c_write_byte(MAX30102_ID, MAX30102_REG_LED1_PA, ...); // LED
Strom 6,2 mA, (bei schlechtem Signal erhöhen)
i2c_write_byte(MAX30102_ID, MAX30102_REG_INT_EN, ...); // PPG_RDY
Interrupt aktivieren
// (wird für die Erkennung neuer Werte
im FIFO benötigt)
}
int main(void)
{
// Konfiguration USART für ausschließlichen Sendebetrieb mit 19200
Baud
uart_setup(..., ..., ...);
// Interrupts global freigeben
...();
// Konfiguration I2C Schnittstelle für MAX30102
DDRE = 0b00001110; // PE0 (SDA1) INPUT, PE1 - PE3
(SCL1, VIN, GND) OUTPUT
PORTE = 0b00000110; // PE0 (SDA1) TRISTATE, PE1
(SCL1) + PE2 (VIN) HIGH,
// PE3 (GND) auf LOW
...(); // Initialisierung des I2C-Bus
_delay_ms(1); // Initialisierungszeit
(sicherheitshalber) abwarten
sensor_init(); // Initialisierung des
PPG-Moduls für die Pulsmessung
while (1)
{
// Prüfung ob "New FIFO Data Ready" (PPG_RDY) Interrupt Flag im
Interrupt Status Register gesetzt wurde und somit ein neuer Wert
bereitsteht
if(i2c_read_byte(MAX30102_ID, ...) == ...)
{ // Nur in diesem Fall ...
// ... einen PPG-Wert per I2C vom Sensor lesen (3 Bytes,
little-endian) ...
i2c_read_n_bytes(MAX30102_ID, ..., ..., ...);
// ... diesen 18-Bit ADC-Wert (rechtsbündig in 3 Bytes) in einen
16-Bit Wert konvertieren ...
// (Nur die Bits [15:0] werden genutzt)
ppg_raw = ...;
// ... diesen in die gleitende Mittelwertbildung über 128 Stellen
einbeziehen ...
buffer_sum -= buffer[buffer_index];
buffer[buffer_index] = ...;
buffer_sum += ...;
buffer_index = ...;
ppg_avg = ...;
// ... mit diesem als Referenz den Wechselanteil (AC-ANteil) des
PPG-Signals ermitteln (kann positiv oder negativ sein) ...
ppg_ac = ...;
// ... und diesen dann abschließend als neuen Balken eines
Balken-Diagramms aus Textzeichenketten über den USART Übertragen
graph = (uint8_t)(...); // Textzeichenzahl für
positiven Wertebereich 0..31
// skalieren und ...
for (uint8_t n = 0; n<graph; n++)
{
printf(...); // ... entsprechende Anzahl
Zeichen ausgeben, dann ...
} // (Textzeichen für Stapel kann
frei gewählt werden)
printf(...); // ... Textzeile abschließen
}
}
}
Tareq schrieb:> Guten Tag liebe Community,
Bist du ein großer Britanier? In Teutonien spricht man eher von einer
Gemeinde oder Gemeinschaft.
> dies ist mein erster Post,
Arbeitest du bei selbiger? Forumsteilnehmer der teutonischen Art
schreiben Beiträg oder Fragen.
> deswegen entschuldige ich mich vorab bei> falscher Formatierung.
Nö. Auch DU darfst und MUSST lesen
"Antwort schreiben
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"
> Hier habe ich nochmal den zu vervollständigenden Code reinkopiert.
Schlecht. U.a. weil die leicht angeschlagene Forensoftware da extra
Umbrüche eingefügt hat.
Also bitte noch einmal als Anhang.
Ach so. Was ist denn eigentlich die Frage? Siehe NetiquetteBeitrag "Einheitlicher Umgang mit faulen Schülern etc.?"
Das Modul ist über vier Leitungen an den Port E des ATmega328PB
angeschlossen. Der Interrupt-Ausgang des Moduls ist nicht mit dem
Controller verbunden, so dass die Verfügbarkeit neuer Messwerte nur
durch wiederholtes Abfragen des Interrupt-Status ("Polling"), ermittelt
werden kann. Dafür muss der Interrupt des Moduls zuvor initial aktiviert
werden.
Die Versorgungsspannung bezieht das Modul aus den Port-Pins des Port E.
Dazu müssen initial die betreffenden Port-Pins PE3 als Masseanschluss
(GND) in den Zustand OUTPUT LOW und PE2 als Versorgungsspannung (+5 V)
in den Zustand OUTPUT HIGH versetzt werden. Da der Mikrocontroller als
einziger I2C-Master am Bus fungiert, erfolgt die Taktversorgung für die
Kommunikation über die SCL-Leitung an PE1 treibend durch ihn, so dass
der betreffende Pin initial in den Leerlaufzustand OUTPUT HIGH versetzt
werden kann . Der Kommunikationsanschluss SDA an PE0 sollte
sicherheitshalber initial
in den rezeptiven Zustand INPUT TRISTATE versetzt werden, damit nach dem
Einschalten der Spannungsversorgung durch unbestimmte Signalzustände
keine ungewollten Schreib- Aktionen auftreten können.
. Zur Durchführung der Messung muss ein Finger ohne Andruck wie in
Abbildung 11 gezeigt vollflächig auf die Aussparung des Gehäusedeckels
gelegt werden, so dass der Finger die nach Aktivierung rot leuchtende
LED des Moduls abdeckt.
Klaus W. schrieb:> ok: ich vermnute, du sollst die mit ... markierten Bereiche sinnvoll> ausfüllen.
Gut, vielleicht deutlicher: ich vermute, DU sollst die mit ...
markierten Bereiche sinnvoll ausfüllen.
Tareq B. schrieb:> Abbildung
Merkwürdig. VIN und GND schließt man nicht an IOs an, sondern an die
Stromversorgung und GND. Bei SCL und SDA fehlen Pull-Up Widerstände nach
VCC. Dann muss man halt das Ding per I2C ansprechen, Dazu muss man
diverse Sequenzen schreiben und lesen. Wie das per I21C geht, steht
sicher im Datenblatt. Wenn nicht, kann man nach I2C googeln und das
Grundprinzip erlernen. Bei direkten Fragen stehen wir gern zur
Verfügung.
Tareq B. schrieb:> Sollten wir nur den Teil 1 als Hausaufgabe fertig machen
Das verstehe ich jetzt nicht.
Welchen Teil 1? Ist das nicht das Blinklicht?
Deine Frage oben ist doch Teil 4?
Falk B. schrieb:> Merkwürdig. VIN und GND schließt man nicht an IOs an, sondern an die> Stromversorgung und GND.
Genau
Zumindest nicht, solange man nicht weiß wieviel Strom das angeschlossene
Teil zieht, und wieviel Strom der Port am AVR liefern mag, bevor etwas
abraucht.
Tareq B. schrieb:> Abbildung
Wo ist denn die Abbildung her? Vom Dozenten so vorgegeben? Das kann ich
kaum glauben.
Tareq B. schrieb:> Sollten wir nur den Teil 1 als Hausaufgabe fertig machen
Aha. Und was hat das mit deiner Überschrift zu tun?
1. Einführung
Kennenlernen der Hardware und
Entwicklungs-Umgebung
• Einführung
• Blinklicht in Assembler
• Sekundenzähler mit der 7-Segment-Anzeige in C
Das ein guter Einstieg für Anfänger. Dazu muss man aber mal ANFANGEN!
Klaus W. schrieb:> Das verstehe ich jetzt nicht.> Welchen Teil 1? Ist das nicht das Blinklicht?>> Deine Frage oben ist doch Teil 4?
Er meint Versuch 4, Teil 1, Seite 11. Dort sieht man auch das
fragwürdige Blockschaltbild.
"Die Versorgungsspannung bezieht das Modul aus den Port-Pins des Port E.
Dazu müssen initial die betreffenden Port-Pins PE3 als Masseanschluss
(GND) in den Zustand OUTPUT LOW und PE2 als Versorgungsspannung (+5 V)
in den Zustand OUTPUT HIGH versetzt werden. Da der Mikrocontroller als
einziger I2C-Master am Bus fungiert, erfolgt die Taktversorgung für die
Kommunikation über die SCL-Leitung an PE1 treibend durch ihn, so dass
der betreffende Pin initial in den Leerlaufzustand OUTPUT HIGH versetzt
werden kann (s. Abbildung 7)."
Ganz schöne Käse.
Die Stromversorgung sollte man nicht mit IOs machen, schon gar nicht bei
GND, der wird fest angeschlossen. VCC KANN man ggf. per IO versorgen,
wenn der Sensor nur wenige mA benötigt.
Wenn man schon I2C macht, dann bitte richtig! D.H. auch SCL wird immer
nur aktiv LOW oder Tristate geschaltet, NIE aktiv HIGH, denn es ist ein
Open Drain Signal. Es kostet weder Geld noch Aufwand, es gleich richtig
zu machen.
Aber alles in Allem ist doch schon verdammt viel erklärt! Es werden auch
ganz konkrete Teilaufgaben gestellt (I2C konfigurieren, UART
konfigurieren etc.) Die muss man Schritt für Schritt abarbeiten und
testen. Ja, das ist Aufwand und nicht in 1h erledigt! Schon gar nicht,
wenn man das lernen will.
Falk B. schrieb:> Er meint Versuch 4, Teil 1, Seite 11. Dort sieht man auch das> fragwürdige Blockschaltbild.
Danke, wollte im Skript nicht weiter lesen als der TO :-)
Ist aber ganz interessant zu lesen:
> Für die Beantwortung der nachfolgenden Fragen finden Sie alle> notwendigen Informationen in den Unterlagen der> Praktikumsversuche1 bis 4, im Datenblatt> des ATmega328PB und im Datenblatt des MAX30102.
Falk B. schrieb:> Schon gar nicht,> wenn man das lernen will.
Geht leider nicht. Du weißt doch, wegen Corona!
Wenn ich das Skript überfliege, finde ich das als Vorbereitung
eigentlich gut gemacht (von der HW-Anbindung mal abgesehen - wenn es
funktioniert, soll es so sein).