This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AFE4404: AFE4404 with Arduino Mega2560

Part Number: AFE4404

I am trying to program and control the operation of AFE4404 using Arduino Mega 2560::

This is the code so far::

#include <Wire.h>
#include "heartrate_3.h"
#include "heartrate_3_hal.h"
#include "heartrate_3_hw.h"




/* Pinbelegung */

int RESETZ = 18;

/* Variablendeklaration */

float befehl = 0;
int AFE_ADDR = 88;


/* AFE440X registers */

#define AFE_CONTROL0                0x00
#define AFE_LED2STC                 0x01
#define AFE_LED2ENDC                0x02
#define AFE_LED1LEDSTC              0x03
#define AFE_LED1LEDENDC             0x04
#define AFE_ALED2STC                0x05
#define AFE_ALED2ENDC               0x06
#define AFE_LED1STC                 0x07
#define AFE_LED1ENDC                0x08
#define AFE_LED2LEDSTC              0x09
#define AFE_LED2LEDENDC             0x0a
#define AFE_ALED1STC                0x0b
#define AFE_ALED1ENDC               0x0c
#define AFE_LED2CONVST              0x0d
#define AFE_LED2CONVEND             0x0e
#define AFE_ALED2CONVST             0x0f
#define AFE_ALED2CONVEND            0x10
#define AFE_LED1CONVST              0x11
#define AFE_LED1CONVEND             0x12
#define AFE_ALED1CONVST             0x13
#define AFE_ALED1CONVEND            0x14
#define AFE_ADCRSTSTCT0             0x15
#define AFE_ADCRSTENDCT0            0x16
#define AFE_ADCRSTSTCT1             0x17
#define AFE_ADCRSTENDCT1            0x18
#define AFE_ADCRSTSTCT2             0x19
#define AFE_ADCRSTENDCT2            0x1a
#define AFE_ADCRSTSTCT3             0x1b
#define AFE_ADCRSTENDCT3            0x1c
#define AFE_PRPCOUNT                0x1d
#define AFE_CONTROL1                0x1e
#define AFE_TIA_GAIN_SEP            0x20
#define AFE_TIA_GAIN                0x21
#define AFE_LEDCNTRL                0x22
#define AFE_CONTROL2                0x23
#define AFE_ALARM                   0x29
#define AFE_LED2VAL                 0x2a
#define AFE_ALED2VAL                0x2b
#define AFE_LED1VAL                 0x2c
#define AFE_ALED1VAL                0x2d
#define AFE_LED2_ALED2VAL           0x2e
#define AFE_LED1_ALED1VAL           0x2f
#define AFE_CONTROL3                0x31
#define AFE_PDNCYCLESTC             0x32
#define AFE_PDNCYCLEENDC            0x33
#define AFE_PROG_TG_STC             0x34
#define AFE_PROG_TG_ENDC            0x35
#define AFE_LED3LEDSTC              0x36
#define AFE_LED3LEDENDC             0x37
#define AFE_CLKDIV_PRF              0x39
#define AFE_OFFDAC                  0x3a
#define AFE_DEC                     0x3d
#define AFE_AVG_LED2_ALED2VAL       0x3f
#define AFE_AVG_LED1_ALED1VAL       0x40


volatile int allow = 0;
long LD1 = 0, LD2 = 0, LD3 = 0, amb1 = 0, amb2 = 0;



void setup() {
  // put your setup code here, to run once:
//AFE AFE AFE AFE AFE AFE AFE AFE AFE AFE AFE AFE
Serial.begin(19200);
Wire.begin();  
pinMode(RESETZ, OUTPUT);
AFE_RESETZ_Init();
AFE_Trigger_HWReset();
AFE_Init();
//AFE AFE AFE AFE AFE AFE AFE AFE AFE AFE AFE AFE
  
// Mega Configuration: Need I2C, CLK config, PIN config
// I/O ports Config(0 for input,1 for out)
DDRD &= 0b11111011 ;  DDRD |= 0b00001000 ;       //Pin PC3 is out for resetting AFE4404, Pin PC2 is input from afe4404 ADC Ready int 
PORTD &= 0b11111110 ;       //Pull up resistor of PC3 is off because ADC Ready is active high
PIND |= 0b00000010;    //Set pin PC3 out to 1 because the AFE4404 reset is active low 


/*
// General Configs
MCUCR |= ( 3 << ISC00 );              // Rising edge
GICR  |= ( 1 << INT2 );               // Enable Interrupts on INT0
SREG  |= ( 1 << 7 );                  //Global Interrupt enable
*/

attachInterrupt(digitalPinToInterrupt(19), Rd_signal, RISING);    //enable INT2

/*
PRR0 = ;              //Power Reduction register
PRR1 = ;
*/

//MicroController internal Clk Config
//clk = 8 Mhz which is compatible with AFE4404 external clock option, which is the default clk of mega2560 MCU

/*//I2C / TWI config
//PINS: SDA=PD1 (44), SCL=PD0 (43)
//START and STOP conditions are signalled by changing the level of the SDA line when the SCL line is high.
//All address packets transmitted on the TWI bus are 9 bits long, consisting of 7 address bits, one READ/WRITE control bit and an acknowledge bit.
//The MSB of the address byte is transmitted first.
//0000 000 is reserved for a general call address, use it to make all slave respond
//READ/WRITE bit is set, a read operation is to be performed
//7b address + 1b R/W + ACK...note that ACK is the slave pulling SDA low in the ninth SCL (ACK) cycle.
//All data packets transmitted on the TWI bus are nine bits long, consisting of one data byte and an acknowledge bit ,During a data transfer,
//The Master generates the clock and the START and STOP conditions, while the Receiver is responsible for acknowledging the reception.
//If the Receiver leaves the SDA line high, a NACK (No ACK) is signalled.
  //1// TWI of Arduion //1//
TWBR = 0h00; // TWI Bit Rate register----> Freq = Fsys/16
TWSR
TWDR    //TWI data and Address shif register

TWCR |= 0b00000001;       //Enable TWI Interrupt, Clear the flag after reading/writing TWI regiser to allow next start ( clear by TWCR |= 0b10000000)
TWCR |= 0b01000000;       //Enable ACK bit otherwise TWI may be considered disconnected.. 
//TWCR |= 0b00100000;     //Use this to initiate a START condition then must clear it to for each cycle of transmission
//TWCR |= 0b00010000;     //This is to initiate a STOP
//TWCR3 is a collision flag, raised if the TWI is busy (ie TWINT = 0  meaning busy)
TWCR |= 0b00000100;       // Enable TWI
//TWCR7 is the TWINT or TWI interrupt flag, raised when TWI module is done, cleared by setting it to 1

//TWSR = (b7:3 is TWI module status + b1:0 for prescaler)
//TWAR = 0h10110000 (b7:1 = 0h58 > TWI slave Address Register, B0=1 Enables general Call Recognition)
//Check page 345 for more details about TWI operation
*/

}


void Rd_signal() {
  allow = 1;
}




void loop() {
  // put your main code here, to run repeatedly:
  
    if (allow == 1) {
  //statement(s)
  allow = 0;
  LD1 = hr3_get_led1_val();
  Serial.print(LD1);
  Serial.print(hr3_get_led2_val());
  Serial.print(hr3_get_led3_val());
  Serial.print(hr3_get_amb1_val());
  Serial.print(hr3_get_led2_amb2_val());
  Serial.print(hr3_get_led1_amb1_val());
  
  //read and transmit data to computer
  
    }

          }



//****************************************************************************************************//
///////////////////////////////////////////////////**///////////////////////////////////////////////////
///////////////////////////////////////////////////**///////////////////////////////////////////////////
//////////////////////////////////////////Function Decleration//////////////////////////////////////////
///////////////////////////////////////////////////**///////////////////////////////////////////////////
///////////////////////////////////////////////////**///////////////////////////////////////////////////
//****************************************************************************************************//




          /**********************************************************************************************************/
/*                              Auslesen der seriellen Eingabeleiste                                      */
/**********************************************************************************************************/
void serialEvent()
{
  befehl = Serial.parseFloat();
}
/**********************************************************************************************************/
/*                              AFE4404_Initialisierung zum Start                                         */
/**********************************************************************************************************/

void AFE_Init()
{
  AFE_RESETZ_Init();
  AFE_Enable_HWPDN();
  AFE_Disable_HWPDN();
  AFE_Trigger_HWReset();
  //AFE_CLK_Init();
  AFE_Reg_Init();

}

/**********************************************************************************************************/
/*                              AFE4404_Registerinitialisierung                                           */
/**********************************************************************************************************/
void AFE_Reg_Init()
{
  AFE_Reg_Write(34, 0x0033C3);
}


/**********************************************************************************************************/
/*                              AFE4404_Enable_Read                                                       */
/**********************************************************************************************************/
void AFE_Enable_Read ()         //Prohibit writing to registers
{
  byte configData[3];
  configData[0]=0x00;
  configData[1]=0x00;
  configData[2]=0x01;
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                              AFE4404_Disable_Read                                                      */
/**********************************************************************************************************/
void AFE_Disable_Read ()        //Permitt writing to registers
{
  byte configData[3];
  configData[0]=0x00;
  configData[1]=0x00;
  configData[2]=0x00;
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                  RESETZ des AFE4404 wird Initialisiert                                                 */
/**********************************************************************************************************/
void AFE_RESETZ_Init()
{
  digitalWrite(RESETZ, HIGH);
}

/**********************************************************************************************************/
/*                  Reset internal registers by setting RESETZ = LOW for 25 - 50 us                       */
/**********************************************************************************************************/
void AFE_Trigger_HWReset()
{
  digitalWrite(RESETZ, LOW);              //Sets Arduino pins 22-29 LOW
  delayMicroseconds(30);
  digitalWrite(RESETZ, HIGH);              //Sets Arduino pins 22-29 HIGH
  delay(10);
}

/**********************************************************************************************************/
/*                             AFE4404 Power Down                                                         */
/**********************************************************************************************************/
void  AFE_Enable_HWPDN()
{
  digitalWrite(RESETZ, LOW);                  //Power Down by setting the RESETZ pin to LOW for more than 200 us
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Power Up                                                        */
/**********************************************************************************************************/
void  AFE_Disable_HWPDN()
{
  digitalWrite(RESETZ, HIGH);                  //Power Up the AFE by setting the RESETZ pin to HIGH   
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Set Clock Mode to Internal                                      */
/**********************************************************************************************************/
void AFE_CLK_Init()
{            
  AFE_Reg_Write(35, 0x104218);        //Set CLK Mode to internal clock (default Wert: 124218 mit interner CLK)
  AFE_Reg_Write(41, 0x2);             //Don´t set the internal clock to the CLK pin for outside usage
  AFE_Reg_Write(49, 0x000021);        //Division ratio for external clock mode set to fit the Arduino Mega 16MHz
  AFE_Reg_Write(57, 0);               //Set the lowes sampling rate to 61Hz (~17 ms)
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Write                                                   */
/*********************************************************************************************************/
void AFE_Reg_Write (int reg_address, unsigned long data)
{
  byte configData[3];
  configData[0]=(byte)(data >>16);
  configData[1]=(byte)(((data & 0x00FFFF) >>8));
  configData[2]=(byte)(((data & 0x0000FF)));
  I2C_write(AFE_ADDR, reg_address, configData, 3); 
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Read                                                    */
/*********************************************************************************************************/
signed long AFE_Reg_Read(int reg_address)
{
  byte configData[3];
  signed long retVal;
  I2C_read (AFE_ADDR, reg_address, configData, 3);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  if (reg_address >= 0x2A && reg_address <= 0x2F)
  {
    if (retVal & 0x00200000)  // check if the ADC value is positive or negative
    {
      retVal &= 0x003FFFFF;   // convert it to a 22 bit value
      return (retVal^0xFFC00000);
    }
  }
  return retVal;
}

/**********************************************************************************************************/
/*                              Write to AFE on I2C                                                       */
/**********************************************************************************************************/
char I2C_write (int slave_address, int reg_address, byte configData[], int byteCount)
{
  int trans_end = 0;
  signed long retVal;
  
  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Serial.print(configData[0]);
  Serial.print(",");
  Serial.print(configData[1]);
  Serial.print(",");
  Serial.println(configData[2]);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  Serial.println(retVal);
  Serial.println(reg_address);
  Wire.write(configData, 3);
  Serial.println("test");
  Wire.endTransmission();
  return (trans_end);
  
 /* while(1)
  {
    if(byteCount == 0)
    {
      Wire.endTransmission();
      Serial.println("test");
      return (trans_end);
    }else{
      //unsigned int reg_data = (unsigned int) *write_data++;
      Wire.write(configData, 3);
      byteCount--;
    }       
  }*/
}

/**********************************************************************************************************/
/*                              Read Data of AFE on I2C                                                   */
/**********************************************************************************************************/
char I2C_read(int slave_address, int reg_address, byte *read_Data, int byteCount)
{
  int trans_end = 0;
  
  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Wire.endTransmission();
  Wire.requestFrom(slave_address, 3);
  while(Wire.available() && (byteCount != 0))
  {
    *read_Data++ = Wire.read();
    byteCount--;
  }
  return (trans_end);
}

===========================================================================================

The problem is :::

When I compile using arduino compiler, i get these errors:

Arduino: 1.8.9 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

C:\Users\adeel\AppData\Local\Temp\ccNpN2Ab.ltrans0.ltrans.o: In function `main':

<artificial>:(.text.startup+0x394): undefined reference to `hr3_get_led1_val()'

<artificial>:(.text.startup+0x39a): undefined reference to `hr3_get_led2_val()'

<artificial>:(.text.startup+0x3a2): undefined reference to `hr3_get_led3_val()'

<artificial>:(.text.startup+0x3aa): undefined reference to `hr3_get_amb1_val()'

<artificial>:(.text.startup+0x3b2): undefined reference to `hr3_get_led2_amb2_val()'

<artificial>:(.text.startup+0x3ba): undefined reference to `hr3_get_led1_amb1_val()'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I tried manualy add #include to the .c and .h files od heartrate_3 , heartrate_3_hal, and heartrate_3_hw but still i get the same errors.

Finally, i just want to read the SFH7050 3-LED readings and its ambient values and send it to computer through serial. Is my code right for that purpose.

pls help, Thanks

  • Hi Hazem.

    This error is related to Arduino. You can search online about how to call a module from other files in Arduino. As we are no expert in Arduino programming, our help will be limited. 

    If you are interested on reading the data then you can use AFE_Reg_Read() function to read the output of the AFE. You can read the output from 0x2A to 0x2D registers.

    Regards,

    Prabin.

  • Hi Parbin,

    Thanks for your reply.... as for the module call error, i managed to solve it but the problem now is that :

    After initialiazing  AFE4404, i setup INT2 (MEGA2560 ) to respond to the ADC_RDY (AFE4404) int, but the interrupt never occured and any read function (AFE_Reg_Read() or HR3 read functions) returns 0.

    I made sure that the MEGA2560 interrupt works, all connections are right, AFE4404 module SFH7050 sensor are not damaged, and finger on sensor but still can get only zero readings.

    What do you think the problem might be?

  • Hi Hazem,

    Following could be the reasons for your issue.

    1) Incorrect register settings. To rule out this cause I would suggest you to try the sample register settings as given in Table 11 of the datasheet.

    2) Absence of external clock to the AFE. To rule this out please program the AFE into internal oscillator mode and check ADC_RDY.

    Regards,

    Prabin

  • I downloaded ti AFE4404 EVM software, it allows setting all the parameters in a GUI, then I can save all register values after verification...I aslo tried the values in table 11...in all cases, the results are the same.

    I applied a 8 MHz clock , made sure the CONTROL registers are set for External oscilator ... Also tried different Vpp values (for the clock signal 0:4 and 0:5 V). Still no results

    The only weird behavior i noticed was that when I fill the READ Enable bit in AFE4404_CONTROL0 with 1, sometimes it forces the arduino to reset the MCU code . I thaught that is is finally working and may be it draws to much current from the board , so i supplied the arduino, and the AFE from different power supplies (with common ground) , but still the MCU code keeps resetting . This happened when i tried reading a register value inside the void setup() before void loop(),