Pulse oximeter (MAX30102) with splash screen

Hi guys,

I hope someone can help me.

To cut to the chase, I am making myself a pulse oximeter with Arduino Nano, a MAX30102 sensor and an 0.96" Inch I2C OLED LCD Module.

The code is not my own, I just made it work as I had some issues with the libraries specified in it.

Now it works, however, I would like to have a small splash screen for 3 seconds displayed (with an image) when the device is turned on. Included in the code is also the image (in const unsigned char), however I don't know how to do it.

If someone can help, pretty please!

#include "ssd1306h.h"
#include "MAX30102.h"
#include "Pulse.h"
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <avr/sleep.h>
#include <Wire.h>

// Routines to clear and set bits 
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


SSD1306 oled; 
MAX30102 sensor;
Pulse pulseIR;
Pulse pulseRed;
MAFilter bpm;

#define LED LED_BUILTIN
#define BUTTON 3
#define OPTIONS 7

static const uint8_t heart_bits[] PROGMEM = { 0x00, 0x00, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0xfe, 0xff, 
                                        0xfe, 0xff, 0xfc, 0x7f, 0xf8, 0x3f, 0xf0, 0x1f, 0xe0, 0x0f,
                                        0xc0, 0x07, 0x80, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
                                        0x00, 0x00 };

//spo2_table is approximated as  -45.060*ratioAverage* ratioAverage + 30.354 *ratioAverage + 94.845 ;
const uint8_t spo2_table[184] PROGMEM =
        { 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99, 
          99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
          100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97, 
          97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 
          90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81, 
          80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67, 
          66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 
          49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29, 
          28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 
          3, 2, 1 } ;
// 'logo', 128x64px
const unsigned char bmp_logo [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x18, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x47, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0xbf, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x20, 0x08, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c, 0x01, 0xfe, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x03, 0xff, 0xff, 0xff, 0x80, 0x00, 0x10, 0x00, 0x10, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x07, 0xff, 0xff, 0xff, 0x80, 0x00, 0x10, 0x00, 0x10, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x07, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x10, 0x00, 0x10, 0x08, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x18, 0x00, 0x10, 0x08, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x07, 0xf0, 0x10, 0x08, 0x22, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x1f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x10, 0x10, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 
	0x00, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x80, 
	0x00, 0x0f, 0xc0, 0x7c, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 
	0x00, 0x0f, 0x00, 0x38, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 
	0x00, 0x0e, 0x00, 0x30, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 
	0x00, 0x0c, 0x00, 0x30, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 
	0x00, 0x1c, 0x00, 0x30, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 
	0x00, 0x1c, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 
	0x00, 0x1c, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 
	0x00, 0x0e, 0x00, 0xf8, 0x00, 0x70, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 
	0x00, 0x0e, 0x00, 0xfc, 0x00, 0xf0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
	0x00, 0x07, 0x07, 0xaf, 0x00, 0xf0, 0x01, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
	0x00, 0x07, 0xdf, 0x27, 0xe3, 0xe0, 0x01, 0x40, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 
	0x00, 0x03, 0xff, 0x27, 0xff, 0xc0, 0x01, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 
	0x00, 0x01, 0xff, 0x27, 0xff, 0xc0, 0x01, 0x10, 0x00, 0x80, 0x00, 0x00, 0x1c, 0x00, 0x08, 0x00, 
	0x00, 0x00, 0x0e, 0x23, 0xe6, 0x00, 0x01, 0x08, 0x00, 0x80, 0x00, 0x00, 0x12, 0x00, 0x08, 0x00, 
	0x00, 0x01, 0xc7, 0x27, 0xe0, 0xc0, 0x01, 0x08, 0x00, 0x80, 0x00, 0x00, 0x22, 0x00, 0x08, 0x00, 
	0x00, 0x01, 0xc7, 0xff, 0xe1, 0xc0, 0x01, 0x04, 0xc0, 0x80, 0x02, 0x04, 0x42, 0x00, 0x08, 0x00, 
	0x00, 0x01, 0xc7, 0xff, 0xe1, 0xc0, 0x01, 0x07, 0x00, 0x40, 0x82, 0x08, 0x44, 0x00, 0x00, 0x00, 
	0x00, 0x01, 0xc6, 0xee, 0xe1, 0xc0, 0x01, 0x79, 0x00, 0x40, 0x82, 0x10, 0x5c, 0x00, 0x00, 0x00, 
	0x00, 0x01, 0xc0, 0x06, 0x01, 0x80, 0x03, 0x81, 0x80, 0x40, 0x82, 0x10, 0x20, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0xe0, 0x58, 0x01, 0x80, 0x04, 0x80, 0x40, 0x20, 0x82, 0x10, 0x20, 0x80, 0x00, 0x00, 
	0x00, 0x00, 0xe2, 0x00, 0x03, 0x80, 0x00, 0x80, 0x40, 0x20, 0x81, 0x20, 0x13, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0xec, 0xc8, 0x6f, 0x80, 0x00, 0x80, 0x20, 0x20, 0x81, 0x20, 0x1e, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0xfc, 0xcc, 0xff, 0x00, 0x00, 0x80, 0x20, 0x20, 0x81, 0x40, 0x00, 0x00, 0x08, 0x00, 
	0x00, 0x00, 0xff, 0xde, 0xff, 0x00, 0x00, 0x80, 0x20, 0x20, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x80, 0x30, 0x20, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


int getVCC() {
  //reads internal 1V1 reference against VCC
  #if defined(__AVR_ATmega1284P__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // For ATmega1284
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // For ATmega328
  #endif
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA, ADSC));
  uint8_t low = ADCL;
  unsigned int val = (ADCH << 8) | low;
  //discard previous result
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA, ADSC));
  low = ADCL;
  val = (ADCH << 8) | low;
  
  return (((long)1024 * 1100) / val)/100;  
}

