SMRM_V4_Teil1_template__2_.c


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
}