How can I interpret this result from ECG sensor?

Good afternoon to all,

I am sorry for my subsequent question but I am struggling on it since this morning and don't know anyone to ask for help.
I have carried out all the registers settings for the ecg extraction from a ECG/GSR Click board employing AS7030B sensor, read through I2C and I have partially followed an example.
The output signal I get is the one represented in the attached image, that I don't know how to interpret.
Why do I get so many superimposed signals...as if "each wave" of the ecg signal is "separated" from the others?
I don't know how to explain this, but I guess it is pretty clear from the image itself.

Could anyone help me?
Thank you

Please post the code, using code tags.

It appears that you have an integer overflow problem.

I have partially followed an example

It is usually a good idea to follow an example completely before modifying anything. I often get into trouble when I skip steps, or modify something before clearly understanding what it does.

Hi,
thank you for the answer.

This is the code:

#include "Wire.h"
#include "ECG_GSR.h"

#define SDA_PIN    21
#define SCL_PIN    22
#define ENABLE_PIN 4

uint32_t I2C_FAST_MODE = 100000;    // 100 kHz

uint8_t i2c_readRegisterByte (uint8_t deviceAddress, uint8_t registerAddress);
uint8_t i2c_writeRegisterByte (uint8_t deviceAddress, uint8_t registerAddress, uint8_t newRegisterByte);
uint8_t i2c_setRegisterBit (uint8_t deviceAddress,  uint8_t registerAddress,  uint8_t bitPosition, bool state);
bool i2c_getRegisterBit (uint8_t  deviceAddress, uint8_t  registerAddress, uint8_t  bitPosition);

void setECGReg(void);
void setEAFReg(void);
void setSequencerReg(void);
void setADCReg(void);
void setI2CReg(void);

uint16_t readECGData(void);
void prep2ForReadECGData(void);

void setup()
{
  // Initialize serial
  Serial.begin(115200);
  while(!Serial);
  Serial.println("\nSerial Initialized\n");

  // Initialize pinMode
  pinMode(ENABLE_PIN, OUTPUT);
  delay(500);
  digitalWrite(ENABLE_PIN, HIGH);
  
  // Initialize I2C communication protocol
  bool initialize = Wire.begin(SDA_PIN, SCL_PIN, I2C_FAST_MODE);
  delay(500);
  if(initialize)
  {
    Serial.println("\nI2C successfully initialized\n");
  } else {
    Serial.println("\nERROR in I2C initialization\n");
  }

  I2Cscan();
  delay(10000);
  
  setECGReg();
  delay(500);

  setEAFReg();
  delay(500);

  setSequencerReg();
  delay(500);
  
  setADCReg();
  delay(500);
  
  setI2CReg();
  delay(500);
  
  return;
}

void loop() 
{
  uint16_t ecg_result = readECGData();
  Serial.println(-ecg_result);
//  
  return;
}

uint8_t i2c_readRegisterByte (uint8_t deviceAddress, uint8_t registerAddress) 
{
  uint8_t registerData;
  Wire.beginTransmission(deviceAddress);
  Wire.write(registerAddress);
  Wire.endTransmission();   
  Wire.requestFrom(deviceAddress,  (byte)1);
  registerData = Wire.read(); 
  // you could add more data reads here if you request more than one byte
  
  return registerData;
}

uint8_t i2c_writeRegisterByte (uint8_t deviceAddress, uint8_t registerAddress, uint8_t newRegisterByte)
{
  uint8_t result;
  Wire.beginTransmission(deviceAddress);
  Wire.write(registerAddress);  
  Wire.write(newRegisterByte); 
  result = Wire.endTransmission();

  delay(5);
  if(result > 0)  
  {
    Serial.print(F("FAIL in I2C register write! Error code: "));
    Serial.println(result);
  }

  return result;
}

uint8_t i2c_setRegisterBit (uint8_t deviceAddress,  uint8_t registerAddress,  uint8_t bitPosition, bool state)
{ 
  static uint8_t registerByte, result;
  registerByte = i2c_readRegisterByte (deviceAddress,  registerAddress);
  if (state)
  {
     bitSet(registerByte, bitPosition); 
  }  else {
     bitClear(registerByte, bitPosition); 
  }
  result = i2c_writeRegisterByte(deviceAddress,  registerAddress,  registerByte);
  
  return result;
} 

bool i2c_getRegisterBit (uint8_t  deviceAddress, uint8_t  registerAddress, uint8_t  bitPosition)
{     
  static uint8_t registerByte;
  registerByte = i2c_readRegisterByte(deviceAddress, registerAddress);
  
//  return ((registerByte >> bitPosition) & 0b00000001);  // or use (bitRead(registerByte, bitPosition))
  return (bitRead(registerByte, bitPosition));
}

/*------------------------------------------ECG REGISTERS SETTING---------------------------------------------------*/

void setECGReg(void)
{
  static bool ECG_reg[8] = {};
  
  ECG_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_MODE_REG, 3, SET);
  ECG_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_MODE_REG, 1, SET);
  ECG_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_MODE_REG, 0, SET);

  // Set G1 = 4, G2 = 6, enable ECG amplifier, set G3 = 16 and enable reference amplifier
  ECG_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGA_REG, 7, SET);
  ECG_reg[4] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGA_REG, 3, SET);
  
  ECG_reg[5] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGB_REG, 6, SET);
  ECG_reg[6] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGB_REG, 2, SET);
  
  ECG_reg[7] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGC_REG, 0, SET);

  if(!(ECG_reg[0] & ECG_reg[1] & ECG_reg[2] & ECG_reg[3] & ECG_reg[4] & ECG_reg[5] & ECG_reg[6] & ECG_reg[7] ))
  {
    Serial.println("Setting of ECG registers completed");
  } else {
    Serial.println("Failed in setting ECG registers");
  }
  
  return;
}

/*------------------------------------------EAF REGISTERS SETTING---------------------------------------------------*/

void setEAFReg(void)
{
  static bool EAF_reg[8] = {};
  
  EAF_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_LED_CFG_REG, 7, SET);
  EAF_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_CFG_REG, 3, SET);
  EAF_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_CFG_REG, 0, SET);

  // Enable Gain stage in EAF
  EAF_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_GST_REG, 7, SET);
  EAF_reg[4] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_GST_REG, 5, SET);
  EAF_reg[5] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_GST_REG, 4, SET);
  EAF_reg[6] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_BIAS_REG, 7, SET);
  EAF_reg[7] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_BIAS_REG, 5, SET);

  if(!(EAF_reg[0] & EAF_reg[1] & EAF_reg[2] & EAF_reg[3] & EAF_reg[4] & EAF_reg[5] & EAF_reg[6] & EAF_reg[7]))
  {
    Serial.println("EAF registers successfully set!");
  } else {
    Serial.println("Failed in setting EAF registers");
  }
  
  return;
}

/*------------------------------------------SEQUENCER REGISTERS SETTING---------------------------------------------------*/

void setSequencerReg(void)
{
  static bool SEQ_reg[4] = {};
  
  // Start sequencer
  SEQ_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 7, SET);
  SEQ_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 6, SET);
  SEQ_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 5, SET);
  SEQ_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 0, SET);

  if(!(SEQ_reg[0] & SEQ_reg[1] & SEQ_reg[2] & SEQ_reg[3]))
  {
    Serial.println("Setting of Sequencer registers completed");
  } else {
    Serial.println("Faile in setting Sequencer registers");
  }
  
  return;
}

/*------------------------------------------ADC REGISTERS SETTING---------------------------------------------------*/

void setADCReg(void)
{
  static bool ADC_reg[10] = {};

  ADC_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGB_REG, 0, SET);
  ADC_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGC_REG, 3, CLEAR);
  ADC_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGC_REG, 4, CLEAR);
  ADC_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_L_REG, 7, CLEAR);
  ADC_reg[4] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_L_REG, 5, CLEAR);
  ADC_reg[5] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_H_REG, 1, SET);
  ADC_reg[6] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_H_REG, 0, CLEAR);

  // Enable ADC
  ADC_reg[7] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGB_REG, 0, SET);
  // Select EAF in ADC masks
  ADC_reg[8] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_L_REG, 6, SET);
  // Select ECG Signal in ADC masks
  ADC_reg[9] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_H_REG, 0, SET);
  
  if(!(ADC_reg[0] & ADC_reg[1] & ADC_reg[2] & ADC_reg[3] & ADC_reg[4] & ADC_reg[5] & ADC_reg[6] & ADC_reg[7] & ADC_reg[8] & ADC_reg[9]))
  {
    Serial.println("Setting of ADC registers completed");
  } else {
    Serial.println("Failed in setting ADC registers");
  }
  
  return;
}

/*------------------------------------------I2C REGISTERS SETTING---------------------------------------------------*/

void setI2CReg(void)
{
  static bool I2C_reg[3] = {};

  // Set clock to 1MHz, enable oscillator and ldo
  I2C_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_CONTROL_REG, 2, SET);   // Set clock to 1MHz
  I2C_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_CONTROL_REG, 1, SET);   // Set OSC
  I2C_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_CONTROL_REG, 0, SET);   // Set LDO

  if(!(I2C_reg[0] & I2C_reg[1] & I2C_reg[2]))
  {
    Serial.println("Setting of i2c control register completed");
  } else {
    Serial.println("Failed in setting I2C control register");
  }
  uint8_t START_CONV = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_SEQ_START_REG, 0, SET);
  
  return;
}

/*------------------------------------------------------------------------------------------------*/
uint16_t readECGData(void)
{
  static uint8_t ADC_LOW_BYTE, ADC_HIGH_BYTE;

  ADC_LOW_BYTE = i2c_readRegisterByte(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_DATA_L_REG);   // Read the ADC corresponding low byte
  ADC_HIGH_BYTE = i2c_readRegisterByte(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_DATA_H_REG);  // Read the ADC corresponding high byte
  
  return((uint16_t)ADC_LOW_BYTE | ((uint16_t)ADC_HIGH_BYTE) << 8);
}

void I2Cscan(void) 
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknown error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  return;
}

And the ECG_GSR.h:

#define CLEAR                           0
#define SET                             1

#define ECG_GSR_SLAVE_ADDRESS 0x30 // 48

#define ECG_GSR_GPIO_SYNC_REG           0x0F
#define ECG_GSR_LED_CFG_REG             0x10
#define ECG_GSR_LED_WAIT_LOW_REG        0x11
#define ECG_GSR_LED1_CURRL_REG          0x12
#define ECG_GSR_LED1_CURRH_REG          0x13
#define ECG_GSR_LED2_CURRL_REG          0x14
#define ECG_GSR_LED2_CURRH_REG          0x15
#define ECG_GSR_LED3_CURRL_REG          0x16
#define ECG_GSR_LED3_CURRH_REG          0x17
#define ECG_GSR_LED4_CURRL_REG          0x18
#define ECG_GSR_LED4_CURRH_REG          0x19
#define ECG_GSR_LED12_MODE_REG          0x2C
#define ECG_GSR_LED34_MODE_REG          0x2D 
#define ECG_GSR_MAN_SEQ_CFG_REG         0x2E
#define ECG_GSR_PD_CFG_REG              0x1A
#define ECG_GSR_PDOFFX_LEDOFF_REG       0x1B
#define ECG_GSR_PDOFFX_LEDON_REG        0x1C
#define ECG_GSR_PD_AMPRCCFG_REG         0x1D
#define ECG_GSR_PD_AMPCFG_REG           0x1E
#define ECG_GSR_OFE1_PD_THCFG_REG       0x1F 
#define ECG_GSR_SEQ_CNT_REG             0x30 
#define ECG_GSR_SEQ_DIV_REG             0x31 
#define ECG_GSR_SEQ_START_REG           0x32 
#define ECG_GSR_SEQ_PER_REG             0x33 
#define ECG_GSR_SEQ_LED_ST_REG          0x34 
#define ECG_GSR_SEQ_LED_STO_REG         0x35 
#define ECG_GSR_SEQ_SECLED_STA_REG      0x36  
#define ECG_GSR_SEQ_SECLED_STO_REG      0x37  
#define ECG_GSR_SEQ_ITG_STA_REG         0x38 
#define ECG_GSR_SEQ_ITG_STO_REG         0x39 
#define ECG_GSR_SEQ_SDP1_STA_REG        0x3A 
#define ECG_GSR_SEQ_SDP1_STO_REG        0x3B 
#define ECG_GSR_SEQ_SDP2_STA_REG        0x3C 
#define ECG_GSR_SEQ_SDP2_STO_REG        0x3D 
#define ECG_GSR_SEQ_SDM1_STA_REG        0x3E 
#define ECG_GSR_SEQ_SDM1_STO_REG        0x3F 
#define ECG_GSR_SEQ_SDM2_STA_REG        0x40 
#define ECG_GSR_SEQ_SDM2_STO_REG        0x41 
#define ECG_GSR_SEQ_ADC_REG             0x42 
#define ECG_GSR_SEQ_ADC2TIA_REG         0x43 
#define ECG_GSR_SEQ_ADC3TIA_REG         0x44 
#define ECG_GSR_SD_SUBS_REG             0x45 
#define ECG_GSR_SEQ_CFG_REG             0x46 
#define ECG_GSR_SEQ_ERR_REG             0x47 
#define ECG_GSR_SEQ_OVS_SEL_REG         0x48
#define ECG_GSR_SEQ_OVS_VAL_REG         0x49
#define ECG_GSR_SEQ_DIS_SEL_REG         0x4A 
#define ECG_GSR_SEQ_DIS_VAL1_REG        0x4B 
#define ECG_GSR_SEQ_DIS_VAL2_REG        0x4C 
#define ECG_GSR_CYC_COUNTER_REG         0x60 
#define ECG_GSR_SEQ_COUNTER_REG         0x61 
#define ECG_GSR_SUBS_COUNTER_REG        0x62 
#define ECG_GSR_OFE_CFGA_REG            0x50 
#define ECG_GSR_OFE1_SD_THCFG_REG       0x51 
#define ECG_GSR_OFE_CFGC_REG            0x52 
#define ECG_GSR_OFE_CFGD_REG            0x53 
#define ECG_GSR_OFE1_CFGA_REG           0x54 
#define ECG_GSR_OFE1_CFGB_REG           0x55 
#define ECG_GSR_OFE2_PD_THCFG_REG       0x56 
#define ECG_GSR_OFE2_SD_THCFG_REG       0x57 
#define ECG_GSR_OFE2_CFGA_REG           0x58 
#define ECG_GSR_OFE2_CFGB_REG           0x59 
#define ECG_GSR_LTFDATA0_L_REG          0x20 
#define ECG_GSR_LTFDATA0_H_REG          0x21 
#define ECG_GSR_LTFDATA1_L_REG          0x22 
#define ECG_GSR_LTFDATA1_H_REG          0x23 
#define ECG_GSR_ITIME_REG               0x24 
#define ECG_GSR_LTF_CONFIG_REG          0x25 
#define ECG_GSR_LTF_SEL_REG             0x26 
#define ECG_GSR_LTF_GAIN_REG            0x27 
#define ECG_GSR_LTF_CONTROL_REG         0x28 
#define ECG_GSR_AZ_CONTROL_REG          0x29 
#define ECG_GSR_OFFSET0_REG             0x2A 
#define ECG_GSR_OFFSET1_REG             0x2B 
#define ECG_GSR_LTF_THRESHOLD_LOW0_REG  0x6C 
#define ECG_GSR_LTF_THRESHOLD_LOW1_REG  0x6D 
#define ECG_GSR_LTF_THRESHOLD_HIGH0_REG 0x6E  
#define ECG_GSR_LTF_THRESHOLD_HIGH1_REG 0x6F  
#define ECG_GSR_EAF_CFG_REG             0x70 
#define ECG_GSR_EAF_GST_REG             0x80 
#define ECG_GSR_EAF_BIAS_REG            0x81 
#define ECG_GSR_EAF_DAC_REG             0x82 
#define ECG_GSR_EAF_DAC1_L_REG          0x83 
#define ECG_GSR_EAF_DAC1_H_REG          0x84 
#define ECG_GSR_EAF_DAC2_L_REG          0x85 
#define ECG_GSR_EAF_DAC2_H_REG          0x86 
#define ECG_GSR_EAF_DAC_CFG_REG         0x87 
#define ECG_GSR_OFE_NOTCH_REG           0x5A 
#define ECG_GSR_ECG_MODE_REG            0x5B 
#define ECG_GSR_ECG_CFGA_REG            0x5C 
#define ECG_GSR_ECG_CFGB_REG            0x5D 
#define ECG_GSR_ECG_THRESHOLD_LOW_REG   0x6A 
#define ECG_GSR_ECG_THRESHOLD_HIGH_REG  0x6B 
#define ECG_GSR_ECG_CFGC_REG            0x5E 
#define ECG_GSR_ECG_CFGD_REG            0x5F 
#define ECG_GSR_ADC_THRESHOLD_REG       0x68 
#define ECG_GSR_ADC_THRESHOLD_CFG_REG   0x69 
#define ECG_GSR_ADC_CFGA_REG            0x88 
#define ECG_GSR_ADC_CFGB_REG            0x89 
#define ECG_GSR_ADC_CFGC_REG            0x8A 
#define ECG_GSR_ADC_CHANNEL_MASK_L_REG  0x8B  
#define ECG_GSR_ADC_CHANNEL_MASK_H_REG  0x8C  
#define ECG_GSR_ADC_DATA_L_REG          0x8E 
#define ECG_GSR_ADC_DATA_H_REG          0x8F 
#define ECG_GSR_FIFO_CFG_REG            0x78 
#define ECG_GSR_FIFO_CNTRL_REG          0x79 
#define ECG_GSR_FIFOL_REG               0xFE 
#define ECG_GSR_FIFOH_REG               0xFF 
#define ECG_GSR_CONTROL_REG             0x00 
#define ECG_GSR_GPIO_A_REG              0x08 
#define ECG_GSR_GPIO_E_REG              0x09 
#define ECG_GSR_GPIO_O_REG              0x0A 
#define ECG_GSR_GPIO_I_REG              0x0B 
#define ECG_GSR_GPIO_P_REG              0x0C 
#define ECG_GSR_GPIO_SR_REG             0x0D 
#define ECG_GSR_SUBID_REG               0x91 
#define ECG_GSR_ID_REG                  0x92 
#define ECG_GSR_STATUS_REG              0xA0 
#define ECG_GSR_STATUS2_REG             0xA1 
#define ECG_GSR_CLIPSTATUS_REG          0xA2 
#define ECG_GSR_LEDSTATUS_REG           0xA3 
#define ECG_GSR_FIFOSTATUS_REG          0xA4 
#define ECG_GSR_LTFSTATUS_REG           0xA5 
#define ECG_GSR_FIFOLEVEL_REG           0xA6 
#define ECG_GSR_INTENAB_REG             0xA8 
#define ECG_GSR_INTENAB2_REG            0xA9 
#define ECG_GSR_INTR_REG                0xAA 
#define ECG_GSR_INTR2_REG               0xAB 

#define ECG_GSR_DEV_ID_MASK             0xFC
#define ECG_GSR_DEV_ID                  0x54


// 35mA current flows through LEDs.
#define ECG_GSR_LED_CURR_LOW_2          0x80
#define ECG_GSR_LED_CURR_HIGH_2         0x59


// 100mA current flows through LEDs.
#define ECG_GSR_LED_CURR_LOW_3          0xC0
#define ECG_GSR_LED_CURR_HIGH_3         0xFF

// PPG related definitions.
#define ECG_GSR_ENABLE_OSC_AND_LDO      0x03
#define ECG_GSR_READ_VALUE_CONTROL_REG  0x83
#define ECG_GSR_ENABLE_REF_AND_DIODES   0x8B
#define ECG_GSR_ENABLE_LED12_OUTPUT     0x99
#define ECG_GSR_ENABLE_LED4_OUTPUT      0x90
#define ECG_GSR_CONF_PHOTODIODE         0x3E
#define ECG_GSR_SUNLIGHT_COMPENSATION   0x5E
#define ECG_GSR_FEEDBACK_RESISTOR       0xE2
#define ECG_GSR_ENABLE_PHOTOAMPLIFIER   0xBC
#define ECG_GSR_START_PPG               0xE1
#define ECG_GSR_ENABLE_ADC              0x01
#define ECG_GSR_START_ADC_CONVERSION    0x01
#define ECG_GSR_ENABLE_OFE_AND_BIAS     0xE6
#define ECG_GSR_OFE1_CFGA               0x70
#define ECG_GSR_OFE2_CFGA               0x70
#define ECG_GSR_ADC_DATA_H_MASK         0x3F
#define ECG_GSR_PPG_SCALE_VAL           0x64
#define ECG_GSR_PD_LED_CURRENT          0x80
#define ECG_GSR_PPG_L_THRESHOLD         0x48
#define ECG_GSR_PPG_H_THRESHOLD         0x5F
#define ECG_GSR_PPG_MAX_VAL             0x64

// ECG related definitions.
#define ECG_GSR_ENABLE_SIG_REFERENCE    0x80
#define ECG_GSR_ENABLE_BIAS_AND_GAIN    0x09
#define ECG_GSR_INPUT_AND_REF_VOLTAGE   0xB0
#define ECG_GSR_RESISTIVE_BIASING       0xA0
#define ECG_GSR_GAIN_SETTINGS_STAGES1_2 0x0B
#define ECG_GSR_ENABLE_ECG_AMPLIFIER    0x88
#define ECG_GSR_GAIN_SETTINGS_STAGE3    0x04
#define ECG_GSR_ENABLE_REF_AMPLIFIER    0x01
#define ECG_GSR_START_SEQUENCER         0xE1
#define ECG_GSR_SELECT_EFE              0x40
#define ECG_GSR_SELECT_AMPLIFIER_INPUT  0x01
#define ECG_GSR_ECG_SCALE_VAL           0x02

// GSR related definitions.
#define ECG_GSR_ENABLE_GPIO1_ANALOG 0x02
#define ECG_GSR_SET_SLEW_RATE_GPIO1 0x02
#define ECG_GSR_SET_GPIO1_AS_INPUT  0x46
#define ECG_GSR_SET_RES_BIAS_GPIO1  0x40

Don't care about the low efficiency - registers setting, it was only to try.

I don't understand where the error could be because I have simply done what the example reports...I am sure that you are more expert than me and that this will be something for dummies...I am sorry about this of course.

Thank in advance for all the help.

That is a problem. A variable declared uint16_t can take on values 0 to 65535, but when you operate on it with '-' it is interpreted as an "int", with negative values for any number above 16383.

Try this and let us know what results:
Serial.println(ecg_result);

