You've stolen the 128-bit encryption key to my heart.
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 19-01-2007, 23:56
maniac_2040's Avatar
maniac_2040 maniac_2040 is offline
Registered User
AKA: Matt
FRC #3302 (Turbo Trojans)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Clawson, Michigan
Posts: 34
maniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these parts
Send a message via MSN to maniac_2040
I hate "C"

I'm having a very tedious coding problem and I know it has something to do with the types/type casting in C.

I was writing/testing some PID code. It worked fine(I was just tweaking gains), but I noticed some overflow, so I changed alot of my variables from ints to longs. Now when I try to print, nearly everything prints as zero. Here is the code in question:

Code:
  
/*
 * pid_output
 *
 * This function outputs a value using a PID control loop for the specified PID struct.
 * Takes a measurement, maximum output, and index of the gains for this loop in EEPROM.
 */
int Pid_Output(Pid_Struct * pid, long measurement,int maxOutput,int eeprom_index)
{
	int output = 0;
    
	//Get smaller names for the gains.
        int pn = EEPROM_Read(eeprom_index);
	int pd = EEPROM_Read(eeprom_index+1);
        int in = EEPROM_Read(eeprom_index+2);
	int id = EEPROM_Read(eeprom_index+3);
        int dn = EEPROM_Read(eeprom_index+4);
	int dd = EEPROM_Read(eeprom_index+5);
	long p, i, d;

	pid->error = pid->setPoint-measurement;

	if( ABS(pid->error) < (long)pid->tolerance )
		pid->error = 0;

	//Accumlate error into the error_i and set the last error.
          pid->error_i+=pid->error;    
	pid->error_d = (pid->error - pid->error_last);
	pid->error_last = pid->error;

	//This is the PID part:

             p =((pid->error * (long)pn) / (long)pd);
             i= ((pid->error_i * (long)in) / (long)id);
	d= (((long)pid->error_d * (long)dn) / (long)dd);

	output = p + i + d;
	//DEBUG UNCONVENTIONAL
	printf("\rMeasure: %d Target: %d Err: %d Err_I: %d Err_d: %d Output: %d Max: %d",measurement,pid->setPoint,
			(int)p,(int)i,(int)d, (int)output, (int)maxOutput );

	//Make sure we're in bounds
    if(ABS(output) > maxOutput )
        output = maxOutput*SIGN(output);

	output+=pid->offset;
        
    return output;
}
(Sorry about some of the indentions, got screwed up when I copied and pasted)

so what is happening here? the value for "output" prints out fine, but everything else comes up as zero... pn, pd, etc are non zero...

Maybe I'm just too tired/lazy to figure this out.
  #2   Spotlight this post!  
Unread 20-01-2007, 00:04
JamesBrown JamesBrown is offline
Back after 4 years off
FRC #5279
Team Role: Engineer
 
Join Date: Nov 2004
Rookie Year: 2005
Location: Lynchburg VA
Posts: 1,285
JamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond reputeJamesBrown has a reputation beyond repute
Re: I hate "C"

I could be wrong, I havent done much with any thing other than ints on the robot but If you are overflowing an int and declared the variable as a long instead then when you print dont you need to put long in front of the variable name in the print statement rather than int.

James
__________________
I'm Back


5279 (2015-Present)
3594 (2011)
3280 (2010)
1665 (2009)
1350 (2008-2009)
1493 (2007-2008)
1568 (2005-2007)
  #3   Spotlight this post!  
Unread 20-01-2007, 00:21
Jake M Jake M is offline
void* Jake;
FRC #1178 (DURT)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Missouri
Posts: 118
Jake M has a spectacular aura aboutJake M has a spectacular aura about
Re: I hate "C"

You know, I don't quite see why you converted everything to long. The two types are essentially the exact same: both are signed, 4 byte numerical variables. It is strange that you would have this problem by switching this yes, but I don't see why you would think it would change anything. In my experiences, I've never seen any difference at all between the two, except for the name. (I may be missing something, but if I am, then I'll learn something here too) If you were trying to make the variable larger, to prevent overflow, the only way you can go bigger is to use a long long or long long int.

Also, could you provide some sample values that those variables might have. If it is indeed a casting problem, and I have an idea of what those values should be, I can run some test code and probably figure it out.
__________________
Code:
void function(void)
 {
  function();
 }

Last edited by Jake M : 20-01-2007 at 00:33.
  #4   Spotlight this post!  
Unread 20-01-2007, 00:26
maniac_2040's Avatar
maniac_2040 maniac_2040 is offline
Registered User
AKA: Matt
FRC #3302 (Turbo Trojans)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Clawson, Michigan
Posts: 34
maniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these parts
Send a message via MSN to maniac_2040
Re: I hate "C"

Quote:
Originally Posted by Jake M View Post
You know, I don't quite see why you converted everything to long. The two types are essentially the exact same: both are unsigned, 4 byte numerical variables. It is strange that you would have this problem by switching this yes, but I don't see why you would think it would change anything. In my experiences, I've never seen any difference at all between the two, except for the name. (I may be missing something, but if I am, then I'll learn something here too) If you were trying to make the variable larger, to prevent overflow, the only way you can go bigger is to use a long long or long long int.

Also, could you provide some sample values that those variables might have. If it is indeed a casting problem, and I have an idea of what those values should be, I can run some test code and probably figure it out.
they're not both 4 bytes. For some reason, an int is two bytes here. I found this out by printing a variable(int type) that was being incremented. When it was incremented pasted 32,xxx it overflowed and went back to -32,xxx. A long is bigger than an int. it wouldn't make much sense if it was the same size.

EDIT: Also, neither are unsigned, I have no idea where you got this from.
  #5   Spotlight this post!  
Unread 20-01-2007, 00:34
dcbrown dcbrown is offline
Registered User
AKA: Bud
no team
Team Role: Mentor
 
Join Date: Jan 2005
Rookie Year: 2005
Location: Hollis,NH
Posts: 236
dcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud of
Re: I hate "C"

Quote:
The two types are essentially the exact same: both are unsigned, 4 byte numerical variables
Both are signed values unless "unsigned" specifier user.

C18 2.1 Data Types and Limits in user guide:
char : signed 8 bits
int, short : signed 16 bits
short long: signed 24 bits
long : signed 32 bits
float : 32 bits
double : 32 bits

The v2.4 C18 library guide says it supports size qualifiers, so could try %ld instead of %d for the long variables. Drop the int cast if using %ld.

Last edited by dcbrown : 20-01-2007 at 00:45.
  #6   Spotlight this post!  
Unread 20-01-2007, 00:38
Unsung FIRST Hero
Mike Betts Mike Betts is offline
Electrical Engineer
no team
Team Role: Engineer
 
Join Date: Dec 2001
Rookie Year: 1995
Location: Homosassa, FL
Posts: 1,442
Mike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond repute
Re: I hate "C"

Matt,

There is a lot of your declarations not shown (such as your pid structure) but I'm guessing your issue is with the printf statement. "measurement" is declared as a long at the top of your function and being passed to printf as a long but printf is expecting an int. It should be cast as "(int) measurement". This would throw off all of your stack variables by two bytes each.

Output may be non-zero but I doubt it is correct.

Good Luck...

Mike
__________________
Mike Betts

Alumnus, Team 3518, Panthrobots, 2011
Alumnus, Team 177, Bobcat Robotics, 1995 - 2010
LRI, Connecticut Regional, 2007-2010
LRI, WPI Regional, 2009 - 2010
RI, South Florida Regional, 2012 - 2013

As easy as 355/113...
  #7   Spotlight this post!  
Unread 20-01-2007, 00:48
maniac_2040's Avatar
maniac_2040 maniac_2040 is offline
Registered User
AKA: Matt
FRC #3302 (Turbo Trojans)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Clawson, Michigan
Posts: 34
maniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these parts
Send a message via MSN to maniac_2040
Re: I hate "C"

Quote:
Originally Posted by Mike Betts View Post
Matt,

There is a lot of your declarations not shown (such as your pid structure) but I'm guessing your issue is with the printf statement. "measurement" is declared as a long at the top of your function and being passed to printf as a long but printf is expecting an int. It should be cast as "(int) measurement". This would throw off all of your stack variables by two bytes each.

Output may be non-zero but I doubt it is correct.

Good Luck...

Mike

ha....it sickens me that this was actually the problem. This was the THIRD time I have been screwed by those printf's in C(used to java, C++). Thank You. That fixed the problem, but I'm curious as to how this works. Why does it throw off the stack variables by two bytes each?(Not that I know much about the "stack" anyways ) and how did you know this? Could you point me to a paper or something that explains how some of these "inner workings" work?

EDIT: I knew it expected ints and I forgot that I changed measurement to a long, but I still wouldn't have expected that one mistake to mess up the rest of the function.
  #8   Spotlight this post!  
Unread 20-01-2007, 00:52
Jake M Jake M is offline
void* Jake;
FRC #1178 (DURT)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Missouri
Posts: 118
Jake M has a spectacular aura aboutJake M has a spectacular aura about
Re: I hate "C"

http://www.drpaulcarter.com/pcasm/

Well, you can't really call this a paper, but it's certainly got what you're looking for, and then some. It's one of the most influential documents in my "career" as a programmer. It deals with assembly language, the lowest programming language there is, unless you count binary as a language. It's pretty mind-boggling stuff, but if you can grasp the basic concepts, you won't believe how much your programming skills will improve. If you can learn and understand assembly, diagnosing code and logic problems will become almost intuitive and you'll be just as much better at coding them in the first place. Knowing assembly gives you a deep understanding of how C and other languages actually work, and how computers and processors themselves work. Of course you could just skip to the section on the Stack, and other things, but I'd recommend reading as much of it as you can, eventually.

However, you do still have a slight problem, I believe. You're casting your 4 byte longs as 2 byte ints. So, when looking at the prints, it may seem like they're overflowing, because you're not seeing the entire variable through the printf function. In memory, though, the value is not overflowing (if it's large enough to overflow 2 bytes) because its being stored as 4 bytes. If you wanted to see the whole variable, you need to use a printf escaped character (like %i and %d) that is used for longs. I can't remember what it is at the moment, though.
__________________
Code:
void function(void)
 {
  function();
 }

Last edited by Jake M : 20-01-2007 at 01:16.
  #9   Spotlight this post!  
Unread 20-01-2007, 00:54
dcbrown dcbrown is offline
Registered User
AKA: Bud
no team
Team Role: Mentor
 
Join Date: Jan 2005
Rookie Year: 2005
Location: Hollis,NH
Posts: 236
dcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud of
Re: I hate "C"

printf can be passed a variable number of arguments. The passed arguments are saved onto the stack and end up just a long list of bytes - no delimiters. The format statement is parsed to determine the number and size of the passed arguments. So, if measurement is a long - 4 bytes are passed because the caller knows its data type. But if the format statement says %d - print out an int - then the only the first two bytes are pulled from the list of argument bytes. The next %d will then print out the last two bytes of measurement, etc. In C, this is a varargs routine.

Last edited by dcbrown : 20-01-2007 at 01:01.
  #10   Spotlight this post!  
Unread 20-01-2007, 01:04
maniac_2040's Avatar
maniac_2040 maniac_2040 is offline
Registered User
AKA: Matt
FRC #3302 (Turbo Trojans)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Clawson, Michigan
Posts: 34
maniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these parts
Send a message via MSN to maniac_2040
Re: I hate "C"

Quote:
Originally Posted by dcbrown View Post
printf can be passed a variable number of arguments. The passed arguments are saved onto the stack and end up just a long list of bytes - no delimiters. The format statement is parsed to determine the number and size of the passed arguments. So, if measurement is a long - 4 bytes are passed because the caller knows its data type. But if the format statement says %d - print out an int - then the only the first two bytes are pulled from the list of argument bytes. The next %d will then print out the last two bytes of measurement, etc. In C, this is a varargs routine.
interesting. makes sense.

I never was really into that whole delimeter thing.
  #11   Spotlight this post!  
Unread 20-01-2007, 01:16
dcbrown dcbrown is offline
Registered User
AKA: Bud
no team
Team Role: Mentor
 
Join Date: Jan 2005
Rookie Year: 2005
Location: Hollis,NH
Posts: 236
dcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud ofdcbrown has much to be proud of
Re: I hate "C"

I should put a caveat on this... if you did a %c - print out a character, printf wouldn't pull just one byte from the argument list... it would pull two bytes. Thats because C18 promotes all smaller sized arguments to int before passing them to printf.

And don't hate C just because the C18 implementation of C is somewhat, um, quirky.

Last edited by dcbrown : 20-01-2007 at 01:21.
  #12   Spotlight this post!  
Unread 20-01-2007, 01:21
Jake M Jake M is offline
void* Jake;
FRC #1178 (DURT)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Missouri
Posts: 118
Jake M has a spectacular aura aboutJake M has a spectacular aura about
Re: I hate "C"

Hear, hear. When it follows the standard, C is one of the most powerful languages around. Windows was written in C.
__________________
Code:
void function(void)
 {
  function();
 }
  #13   Spotlight this post!  
