Need help with simple math code please!

This is a discussion on Need help with simple math code please! within the C Programming forums, part of the General Programming Boards category; Hey guys, I'm having some trouble with some math code used for my PIC16F684. Code: int16 PV, SP; int16 E0; ...

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    10

    Need help with simple math code please!

    Hey guys,

    I'm having some trouble with some math code used for my PIC16F684.

    Code:
    int16 PV, SP;
    int16 E0;
    uns8 gain;
    int16 output;							
    uns16 temp;
    
    SP = 128;
    
    PV = ADRESH;	// ADC value = ADRESH (8 MSbs)
    
    E0 = PV - SP;
    
    output = gain*E0;
    
    if(output > 0){
    	P1M1 = 0;
    	temp = output;			
    	temp /= 4;		// Shift bits 3 to 10 of temp twice to the right
    	CCPR1L = temp;
    	}
    
    if(output < 0){
    	P1M1 = 1;			
    	temp = -output;
    	temp /= 4;		// Shift bits 3 to 10 of temp twice to the right
    	CCPR1L = temp;	
    	}
    Don't worry about the A/D conversion, I just deleted the other code. The problem I'm having is that I don't believe the second if statement is working properly. I want to take the absolute value of "gain" but my compiler doesn't have the absolute function. Instead I just put "-gain" which compiles fine and I think works.

    When output > 0, the PIC outputs a PWM square wave which shows up fine on the oscilloscope. It's when output should be < 0, the output on the oscilloscope is a very strange square wave, that looks noisy and has weird superimposing square waves. I think the problem is with the math though.

    Can someone verify if the way I initialized the variables will properly store data? I get confused when I'm doing math with mixes of signed and unsigned numbers. Keep in mind CCPR1L and ADRESH can only store 8 bit numbers.

    I'd appreciate the help a lot. Thanks!

  2. #2
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    Seems ok.

    You can condense:
    Code:
    if (output > 0) {
    	P1M1 = 0 ; 
    	CCPR1L = (output >> 2) ; // Shift bits 3 to 10 of temp twice to the right
    }
    
    if (output < 0) {
    	P1M1 = 1;			
    	CCPR1L = ((-output) >> 2) ; // Shift bits 3 to 10 of temp twice to the right
    }
    Mac and Windows cross platform programmer. Ruby lover.

    Quote of the Day
    12/20: Mario F.:I never was, am not, and never will be, one to shut up in the face of something I think is fundamentally wrong.

    Amen brother!

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    10
    Hey,

    Unfortunately the compiler I use doesn't have that shift command for some reason .

    Otherwise looks okay? My concern is with the temp. It's okay that it takes the -output value? That value is technically a signed integer, so does temp just throw away the sign bit?

  4. #4
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    Assuming you have a standard compiler... (and you obviously don't...), putting the - prefix on a signed field will flip the sign, just like multiplying by -1.
    Mac and Windows cross platform programmer. Ruby lover.

    Quote of the Day
    12/20: Mario F.:I never was, am not, and never will be, one to shut up in the face of something I think is fundamentally wrong.

    Amen brother!

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    10
    yea that makes sense. but my point is that "temp" is unsigned and -output is signed. When -output gets placed inside "temp", does it just drop the sign bit?

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I wouldn't count on that.

    if(number < 0) number *= -1;

    Would be my preference.

  7. #7
    Registered User
    Join Date
    Mar 2006
    Posts
    10
    My concern is that because i'm using a mix of signed and unsigned integers, the sign bit might be getting lost somewhere, or even worse used as a bit that is placed inside a register such as CCPR1L.

    Code:
    int16 temp;
    int16 output;
    
    if(output < 0){
    	P1M1 = 1;			
    	temp = -output;
    	CCPR1L = (unsigned char)temp/4;	
    	}
    Would the code above guarantee that CCPR1L only gets the MSBs without the sign bit? For example, if temp is 10 bits of data + 1 sign bit (11 bits), would the CCPR1L register be given bits 2-9 (disregarding the 10th bit)? Hope this ain't too confusing lol

  8. #8
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    OK. the $64 question.

    WHY are you using a mix of signed and unsigned for your calculations?????
    Mac and Windows cross platform programmer. Ruby lover.

    Quote of the Day
    12/20: Mario F.:I never was, am not, and never will be, one to shut up in the face of something I think is fundamentally wrong.

    Amen brother!

  9. #9
    Registered User
    Join Date
    Mar 2006
    Posts
    10
    Well, I need to keep track of negatives so they must be signed integers. The only reason I'm using UNSIGNED is because "CCPR1L" is a register in a microcontroller. I do not want a sign bit being placed in a register as it will just consider it part of the numerical value. I want to make the number unsigned THEN put it into the register to ensure this.

    I definitely am not an expert programmer so if someone knows a better way I'd really appreciate it. I simulated the code and the CCPR1L values are not correct in the (output < 0) part of the code. There is definitely something wrong with them but I can't figure it out

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by MetaMorphicX View Post
    yea that makes sense. but my point is that "temp" is unsigned and -output is signed. When -output gets placed inside "temp", does it just drop the sign bit?
    No, that is not what will happen.

    Anyway, what you want is the absolute (positive) value of the number.

    So use abs(). You may have to cast the return value to unsigned but that is okay.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Weird error in this simple code! C2248!
    By gross100 in forum C++ Programming
    Replies: 2
    Last Post: 12-10-2005, 01:31 AM
  2. Replies: 14
    Last Post: 11-23-2005, 08:53 AM
  3. << !! Posting Code? Read this First !! >>
    By kermi3 in forum C# Programming
    Replies: 0
    Last Post: 10-14-2002, 02:26 PM
  4. << !! Posting Code? Read this First !! >>
    By biosx in forum C++ Programming
    Replies: 1
    Last Post: 03-20-2002, 12:51 PM
  5. Simple Code, looking for input.
    By Alien_Freak in forum C Programming
    Replies: 3
    Last Post: 03-03-2002, 11:34 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21