void print_digit(int x, int y, long val, char c=' ', uint8_t field = 3,const int BIG = 2)
    {  
    uint8_t ff = field;
    do { 
        char ch = (val!=0) ? val%10+'0': c;
        oled.drawChar( x+BIG*(ff-1)*6, y, ch, BIG);
        val = val/10; 
        --ff;
    } while (ff>0);
}


/*
 *   Record, scale  and display PPG Wavefoem
 */
const uint8_t MAXWAVE = 72;

class Waveform {
  public:
    Waveform(void) {wavep = 0;}

      void record(int waveval) {
        waveval = waveval/8;         // scale to fit in byte  缩放以适合字节
        waveval += 128;              //shift so entired waveform is +ve  
        waveval = waveval<0? 0 : waveval;
        waveform[wavep] = (uint8_t) (waveval>255)?255:waveval; 
        wavep = (wavep+1) % MAXWAVE;
      }
  
      void scale() {
        uint8_t maxw = 0;
        uint8_t minw = 255;
        for (int i=0; i<MAXWAVE; i++) { 
          maxw = waveform[i]>maxw?waveform[i]:maxw;
          minw = waveform[i]<minw?waveform[i]:minw;
        }
        uint8_t scale8 = (maxw-minw)/4 + 1;  //scale * 8 to preserve precision
        uint8_t index = wavep;
        for (int i=0; i<MAXWAVE; i++) {
          disp_wave[i] = 31-((uint16_t)(waveform[index]-minw)*8)/scale8;
          index = (index + 1) % MAXWAVE;
        }
      }

void draw(uint8_t X) {
  for (int i=0; i<MAXWAVE; i++) {
    uint8_t y = disp_wave[i];
    oled.drawPixel(X+i, y);
    if (i<MAXWAVE-1) {
      uint8_t nexty = disp_wave[i+1];
      if (nexty>y) {
        for (uint8_t iy = y+1; iy<nexty; ++iy)  
        oled.drawPixel(X+i, iy);
        } 
        else if (nexty<y) {
          for (uint8_t iy = nexty+1; iy<y; ++iy)  
          oled.drawPixel(X+i, iy);
          }
       }
    } 
}

private:
    uint8_t waveform[MAXWAVE];
    uint8_t disp_wave[MAXWAVE];
    uint8_t wavep = 0;
    
} wave;

int  beatAvg;
int  SPO2, SPO2f;
int  voltage;
bool filter_for_graph = false;
bool draw_Red = false;
uint8_t pcflag =0;
uint8_t istate = 0;
uint8_t sleep_counter = 0;

