Heart rate sensor MAX30102


+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 79
  1. #1

    Default Heart rate sensor MAX30102

    Dear all,

    the covid-19 period, i have spent lots of time designing a 3D printed Adaptable medical Mask for covid-19. It was succesful using bio-compatible materials

    (here's the liink: https://www.linkedin.com/feed/update...6630277947393/)

    I have printed free of charge, for the kids in school about 50 of face shields in order to be safe inside the lectures.

    The same i did for the professional 3D printed Adaptable Medical Mask, for Hospitals. Just printed couple of those for testing.

    Now i would like to prepare a free of charge again low cost electronic heart rate circuit, for my sons classroom. Kids are in total 15 in class.


    As it is my first time using I2C protocol, i would like your help in order to establish a connection with the heart sensor MAX30102.

    If anyone have tried this sensor i would be much appreciated if you could share a part of your code.

    I have in front of me the manual of the MAX30102 and all the control and register modes. Actually i'm reading this 2 days now, and really as a newbie, cant understand where to start from.

    I will use the PIC18F26K22 at 16Mhz as from the PICBASIC manual I2C protocol needs to run up to 20MHZ using the I2CWRITE or I2CREAD software commands. (i hope i'm right)

    Next the following ports will be used.

    Code:
    LATC.1 for Data 
    LATC.2 for Clock 
    
    also reserved two more ports for external serial display
    
    LATC.6 for TX
    LATC.7 for RX
    Some MAX30102 registers

    Code:
    ;-------------------------------------------------------------|
    ;------------------------ max30102 registers------------------|
    ;-------------------------------------------------------------|
    define  I2C_WRITE_ADDR  $AE     ; b10101110
    define  I2C_READ_ADDR   $AF     ; b10101111
    define  I2C_ID_ADDR     $57     ; 7-bit version of the above
    ;define I2C_ID_ADDR  57h ; 7-bit version of the above
    
    ;//register addresses
    ;---------------------- STATUS REGISTER -----------------------
    define REG_INTR_STATUS_1   $00
    define REG_INTR_STATUS_2   $01
    
    define REG_INTR_ENABLE_1   $02
    define REG_INTR_ENABLE_2   $03
    
    ;----------------------- FIFO REGISTERS -----------------------
    define REG_FIFO_WR_PTR     $04   ; FIFO WRITE POINTER REG ADDR IS 0X04
    define REG_OVF_COUNTER     $05
    define REG_FIFO_RD_PTR     $06
    define REG_FIFO_DATA       $07
    
    ;---------------------- CONFIG REGISTER -----------------------
    define REG_FIFO_CONFIG     $08
    define REG_MODE_CONFIG     $09
    define REG_SPO2_CONFIG     $0A
    define REG_LED1_PA         $0C
    define REG_LED2_PA         $0D
    
    
    define REG_PILOT_PA        $10
    define REG_MULTI_LED_CTRL1 $11
    define REG_MULTI_LED_CTRL2 $12
    
    ;----------------------- TEMP REGISTER -------------------------
    define REG_TEMP_INTR       $1F
    define REG_TEMP_FRAC       $20
    define REG_TEMP_CONFIG     $21
    define REG_PROX_INT_THRESH $30
    
    ;----------------------- PART ID REGISTER ----------------------
    define REG_REV_ID          $FE
    define REG_PART_ID         $FF
    Now i'm trying to understand based on the manual how could i communicate with sensor and at least see it alive (any led light on the sensor)

    Really looking for your help.

  2. #2

    Default Re: Heart rate sensor MAX30102

    on the first post i think i made a mistake with Defines.

    Is this the correct way to assign a constant value to the name?

    Code:
    ;-------------------------------------------------------------|
    ;------------------------ max30102 registers------------------|
    ;-------------------------------------------------------------|
    I2C_WRITE_ADDR con  $AE     ; b10101110
    I2C_READ_ADDR con   $AF     ; b10101111
    I2C_ID_ADDR  con    $57     ; 7-bit version of the above
    ;I2C_ID_ADDR con  57h ; 7-bit version of the above
    
    ;//register addresses
    ;---------------------- STATUS REGISTER -----------------------
    REG_INTR_STATUS_1 con   $00
    REG_INTR_STATUS_2 con   $01
    
    REG_INTR_ENABLE_1 con   $02
    REG_INTR_ENABLE_2 con   $03
    
    ;----------------------- FIFO REGISTERS -----------------------
    REG_FIFO_WR_PTR con     $04   ; FIFO WRITE POINTER REG ADDR IS 0X04
    REG_OVF_COUNTER con     $05
    REG_FIFO_RD_PTR con     $06
    REG_FIFO_DATA con       $07
    
    ;---------------------- CONFIG REGISTER -----------------------
    REG_FIFO_CONFIG con     $08
    REG_MODE_CONFIG con     $09
    REG_SPO2_CONFIG con     $0A
    REG_LED1_PA con         $0C
    REG_LED2_PA con         $0D
    
    
    REG_PILOT_PA con        $10
    REG_MULTI_LED_CTRL1 con $11
    REG_MULTI_LED_CTRL2 con $12
    
    ;----------------------- TEMP REGISTER -------------------------
    REG_TEMP_INTR con       $1F
    REG_TEMP_FRAC con       $20
    REG_TEMP_CONFIG con     $21
    REG_PROX_INT_THRESH con $30
    
    ;----------------------- PART ID REGISTER ----------------------
    REG_REV_ID  con         $FE
    REG_PART_ID  con        $FF

  3. #3
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    LATC.1 for Data
    LATC.2 for Clock
    a recipe for failure in the making ?
    use of LATx ports in "highlevel" commands is incorrect and will not work as expected



    Is this the correct way to assign a constant value to the name?
    a quick little exercise trying to compile this will reveal the differences between defines and constants
    Code:
    reg var byte'#define bite_me 5     ;try one or the other of these two or niether 
    'bite_me con 5         ;                      "
    
    
    REG_INTR_STATUS_1 con   $00
    REG_INTR_STATUS_2 con   $01
    REG_INTR_STATUS_2 con   $07
    REG_INTR_STATUS_3 con   bite_me
    
    
    define REG_INTR_ENABLE_1   $02
    define REG_INTR_ENABLE_2  bite_me
    define REG_INTR_ENABLE_2  1
    
    
    #define REG_INTR_ENABLE_3   $02
    #define REG_INTR_ENABLE_4  bite_me
    #define REG_INTR_ENABLE_4  1
    
    
    loopy:
    
    
    reg =  bite_me
    reg = REG_INTR_ENABLE_3 
    reg = REG_INTR_ENABLE_1
    reg = REG_INTR_STATUS_1
    
    
    goto loopy
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  4. #4

    Default Re: Heart rate sensor MAX30102

    Thanks for the reply.

    do you mean that i cannot use the following format?

    Code:
    DataPin var LATC.1
    ClockPin var LATC.2

  5. #5
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    if that will become

    I2CREAD DataPin, ClockPin, Control,{Address,}[Var{,Var...}]{,Label}

    then yes that is not allowable and will cause difficult to determine bugs.
    you have to remember pbp is ancient technology, latx registers did not exist when it was created
    it never gets any significant updates
    Last edited by richard; - 17th August 2020 at 15:06.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  6. #6

    Default Re: Heart rate sensor MAX30102

    It is a bit consfusing for me.

    But i will try to figure it out.

    My goal is to communicate with this heart sensor. First step is to send this command to light up the LED and then try to read the information needed.

    I have tried this I2C ping program http://www.picbasic.co.uk/forum/showthread.php?t=20185, in order to see if the sensor responds with the ACK. (i though that the sensor was dead)

  7. #7
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    this i2c sniffer will usually do the job


    Code:
      
    DEFINE I2C_SLOW 1    
          anselA=0        'dig i/o 
          ANSELC=0
          TRISC= %11111111
          TRISA= %11111110  
    
    
    SCL                 var Portc.1                     ' I2C Clock  PortA.3
    SDA                 var Portc.0                     ' I2C Data   PortA.2
    I                   VAR BYTE  
    addr                var byte
    rd                   var byte
    
        porta.0=1
        DEFINE DEBUG_REG PORTA
        DEFINE DEBUG_BIT 0      ;  if not used for pwr  
        DEFINE DEBUG_BAUD 38400
        DEFINE DEBUG_MODE 0     
        pause 2000
        Debug "Start",13 ,10
       addr=0
    
    
    for I = $02 to $fe step 2
    I2Cread SDA,SCL,i,addr,[rd] ; or I2Cread SDA,SCL,i,[rd] ;
    Debug "found addr ",#i , 13,10 
    nak:
    Next I
    end
    Last edited by richard; - 18th August 2020 at 01:32.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  8. #8

    Default Re: Heart rate sensor MAX30102

    thanks for the book.

    on the other hand, i would like to continue with this project as it is important for me and the kids in school.

    I have done the first attempt to communicate with the sensor but no luck.

    Based on the Datasheet MAX30102, device address, or slave id: %1010111, consists of 7 bit, B7-B1,and the MSB-7 is transmitted first followed by the remaining bits. B0 is LSB which can be 0 if we write or 1 if we read.

    Then again from the manual explains that for the first write operation, we send the slave id as the first byte!....followed by the register address byte and then one or more data.

    From the PBP manual, and from this link http://www.picbasic.co.uk/forum/cont...-EEPROM-Part-1

    It is clear that I2CWRITE and I2CREAD command takes care of the write or read bit, also for the ACK.

    Name:  from max30102.png
Views: 232
Size:  101.9 KB

    Now i have tried to send the following:

    if PBP and command I2CWRITE takes care of the 8th bit then how could i manage to correspond it in the code.

    Code:
    i2cwrite sda,scl,%1010111,$04,error ' this is slave id cosnist of 7 bits.
    If i send the above command nothing will happen, and the data line will be offset from the clock.

    Name:  wrong code.png
Views: 228
Size:  423.1 KB

    Now using the following code:

    Code:
    i2cwrite sda,scl,%10101110,$04,error
    i get this on the scope:

    Name:  no ack.png
Views: 222
Size:  663.0 KB

    then i tried the following:
    Code:
    i2cwrite sda,scl,%10101110,$04,error
    pause 100
    i2cwrite sda,scl,%10101110,$04,error
    and the result on the scope: it looks strange again.

    Name:  strange.png
Views: 232
Size:  604.4 KB

  9. #9
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    did you try my i2c sniffer ?

    i2cwrite sda,scl,%10101110,$04,error
    how can that work ? you are attempting to write to the FIFO_WR_PTR yet providing no data to be written .

    i2cwrite sda,scl,$ae,$04,[1],error

    in general code snippets are a waste of time
    what pins , how are they set
    a schematic
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  10. #10

    Default Re: Heart rate sensor MAX30102

    Richard i havent used your sniffer code. Will do today it today.

    The breadboarding....i think is clear as schematic, if you like schematic i could also make one.

    Name:  breadboard.png
Views: 280
Size:  548.6 KB

    SCL is set as input in TRISC

    Code:
    TRISC = %10000100 ' portc.7 and portc.2 set as input. 
    
    all other unused ports are configured as output and set to low. 
    
    SDA var portc.1
    SCL var portc.2
    Now regarding the FIFO_WR_PTR it is not clear to me in the manual what data to write to it.

    Name:  Register maps.png
Views: 292
Size:  146.8 KB

    for example for the REG_MODE_CONFIG which is $09

    Name:  mode config.png
Views: 227
Size:  9.0 KB

    there is a detailed info of the bits need to be set.

    Name:  mode.png
Views: 218
Size:  81.4 KB

    For someone that is the first time working with a peripheral or a new method, it should be so many years a detailed info for configuration. At least a step by step guide.

    I'm not talking about you, but for all the others were in this forum for so many years. There were few guys were really helping. We lost a chief who was really made detailed explanations like talking to a baby.

    If we need to keep PBP alive, we need to start from 0. Here is not a plave to learn from skratch, and i agree. But if anyone loves PBP, we need to do that. Attract newbies like me, that would like to learn.

    Anyway, i will get in focus on this project, because it matters to me. If anyone would like to get involved and have in house a MAX30102, i would be really happy if could help me out as well.

    Richard i understand that you have no time and you have really other things to focus. Really appreciate your help, and i think you are one of the persons help in here.

    Many thanks.

  11. #11
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    The breadboarding....i think is clear as schematic, if you like schematic i could also make one
    not really , i looked at 3 modules the mikroe one is 3.3v only .the one mouser/e14 sell is 3.3 or 5v and has a logic level converter on board
    another provides no schematic and only vague spec no schema, i cannot identify your module

    by the look of your cro traces you are belting 5v in on the scl,sda pins , better hope its 5v tolerant

    TRISC = %10000100 ' portc.7 and portc.2 set as input.
    is wrong both must be input , the routine will switch tris as req
    if the module have 3.3 v pull ups might be better to use the open collector/drain method for i2c command
    [edit] forget that ,its open collecter by default.


    all other unused ports are configured as output and set to low.
    unnecessary


    SDA var portc.1
    SCL var portc.2
    conflicts with your tris statement anyway


    Now regarding the FIFO_WR_PTR it is not clear to me in the manual what data to write to it.
    me either but it will do something if everything else is correct
    Last edited by richard; - 21st August 2020 at 11:20.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  12. #12
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    For someone that is the first time working with a peripheral or a new method, it should be so many years a detailed info for configuration. At least a step by step guide.


    I'm not talking about you, but for all the others were in this forum for so many years. There were few guys were really helping. We lost a chief who was really made detailed explanations like talking to a baby.


    If we need to keep PBP alive, we need to start from 0. Here is not a plave to learn from skratch, and i agree. But if anyone loves PBP, we need to do that. Attract newbies like me, that would like to learn
    if you are familiar with i2c protocol and the vagaries of the device you have studied and intend to use then the pbp manual
    tells you everything you need to know to communicate with your device with pbp's i2c commands.
    the pbp manual is not there to teach i2c protocol to a novice , its raison d'etre is to explain usage of pbp implementation.

    having said that you can always ask questions on forums but really the onus is on you to do the ground work. its your project.
    its a pretty tall order to expect a complete novice tutorial for every device you can pluck out of the air from unpaid volunteers
    there are still few here willing to have a go at helping but don't forget dt was paid support , that resource has never been replaced.
    leo will usually help but he has not ventured onto this forum for years and years afaik.
    Last edited by richard; - 21st August 2020 at 12:01.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  13. #13

    Default Re: Heart rate sensor MAX30102

    Changed to input both portc.1 and portc.2

    This is the module.

    https://reedpaper.wordpress.com/2018...x-wrong-board/

    I have also following the "fix". Well module is 3.3V but i have never seen in all of the Arduino connections any note.

    I have changed the connections and used the 3.3V output from the Display to power the rest of the circuit.

    I dont beleive that i have burned the module as this is the result before i change the voltage supply from 5V to 3.3V.

    Code:
    i2cwrite sda,scl,$AE,$04
    pause 100
    This is the proof of ACK in 9th bit. As from the data sheet if the Id is the right one, the module pulls down the SDA during 9th bit to acknowledge receipt of data.

    Name:  ACK correct.png
Views: 218
Size:  648.2 KB
    Last edited by astanapane; - 21st August 2020 at 13:16.

  14. #14
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    i2cwrite sda,scl,$AE,$04
    i see you're still torturing the device sending incomplete write resister i2c control messages at it
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  15. #15

    Default Re: Heart rate sensor MAX30102

    yes i havent send any data yet as i'm searching in the i2c how to do that corresponds to the max30102 manual.

    At least i know sensor is responded by pulling SDA down on 9th bit. This is something for me.

  16. #16

    Default Re: Heart rate sensor MAX30102

    i've done many tries. I just want to see if the red LED inside the sensor is alive. At least by sending a command to activate it.

    Code:
    This is as from the pseudo code the first step. I really do not know if that is the right way to send Device ID + write mode
    Then send the FIFO_WR_PTR (i still dont know what are the bits needs to be configured)
    REPEAT START
    
    addr = $04   ; FIFO WRITE POINTER REG ADDR IS 0X04
    i2cwrite  SDA,scl,contwr
    i2cwrite  SDA,scl,contwr,addr
    i2cwrite  SDA,scl,contwr
    i2cwrite  SDA,scl,contwr,addr
    
    Apart from pseudo code in the datasheet, Next i tried to send mode for the heart rate mode only
    
    addr = $09   ' mode configuration 
    i2cwrite  SDA,scl,contwr,addr,[modled],error ' ModLED = $02 as per data sheet heart rate mode only
    
    In the end i tried to send the led pulse amplitute. 
    
    addr = $0C   ' led pulse amplitute
    i2cwrite  SDA,scl,contwr,addr,[led1_pa],error' LED1_PA = $3F  , 12.6 mA
    no luck......keep walking.

  17. #17
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    given that you can buy these for < $20us delivered to your door i doubt its worth while making them other than as an intellectual exercise
    https://au.banggood.com/BOXYM-oFit-2...r_warehouse=CN
    i have tried the sparkfun arduino demos and was not particularly impressed with accuracy or stability of readings obtained
    {maybe my heart is inaccurate and unstable}
    the raspberrypi code goes about it quite differently&nbsp; with some dsp done on data collected in a fixed sampling period [not tried it].
    i have no experience with these things , i don't know if reverse engineering the arduino code is even worthwhile
    but no matter how you go about it the sort of digital signal processing needed will be lots and lots of hard work with pbp
    do you have a plan ? have you established optimal device settings to get the best readings ? how much data is needed and from where ?
    reading and writing to the device is child's play, setting it up to get meaningful data and being able to extract information from that data is another story
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  18. #18
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,179

    Default Re: Heart rate sensor MAX30102

    I double what Richard pointed.

    Ioannis

  19. #19

    Default Re: Heart rate sensor MAX30102

    Thanks both for your kind reply.

    I will find the way. I know it is quite difficult and options are limited to use Arduino.

  20. #20
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    i tried the arduino code again with the sensor attached to my finger with a rubber band , it works a bit better that way
    do you have a stl model for an enclosure ? . its difficult to make any sense of wildly unstable readings

    i'm thinking a ESP8285 M3 board would make a better platform and allow use of arduino libs if they can be proven to be adequate
    ESP8285's these cut down esp8266's are very cheap and still have more processing power than a bucket full of pic chips they are quite happy to run on two aaa batteries and consume little energy if wifi not engaged
    Last edited by richard; - 4th September 2020 at 11:24.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  21. #21

    Default Re: Heart rate sensor MAX30102

    Hi Richard,

    once i have all the components (including the arduino board or ESP8285) then i will be ready to design the 3D cad model and printed.

    I will order some arduino and ESP and check them out.

  22. #22
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,179

    Default Re: Heart rate sensor MAX30102

    Use of such finger sensors need to have your finger cleaned from oil with alcohol (isoprop. alcohol or similar).

    It is necessary for the sensors to keep working with consistency.

    Ioannis

  23. #23
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    thanks ioannis, with out the repeatable test conditions its all guess work

    i might see if i can print this
    https://www.thingiverse.com/thing:4395147
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  24. #24
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,179

    Default Re: Heart rate sensor MAX30102

    Interesting 3D print!

    Ioannis

  25. #25

    Default Re: Heart rate sensor MAX30102

    I will try once again to find out how could i make this sensor work.

    Anyone is interested of helping in creating a simple driver for this sensor, please any help is much appreciated.

    At the moment i have changed the diagram. For being aligned with the following code please check the test board as well.

    Name:  circuit board.png
Views: 57
Size:  716.0 KB

    Up to now the componets im using:

    1. PIC18F26K22
    2. A Crystal 16Mhz
    3. 2 capacitors 22p
    4. 2 capacitors 100n
    5. 3 LEDs, RED, ORANGE, BLUE
    6. couple of resistors, 4.7K, 100Ohm, 220Ohm
    7. An LCD screen from 4D Systems
    8. MAX30102 Heart Rate Sensor

    I have managed with the following code to understand and complete easy tasks like:

    1. to read the PART NUMBER ID of the sensor based on the manual.
    2. How to light up the LEDs (IR and RED LEDs) Cant really understand how to send the right command for controlling the current)


    Code:
    '*********************************************************************************
    @ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of   *
                      ; crossing page boundary - make sure bits are set              *
    '********************************************************************************* 
     
      #CONFIG   ;  The PBP configuration for the PIC18F26K22 is:
    
        CONFIG FOSC     = HSHP	        ; HS oscillator (high power &gt; 16 MHz)
        CONFIG PLLCFG   = ON	        ;Oscillator multiplied by 4                       
        CONFIG PRICLKEN  = ON	        ;Primary clock enabled
        CONFIG FCMEN     = OFF	        ;Fail-Safe Clock Monitor disabled
        CONFIG IESO      = OFF	        ;Oscillator Switchover mode disabled
        CONFIG  BOREN    = SBORDIS      ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
        CONFIG  WDTEN    = ON           ; WDT is always enabled. SWDTEN bit has no effect                     ;|
        CONFIG  WDTPS    = 32768        ; 1:32768 ---> HERE enable the watchdog timer with a 1:32768 postscale;|
        CONFIG  PWRTEN   = ON
        CONFIG  HFOFST   = ON           ; HFINTOSC output and ready status are not delayed by the oscillator stable status
        CONFIG  MCLRE    = EXTMCLR      ; MCLR pin enabled, RE3 input pin disabled
        CONFIG  LVP      = OFF          ; Single-Supply ICSP disabled
        CONFIG  XINST    = OFF          ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
        CONFIG  DEBUG    = OFF          ; Disabled
        CONFIG  CP0 = OFF             ; Block 0 (000800-003FFFh) not code-protected
        CONFIG  CP1 = OFF             ; Block 1 (004000-007FFFh) not code-protected
        CONFIG  CP2 = OFF             ; Block 2 (008000-00BFFFh) not code-protected
        CONFIG  CP3 = OFF             ; Block 3 (00C000-00FFFFh) not code-protected
        CONFIG  CPB = OFF             ; Boot block (000000-0007FFh) not code-protected
        CONFIG  CPD = OFF             ; Data EEPROM not code-protected
        CONFIG  WRT0 = OFF            ; Block 0 (000800-003FFFh) not write-protected
        CONFIG  WRT1 = OFF            ; Block 1 (004000-007FFFh) not write-protected
        CONFIG  WRT2 = OFF            ; Block 2 (008000-00BFFFh) not write-protected
        CONFIG  WRT3 = OFF            ; Block 3 (00C000-00FFFFh) not write-protected
        CONFIG  WRTC = OFF            ; Configuration registers (300000-3000FFh) not write-protected
        CONFIG  WRTB = OFF            ; Boot Block (000000-0007FFh) not write-protected
        CONFIG  WRTD = OFF            ; Data EEPROM not write-protected
        CONFIG  EBTR0 = OFF           ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR1 = OFF           ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR2 = OFF           ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR3 = OFF           ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTRB = OFF           ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
        
      #ENDCONFIG
      
    ;*---------------------------------------------------------------------------------------------------------|
    ;*---------------------------------------------------------------------------------------------------------|
    'define I2C_SLOW 1
    define  OSC 64
    
            INCLUDE "modedefs.bas"
            INCLUDE "ALLDIGITAL.pbp"
    
    OSCCON    = %01110000   ; 16Mhz
    OSCTUNE.6 = 1           ; Enable 4x PLL
    
    while ! osccon2.7 :WEND ; to make sure the pll has stabilised before you run any other code
    
    TRISA = %00000000  
    TRISB = %00000000   
    TRISC = %10011000                  
    
    '----------------------- At start all PORTS LOW -------------------------|
    '------------------------------------------------------------------------|
    PORTA = 0            'make low all ports at A range                      |
    PORTB = 0            'make low all ports at B range                      |
    PORTC = 0            'make low all ports at C range                      |
    PORTE = 0            'make low all ports at E range                      |
    '------------------------------------------------------------------------|
    
    '-------------------------- COMPARATORS OFF -----------------------------|
    '------------------------------------------------------------------------|
    CM1CON0.7 = 0 'Disable comparator1                                       |
    CM2CON0.7 = 0 'Disable comparator2                                       |
    '------------------------------------------------------------------------|
    
    '*----------------------- | EUART 1 Configuration  | --------------------------|
    
            DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
            DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
            DEFINE HSER_CLROERR 1 ' Clear overflow automatically
            DEFINE HSER_SPBRG 160 ' 38400 Baud @ 64MHz, -0.08%
            SPBRGH = 1
            BAUDCON.3 = 1         ' Enable 16 bit baudrate generator
    '*-----------------------------------------------------------------------------|
    
    ORANGE  var LATA.2   ' ORANGE LED TO INDICATE POWER ON OF THE PIC
    BLUE    var LATC.0   ' BLUE LED TO INDICATE SENSOR WOKRING CONDITION
    RED     VAR LATC.5   ' RED LED TO INDICATE ERROR
    SDA     var portc.4  ' DATA PIN
    SCL     VAR portc.3  ' CLOCK PIN
    
    ;-------------------------------------------------------------|
    ;------------------------ max30102 registers------------------|
    ;-------------------------------------------------------------| 
    Timeout  cON 2000
    i        var byte
    mydata   var BYTE
    fifowr   var byte
    fiford   var byte
    fifoD1   var byte
    fifoD2   var byte
    fifoD3   var byte
    
    ContWR   var byte      ; $AE or b10101110
    ContRD   var byte      ; $AF or b10101111
    ContRD = $AF           ; b10101111
    ContWR = $AE           ; b10101110
    addr     var byte      ; this must be defined as variable word
    
    'I2C_ID_ADDR  con   $57     ; 7-bit version of the above
    'define I2C_ID_ADDR  57h ; 7-bit version of the above
    
    ;//register addresses
    ;---------------------- STATUS REGISTER -----------------------
    REG_INTR_STATUS_1 var byte ' con  $00
    REG_INTR_STATUS_2 var byte ' con $01
    
    REG_INTR_ENABLE_1 var byte ' con  $02
    REG_INTR_ENABLE_2 var byte 'con  $03
    
    ;----------------------- FIFO REGISTERS -----------------------
    REG_FIFO_WR_PTR  var byte 'con   $04   ; FIFO WRITE POINTER REG ADDR IS 0X04
    REG_OVF_COUNTER  var byte 'con   $05
    REG_FIFO_RD_PTR  var byte 'con   $06
    REG_FIFO_DATA    var byte 'con   $07
    
    ;---------------------- CONFIG REGISTER -----------------------
    REG_FIFO_CONFIG  var byte 'con   $08
    REG_MODE_CONFIG  var byte 'con   $09
    REG_SPO2_CONFIG  var byte 'con   $0A
    REG_LED1_PA      var byte 'con   $0C
    REG_LED2_PA      var byte 'con   $0D
    
    
    REG_PILOT_PA        var byte 'con $10
    REG_MULTI_LED_CTRL1 var byte 'con $11
    REG_MULTI_LED_CTRL2 var byte 'con $12
    
    ;----------------------- TEMP REGISTER -------------------------
    REG_TEMP_INTR        var byte 'con $1F
    REG_TEMP_FRAC        var byte 'con $20
    REG_TEMP_CONFIG      var byte 'con $21
    REG_PROX_INT_THRESH  var byte 'con $30
    
    ;----------------------- PART ID REGISTER ----------------------
    REG_PART_ID      var byte
    ' -----------------------------------------------------------------------------|  
    ' indication of the working code
    
    for i= 0 to 3
    orange = 1
    pause 100
    orange = 0
    pause 50
    next i
    orange = 1
    
    init: 
    low blue
    low red
    pause 100
    
    REG_PART_ID = $FF     ' this is the part id reg adress which gives hex 15
    i2cread  SDA,scl,contrd,REG_PART_ID,[mydata],error
    
    '*******************************************************************************
    ' if %00000010 is used then only IR LED for heart rate mode is set             *
    ' if %00000011 is used then only RED & IR LED for SPO2 mode is set             *
    ' if %00000111 is used then Multi Led Mode is set                              *
    '*******************************************************************************
    
    addr = $09   ' MODE CONFIGURATION 
    i2cwrite  SDA,scl,contwr,addr,%00000010,error  ' ModLED = $02 as per data sheet heart rate mode, $03 SpO2 mode
    'pause 100
    
    addr = $0C    'LED PULSE AMLIDUDE FOR for LED1_PA[7:0] 0x0C
    i2cwrite  SDA,scl,Contwr,addr,$3f,error' if LED1_PA = $3F  , 12.6 mA , ($7F is 25.4 mA)
    'pause 100
    
    '********************************************************************************
    
    REG_FIFO_DATA = $07
    i2cread  sda,scl,contrd,REG_FIFO_DATA,[fifod1,fifod2,fifod3],error
    '********************************************************************************
    
    start:
    HSEROUT [$73,$03,$04,$11,$ff,$ff,"PART ID: ",hex mydata,"h",$00]
    Hserin  timeout,error,[wait(6)]
    
    HSEROUT [$73,$05,$0A,$11,$07,$E0,"FIFO DT: ",$00]   ' lime color $07,$E0
    Hserin  timeout,error,[wait(6)]
    
    HSEROUT [$73,$03,$0C,$11,$07,$E0,dec fifod1,dec fifod2,dec fifod3,$00]   ' lime color $07,$E0
    Hserin  timeout,error,[wait(6)]
    'goto start
    
    blueled: 
    high blue
    PAUSE 300
    goto init
    
    error:
    high RED
    pause 100
    end

  26. #26
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    it looks like there is not much interest in this project

    there are a number of issues i can see, starting at the top with the physicals

    1, why a xtal osc, getting a stable xtal osc to work on a bread board is not guaranteed.
    xtal pins are often too thin for reliable connection and the capacitive coupling between strips is high.
    the internal osc is easily stable enough for this project and so much simpler.
    2, you provide nil detail on the display specs, the 3.3 v supply from lcd is it stable and capable of suppling the project ?
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  27. #27

    Default Re: Heart rate sensor MAX30102

    Thanks for the reply.

    I will give it a try as i would like to make this sensor work. I just need some guidance if possible.

    1. I will remove the external crystal, less part the better, in case for this project the internal is stable enough.
    2. The 4D Systems display, is an easy display to use, as they have on board chip and loaded a ready made driver for ease of use. I have this display couple of years now and it works as expected.

    You can find the datashet of the display here and the SERIAL COMMAND REFERENCE

    Regarding the output 3.3V from the display, looks like it is quite stable as i measured it. The Sensor's Power Supply: 3.3V~5V, so i could also use 5V.

  28. #28
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    There is your first major hurdle

    Name:  LEO.jpg
Views: 49
Size:  171.9 KB

    each led in 30102 can draw 50ma the two leds on your board 20ma each , the pic chip maybe another 20ma.
    at least use a 470uF smoothing cap but another 3.3v power source would be better

    the led can be lit
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  29. #29
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    mine has 3.3v written on it but the data sheet says the led supply can be 6v and the other sda scl pins are 6v tolerant
    maybe mine has a cheap 1.8v regulator , it works fine at 3.3v
    Last edited by richard; - 11th January 2022 at 10:43.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  30. #30

    Default Re: Heart rate sensor MAX30102

    well noted,

    1. Changed the crystal and used only the interal

    CONFIG FOSC = INTIO67 ; Internal oscillator block
    2. i've changed the circuit from 3.3V which was the output of the Display, and supplied the circuit with the PICKIT2 5V. I checked that this specific circuit draws up to 80mA. (USB 2 can deliver 100mA and at its maximum 500mA)

    MAX30102 can be supplied with 5V as from the following link.

    Name:  MAX30102 drawing.png
Views: 42
Size:  258.2 KB

    I have also applied the fix they have from the given link, and measured the output voltage at 1.8V which goes to the MAX30102 chip on the tiny board. So everything looks good now.

    Name:  MAX30102 board.png
Views: 42
Size:  373.4 KB

    Name:  MAX30102 board fix.png
Views: 44
Size:  264.8 KB

    Name:  1.8V output.png
Views: 43
Size:  567.8 KB
    Last edited by astanapane; - 11th January 2022 at 17:35.

  31. #31

    Default Re: Heart rate sensor MAX30102

    up to now this is the code and the output.....

    Code:
    '*********************************************************************************
    @ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of   *
                      ; crossing page boundary - make sure bits are set              *
    '********************************************************************************* 
     
      #CONFIG   ;  The PBP configuration for the PIC18F26K22 is:
    
        CONFIG FOSC     = INTIO67  ; Internal oscillator block
        CONFIG PLLCFG   = ON	   ; Oscillator multiplied by 4                       
        CONFIG PRICLKEN = ON	   ; Primary clock enabled
        CONFIG FCMEN    = OFF	   ; Fail-Safe Clock Monitor disabled
        CONFIG IESO     = OFF	   ; Oscillator Switchover mode disabled
        CONFIG  BOREN   = SBORDIS  ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
        CONFIG  WDTEN   = ON       ; WDT is always enabled. SWDTEN bit has no effect                     
        CONFIG  WDTPS   = 32768    ; 1:32768 ---> HERE enable the watchdog timer with a 1:32768 postscale;|
        CONFIG  PWRTEN  = ON
        CONFIG  HFOFST  = ON       ; HFINTOSC output and ready status are not delayed by the oscillator stable status
        CONFIG  MCLRE   = EXTMCLR  ; MCLR pin enabled, RE3 input pin disabled
        CONFIG  LVP     = OFF      ; Single-Supply ICSP disabled
        CONFIG  XINST   = OFF      ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
        CONFIG  DEBUG   = OFF      ; Disabled
        CONFIG  CP0     = OFF      ; Block 0 (000800-003FFFh) not code-protected
        CONFIG  CP1     = OFF      ; Block 1 (004000-007FFFh) not code-protected
        CONFIG  CP2     = OFF      ; Block 2 (008000-00BFFFh) not code-protected
        CONFIG  CP3     = OFF      ; Block 3 (00C000-00FFFFh) not code-protected
        CONFIG  CPB     = OFF      ; Boot block (000000-0007FFh) not code-protected
        CONFIG  CPD     = OFF      ; Data EEPROM not code-protected
        CONFIG  WRT0    = OFF      ; Block 0 (000800-003FFFh) not write-protected
        CONFIG  WRT1    = OFF      ; Block 1 (004000-007FFFh) not write-protected
        CONFIG  WRT2    = OFF      ; Block 2 (008000-00BFFFh) not write-protected
        CONFIG  WRT3    = OFF      ; Block 3 (00C000-00FFFFh) not write-protected
        CONFIG  WRTC    = OFF      ; Configuration registers (300000-3000FFh) not write-protected
        CONFIG  WRTB    = OFF      ; Boot Block (000000-0007FFh) not write-protected
        CONFIG  WRTD    = OFF      ; Data EEPROM not write-protected
        CONFIG  EBTR0   = OFF      ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR1   = OFF      ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR2   = OFF      ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR3   = OFF      ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTRB   = OFF      ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
        
      #ENDCONFIG
      
    ;*---------------------------------------------------------------------------------------------------------|
    ;*---------------------------------------------------------------------------------------------------------|
    'define I2C_SLOW 1
    define  OSC 64
    
            INCLUDE "modedefs.bas"
            INCLUDE "ALLDIGITAL.pbp"
    
    OSCCON    = %01110000   ; 16Mhz
    OSCTUNE.6 = 1           ; Enable 4x PLL
    
    while ! osccon2.7 :WEND ; to make sure the pll has stabilised before you run any other code
    
    TRISA = %00000000  
    TRISB = %00000000   
    TRISC = %10011000                  
    
    '----------------------- At start all PORTS LOW -------------------------|
    '------------------------------------------------------------------------|
    PORTA = 0            'make low all ports at A range                      |
    PORTB = 0            'make low all ports at B range                      |
    PORTC = 0            'make low all ports at C range                      |
    PORTE = 0            'make low all ports at E range                      |
    '------------------------------------------------------------------------|
    
    '-------------------------- COMPARATORS OFF -----------------------------|
    '------------------------------------------------------------------------|
    CM1CON0.7 = 0 'Disable comparator1                                       |
    CM2CON0.7 = 0 'Disable comparator2                                       |
    '------------------------------------------------------------------------|
    
    '*----------------------- | EUART 1 Configuration  | --------------------------|
    
            DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
            DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
            DEFINE HSER_CLROERR 1 ' Clear overflow automatically
            DEFINE HSER_SPBRG 160 ' 38400 Baud @ 64MHz, -0.08%
            SPBRGH = 1
            BAUDCON.3 = 1         ' Enable 16 bit baudrate generator
    '*-----------------------------------------------------------------------------|
    
    ORANGE  var LATA.2   ' ORANGE LED TO INDICATE POWER ON OF THE PIC
    GREEN   var LATC.0   ' BLUE LED TO INDICATE SENSOR WOKRING CONDITION
    RED     VAR LATC.5   ' RED LED TO INDICATE ERROR
    SDA     var portc.4  ' DATA PIN
    SCL     VAR portc.3  ' CLOCK PIN
    
    ;-------------------------------------------------------------|
    ;----------------------      variables      ------------------|
    ;-------------------------------------------------------------| 
    Timeout  cON 2000
    i        var byte
    mydata   var BYTE
    fifowr   var byte
    fiford   var byte
    fifoD1   var byte
    fifoD2   var byte
    fifoD3   var byte
    
    ContWR   var byte      ; $AE or b10101110
    ContRD   var byte      ; $AF or b10101111
    ContRD = $AF           ; b10101111
    ContWR = $AE           ; b10101110
    addr     var byte      ; this must be defined as variable word
    
    'I2C_ID_ADDR  con   $57     ; 7-bit version of the above
    'define I2C_ID_ADDR  57h ; 7-bit version of the above
    
    ;//register addresses
    ;---------------------- STATUS REGISTER -----------------------
    REG_INTR_STATUS_1 var byte 'con  $00
    REG_INTR_STATUS_2 var byte 'con  $01
    
    REG_INTR_ENABLE_1 var byte 'con  $02
    REG_INTR_ENABLE_2 var byte 'con  $03
    
    ;----------------------- FIFO REGISTERS -----------------------
    REG_FIFO_WR_PTR  var byte 'con   $04   ; FIFO WRITE POINTER REG ADDR IS 0X04
    REG_OVF_COUNTER  var byte 'con   $05
    REG_FIFO_RD_PTR  var byte 'con   $06
    REG_FIFO_DATA    var byte 'con   $07
    
    ;---------------------- CONFIG REGISTER -----------------------
    REG_FIFO_CONFIG  var byte 'con   $08
    REG_MODE_CONFIG  var byte 'con   $09
    REG_SPO2_CONFIG  var byte 'con   $0A
    REG_LED1_PA      var byte 'con   $0C
    REG_LED2_PA      var byte 'con   $0D
    
    
    REG_PILOT_PA        var byte 'con $10
    REG_MULTI_LED_CTRL1 var byte 'con $11
    REG_MULTI_LED_CTRL2 var byte 'con $12
    
    ;----------------------- TEMP REGISTER -------------------------
    REG_TEMP_INTR        var byte 'con $1F
    REG_TEMP_FRAC        var byte 'con $20
    REG_TEMP_CONFIG      var byte 'con $21
    REG_PROX_INT_THRESH  var byte 'con $30
    
    ;----------------------- PART ID REGISTER ----------------------
    REG_PART_ID      var byte
    ' -----------------------------------------------------------------------------|  
    ' -----------------------------------------------------------------------------|  
    '                          [ LCD Initialization ]                              |
    '------------------------------------------------------------------------------|
              ' FIRST TIME BOOTUP: We give plenty of time for tbe LCD '
              
    pause 1000  
    HSEROUT[$55]      ' uOLED Initialize this is the 'U' character of autoband rate to LCD
    Hserin  timeout,error,[wait(6)]
    HSEROUT [$45]    ' clear the LCD
    Hserin  timeout,error,[wait(6)]
    hserout[$73,$00,$03,$11,$ff,$ff,"HEART RATE SENSOR",$00] 
    Hserin  timeout,error,[wait(6)]           
    Hserout[$4F,$01] ; Set Transparent-Opaque Text - 4Fhex
    Hserin  timeout,error,[wait(6)]
    pause 500
    HSEROUT [$45]    ' clear the LCD
    Hserin  timeout,error,[wait(6)]
    
    ' indication of the working code
    
    for i= 0 to 3
    orange = 1
    pause 100
    orange = 0
    pause 50
    next i
    orange = 1
    
    init: 
    low green
    low red
    pause 100
    
    REG_PART_ID = $FF     ' this is the part id reg adress which gives hex 15
    i2cread  SDA,scl,contrd,REG_PART_ID,[mydata],error
    
    '*******************************************************************************
    ' if %00000010 is used then only IR LED for heart rate mode is set             *
    ' if %00000011 is used then only RED & IR LED for SPO2 mode is set             *
    ' if %00000111 is used then Multi Led Mode is set                              *
    '*******************************************************************************
    
    addr = $09   ' MODE CONFIGURATION 
    i2cwrite  SDA,scl,contwr,addr,%00000010,error  ' ModLED = $02 as per data sheet heart rate mode, $03 SpO2 mode
    'pause 100
    
    addr = $0C    'LED PULSE AMLIDUDE FOR for LED1_PA[7:0] 0x0C
    i2cwrite  SDA,scl,Contwr,addr,$3f,error' if LED1_PA = $3F  , 12.6 mA , ($7F is 25.4 mA)
    'pause 100
    '********************************************************************************
    REG_FIFO_WR_PTR = $04   ; FIFO WRITE POINTER REG ADDR IS 0X04
    i2cwrite  SDA,scl,contrd,REG_FIFO_WR_PTR,[fifowr],error
    
    REG_FIFO_RD_PTR = $06   ; FIFO READ POINTER REG ADDR IS 0X06
    i2cread  SDA,scl,contrd,REG_FIFO_rd_PTR,[fiford],error
    
    REG_FIFO_DATA = $07
    i2cread  sda,scl,contrd,REG_FIFO_DATA,[fifod1,fifod2,fifod3],error
    '********************************************************************************
    
    start:
    HSEROUT [$73,$03,$04,$11,$ff,$ff,"PART ID: ",hex mydata,"h",$00]
    Hserin  timeout,error,[wait(6)]
    
    HSEROUT [$73,$05,$0A,$11,$07,$E0,"FIFO DT: ",$00]   ' lime color $07,$E0
    Hserin  timeout,error,[wait(6)]
    
    HSEROUT [$73,$04,$0C,$11,$F8,$1F,dec fifod1,dec fifod2,dec fifod3,$00]   ' fuchsia color $F8, $1F
    Hserin  timeout,error,[wait(6)]
    'goto start
    
    blueled: 
    high green
    PAUSE 300
    goto init
    
    error:
    high RED
    pause 100
    end
    Name:  IR LED HR MODE.png
Views: 38
Size:  730.5 KB

    Name:  FIFODT.png
Views: 40
Size:  726.6 KB
    Last edited by astanapane; - 11th January 2022 at 20:22.

  32. #32

    Default Re: Heart rate sensor MAX30102

    Ok the FIFODT, FIFO DATA is not the one we are looking for.

    Just tried to see what could i get by requesting it using the following code. Also the code is not right but that is why i would like your help in here.
    Code:
    REG_FIFO_DATA = $07
    i2cread  sda,scl,contrd,REG_FIFO_DATA,[fifod1,fifod2,fifod3],error
    
    HSEROUT [$73,$04,$0C,$11,$F8,$1F,dec fifod1,dec fifod2,dec fifod3,$00]   ' fuchsia color $F8, $1F
    Hserin  timeout,error,[wait(6)]
    First i would like to retrieve the raw data of the IR LED.

  33. #33
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    my code , you should know i have no idea :-
    1, what led pwr to use
    2, what led pwidth to use
    3, what sample rate to use
    4, what sample resolution to use
    5, if there are any fifo overflows and if it matters much
    6, what led the readings represents
    7, how to interpret the data
    8, how much data to collect [i assume at least 2 seconds worth]

    when graphed i see no regular pattern that could be a heart beat
    there is a difference between finger and no finger pattern



    Code:
    '****************************************************************'*  Name    : MAX30102  FOR PIC 18 test                         *
    '*  Author  :  Richard                                          *
    '*  Notice  :                                                   *
    '*          :                                                   *
    '*  Date    : 9/1/2022                                          *
    '*  Version : 1.0                                               *
    '*  Notes   : MAX30102                                          *        
    '*          :18f26k22 @64Mhz                                    *
    '****************************************************************
     
      #CONFIG   ;  The PBP configuration for the PIC18F26K22 is:
        CONFIG FOSC     = INTIO67	       
        CONFIG PLLCFG   = OFF	        ;Oscillator multiplied by 4                       
        CONFIG PRICLKEN  = ON	        ;Primary clock enabled
        CONFIG FCMEN     = OFF	        ;Fail-Safe Clock Monitor disabled
        CONFIG IESO      = OFF	        ;Oscillator Switchover mode disabled
        CONFIG  BOREN    = SBORDIS      ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
        CONFIG  WDTEN    = ON           ; WDT is always enabled. SWDTEN bit has no effect                     ;|
        CONFIG  WDTPS    = 32768        ; 1:32768 ---> HERE enable the watchdog timer with a 1:32768 postscale;|
        CONFIG  PWRTEN   = ON
        CONFIG  HFOFST   = ON           ; HFINTOSC output and ready status are not delayed by the oscillator stable status
        CONFIG  MCLRE    = EXTMCLR      ; MCLR pin enabled, RE3 input pin disabled
        CONFIG  LVP      = OFF          ; Single-Supply ICSP disabled
        CONFIG  XINST    = OFF          ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
        CONFIG  DEBUG    = OFF          ; Disabled
        CONFIG  CP0 = OFF             ; Block 0 (000800-003FFFh) not code-protected
        CONFIG  CP1 = OFF             ; Block 1 (004000-007FFFh) not code-protected
        CONFIG  CP2 = OFF             ; Block 2 (008000-00BFFFh) not code-protected
        CONFIG  CP3 = OFF             ; Block 3 (00C000-00FFFFh) not code-protected
        CONFIG  CPB = OFF             ; Boot block (000000-0007FFh) not code-protected
        CONFIG  CPD = OFF             ; Data EEPROM not code-protected
        CONFIG  WRT0 = OFF            ; Block 0 (000800-003FFFh) not write-protected
        CONFIG  WRT1 = OFF            ; Block 1 (004000-007FFFh) not write-protected
        CONFIG  WRT2 = OFF            ; Block 2 (008000-00BFFFh) not write-protected
        CONFIG  WRT3 = OFF            ; Block 3 (00C000-00FFFFh) not write-protected
        CONFIG  WRTC = OFF            ; Configuration registers (300000-3000FFh) not write-protected
        CONFIG  WRTB = OFF            ; Boot Block (000000-0007FFh) not write-protected
        CONFIG  WRTD = OFF            ; Data EEPROM not write-protected
        CONFIG  EBTR0 = OFF           ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR1 = OFF           ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR2 = OFF           ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR3 = OFF           ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTRB = OFF           ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
     #ENDCONFIG    
     
      
    'define I2C_SLOW 1
    define  OSC 64
    
    
    OSCCON    = %01110000   ; 16Mhz
    OSCTUNE.6 = 1           ; Enable 4x PLL
    
    
    while ! osccon2.7 :WEND ; to make sure the pll has stabilised before you run any other code
    
    
       
    TRISC = %11011000                  
    ANSELC=0
    
    
    #DEFINE    DEBUGING 1   
    
    
    #IFNDEF  DEBUGING       
        DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
        DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
        DEFINE HSER_CLROERR 1 ' Clear overflow automatically
        DEFINE HSER_SPBRG 160 ' 38400 Baud @ 64MHz, -0.08%
        SPBRGH = 1
        BAUDCON.3 = 1         ' Enable 16 bit baudrate generator
    #ELSE        
        DEFINE DEBUG_REG PORTB
        DEFINE DEBUG_BIT 7
        DEFINE DEBUG_BAUD 9600
        DEFINE DEBUG_MODE 0
        ANSELB=0
        LATB.7=1
    #ENDIF
    SDA     var portc.4  ' DATA PIN
    SCL     VAR portc.3  ' CLOCK PIN
    
    
    Timeout    cON 2000
    reg        var BYTE
    fifo       var byte[6]
    addr       var byte 
    REVISION   var byte
    PARTID     var byte
    buffer     var byte[1152]
    ptr        var byte
    btr        var byte
    index      var word
    ;-----------------------  REGISTER -------------------------
    REG_TEMP_INT         con $1F
    REG_TEMP_FRAC        con $20
    REG_TEMP_CONFIG      con $21
    REG_PART_REVISION    con $FE
    REG_MODE             con $09
    REG_SPO2_CONFIG      con $0A        ;SPO2_ADC_RGE[6:5]SPO2_SR[4:2]LED_PW[1:0]
    REG_LED1_PA          con $0C
    REG_LED2_PA          con $0D
    FIFO_WR_PTR          con $04        ;FIFO_WR_PTR[4:0]
    FIFO_RD_PTR          con $06
    FIFO_DATA            con $07
    FIFO_CONFIG          con $08        ;FIFO_A_FULL[3:0]   SMP_AVE[7:5]
    STATUS1              con 0          ;A_FULL[7]
    
    
    ' -----------------------------------------------------------------------------|  
    
    
    #IFDEF  DEBUGING
        PAUSE 2000
        DEBUG 13,10,  "READY"
    #ENDIF
        ADDR  =  $ae     ; addr is  0x57 << 1
        reg= REG_PART_REVISION
        i2cread  SDA,scl,ADDR,reg,[REVISION,PARTID]
        reg= REG_MODE 
        i2cwrite  SDA,scl,ADDR,reg,[3] 
        reg= REG_SPO2_CONFIG
        i2cwrite  SDA,scl,ADDR,reg,[$30]
        reg = REG_LED2_PA 
        i2cwrite  SDA,scl,ADDR,reg,[2]
        reg = REG_LED1_PA 
        i2cwrite  SDA,scl,ADDR,reg,[2]
        reg = FIFO_CONFIG  
        i2cwrite  SDA,scl,ADDR,reg,[16]        
        
    #IFNDEF  DEBUGING
        HSEROUT [$73,$03,$04,$11,$ff,$ff,"PART ID: 0X",hex PARTID,"/0X", hex REVISION,$00]
        Hserin  timeout,error,[wait(6)]
    #ELSE
        DEBUG 13,10,  "PART ID: 0X",hex PARTID,"/0X",hex REVISION
    #ENDIF 
    
    
    '********************************************************************************
    start:
        reg= REG_TEMP_CONFIG
        i2cwrite  SDA,scl,ADDR,reg,[1] 
        reg= REG_TEMP_INT        
        i2cread  sda,scl,ADDR,reg,[fifo[0],fifo[1]]
    #IFNDEF  DEBUGING
        HSEROUT [$73,$05,$0A,$11,$07,$E0,"TEMP: ",DEC fifo[0],".",DEC2( fifo[1]<<6),$00]  
        Hserin  timeout,error,[wait(6)]
    #ELSE
        DEBUG 13,10, "TEMP: ",DEC fifo[0],".",DEC2( fifo[1]<<6) 
    #ENDIF
        GOSUB AQUIRE
        pause 5000
    goto start
    
    
    aquire:
        reg= FIFO_WR_PTR
        i2cwrite  SDA,scl,ADDR,reg,[0]
        reg= FIFO_RD_PTR
        i2cwrite  SDA,scl,ADDR,reg,[0]
         
     FOR index = 0 TO 1151 STEP 0
        
        btr =0
        reg= STATUS1
        WHILE btr&$80=0
        i2cread  sda,scl,ADDR,reg,[btr]
              
        WEND
        reg= FIFO_RD_PTR
        i2cread  SDA,scl,ADDR,reg,[btr]
        btr =  (btr- ptr) &  31
        WHILE btr
        reg = FIFO_DATA         
        i2cread  sda,scl,ADDR,reg,[buffer[index],buffer[index+1],buffer[index+0],buffer[index+5],buffer[index+4],buffer[index+3]]
        index=index+6
        btr=btr-1
        ptr = (Ptr+1) &  31
        WEND
        pause 200 ; no sure about this either
     NEXT  
        FOR index = 0 TO 1151 STEP 0
        DEBUG 13,10,HEX2 buffer[index+0],HEX2 buffer[index+1],9,HEX2 buffer[index+3],HEX2 buffer[index+4]     
        index=index+6
       NEXT 
    RETURN
    Last edited by richard; - 11th January 2022 at 22:21.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  34. #34

    Default Re: Heart rate sensor MAX30102

    thanks Richard,

    i will read carefully your code and will come back because i have couple of questions.

    In the begging i got confused the way you use addr and reg names inside the I2Cread or write command.

    Code:
    ADDR  =  $ae     ; addr is  0x57 << 1
        reg= REG_PART_REVISION
        i2cread  SDA,scl,ADDR,reg,[REVISION,PARTID]
    I followed the manual example: so i wont get consfused.

    Code:
    I2CWRITE PORTA.0,PORTA.1,cont,addr,[B2]

  35. #35
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    I followed the manual example: so i wont get consfused.
    not really

    addr is the i2c device address , reg is the register you are accessing. that example you refer is for an eeprom
    where those words make a little sense, in this context they are totally misleading
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  36. #36

    Default Re: Heart rate sensor MAX30102

    Quote Originally Posted by richard View Post
    not really

    addr is the i2c device address , reg is the register you are accessing. that example you refer is for an eeprom
    where those words make a little sense, in this context they are totally misleading
    once again you are right. I will change the names in the code as well.

    One more question. What is the difference on the following?

    With the [] and without them. I noticed that i get completely different results. The ones with the [] looks like is the right one as once i place them, i can control the values of the LED's pulse amplidute. Now it is visible the difference.

    Code:
    addr = $09   ' MODE CONFIGURATION 
    i2cwrite  SDA,scl,contwr,addr,[%00000011],error  ' ModLED = $02 as per data sheet heart rate mode, $03 SpO2 mode
    pause 10
    
    addr = $0A   ' SpO2 mode configuration 
    i2cwrite  SDA,scl,contwr,addr,[%01111101],error  ' check the manual for this configuration
    pause 100
    
    addr = $0C    'LED PULSE AMLIDUDE FOR for LED1_PA[7:0] 0x0C
    i2cwrite  SDA,scl,Contwr,addr,[$03],error' if LED1_PA = $3F  , 12.6 mA , ($7F is 25.4 mA)
    pause 10
    
    addr = $0D    'LED PULSE AMLIDUDE FOR LED2_PA[7:0] 0x0D
    i2cwrite  SDA,scl,contwr,addr,[$03],error ' if LED2_PA = $1F , 6.2 mA  , ($7F is 25.4 mA)
    pause 10
    and the following:

    Code:
    addr = $09   ' MODE CONFIGURATION 
    i2cwrite  SDA,scl,contwr,addr,%00000011,error  ' ModLED = $02 as per data sheet heart rate mode, $03 SpO2 mode
    pause 10
    
    addr = $0A   ' SpO2 mode configuration 
    i2cwrite  SDA,scl,contwr,addr,%01111101,error  ' check the manual for this configuration
    pause 100
    
    addr = $0C    'LED PULSE AMLIDUDE FOR for LED1_PA[7:0] 0x0C
    i2cwrite  SDA,scl,Contwr,addr,$03,error' if LED1_PA = $3F  , 12.6 mA , ($7F is 25.4 mA)
    pause 10
    
    addr = $0D    'LED PULSE AMLIDUDE FOR LED2_PA[7:0] 0x0D
    i2cwrite  SDA,scl,contwr,addr,$03,error ' if LED2_PA = $1F , 6.2 mA  , ($7F is 25.4 mA)
    pause 10

  37. #37
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    no brackets means no data will be written
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  38. #38
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    fifo read was stuffed up

    reg = FIFO_DATA
    i2cread sda,scl,ADDR,reg,[buffer[index+2],buffer[index+1],buffer[index+0],buffer[index+5],buffer[index+4],buffer[index+3]]

    the fifo print out is incorrect also , not yet solved
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  39. #39

    Default Re: Heart rate sensor MAX30102

    my code , you should know i have no idea :-
    1, what led pwr to use
    2, what led pwidth to use
    3, what sample rate to use
    4, what sample resolution to use
    5, if there are any fifo overflows and if it matters much
    6, what led the readings represents
    7, how to interpret the data
    8, how much data to collect [i assume at least 2 seconds worth]
    most of the drivers i've seen over the net are using the following...


    1, what led pwr to use : 0x1F about 6.2 mA
    2, what led pwidth to use : 411 which is 18 ADC BIT RESOLUTION based on the manual.
    3, what sample rate to use : sample rate per second 100

    a configuration should also include: sampleAverage = 8

    4, what sample resolution to use :
    5, if there are any fifo overflows and if it matters much.
    6, what led the readings represents. I will search and find out.
    7, how to interpret the data....
    8, how much data to collect [i assume at least 2 seconds worth]

  40. #40
    Join Date
    May 2013
    Location
    australia
    Posts
    2,038

    Default Re: Heart rate sensor MAX30102

    this looks like something, probably needs a lpf and sum of the squares function to remove dc drift

    Code:
    '****************************************************************'*  Name    : MAX30102  FOR PIC 18 DEMO                         *
    '*  Author  :  Richard                                          *
    '*  Notice  :                                                   *
    '*          :                                                   *
    '*  Date    : 9/1/2022                                          *
    '*  Version : 1.0                                               *
    '*  Notes   : MAX30102                                          *        
    '*          :18f26k22 @64Mhz                                    *
    '****************************************************************
     
      #CONFIG   ;  The PBP configuration for the PIC18F26K22 is:
        CONFIG FOSC     = INTIO67	       
        CONFIG PLLCFG   = OFF	        ;Oscillator multiplied by 4                       
        CONFIG PRICLKEN  = ON	        ;Primary clock enabled
        CONFIG FCMEN     = OFF	        ;Fail-Safe Clock Monitor disabled
        CONFIG IESO      = OFF	        ;Oscillator Switchover mode disabled
        CONFIG  BOREN    = SBORDIS      ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
        CONFIG  WDTEN    = ON           ; WDT is always enabled. SWDTEN bit has no effect                     ;|
        CONFIG  WDTPS    = 32768        ; 1:32768 ---> HERE enable the watchdog timer with a 1:32768 postscale;|
        CONFIG  PWRTEN   = ON
        CONFIG  HFOFST   = ON           ; HFINTOSC output and ready status are not delayed by the oscillator stable status
        CONFIG  MCLRE    = EXTMCLR      ; MCLR pin enabled, RE3 input pin disabled
        CONFIG  LVP      = OFF          ; Single-Supply ICSP disabled
        CONFIG  XINST    = OFF          ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
        CONFIG  DEBUG    = OFF          ; Disabled
        CONFIG  CP0 = OFF             ; Block 0 (000800-003FFFh) not code-protected
        CONFIG  CP1 = OFF             ; Block 1 (004000-007FFFh) not code-protected
        CONFIG  CP2 = OFF             ; Block 2 (008000-00BFFFh) not code-protected
        CONFIG  CP3 = OFF             ; Block 3 (00C000-00FFFFh) not code-protected
        CONFIG  CPB = OFF             ; Boot block (000000-0007FFh) not code-protected
        CONFIG  CPD = OFF             ; Data EEPROM not code-protected
        CONFIG  WRT0 = OFF            ; Block 0 (000800-003FFFh) not write-protected
        CONFIG  WRT1 = OFF            ; Block 1 (004000-007FFFh) not write-protected
        CONFIG  WRT2 = OFF            ; Block 2 (008000-00BFFFh) not write-protected
        CONFIG  WRT3 = OFF            ; Block 3 (00C000-00FFFFh) not write-protected
        CONFIG  WRTC = OFF            ; Configuration registers (300000-3000FFh) not write-protected
        CONFIG  WRTB = OFF            ; Boot Block (000000-0007FFh) not write-protected
        CONFIG  WRTD = OFF            ; Data EEPROM not write-protected
        CONFIG  EBTR0 = OFF           ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR1 = OFF           ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR2 = OFF           ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR3 = OFF           ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
        CONFIG  EBTRB = OFF           ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
     #ENDCONFIG    
     
      
    'define I2C_SLOW 1
    define  OSC 64
    
    
    OSCCON    = %01110000   ; 16Mhz
    OSCTUNE.6 = 1           ; Enable 4x PLL
    
    
    while ! osccon2.7 :WEND ; to make sure the pll has stabilised before you run any other code
    
    
       
    TRISC = %11011000                  
    ANSELC=0
    
    
    #DEFINE    DEBUGING 1   
    
    
    #IFNDEF  DEBUGING       
        DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
        DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
        DEFINE HSER_CLROERR 1 ' Clear overflow automatically
        DEFINE HSER_SPBRG 160 ' 38400 Baud @ 64MHz, -0.08%
        SPBRGH = 1
        BAUDCON.3 = 1         ' Enable 16 bit baudrate generator
    #ELSE        
        DEFINE DEBUG_REG PORTB
        DEFINE DEBUG_BIT 7
        DEFINE DEBUG_BAUD 9600
        DEFINE DEBUG_MODE 0
        ANSELB=0
        LATB.7=1
    #ENDIF
    SDA     var portc.4  ' DATA PIN
    SCL     VAR portc.3  ' CLOCK PIN
    
    
    Timeout    cON 2000
    reg        var BYTE
    fifo       var byte[6]
    addr       var byte 
    REVISION   var byte
    PARTID     var byte
    buffer     var byte[1152]
    ptr        var byte
    btr        var byte
    index      var word
    result     var word ext
    @result = _fifo 
    ;-----------------------  REGISTER -------------------------
    REG_TEMP_INT         con $1F
    REG_TEMP_FRAC        con $20
    REG_TEMP_CONFIG      con $21
    REG_PART_REVISION    con $FE
    REG_MODE             con $09
    REG_SPO2_CONFIG      con $0A        ;SPO2_ADC_RGE[6:5]SPO2_SR[4:2]LED_PW[1:0]
    REG_LED1_PA          con $0C
    REG_LED2_PA          con $0D
    FIFO_WR_PTR          con $04        ;FIFO_WR_PTR[4:0]
    FIFO_RD_PTR          con $06
    FIFO_DATA            con $07
    FIFO_CONFIG          con $08        ;FIFO_A_FULL[3:0]   SMP_AVE[7:5]
    STATUS1              con 0          ;A_FULL[7]
    
    
    ' -----------------------------------------------------------------------------|  
    
    
    #IFDEF  DEBUGING
        PAUSE 2000
        DEBUG 13,10,  "READY"
    #ENDIF
        ADDR = $ae     ; addr is  0x57 << 1
        reg = REG_PART_REVISION
        i2cread  SDA,scl,ADDR,reg,[REVISION,PARTID]
        reg = REG_MODE 
        i2cwrite  SDA,scl,ADDR,reg,[3] 
        reg = REG_SPO2_CONFIG
        i2cwrite  SDA,scl,ADDR,reg,[$20]
        reg = REG_LED2_PA 
        i2cwrite  SDA,scl,ADDR,reg,[9]
        reg = REG_LED1_PA 
        i2cwrite  SDA,scl,ADDR,reg,[9]
        reg = FIFO_CONFIG  
        i2cwrite  SDA,scl,ADDR,reg,[16]        
        
    #IFNDEF  DEBUGING
        HSEROUT [$73,$03,$04,$11,$ff,$ff,"PART ID: 0X",hex PARTID,"/0X", hex REVISION,$00]
        Hserin  timeout,error,[wait(6)]
    #ELSE
        DEBUG 13,10,  "PART ID: 0X",hex PARTID,"/0X",hex REVISION
    #ENDIF 
    
    
    '********************************************************************************
    start:
        reg= REG_TEMP_CONFIG
        i2cwrite  SDA,scl,ADDR,reg,[1] 
        reg= REG_TEMP_INT        
        i2cread  sda,scl,ADDR,reg,[fifo[0],fifo[1]]
    #IFNDEF  DEBUGING
        HSEROUT [$73,$05,$0A,$11,$07,$E0,"TEMP: ",DEC fifo[0],".",DEC2( fifo[1]<<6),$00]  
        Hserin  timeout,error,[wait(6)]
    #ELSE
        DEBUG 13,10, "TEMP: ",DEC fifo[0],".",DEC2( fifo[1]<<6) 
    #ENDIF
        GOSUB AQUIRE
        pause 5000
    goto start
    
    
    aquire:
        reg= FIFO_WR_PTR
        i2cwrite  SDA,scl,ADDR,reg,[0]
        reg= FIFO_RD_PTR
        i2cwrite  SDA,scl,ADDR,reg,[0]
        pause 200 
     FOR index = 0 TO 1151 STEP 0
        
        btr = 0
        reg = STATUS1
        WHILE btr&$80 = 0
        i2cread  sda,scl,ADDR,reg,[btr]
        WEND      
        
        reg = FIFO_RD_PTR
        i2cread  SDA,scl,ADDR,reg,[btr]
        btr = (btr - ptr) &  31
        WHILE btr
        reg = FIFO_DATA         
        i2cread  sda,scl,ADDR,reg,[buffer[index + 2],buffer[index + 1],buffer[index + 0],buffer[index + 5],buffer[index + 4],buffer[index + 3]]
        index = index + 6
        btr = btr - 1
        ptr = (Ptr + 1) &  31
        WEND
         pause 200 
        DEBUG "."
     NEXT  
        FOR index = 0 TO 1151 STEP 0
        for ptr = 0 to 2
        fifo[ptr] = buffer[index + ptr]
        next
        DEBUG 13,10;,  hex2 fifo[2] , hex2 fifo[1],  hex2 fifo[0]
    '    asm         ;ROTATE READING TO GET SUFFICIENT RESOLOUTION INTO UPPER WORD
    '    banksel _fifo 
    '    bcf STATUS,C
    '    RRCF  _fifo + 2 ,f
    '    RRCF  _fifo + 1 ,f
    '    RRCF  _fifo    ,f
    '    bcf STATUS,C
    '    RRCF  _fifo + 2 ,f
    '    RRCF  _fifo + 1 ,f
    '    RRCF  _fifo    ,f
    '    banksel 0
    '    endasm
        DEBUG 9,HEX4 result 
        index = index + 3
    '    DEBUG 13,10, hex2 buffer[index+2],hex2 buffer[index+1],hex2 buffer[index],9 ,HEX4 result  
    '    DEBUG 9,  hex2 fifo[2] , hex2 fifo[1],  hex2 fifo[0]
        for ptr = 0 to 2
        fifo[ptr] = buffer[index + ptr]
        next
        
    '    DEBUG 9,  hex2 fifo[2] , hex2 fifo[1],  hex2 fifo[0]
    '    asm         ;ROTATE READING TO GET SUFFICIENT RESOLOUTION INTO UPPER WORD 
    '    banksel _fifo
    '    bcf STATUS,C
    '    RRCF  _fifo +2 ,f
    '    RRCF  _fifo +1 ,f
    '    RRCF  _fifo    ,f
    '    bcf STATUS,C
    '    RRCF  _fifo +2 ,f
    '    RRCF  _fifo +1 ,f
    '    RRCF  _fifo    ,f
    '    banksel 0
    '    endasm
        DEBUG 9,HEX4 result
        index = index + 3
       NEXT 
    RETURN
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

Similar Threads

  1. New PIC failure rate
    By timmers in forum General
    Replies: 5
    Last Post: - 26th March 2009, 13:11
  2. Rf module baud rate
    By tazntex in forum Serial
    Replies: 4
    Last Post: - 5th August 2008, 19:47
  3. Replies: 6
    Last Post: - 18th January 2008, 09:17
  4. SHIFTOUT Clock rate
    By Brock in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 9th July 2006, 00:42
  5. Detect baud rate
    By Dick M in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 2nd July 2005, 22:10

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts