Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

Need help on Coding for storing 2 values at different intervals from counter timer.

Status
Not open for further replies.

Brien Cheow

Newbie level 6
Joined
Apr 29, 2015
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
168
P= Old ADC0 value.
n= First peak time taken
a=Second peak time taken
v= Difference in time between the two peaks
b=Difference in time converted to seconds
f=Calculation for beats per minute
s=Counter for every 10ms overflow from timer0.



Code:
{
   
	h= (ADC0>>4);
	
        for(l=0; l<127; l++)

		{
	
		if(p<h+5)
        {
		p=h;
		}
		
		else
		{
		n=s;
		break;
		}
		
		}
		for(l=0; l<127; l++)
{
        
		if(p>h-1)
   { 
		p=h;
   }
		else
	{
	
		break;
		
	}
		}
       for(l=0; l<127; l++)
	{
		if(p-1<h)
		{
		
		p=h;
		}
		
		else
		{
		  a=s;
		  break;
}
}
          v=a-n;
		  b =v*0^01;
		  f = (1/b)*60;
   
    for (l=0; l<127; l++)
{

if(p>h-1)
{
p=h;
}

else
{

break;
}

}
     
        
 
}
}
Somehow i cannot seem to get int a to copy value of s at second peak of my sin wave. Where as for n i can get it to copy value s when the peak of my sin wave reaches. The thing is that it constantly copies the s value when a peak reaches as compared to what i initially planned, that was to hold value for first peak and a will hold value of s on second peak.
Any help is greatly appreciated and thank you in advance:)
 

doraemon

Super Moderator
Staff member
Joined
Jun 21, 2009
Messages
1,068
Helped
273
Reputation
554
Reaction score
248
Trophy points
1,343
Location
Japan
Activity points
10,597
Hello!

A good way to get help would to tell us what exactly you are trying to do.
Do you want to count peaks per minute for some signal? Is it really a sine wave?
- Your code has no comments.
- I don't understand what your loops from 0 to 127 do.
- I don't understand what you mean by b = v * 0^01;
- I don't know what your variable types are
- Your code starts in the middle of nowhere with a {. What was before, what is next?
- Your code is likely to use float numbers, which is also useless.

Beside this, you also complicate simple things. Example:

if(p > h-1) p = h ... Why not if(p > h) p = h? It's the same and easier to
understand, the -1 is useless: Here is a list of p, h and results with your method
18 20 -> h=1 = 19, p is unchanged
19 20 -> p is still unchanged
20 20 -> p is more than 20-1, so it is replaced by h, which is 20 -> p is unchanged -> useless assignment with the same value.
21 20 -> p is replaced by 20. The equivalence with "if(p > h) p = h" seems to be proved.

A few advices:
1. Use meaningful variable names. Example;
P= Old ADC0 value.----------> adc_prevval, and possibly adc_val for the current value.
n= First peak time taken------> ???
a=Second peak time taken------> ???
v= Difference in time between the two peaks------> time_diff_ms
b=Difference in time converted to seconds--------> time_diff
f=Calculation for beats per minute-------> signal_bpm
s=Counter for every 10ms overflow from timer0.
2. Comment your code. This would help to understand for instance what your loops are for,
and what your b = v * 0^01; calculates.
3. Try to think first, program next, not the opposite.

Dora.
 

Brien Cheow

Newbie level 6
Joined
Apr 29, 2015
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
168
Hi doraemon! Thank you so very much for replying to my post!!
I have written comments for my code shown below so that people can understand it now!!
As for the question on why (p>h-1), i did it so that there is a threshold to be reached before the calculations begin as opposed to putting (p>h).






Code:
{
   
	h= (ADC0>>4);//initialisation for ADC0
	
        for(l=0; l<127; l++)//For loop for sampling till peak is reached and after that break out of loop in else function.

		{
	
		if(p<h+5)//if old ADC0 value<Current ADC0 value+5
        {
		p=h; //Old ADC0 value=Current ADC0 Value
		}
		
		else
		{
		n=s;//Int variable to store value from running overflow counter at first peak
		break;//Break out of for loop and move on to next for loop
		}
		
		}
		for(l=0; l<127; l++)//For Loop to sample till bottom of sin wave is reached.
{
        
		if(p>h-1)//If Old ADC0 value is more > current ADC0 value-1, Old ADC0 value = New ADC0 value.
   { 
		p=h;
   }
		else
	{
	
		break;//Break out of for loop
		
	}
		}
       for(l=0; l<127; l++)//For loop for continues sampling until peak is reached
	{
		if(p-1<h)//Same as previous peak detection loop.T his time i am storing the counter value in another int variable to calculate time elapsed between two peaks.
		{
		
		p=h;
		}
		
		else
		{
		  a=s;
		  break;
}
}
          v=a-n;//Time between two peaks of sin wave
		  b =v*0^01;//My counter s shows number of overflows my timer0 has, and for a single overflow it takes timer0 10ms, therefore i am converting the time to seconds as opposed to ms.
		  f = (1/b)*60; //1/T*60 for calculation of beats per minute.
   
    for (l=0; l<127; l++)//This for loop is to bring Old ADC0 value back to bottom of sin wave before the whole process can be repeated.
{

if(p>h-1)
{
p=h;
}

else
{

break;
}

}
     
        
 
}
}
 

