1 | /*
|
2 | * SMRM_V4_Teil1.c
|
3 | *
|
4 | * Created: 21.06.2021
|
5 | * Author : viga, rosenkranz
|
6 | */
|
7 |
|
8 | #define F_CPU 16000000
|
9 |
|
10 | //Nachfolgend müssen vier Bibliotheks-Dateien eingebunden werden (bitte Punkte passend ersetzen)
|
11 | #include ...
|
12 | #include ...
|
13 | #include ...
|
14 | #include ...
|
15 |
|
16 | // MAX30102 I2C device ID & Konfigurationsregister Adressen
|
17 | #define MAX30102_ID 0xAE
|
18 | #define MAX30102_REG_INT_STATUS 0x00
|
19 | #define MAX30102_REG_INT_EN 0x02
|
20 | #define MAX30102_REG_FIFO_DATA 0x07
|
21 | #define MAX30102_REG_FIFO_CONFIG 0x08
|
22 | #define MAX30102_REG_MODE_CONFIG 0x09
|
23 | #define MAX30102_REG_SPO2_CONFIG 0x0A
|
24 | #define MAX30102_REG_LED1_PA 0x0C
|
25 |
|
26 |
|
27 | // Ring Puffer für gleitende Mittelwertbildung
|
28 | #define BUFFER_SIZE 128 // Mittelwertbildung über 128 Werte ...
|
29 | #define BUFFER_BITS 7 // ... entsprechend 2^7 (=128)
|
30 | #define BUFFER_MASK 0x7F // Maskierwort für das Überlauf-Handling von 127 --> 0
|
31 |
|
32 | uint16_t buffer[BUFFER_SIZE]; // Enthält letzte 128 PPG-Werte für die Mittelwertbildung
|
33 | uint8_t buffer_index = 0; // Index-Nummer des nächsten Eintragselements im Array
|
34 | uint32_t buffer_sum = 0; // Laufende Summe über alle Array-Werte
|
35 |
|
36 | // Weitere globale Variablen und Felder
|
37 | uint8_t i2c_data[3]; // Array für neu ausgelesene FIFO-Werte
|
38 | uint16_t ppg_raw; // Enthält Höchstwertige 16 Bits des 18-Bit FIFO-Werts
|
39 | uint16_t ppg_avg; // Enthält den aus buffer_sum berechneten Mittelwert
|
40 | int16_t ppg_ac; // Enthält Wechselanteil des PPG-Wertes
|
41 | // (aus Differenz zum Mittelwert)
|
42 | uint8_t graph; // Enthält Anzahl der Zeichen je Zeile für den Text-Graph
|
43 |
|
44 |
|
45 | void sensor_init(void)
|
46 | { // Initialisierungssequenz für die Pulsmessung
|
47 | // (nicht genannte Parameter auf "0" setzen!)
|
48 | i2c_write_byte(MAX30102_ID, MAX30102_REG_MODE_CONFIG, ...); // Heart-Rate Modus (nur rote LED)
|
49 | i2c_write_byte(MAX30102_ID, MAX30102_REG_FIFO_CONFIG, ...); // FIFO-Rollover aktiviert, chipinterne Mittelwert-
|
50 | // bildung über 8 Werte je FIFO Wert
|
51 | i2c_write_byte(MAX30102_ID, MAX30102_REG_SPO2_CONFIG, ...); // 18 Bit Auflösung, 400 samples/s
|
52 | // (Mittelwert über 8 Werte entspricht 50 FIFO Werte/s)
|
53 | i2c_write_byte(MAX30102_ID, MAX30102_REG_LED1_PA, ...); // LED Strom 6,2 mA, (bei schlechtem Signal erhöhen)
|
54 | i2c_write_byte(MAX30102_ID, MAX30102_REG_INT_EN, ...); // PPG_RDY Interrupt aktivieren
|
55 | // (wird für die Erkennung neuer Werte im FIFO benötigt)
|
56 | }
|
57 |
|
58 |
|
59 | int main(void)
|
60 | {
|
61 | // Konfiguration USART für ausschließlichen Sendebetrieb mit 19200 Baud
|
62 | uart_setup(..., ..., ...);
|
63 |
|
64 | // Interrupts global freigeben
|
65 | ...();
|
66 |
|
67 | // Konfiguration I2C Schnittstelle für MAX30102
|
68 | DDRE = 0b00001110; // PE0 (SDA1) INPUT, PE1 - PE3 (SCL1, VIN, GND) OUTPUT
|
69 | PORTE = 0b00000110; // PE0 (SDA1) TRISTATE, PE1 (SCL1) + PE2 (VIN) HIGH,
|
70 | // PE3 (GND) auf LOW
|
71 | ...(); // Initialisierung des I2C-Bus
|
72 | _delay_ms(1); // Initialisierungszeit (sicherheitshalber) abwarten
|
73 | sensor_init(); // Initialisierung des PPG-Moduls für die Pulsmessung
|
74 |
|
75 | while (1)
|
76 | {
|
77 | // Prüfung ob "New FIFO Data Ready" (PPG_RDY) Interrupt Flag im Interrupt Status Register gesetzt wurde und somit ein neuer Wert bereitsteht
|
78 | if(i2c_read_byte(MAX30102_ID, ...) == ...)
|
79 | { // Nur in diesem Fall ...
|
80 | // ... einen PPG-Wert per I2C vom Sensor lesen (3 Bytes, little-endian) ...
|
81 | i2c_read_n_bytes(MAX30102_ID, ..., ..., ...);
|
82 |
|
83 | // ... diesen 18-Bit ADC-Wert (rechtsbündig in 3 Bytes) in einen 16-Bit Wert konvertieren ...
|
84 | // (Nur die Bits [15:0] werden genutzt)
|
85 | ppg_raw = ...;
|
86 |
|
87 | // ... diesen in die gleitende Mittelwertbildung über 128 Stellen einbeziehen ...
|
88 | buffer_sum -= buffer[buffer_index];
|
89 | buffer[buffer_index] = ...;
|
90 | buffer_sum += ...;
|
91 | buffer_index = ...;
|
92 | ppg_avg = ...;
|
93 |
|
94 | // ... mit diesem als Referenz den Wechselanteil (AC-ANteil) des PPG-Signals ermitteln (kann positiv oder negativ sein) ...
|
95 | ppg_ac = ...;
|
96 |
|
97 | // ... und diesen dann abschließend als neuen Balken eines Balken-Diagramms aus Textzeichenketten über den USART Übertragen
|
98 | graph = (uint8_t)(...); // Textzeichenzahl für positiven Wertebereich 0..31
|
99 | // skalieren und ...
|
100 | for (uint8_t n = 0; n<graph; n++)
|
101 | {
|
102 | printf(...); // ... entsprechende Anzahl Zeichen ausgeben, dann ...
|
103 | } // (Textzeichen für Stapel kann frei gewählt werden)
|
104 | printf(...); // ... Textzeile abschließen
|
105 | }
|
106 | }
|
107 | }
|