void button(void){
    pcflag = 1;
}

void checkbutton(){
    if (pcflag && !digitalRead(BUTTON)) {
      istate = (istate +1) % 4;
      filter_for_graph = istate & 0x01;
      draw_Red = istate & 0x02;
      EEPROM.write(OPTIONS, filter_for_graph);
      EEPROM.write(OPTIONS+1, draw_Red);
    }
    pcflag = 0;
}



void Display_5(){
   if(pcflag && !digitalRead(BUTTON)){
     draw_oled(5);
     delay(1100);
   }
   pcflag = 0;
 

}

void go_sleep() {
    oled.fill(0);
    oled.off();
    delay(10);
    sensor.off();
    delay(10);
    cbi(ADCSRA, ADEN);  // disable adc
    delay(10);
    pinMode(0,INPUT);
    pinMode(2,INPUT);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);     
    sleep_mode();  // sleep until button press 
    // cause reset
    setup();
}

void draw_oled(int msg) {
    oled.firstPage();
    do{
    switch(msg){
        case 0:  oled.drawStr(10,0,F("Device error"),1); 
                 break;
        case 1:  oled.drawStr(13,10,F("PLACE"),1); 
                 oled.drawStr(10,20,F("SAUSAGE"),1);
                 oled.drawChar(100,0,voltage/10+'0');
                 oled.drawChar(106,0,'.');
                 oled.drawChar(112,0,voltage%10+'0');
                 oled.drawChar(118,0,'V');
                 oled.drawStr(84,14,F("Display"),1); 
                 if (draw_Red) 
                    oled.drawStr(84,24,F("Red"),1); 
                 else
                    oled.drawStr(84,24,F("IR"),1); 
                 if (filter_for_graph) 
                    oled.drawStr(108,24,F("Avg"),1); 
                 else
                    oled.drawStr(108,24,F("Raw"),1); 
                 break;
        case 2:  print_digit(86,0,beatAvg);
                 wave.draw(8);
                 print_digit(98,16,SPO2f,' ',3,1);
                 oled.drawChar(116,16,'%');
                 print_digit(98,24,SPO2,' ',3,1);
                 oled.drawChar(116,24,'%');
                 break;
        case 3:  oled.drawStr(0,9,F("Instagram"),1);
                 oled.drawStr(0,20,F("diavolulmentolat"),1);
                 //oled.drawXBMP(6,8,16,16,heart_bits);
                
                 break;
        case 4:  oled.drawStr(28,12,F("OFF IN"),1);
                 oled.drawChar(76,12,10-sleep_counter/10+'0');
                 oled.drawChar(82,12,'*');
                 break;
        case 5:  oled.drawStr(0,0,F("BMP:"),1); 
                 print_digit(25,0,beatAvg);
                 oled.drawStr(0,15,F("SpO2:"),1); 
                 print_digit(25,15,SPO2);
                 oled.drawXBMP(106,8,16,16,heart_bits);
                 break;
        }
    } while (oled.nextPage());
}

void setup(void) {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  filter_for_graph = EEPROM.read(OPTIONS);
  draw_Red = EEPROM.read(OPTIONS+1);
  oled.init();
  oled.fill(0x00);
  draw_oled(3);
  delay(3000); 
  if (!sensor.begin())  {
    draw_oled(0);
    while (1);
  }
  sensor.setup(); 
  attachInterrupt(digitalPinToInterrupt(BUTTON),button, CHANGE);
}

long lastBeat = 0;    //Time of the last beat 
long displaytime = 0; //Time of the last display update
bool led_on = false;