Unread 20-01-2007, 01:30
Unsung FIRST Hero
Mike Betts Mike Betts is offline
Electrical Engineer
no team
Team Role: Engineer
 
Join Date: Dec 2001
Rookie Year: 1995
Location: Homosassa, FL
Posts: 1,442
Mike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond reputeMike Betts has a reputation beyond repute
Re: I hate "C"

Quote:
Originally Posted by maniac_2040 View Post
...Why does it throw off the stack variables by two bytes each?(Not that I know much about the "stack" anyways ) and how did you know this?
I've been working with embedded processors for over 25 years (and vacuum tubes, et cetera for 10 years before that). I think that I first learned about C and stack variables in college (circa 1978).

dcbrown's explanation is correct. When viewed from a pure "software" perspective, the fact that this processor passes parameters on the stack is, perhaps, confusing. C allows a variable argument list and it is up to the called function (in this case, printf) to parse the format string (the first parameter of the function is actually a pointer to a string) and determine how many variables there are and how large each one is. Your first %d in your format string indicated a 2 byte variable was the second parameter on the stack. When you put a long variable in the calling statement, 4 bytes were pushed onto the stack. That meant that all of your subsequent parameters were 2 bytes off...

I would refer you to K&R for more details. It was the bible back in the 70's and, in my opinion, it is still the bible.

For specifics on C as implemented for this processor, I'd look here.

Regards,

Mike
__________________
Mike Betts

Alumnus, Team 3518, Panthrobots, 2011
Alumnus, Team 177, Bobcat Robotics, 1995 - 2010
LRI, Connecticut Regional, 2007-2010
LRI, WPI Regional, 2009 - 2010
RI, South Florida Regional, 2012 - 2013

As easy as 355/113...
  #14   Spotlight this post!  
Unread 20-01-2007, 01:39
maniac_2040's Avatar
maniac_2040 maniac_2040 is offline
Registered User
AKA: Matt
FRC #3302 (Turbo Trojans)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Clawson, Michigan
Posts: 34
maniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these parts
Send a message via MSN to maniac_2040
Re: I hate "C"

Quote:
Originally Posted by Jake M View Post
Hear, hear. When it follows the standard, C is one of the most powerful languages around. Windows was written in C.
heh, maybe. but coming from Java and C++....C is definetely a step down.
  #15   Spotlight this post!  
Unread 20-01-2007, 01:53
maniac_2040's Avatar
maniac_2040 maniac_2040 is offline
Registered User
AKA: Matt
FRC #3302 (Turbo Trojans)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Clawson, Michigan
Posts: 34
maniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these partsmaniac_2040 is infamous around these parts
Send a message via MSN to maniac_2040
Re: I hate "C"

Quote:
Originally Posted by Mike Betts View Post
I've been working with embedded processors for over 25 years (and vacuum tubes, et cetera for 10 years before that). I think that I first learned about C and stack variables in college (circa 1978).

dcbrown's explanation is correct. When viewed from a pure "software" perspective, the fact that this processor passes parameters on the stack is, perhaps, confusing. C allows a variable argument list and it is up to the called function (in this case, printf) to parse the format string (the first parameter of the function is actually a pointer to a string) and determine how many variables there are and how large each one is. Your first %d in your format string indicated a 2 byte variable was the second parameter on the stack. When you put a long variable in the calling statement, 4 bytes were pushed onto the stack. That meant that all of your subsequent parameters were 2 bytes off...

I would refer you to K&R for more details. It was the bible back in the 70's and, in my opinion, it is still the bible.

For specifics on C as implemented for this processor, I'd look here.

Regards,

Mike
Hmm, very interesting.

Last time I'll make a printf mistake...once tried to concatenate strings in a prtinf...printf("measurement: "+measurement);..have to start remembering what language I'm in
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
New NEMO White Papers! "Creating a Killer Packet" and "25 Ways to Sponsor" Jessica Boucher Team Organization 0 10-08-2005 10:55
"Thunderbirds" Vs. "Team America" Which one will rule the box office? Elgin Clock Chit-Chat 3 07-09-2004 19:53
Conflict between "Initialize_Tracker()" and "pwm13 & pwm15"? Kevin? gnormhurst Programming 3 22-02-2004 02:55
how tall is the ramp when in "up" and "balanced" position??? archiver 2001 1 24-06-2002 00:54
I "hate" the new first site Dima General Forum 11 06-01-2002 19:40


All times are GMT -5. The time now is 03:50.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi