/* * SMRM_V4_Teil1.c * * Created: 21.06.2021 * Author : viga, rosenkranz */ #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