void loop()  {
  
    sensor.check();
    long now = millis();   //start time of this cycle
    if (!sensor.available()) return;
    uint32_t irValue = sensor.getIR(); 
    uint32_t redValue = sensor.getRed();
    sensor.nextSample();
    if (irValue<5000) {
        voltage = getVCC();
        checkbutton();
        draw_oled(sleep_counter<=50 ? 1 : 4); // finger not down message
        //? : 是三元运算符,整个表达式根据条件返回不同的值,如果x>y为真则返回x,如果为假则返回y,之后=赋值给z。相当于:if(x>y)z=x;elsez=y
        delay(200);
        ++sleep_counter;
        if (sleep_counter>100) {
          go_sleep(); 
          sleep_counter = 0;
        }
    } else {
        sleep_counter = 0;
        // remove DC element移除直流元件
        int16_t IR_signal, Red_signal;
        bool beatRed, beatIR;
        if (!filter_for_graph) {//图形过滤器
           IR_signal =  pulseIR.dc_filter(irValue) ;
           Red_signal = pulseRed.dc_filter(redValue);
           beatRed = pulseRed.isBeat(pulseRed.ma_filter(Red_signal));
           beatIR =  pulseIR.isBeat(pulseIR.ma_filter(IR_signal));        
        } else {
           IR_signal =  pulseIR.ma_filter(pulseIR.dc_filter(irValue)) ;
           Red_signal = pulseRed.ma_filter(pulseRed.dc_filter(redValue));
           beatRed = pulseRed.isBeat(Red_signal);
           beatIR =  pulseIR.isBeat(IR_signal);
        }
        // invert waveform to get classical BP waveshape
        wave.record(draw_Red ? -Red_signal : -IR_signal ); 
        // check IR or Red for heartbeat     
        if (draw_Red ? beatRed : beatIR){
            long btpm = 60000/(now - lastBeat);
            if (btpm > 0 && btpm < 200) beatAvg = bpm.filter((int16_t)btpm);
            lastBeat = now; 
            digitalWrite(LED, HIGH); 
            led_on = true;
            // compute SpO2 ratio
            long numerator   = (pulseRed.avgAC() * pulseIR.avgDC())/256;
            long denominator = (pulseRed.avgDC() * pulseIR.avgAC())/256;
            int RX100 = (denominator>0) ? (numerator * 100)/denominator : 999;
            // using formula
            SPO2f = (10400 - RX100*17+50)/100;  
            // from table
            if ((RX100>=0) && (RX100<184))
              SPO2 = pgm_read_byte_near(&spo2_table[RX100]);
        }
        // update display every 50 ms if fingerdown
        if (now-displaytime>50) {
            displaytime = now;
            wave.scale();
            draw_oled(2);
            
        }
        Display_5();

 
    }
    // flash led for 25 ms
    if (led_on && (now - lastBeat)>25){
        digitalWrite(LED, LOW);
        led_on = false;
     }
}

Among the thousands of examples...

Most OLED are monochrome.

I did read all the thousands and thousands of them, however I do not understand how I should display the shape before initializing the readings and the rest of the functions upon turning it on.
I can do it individually following tutorials for doing the pulse oximeter or displaying the image, but I cannot understand how to mix them both

my oled is yellow-blue

That's just a mask. It's monochrome.

If I understand you...

  1. place the cursor
  2. display the image.

"the image" can be any of the images you loaded into memory using the arrays (like your image above).

This is the image display example from the link above... it says, "At 0,0, display image_data_Saraarray, for 128x64 pixels, color WHITE"

  // Draw bitmap on the screen
  display.drawBitmap(0, 0, image_data_Saraarray, 128, 64, 1);
  display.display();

If you want other images, just replace "image_data_Saraarray" with any of your image names.

Give it a try, here.

1 Like

Ok, thanks guys, so I got it working at last!

Following the error, I changed the code here in "case 3" of the code, where I was displaying two lines of text.

case 3:  oled.drawXBMP(0,0,128, 64, LOGO);
                 //oled.drawXBMP(6,8,16,16,heart_bits);
                 break;

I finally found this Arduino_701/DrawLogo/DrawLogo.ino at master · kjellcompany/Arduino_701 · GitHub

which I replaced from the initial oled.drawStr which I understood that drawStr is for text:

at the moment the image is stretched but I guess I'll fix it fast.

Thanks guys!

For the setup, it's the one here:

for portability, I will add a LiPo battery with a TP4056 charging module and a boost converter to use 5V.
afaik, the switch for power, I have to add between the charging module and the boost converter.

@Theronredmond - You should start your own topic to get help for your code. Do not hijack other topics.

Also, wrap your code in a code block...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.