Better, declare ecg_result as "int" and see how that behaves when you print. You should check on the type of value represented by the registers in the sensor. I would expect 16 bit signed integers.

Hi,

I am still getting the same, as you can see in the attached image (I have done just a screenshot and rotated it).
What do you think? And, addiotionally, what could I try?

Thank you!

Please post the revised code, and a link to the sensor data sheet.

Did you check on the data type actually contained in the result register(s)?

Why is the screenshot posted upside down?

Hi,
I posted the image upside down just to let you see that the problem doesn't change, albeit I set ecg_result instead of -ecg_result.

This is the sensor datasheet link--> http://download.mikroe.com/documents/datasheets/AS7030B%20Datasheet.pdf

In the following, the code:

#include "Wire.h"
#include "ECG_GSR.h"

#define SDA_PIN    21
#define SCL_PIN    22
#define ENABLE_PIN 4

uint32_t I2C_FAST_MODE = 100000;    // 100 kHz

int i2c_readRegisterByte (uint8_t deviceAddress, uint8_t registerAddress);
int i2c_writeRegisterByte (uint8_t deviceAddress, uint8_t registerAddress, uint8_t newRegisterByte);
int i2c_setRegisterBit (uint8_t deviceAddress,  uint8_t registerAddress,  uint8_t bitPosition, bool state);
bool i2c_getRegisterBit (uint8_t  deviceAddress, uint8_t  registerAddress, uint8_t  bitPosition);

void setECGReg(void);
void setEAFReg(void);
void setSequencerReg(void);
void setADCReg(void);
void setI2CReg(void);

int readECGData(void);
void prep2ForReadECGData(void);

void setup()
{
  // Initialize serial
  Serial.begin(115200);
  while(!Serial);
  Serial.println("\nSerial Initialized\n");

  // Initialize pinMode
  pinMode(ENABLE_PIN, OUTPUT);
  delay(500);
  digitalWrite(ENABLE_PIN, HIGH);
  
  // Initialize I2C communication protocol
  bool initialize = Wire.begin(SDA_PIN, SCL_PIN, I2C_FAST_MODE);
  delay(500);
  if(initialize)
  {
    Serial.println("\nI2C successfully initialized\n");
  } else {
    Serial.println("\nERROR in I2C initialization\n");
  }

  I2Cscan();
  delay(10000);
  
  setECGReg();
  delay(500);

  setEAFReg();
  delay(500);

  setSequencerReg();
  delay(500);
  
  setADCReg();
  delay(500);
  
  setI2CReg();
  delay(500);
  
  return;
}

void loop() 
{
  int ecg_result = readECGData();
  Serial.println(ecg_result);

  return;
}

int i2c_readRegisterByte (uint8_t deviceAddress, uint8_t registerAddress) 
{
  int registerData;
  Wire.beginTransmission(deviceAddress);        // set sensor target
  Wire.write(registerAddress);
  Wire.endTransmission();   
  Wire.requestFrom(deviceAddress,  (byte)1);    // request one byte
  registerData = Wire.read(); 
  
  return registerData;
}

int i2c_writeRegisterByte (uint8_t deviceAddress, uint8_t registerAddress, uint8_t newRegisterByte)
{
  int result;
  Wire.beginTransmission(deviceAddress);
  Wire.write(registerAddress);  
  Wire.write(newRegisterByte); 
  result = Wire.endTransmission();

  delay(5);
  if(result > 0)  
  {
    Serial.print(F("FAIL in I2C register write! Error code: "));
    Serial.println(result);
  }

  return result;
}

int i2c_setRegisterBit (uint8_t deviceAddress,  uint8_t registerAddress,  uint8_t bitPosition, bool state)
{ 
  static int registerByte, result;
  registerByte = i2c_readRegisterByte (deviceAddress,  registerAddress);
  if (state)
  {
     bitSet(registerByte, bitPosition); 
  }  else {
     bitClear(registerByte, bitPosition); 
  }
  result = i2c_writeRegisterByte(deviceAddress,  registerAddress,  registerByte);
  
  return result;
} 

bool i2c_getRegisterBit (uint8_t  deviceAddress, uint8_t  registerAddress, uint8_t  bitPosition)
{     
  static int registerByte;
  registerByte = i2c_readRegisterByte(deviceAddress, registerAddress);

  return (bitRead(registerByte, bitPosition));
}

/*------------------------------------------ECG REGISTERS SETTING---------------------------------------------------*/

void setECGReg(void)
{
  static bool ECG_reg[8] = {};
  
  ECG_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_MODE_REG, 3, SET);
  ECG_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_MODE_REG, 1, SET);
  ECG_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_MODE_REG, 0, SET);

  // Set G1 = 4, G2 = 6, enable ECG amplifier, set G3 = 16 and enable reference amplifier
  ECG_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGA_REG, 7, SET);
  ECG_reg[4] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGA_REG, 3, SET);
  
  ECG_reg[5] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGB_REG, 6, SET);
  ECG_reg[6] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGB_REG, 2, SET);
  
  ECG_reg[7] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ECG_CFGC_REG, 0, SET);

  if(!(ECG_reg[0] & ECG_reg[1] & ECG_reg[2] & ECG_reg[3] & ECG_reg[4] & ECG_reg[5] & ECG_reg[6] & ECG_reg[7] ))
  {
    Serial.println("Setting of ECG registers completed");
  } else {
    Serial.println("Failed in setting ECG registers");
  }
  
  return;
}

/*------------------------------------------EAF REGISTERS SETTING---------------------------------------------------*/

void setEAFReg(void)
{
  static bool EAF_reg[8] = {};
  
  EAF_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_LED_CFG_REG, 7, SET);
  EAF_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_CFG_REG, 3, SET);
  EAF_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_CFG_REG, 0, SET);

  // Enable Gain stage in EAF
  EAF_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_GST_REG, 7, SET);
  EAF_reg[4] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_GST_REG, 5, SET);
  EAF_reg[5] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_GST_REG, 4, SET);
  EAF_reg[6] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_BIAS_REG, 7, SET);
  EAF_reg[7] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_EAF_BIAS_REG, 5, SET);

  if(!(EAF_reg[0] & EAF_reg[1] & EAF_reg[2] & EAF_reg[3] & EAF_reg[4] & EAF_reg[5] & EAF_reg[6] & EAF_reg[7]))
  {
    Serial.println("EAF registers successfully set!");
  } else {
    Serial.println("Failed in setting EAF registers");
  }
  
  return;
}

/*------------------------------------------SEQUENCER REGISTERS SETTING---------------------------------------------------*/

void setSequencerReg(void)
{
  static bool SEQ_reg[4] = {};
  
  // Start sequencer
  SEQ_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 7, SET);
  SEQ_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 6, SET);
  SEQ_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 5, SET);
  SEQ_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_MAN_SEQ_CFG_REG, 0, SET);

  if(!(SEQ_reg[0] & SEQ_reg[1] & SEQ_reg[2] & SEQ_reg[3]))
  {
    Serial.println("Setting of Sequencer registers completed");
  } else {
    Serial.println("Failed in setting Sequencer registers");
  }
  
  return;
}

/*------------------------------------------ADC REGISTERS SETTING---------------------------------------------------*/

void setADCReg(void)
{
  static bool ADC_reg[10] = {};

  ADC_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGB_REG, 0, SET);
  ADC_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGC_REG, 3, CLEAR);
  ADC_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGC_REG, 4, CLEAR);
  ADC_reg[3] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_L_REG, 7, CLEAR);
  ADC_reg[4] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_L_REG, 5, CLEAR);
  ADC_reg[5] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_H_REG, 1, SET);
  ADC_reg[6] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_H_REG, 0, CLEAR);

  // Enable ADC
  ADC_reg[7] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CFGB_REG, 0, SET);
  // Select EAF in ADC masks
  ADC_reg[8] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_L_REG, 6, SET);
  // Select ECG Signal in ADC masks
  ADC_reg[9] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_CHANNEL_MASK_H_REG, 0, SET);
  
  if(!(ADC_reg[0] & ADC_reg[1] & ADC_reg[2] & ADC_reg[3] & ADC_reg[4] & ADC_reg[5] & ADC_reg[6] & ADC_reg[7] & ADC_reg[8] & ADC_reg[9]))
  {
    Serial.println("Setting of ADC registers completed");
  } else {
    Serial.println("Failed in setting ADC registers");
  }
  
  return;
}

/*------------------------------------------I2C REGISTERS SETTING---------------------------------------------------*/

void setI2CReg(void)
{
  static bool I2C_reg[3] = {};

  // Set clock to 1MHz, enable oscillator and ldo
  I2C_reg[0] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_CONTROL_REG, 2, SET); // Set clock to 1MHz
  I2C_reg[1] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_CONTROL_REG, 1, SET);   // Set OSC
  I2C_reg[2] = i2c_setRegisterBit(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_CONTROL_REG, 0, SET);   // Set LDO

  if(!(I2C_reg[0] & I2C_reg[1] & I2C_reg[2]))
  {
    Serial.println("Setting of i2c control register completed");
  } else {
    Serial.println("Failed in setting I2C control register");
  }
  
  return;
}

/*------------------------------------------------------------------------------------------------*/
int readECGData(void)
{
  static int ADC_LOW_BYTE, ADC_HIGH_BYTE;

  ADC_LOW_BYTE = i2c_readRegisterByte(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_DATA_L_REG);   // Read the ADC corresponding low byte
  ADC_HIGH_BYTE = i2c_readRegisterByte(ECG_GSR_SLAVE_ADDRESS, ECG_GSR_ADC_DATA_H_REG);  // Read the ADC corresponding high byte

  return(ADC_LOW_BYTE | (ADC_HIGH_BYTE) << 8);
}

void I2Cscan(void) 
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknown error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  return;
}

Just to be sure, I also changed all the returned values into int type, but unfortunately , after the modifications you suggested, nothing changes.

I cannot get into the error...

Thank you for the help you provide to me!

Sorry, I haven't used that sensor, and can't make much sense out of the data sheet.

Clearly you are either reading the sensor incorrectly, or handling the output incorrectly with respect to variable type and sign, but just what that should be isn't made clear in the data sheet.

The ADC register is only 14 bits, though, so it can't possibly contain a value large enough to overflow an int variable. Perhaps you need to mask off the upper two bits and treat bit 14 as the sign.

Surely someone else has implemented this on Arduino, most likely the MikroE folks. You might get some leads on the Sparkfun page: MIKROE ECG/GSR Click - SEN-18801 - SparkFun Electronics

Good afternoon,

the example I have followed is this one, maybe it could help...but sincerly I don't know because I think that there are some errors in it, that's why I didn't follow it precisely step - by - step --> mikrosdk_click_v2/clicks/ecg_gsr/example at master · MikroElektronika/mikrosdk_click_v2 · GitHub

Could you understand anything more by looking at it?

I have given a look to the link you provided and didn't find nothing that solves my problem/makes clarity on this issue, but what I can tell you is that I have searched about someone using it with Arduino and didn't find anyone yet (unfortunately).

Looking forward to hearing from you,
Thank you!

There appears to be good reason for the lack of hobby-level interest in that sensor. For an Arduino project, I would choose one with less obscure documentation.

In this regard and in your experience, what sensor (or sensors) do you advice? I should perform some vital parameters measurement, let's say quite accurate and precise (ecg, saturation, temperature).

I have already used AD8232 but I wanted either to change sensor or to integrate it with other ones (NTC and/or pulse oximeters) that allow to extract reliable data.

By the way, I am using an ESP32 - WROOM32, whose pinout is in the following:
image

That specification is too vague to be meaningful.

With a hobby project you have no way of knowing how "accurate and precise" the results are, without comparing to them to results obtained using professionally calibrated, commercial instruments.

Check whether AMS has an application note explaining more clearly how their sensor works and is expected to be used. I have used other sensors from that company and their documentation is usually better than the data sheet you linked.

Ok thank you for the advices.
Thus, do you have any other advice, like some sensors you got on well with? It would be very appreciated.

So far, I have decided to give up on this sensor..I hope that someone will start to use it because it seems very powerful but you are right, it reports a too much obscure documentation.

Thank you again!

Adafruit has quite a good selection of sensors and almost always, software and tutorials that work well with them. They have both pulse and oximeter sensors, so that would be worth a look.

My experience with using these types of sensors shows that how the sensor is connected to the finger determines a good signal or not.

I was curious how the OP comes to make this setting uint32_t I2C_FAST_MODE = 100000; // 100 kHz when the device runs at 400K:

SCL Clock Frequency 0 400 kHz from page 14 of the data sheet.

What does this do

I2Cscan();
  delay(10000);
  

Why do you require a 10 second delay?

Show a wiring diagram and a photo of the device in use.

Hi,
10 seconds delay were an arbitrary delay, put very high only in order to have the time to open the serial plotter/terminal, there is no logical reason behind it.

I am sorry for the 100kHz setting, indeed just after I posted the code here I found out it had to be 400 kHz and set the I2C speed mode to 400 kHz, but nothing changed.

Foreseeing the wiring diagram, I have not sketched it yet, albeit it is very simple: I connected the supply to the 3.3V pin of ESP32 (previously de - soldering the selector from 5V to 3.3V supply in the ECG/GSR Click board), the ground to the GND pin of ESP32, the ENABLE pin to a digital pin (D4), even though it is not that necessary in my application because I2C is always enabled and, last but not least, SDA and SCL to the default - I2C compliant GPIO21 and GPIO22 pins of ESP32 (the pinout of ESP32 is in post #12).
What I checked is that the registers I set, are always correctly set, thus I guess that I2C works correctly, that's why I cannot find the real problem influencing the "wrongness" of the output signal.

Let me know if I've been enough clear in answering all your questions,
Thank you!

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