doraemon

Super Moderator
Staff member
Joined
Jun 21, 2009
Messages
1,068
Helped
273
Reputation
554
Reaction score
248
Trophy points
1,343
Location
Japan
Activity points
10,597
Hello!

As for the question on why (p>h-1), i did it so that there is a threshold to be reached before the calculations begin
as opposed to putting (p>h).
I have just demonstrated above that:
Code:
if(p > h -1) {
    p = h;
}
is equivalent to:
Code:
if(p > h) {
    p = h;
}
Therfore thers is no opposition between f(p > h -1) p = h and if(p > h) p = h. It's the same!!! Read my example again.

Now you should consider replying to my first question: what are you trying to do?
The reply should not be "Coding for storing 2 values at different intervals from counter time" but more something like
"Try to measure the time difference between 2 peaks". Note that I'm not sure of this, it's an example.

Beside this, you have added comments, which is good, but most of them are almost useless.
Example:
Code:
if(p<h+5)//if old ADC0 value<Current ADC0 value+5
I know what "if(p<h+5)" means, so the comment is useless. The problem is: why are you doing this test? Why
ADC0 value + 5 and not ADC0 value + 69 or -45? Where does this +5 come from? That should be explained in
your comments. Comments' purpose is not to translate C into english, but to explain what you do.

It's not mandatory to have one comment per line. The best is to find an explanation that explains what you do
in plain english.

And while I'm writing this, here is another advice: Never use hard-coded constants.

Code:
if(p<h+5)
If this 5 has a well-defined meaning (for example some kind of hysteresis), then define a constant

Code:
#define   SIG_HYS  5
if(p < h + SIG_HYS) {
And to make it clear: don't use variables like p, v, n. If you read your code in 3 months from now, you will not even
understand it yourself. And don't use l as a variable because it can be confused with I (capital i) or even with 1.
And don't use capital I either.

Dora
 

Brien Cheow

Newbie level 6
Joined
Apr 29, 2015
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
168
Hello!



I have just demonstrated above that:
Code:
if(p > h -1) {
    p = h;
}
is equivalent to:
Code:
if(p > h) {
    p = h;
}
Therfore thers is no opposition between f(p > h -1) p = h and if(p > h) p = h. It's the same!!! Read my example again.

Now you should consider replying to my first question: what are you trying to do?
The reply should not be "Coding for storing 2 values at different intervals from counter time" but more something like
"Try to measure the time difference between 2 peaks". Note that I'm not sure of this, it's an example.

Beside this, you have added comments, which is good, but most of them are almost useless.
Example:
Code:
if(p<h+5)//if old ADC0 value<Current ADC0 value+5
I know what "if(p<h+5)" means, so the comment is useless. The problem is: why are you doing this test? Why
ADC0 value + 5 and not ADC0 value + 69 or -45? Where does this +5 come from? That should be explained in
your comments. Comments' purpose is not to translate C into english, but to explain what you do.

It's not mandatory to have one comment per line. The best is to find an explanation that explains what you do
in plain english.

And while I'm writing this, here is another advice: Never use hard-coded constants.

Code:
if(p<h+5)
If this 5 has a well-defined meaning (for example some kind of hysteresis), then define a constant

Code:
#define   SIG_HYS  5
if(p < h + SIG_HYS) {
And to make it clear: don't use variables like p, v, n. If you read your code in 3 months from now, you will not even
understand it yourself. And don't use l as a variable because it can be confused with I (capital i) or even with 1.
And don't use capital I either.

Dora
Hi Dora!
the purpose for
Code:
(p<h+5)
is basically because i do not want the sampling to jump to else and break out of the for loop when there is no signal therefore the +5 or -1. As for the Value why it is +5 or -1 is because i found it to be most effective to removing any other interference during the sampling stage such as peaks that normal pulse signals will encounter before/after hitting the true peak(e.g Dicrotic notch) in a PPG signal. Also Trying to measure the time difference between 2 peaks could be a btr header lol but i feel that its too much to ask from the community hee therefore i would rather work out most of the things myself and ask for help only when i narrow down towards the main problem in my coding
 

doraemon

Super Moderator
Staff member
Joined
Jun 21, 2009
Messages
1,068
Helped
273
Reputation
554
Reaction score
248
Trophy points
1,343
Location
Japan
Activity points
10,597
Hello!

The problem is that if you don't give the overall picture, then nobody is going to understand the process
of your code. Detecting the interval between peaks is easy.

As for the Value why it is +5 or -1
Again, your -1 has NO EFFECT!!!

because i found it to be most effective to removing any other interference
What do you call interference? Is it noise of your input signal?
As you use the word "dicrotic", I guess you are trying to develop a heart pulse counter. In this case, why not
asking how to measure the time between two peaks of an ECG? It would be clear to everybody, and
certainly more than "storing 2 values at different intervals from counter time". By the way I still don't understand
what these 2 values are.
Then you show your code, what you have already done, and it would be easier to help.

could be a btr header
What is a btr header?

Beside this, there are still plenty of obscure operations in your code. I don't understand the meaning of the
l loops (0 ~ 126) because all what's inside does not depend on l.

I think it should be like this: (in pseudo code)
Code:
Loop {
    Get sample;
    Calculate variation since last sample;
    If variation was positive AND is now negative AND greater than a preset theshold {
        Store current time
        Calculate difference with previous time, calculate bps, display result, etc
        Update previous time stamp for next time
    }
}
It's possible to add some filtering, etc. By the way, for reliable peak detection and RRI measurement, you
should work at 500 or 1000 Hz. But it depends how your signal is detected (electrodes? optical?...)

That's about it.

Dora.
 

Brien Cheow

Newbie level 6
Joined
Apr 29, 2015
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
168
Hi Dora my full code is here.
I am using an optical sensor to detect BVP
I have implemented hardware filters to cancel out noise but interference in this case is false peak caused by a unstable amplitude of the signal which means most probably the person moved.
As for better header i mean that your suggestion to change the post title.
Thanks for all your help so far
Code:
/* 
    Graphic LCD 64 by 128 pixels, Monochrome 
    SP5-GFX1 
     Connection to P2 of 8051  : Silicon Lab C8051F340 
    #1 GND 
    #2 +5V 
    #3 SI  serial data -- P2.7 
    #4 SCL serial clock -- P2.6 
    #5 A0P  0 = select control, 1 = data port --- P2.5 
    #6 RESET low to reset LCD panel -- P2.4 
    #7 CS1    chip select, 0 = enable data transfer -- P2.3 
    #8 BL-  Back light - GND 
    #9 BL+  Back light - +5V 
 
    Page memory for display : B0 to B7, eight pages, one page 128 bytes 
        each byte for 8 rows x 1 column, bit 0 at row 0, bit 1 at row 1 etc.     
 
    last edited : 15 Jan 2015. 
    Version 1.0 
*/ 
//#include <reg51.h> 
#include <c8051f340.h>                 // SFR declarations 
#include "stdio.h" 
 
//----------------------------------------------------------------------------- 
// Global CONSTANTS 
//----------------------------------------------------------------------------- 
 
#define SYSCLK      12000000           // SYSCLK frequency in Hz 
 
sfr16 ADC0 = 0xbd;      // ADC0 result register 
sfr16 TMR2RL   = 0xca;                 // Timer2 reload value 
sfr16 TMR2     = 0xcc;                 // Timer2 counter 
 
/* 
sbit LCD_SI = P2^1; 
sbit LCD_SCL = P2^2; 
sbit LCD_A0P = P2^3; 
sbit LCD_RESET = P2^4; 
sbit LCD_CS1 = P2^5; 
*/ 
 
 
sbit LCD_SI = P2^7; 
sbit LCD_SCL = P2^6; 
sbit LCD_A0P = P2^5; 
sbit LCD_RESET = P2^4; 
sbit LCD_CS1 = P2^3; 
 
int i,j,k,m,s,p,n,l,a,v,b,f,h,x; 
char fp[6];  
char sp[6]; 
p = 0; 
s = 0; 
a = 0; 
v = 0; 
b=0; 
n=0; 
f=0; 
x=1; 
 
 
 
// 5 columns by 8 rows ASCII font, starting from SPACE, 0x20 
code unsigned char font[] = { 
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,   //  ! 
   0x00,0x03,0x00,0x03,0x00,0x14,0x7f,0x14,0x7f,0x14,   // "# 
   0x24,0x2a,0x7f,0x2a,0x12,0x23,0x13,0x08,0x64,0x62,   // $% 
   0x36,0x49,0x55,0x22,0x50,0x00,0x05,0x03,0x00,0x00,   // &' 
   0x00,0x1c,0x22,0x41,0x00,0x00,0x41,0x22,0x1c,0x00,   // () 
   0x14,0x08,0x3e,0x08,0x14,0x08,0x08,0x3e,0x08,0x08,   // *+ 
   0x00,0x50,0x30,0x00,0x00,0x08,0x08,0x08,0x08,0x08,   // ,- 
   0x00,0x60,0x60,0x00,0x00,0x20,0x10,0x08,0x04,0x02,   // ./ 
   0x3e,0x51,0x49,0x45,0x3e,0x00,0x42,0x7f,0x40,0x00,   // 01 
   0x42,0x61,0x51,0x49,0x46,0x21,0x41,0x45,0x4b,0x31,   // 23 
   0x18,0x14,0x12,0x7f,0x10,0x27,0x45,0x45,0x45,0x39,   // 45 
   0x3c,0x4a,0x49,0x49,0x30,0x01,0x71,0x09,0x05,0x03,   // 67 
   0x36,0x49,0x49,0x49,0x36,0x06,0x49,0x49,0x29,0x1e,   // 89 
   0x00,0x36,0x36,0x00,0x00,0x00,0x56,0x36,0x00,0x00,   // :; 
   0x08,0x14,0x22,0x41,0x00,0x14,0x14,0x14,0x14,0x14,   // <= 
   0x00,0x41,0x22,0x14,0x08,0x02,0x01,0x51,0x09,0x06,   // >? 
   0x32,0x49,0x79,0x41,0x3e,0x7e,0x11,0x11,0x11,0x7e,   // @A 
   0x7f,0x49,0x49,0x49,0x36,0x3e,0x41,0x41,0x41,0x22,   // BC 
   0x7f,0x41,0x41,0x22,0x1c,0x7f,0x49,0x49,0x49,0x41,   // DE 
   0x7f,0x09,0x09,0x09,0x01,0x3e,0x41,0x49,0x49,0x7a,   // FG 
   0x7f,0x08,0x08,0x08,0x7f,0x00,0x41,0x7f,0x41,0x00,   // HI 
   0x20,0x40,0x41,0x3f,0x01,0x7f,0x08,0x14,0x22,0x41,   // JK 
   0x7f,0x40,0x40,0x40,0x40,0x7f,0x02,0x0c,0x02,0x7f,   // LM 
   0x7f,0x04,0x08,0x10,0x7f,0x3e,0x41,0x41,0x41,0x3e,   // NO 
   0x7f,0x09,0x09,0x09,0x06,0x3e,0x41,0x51,0x21,0x5e,   // PQ 
   0x7f,0x09,0x19,0x29,0x46,0x46,0x49,0x49,0x49,0x31,   // RS 
   0x01,0x01,0x7f,0x01,0x01,0x3f,0x40,0x40,0x40,0x3f,   // TU 
   0x1f,0x20,0x40,0x20,0x1f,0x3f,0x40,0x38,0x40,0x3f,   // VW 
   0x63,0x14,0x08,0x14,0x63,0x07,0x08,0x70,0x08,0x07,   // XY 
   0x61,0x51,0x49,0x45,0x43,0x00,0x7f,0x41,0x41,0x00,   // Z[ 
   0x02,0x04,0x08,0x10,0x20,0x00,0x41,0x41,0x7f,0x00,   // \] 
   0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40,   // ^_ 
   0x00,0x01,0x02,0x04,0x00,0x20,0x54,0x54,0x54,0x78,   // `a 
   0x7f,0x48,0x44,0x44,0x38,0x38,0x44,0x44,0x44,0x20,   // bc 
   0x38,0x44,0x44,0x48,0x7f,0x38,0x54,0x54,0x54,0x18,   // de 
   0x08,0x7e,0x09,0x01,0x02,0x0c,0x52,0x52,0x52,0x3e,   // fg 
   0x7f,0x08,0x04,0x04,0x78,0x00,0x44,0x7d,0x40,0x00,   // hi 
   0x20,0x40,0x44,0x3d,0x00,0x7f,0x10,0x28,0x44,0x00,   // jk 
   0x00,0x41,0x7f,0x40,0x00,0x7c,0x04,0x18,0x04,0x78,   // lm 
   0x7c,0x08,0x04,0x04,0x78,0x38,0x44,0x44,0x44,0x38,   // no 
   0x7c,0x14,0x14,0x14,0x08,0x08,0x14,0x14,0x18,0x7c,   // pq 
   0x7c,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x20,   // rs 
   0x04,0x3f,0x44,0x40,0x20,0x3c,0x40,0x40,0x20,0x7c,   // tu 
   0x1c,0x20,0x40,0x20,0x1c,0x3c,0x40,0x30,0x40,0x3c,   // vw 
   0x44,0x28,0x10,0x28,0x44,0x0c,0x50,0x50,0x50,0x3c,   // xy 
   0x44,0x64,0x54,0x4c,0x44,0x00,0x08,0x36,0x41,0x00,   // z{ 
   0x00,0x00,0x7f,0x00,0x00,0x00,0x41,0x36,0x08,0x00,   // |} 
   0x10,0x08,0x08,0x10,0x08,0x00,0x00,0x02,0x05,0x02 }; // ^degree 
 
 
//----------------------------------------------------------------------------- 
// Function PROTOTYPES 
//----------------------------------------------------------------------------- 
 
void delay(int d);               // delay by d ms 
void delaya(void);               // a short delay 
void SYSCLK_Init (void);       // set CPU clock 
void PORT_Init (void);           // init CPU ports 
void LCD_reset(void);           // reset LCD 
void LCD_command(unsigned char);        // Send command code to LCD   
void LCD_data(unsigned char);        // ASCII character to be displayed on LCD  
void SPI_send(unsigned char);        // shift 8 bit data to LCD interface, high bit first 
void write_char(unsigned char);        // display an ASPI intSCII code at current position 
void write_msg_xy(unsigned char, unsigned char, unsigned char*); // write strting at x col, y row 
void set_xy(unsigned char x, unsigned char y);    // set cursor position 
void plot_xy(unsigned char x, unsigned char y); 
 
//----------------------------------------------------------------------------- 
 
 
//void timer0_interrupt(void) interrupt 1 using 1   //auto reload every 50us 
//{ 
  
//} 
 
 
void LCD_Clear_Display() 
{ 
     for(k=0; k<8; k++)        // clear display 
    { 
        LCD_command(0xB0 + k); delay(20); 
        LCD_command(0x10);    //high nibble of column address 
        LCD_command(0x00);    // low 4 bits of column address 
      for(i=0; i<128; i++) 
      { 
        LCD_data(0x00);   
      } 
    } 
} 
 
void delay(int d)  // delay for d ms 
{ 
   int i, j; 
   for(i=0; i<d; i++) 
     for(j=0; j<1179; j++); 
} 
 
void delaya()      //a short delay 
{ 
  char j; 
  for(j=0; j<1; j++); 
} 
void timer0_interrupt_init() 
{ 
    TMOD = 0x01; 
  //  TR0 = 0; 
    //TL0 = 0xEF;  
    //TH0 = 0xD8;  
    TR0 = 1; 
    EA = 1; 
    ET0 = 1; 
    
//  while(TF0==0); 
 
   //TF0 = 0; 
  
   
} 
 
void timer0 (void) interrupt 1 
{  
    
   
    s++; 
// sp = &s; 
    TL0 = 0xEF; //lower bit 
    TH0 = 0xD8; //higher bit 
    TF0 = 0; 
 
     
} 
 
 
void main (void)  
{ 
   PCA0MD &= ~0x40;                    // WDTE = 0 (clear watchdog timer                                                                                    
                                       // enable) 
   PORT_Init();                        // Initialize Port I/O 
   SYSCLK_Init ();                     // Initialize Oscillator 
  
// ADC init. 
   ADC0CN = 0x00;                      // ADC0 disabled, normal tracking,  
                                       // conversion triggered on TMR2 overflow 
   REF0CN = 0x03;                       //Internal voltage reference for ADC  
   AMX0P = 0x00;                       //   0x05=P2^6.. 0x13 ADC0 positive input = P1.1 
   AMX0N = 0x1F;                       // ADC0 negative input = GND 
                                       // i.e., single ended mode 
   ADC0CF = ((SYSCLK/3000000)-1)<<3;   // set SAR clock to 3MHz 
   ADC0CF |= 0x00;                     // right-justify results  
   AD0EN = 1;  
    
  // SFRPAGE = TIMER01_PAGE;             // Set SFR page 
 
/* 
   TH0 = -151;    // -149;                           // Init Timer0 High register 
   TL0 = TH0;                          // Set the intial Timer0 value 
   ET0=1;                              // Timer0 interrupt enabled 
   TCON = 0x10;                        // Timer0 ON 
  // TMOD = 0x02;                        // Timer0 in 8-bit reload mode 
    EA = 1;       // allows interrupt 
*/ 
   //delay(200); 
   
  
 
// initialize graphic LCD, set 8x8 fonts and graphic, OR mode for text and graphic 
     LCD_reset();   
    LCD_command(0xA2);       // LCD bias, 1/9 bias 
    LCD_command(0xA0);       // set normal display mode 
    LCD_command(0xC8);       // set output mode 
    LCD_command(0x23);       // set voltage regulator internal resistor 
    LCD_command(0x81);       // electronic voltage double - two byte instruction 
    LCD_command(0x1D);       // 6 bits, 0 to 0x2F, increase contrast 
    LCD_command(0x2B);       // set power control circuit 
    LCD_command(0x40);       // set start line = 0 
    LCD_command(0xAF);       // setdisplay on 
    LCD_command(0x10);     // lower 4 bits for high nibble of column address, 0 to 127 
    LCD_command(0x00);       // lower 4 bits for low nibble of column address 
    LCD_command(0xB0);     // set page address, B0 to B7 for 8 pages 
    LCD_Clear_Display();    //clear LCD screen 
  
 
 
     write_msg_xy(0, 0, "BVP(C)2015 NYP/BEMG 70BPM"); 
 
     delay(30); 
 
 
         
// enable timer interrupts 
//    ET0=1; 
//    TMOD=0x21; 
//    TR0=1; 
//    EA=1; 
 
  while(1) 
  { 
   timer0_interrupt_init();//initialise timer0 mode1 
     
    for(k=0; k<127; k++) 
    { 
 
      m= 63 - (ADC0>>4);      //take high 6 bits from the 10-bit adc 
      plot_xy(k, m); 
      plot_xy(k, m-1);    // add two more dots for thicker lines 
      plot_xy(k, m+1); 
       delay(30); 
      AD0BUSY = 1;     // start ADC conversion 
 
       
/*   
      if ((k & 0x1F) == 0 )          //draw straight lines 
      { 
        for(j=0; j<4; j++) 
        { 
            set_xy(k,4+j);     
            LCD_data(0xFF); 
         } 
      } 
*/ 
 
        
{ 
    
    //h= (ADC0>>4); 
     
  //  for(l=0; l<50; l++) 
    while(1) 
 
    { 
        h= (ADC0>>4); 
SPI_send; 
LCD_reset; 
LCD_command; 
LCD_data; 
write_msg_xy; 
plot_xy; 
set_xy; 
        if(p<h+4)    p=h; 
        else 
        { 
            n=s; 
            break; 
        } 
 
    } 
 
//for(l=0; l<50; l++) 
while(1) 
    { 
        h= (ADC0>>4); 
SPI_send; 
LCD_reset; 
LCD_command; 
LCD_data; 
write_msg_xy; 
plot_xy; 
set_xy; 
        if(p+1>h)    p=h; 
        else    break; 
 
    } 
         
//for(l=0; l<50; l++) 
while(1) 
    { 
       h= (ADC0>>4); 
SPI_send; 
LCD_reset; 
LCD_command; 
LCD_data; 
write_msg_xy; 
plot_xy; 
set_xy; 
        if(p<h+4)  p=h; 
        else 
        { 
          a=s; 
          break; 
        } 
 
    } 
          v = a-n; 
          b = v/100; 
          f = 60/b; 
    
 
//for(l=0; l<50; l++) 
while(1) 
{ 
h= (ADC0>>4); 
SPI_send; 
LCD_reset; 
LCD_command; 
LCD_data; 
write_msg_xy; 
plot_xy; 
set_xy; 
if(p+1>h) 
{ 
p=h; 
} 
 
else 
{ 
 
break; 
} 
 
 
} 
      
         
  
} 
    
//delay(30); 
}    LCD_Clear_Display(); 
    //sprintf(sp,"%4D",b); 
    //write_msg_xy(100, 55, sp); 
  
  } // end while(1)  
} // end main  
 
 
// configure I/O ports 
void PORT_Init (void) 
{ 
/* 
    P1SKIP=0x20; 
    P1MDOUT = 0x0F;             
    P2MDOUT = 0x3F; 
  //  P3MDOUT = 0xFF;             // for ULN2803 drivers 
  //  P4MDOUT = 0xFF; 
  //  P0MDOUT = 0xFF;             // for LTC1298, LCD interfaces 
    P2MDIN &= 0x0BF;        // P2.6 as ADC0 
 
    P0MDOUT |= 0x10;        // Enable UTX as push-pull output 
       XBR0     = 0x01;        // Enable UART on P0.4(TX) and P0.5(RX)                      
       XBR1     = 0x40;        //0x40; Enable crossbar and weak pull-ups 
//    P2 = 0xFF; 
//    P3 = 0xFF; 
//    P4 = 0xFF; 
*/ 
 
    P1MDOUT = 0x00;            // enable P1 outputs 
    P2MDOUT = 0xFE; 
    P3MDOUT = 0xFF;             // for ULN2803 drivers 
    P4MDOUT = 0xFF; 
    P0MDOUT = 0xFF;             // for LTC1298, LCD interfaces 
 
//    P0MDOUT |= 0x10;        // Enable UTX as push-pull output 
//       XBR0     = 0x01;        // Enable UART on P0.4(TX) and P0.5(RX)                      
       XBR1     = 0x40;        //0x40; Enable crossbar and weak pull-ups 
    P2 = 0xFF; 
    P3 = 0xFF; 
    P4 = 0xFF; 
} 
 
//----------------------------------------------------------------------------- 
// initializes the system clock to use the internal oscillator 
void SYSCLK_Init (void) 
{ 
   OSCICN |= 0x03;                     // Configure internal oscillator  
   RSTSRC  = 0x04;                     // Enable missing clock detector 
} 
 
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
// LCD routnies  
// send one byte to SPI interface 
void SPI_send(unsigned char dd) 
{ 
unsigned char i; 
    LCD_CS1=0; 
     for(i=0; i<8; i++) 
    { 
       LCD_SCL=0;          // set clock pulse low first 
        if( dd  & 0x80 )     // set data bit 
           LCD_SI=1; 
       else 
           LCD_SI=0; 
       LCD_SCL=1;        // clock high 
       dd = dd <<= 1;   // shifted to next bit 
      } 
    LCD_CS1=1; 
    delaya(); 
} 
 
 
void LCD_reset() 
{ 
  LCD_RESET = 0; 
  delay(10); 
  LCD_RESET = 1; 
  delay(10); 
} 
 
 
void LCD_command(unsigned char ch) {    //send a command byte to LCD  
     LCD_A0P = 0; 
    SPI_send(ch); 
    delaya(); 
} 
 
void LCD_data(unsigned char ch) {    //send a data byte to LCD data port 
     LCD_A0P = 1; 
    SPI_send(ch); 
} 
 
// print an ASCII code on LCD at current text position 
void write_char(unsigned char ch) 
{ 
unsigned char * fontptr, k; 
    fontptr = font + (ch-0x20) * 5;          // get the font pattern, 8 by 5 
    for(k=0; k<5; k++) 
      LCD_data( *fontptr++); 
} 
 
 
// display a message at column x, row y 
void write_msg_xy(unsigned char x, unsigned char y, unsigned char *chptr) 
{ 
char * ptr; 
    ptr = chptr; 
    set_xy(x, y); 
    while(*ptr) 
      write_char(*ptr++); 
 
} 
 
void plot_xy(unsigned char x, unsigned char y)  // draw a dot at position x, y, x: 0 to 127, y:0 to 63 
{ 
char ypage, dd=1; 
    ypage = y >>3; 
    set_xy(x, ypage); 
    ypage = y & 0x7; //low 3 bits for dot position 
    dd = dd << ypage; 
    LCD_data(dd); 
    sprintf(fp,"%4D",n); 
    write_msg_xy(100, 55, sp); 
 
    sprintf (sp,"%4D",a); 
    write_msg_xy(100, 65,fp); 
 
     
 
} 
 
 
// set LCD display position 
void set_xy(unsigned char x, unsigned char y) 
{ 
       LCD_command(0x10 | ( x>> 4) & 0x07  );    // lower 4 bits for high nibble of column address, 0 to 127 
    LCD_command(0x00 | x & 0x0F);    // lower 4 bits for low nibble of column address 
    LCD_command(0xB0 | y & 0x07);  // set page address, B0 to B7 for 8 pages 
} 
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 

doraemon

Super Moderator
Staff member
Joined
Jun 21, 2009
Messages
1,068
Helped
273
Reputation
554
Reaction score
248
Trophy points
1,343
Location
Japan
Activity points
10,597
Hello!

Apparently you don't want to listen (or read) what I'm telling you. I suggested some ways to make
the code easier to read and to improve it.
- You still use hardcoded constants
- You still use one-letter variables (int i,j,k,m,s,p,n,l,a,v,b,f,h,x; ) which makes your code unreadable
- I also proved that your "if(p+1>h) p=h;" is the same as if(p > h) p = h,
but you still write "if(p+1>h) p=h;", so I guess all the efforts to help you will be in vain.
I stongly encourage that you write your code yourself. At least I will not dig in it.

Now a possible cause of error:
v = a-n;
b = v/100;
f = 60/b;
All are integers.
If I suppose that f is a frequency in beats per minute, and if I also suppose the b cannot be 0 (therefore
v is necessarily greater than or equal to 100.
Possible valies for b: 1, 2, 3, etc...
Therefore possible values for f:
60, 30, 20, etc...
You will never be able to detect a pulse rate of, say, 50 bps.It will be either 60 or 30. And you will never
detect more than 60 bps.

Dora.
 

Brien Cheow

Newbie level 6
Joined
Apr 29, 2015
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
168
Hi Dora i am sorry if i angered you but i am really new to coding. Btw the bulk of the code was written by my lecturer and i was suppose to implement the peak detection algorithm and calculate the heartbeat rate from there.And btw i was the one who wrote the logic. i have a few questions. first off what is hardcoded constants. and also the part where you said that it is either 30 or 60 BPM is true.. but i dont understand what you are trying to explain.
 
Last edited by a moderator:

doraemon

Super Moderator
Staff member
Joined
Jun 21, 2009
Messages
1,068
Helped
273
Reputation
554
Reaction score
248
Trophy points
1,343
Location
Japan
Activity points
10,597
Hello!

I'm not angry, I was just suggesting that you should make efforts to write code which is self
explanatory, and also take into account what people reply.
That said, this is a forum. Therefore I prefer not to reply by mail, but reply on the forum so that
everybody can benefit from what has been said.
As for what I was trying to explain:

1. You have these variables, all integers:
int i,j,k,m,s,p,n,l,a,v,b,f,h,x;
Now you use these variables like this:
Code:
    v = a-n;        //  The result is an integer, no surprise
    b = v/100;    //  Here comes the surprise: the result is also an integer
    f = 60/b;       //  Second surprise, f is also an integer
I didn't read all the code, but from what I guess: v is a time expressed in 1/100 seconds, right?
Now you calculate this time in second, so that's why you divide by 100. You can consider that b is the period, and 1/b the
frequency.
Next, you calculate the frequency not in Hz, but in bpm, that's why you multiply the frequency (1/b) by 60.

Now let's examine what happens:
I suppose that you know that if you use only integers, dividing for example 3 by 2 gives you 1. Not 1.5 because you
are using integers.

Let's say that in the above code, v is 115.
If you divide v by 100, you will get b = 1. Not 1.15.
Now if you calculate 60 / b, you will get 60 and not the 60/1.15 = 52 that you could expect.
I suppose you agree that for any value of v in the [100, 200[ interval (the [ is not a typo, it means that 200 is not included)
you will get a b of 1, then a f of 60.
Now what happens for 200 and for any value in the [200, 300[ interval?
v/100 will be 2 and 60 / b will be 30. No intermediate value.
If you continue with the subsequent values, you will get a f of 30 for any value of v in [300, 400[, etc.

In order to solve this, you have 2 methods. One idiotic method, and one smart method.
The idiotic method consists in using float numbers. Therefore in my above example, b would become 1.15 and
f would become 60.

The smart method consists in staying in the integer domain, but thinking about what you do.

If you do: b = v/100 and f = 60 / b, then f = 60 / (v/100)
In other words, if you revert the last (v/100) and put it at the numerator, you will have 60 * 100 / v or f = 6000 / v
This time, if you get, like in the above example, a v of 115, then your final f will be 6000/115 = 52

Dora.
 

Status
Not open for further replies.
Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top