February 11, 2012 by lsoltmann I am trying to build a temperature controller and am having some trouble with what seems to be a coupling between two ADC pins. I have a 10K thermistor connected to PC0 using a voltage divider, an LED connected to PC1, and a 5K potentiometer connected to PC2. The code is as follows ``````#define F_CPU 14745600 #include #include #include #include #include #include #include "../libnerdkits/delay.h" #include "../libnerdkits/lcd.h" #include "../libnerdkits/uart.h" // PIN DEFINITIONS: // // PC0 -- thermistor input // PC1 -- relay output // PC2 -- potentiometer input // ******** Initialize Variables ******** uint16_t adc0; uint16_t adc2; uint16_t adc_val; uint8_t i; double ctemp; double ctemp_avg; double sysv; double pottemp; double setpoint; int dev; void adc_init() { ADCSRA = (1< library? Both variables need to be "doubles" and it is x raised to the y power. One problem that can come up is a 'double' in AVR is only good for 7 significant digits. I did try the pow function ,but now that you mention it I did forget to add the math.h library. Just ran a test case and it did work. Guess I'm too used to MATLAB where all these function are built in ... Lars - As you found out pcbolt is correct with the Pow function in the math library. There is nothing wrong with your code, you are trying to learn as I am. One thing you might want to consider is store ((adc0/1024.0)*5.0) in a variable. For example: ``````volts = ((adc0/1024.0)*5.0); ctemp = -0.494*pow(volts,5) +6.8723*pow(volts,4) -39.559*pow(volts,3) +117.59*pow(volts,2) -212.09*volts +270.24; `````` The reason for this is because it takes quite a bit of time to multiply and divide doubles. A lot of my experience was from writing drivers for SCSI and USB controller boards, so performance was always a big issue. Some compilers will optimize it, but I never take that for granted. What are the constant values you are using. i.e. -0.494, 6.8723, -39.559, etc? That does make sense and makes it look better. I'll definitely go back and change that in the code. I appreciate the help. The constant values in the equation are just the coefficients for each the terms to shape the polynomial. I obtained them from the calibration curve that I generated from the data sheet. The 5th order fit is overkill but it does provide a perfect fit, at least within the region I am interested. If anyone is interested, I got the thermistors from DigiKey http://www.digikey.com/product-detail/en/B57861S0103F040 wisc4ever - I tried the block of code you suggested, ``````volts = ((adc0/1024.0)*5.0); ctemp = -0.494*pow(volts,5) +6.8723*pow(volts,4) -39.559*pow(volts,3) +117.59*pow(volts,2) -212.09*volts +270.24; `````` but I keep getting errors when I compile. I ran some tests and it appears that I can not use an exponent higher than 2 if my base is not an integer. Is this a limitation of the pow function or am I just doing something wrong? I will try a couple of tests, but pow function should handle a double in both parameters and should return a double. Send a code snippet when you get the chance, I will try the test right away. This compiles... ``````volts = ((adc0/1024.0)*5.0); ctemp = -0.494*pow(volts,2); `````` This does not... ``````volts = ((adc0/1024.0)*5.0); ctemp = -0.494*pow(volts,3); `````` I can string them together and it works as long as the exponent is less than or equal to 2. The error i'm getting is this nom27883d:rims_controller lsoltmann\$ make make -C ../libnerdkits make[1]: Nothing to be done for `all'. avr-gcc -g -Os -Wall -mmcu=atmega168 -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm -o erims.o erims.c ../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(inverse.o):../../../libm/fplib/inverse.S:50: relocation truncated to fit: R_AVR_13_PCREL against symbol `__divsf3' defined in .text section in /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/avr5/libgcc.a(_div_sf.o) /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(log.o):../../../libm/fplib/log.S:94: relocation truncated to fit: R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/avr5/libgcc.a(_addsub_sf.o) /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(log.o):../../../libm/fplib/log.S:98: relocation truncated to fit: R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/avr5/libgcc.a(_addsub_sf.o) /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(modf.o):../../../libm/fplib/modf.S:87: relocation truncated to fit: R_AVR_13_PCREL against symbol `__subsf3' defined in .text section in /usr/local/AVRMacPack-20080721/lib/gcc/avr/4.3.0/avr5/libgcc.a(_addsub_sf.o) make: *** [erims.hex] Error 1 Your pow function call should not be causing these errors. From what I see (I will continue looking in case I am wrong) is being caused in the make command and not your code, but it appears your code is making it happen. What development system are you using (computer/OS)? Check your include for math.h is it: #include I did a cut and paste of the original snippet I posted and it works fine, but my dev system is a Mac running OS 10.4. I am running the code on a MacBook Pro with OS 10.6. I checked to make sure that I had the #include in the code. I assuming that the make file did not need any modifications when I added the math.h library. I appreciate the help. For what you are doing you should not have to change your make file. Your C compiler and libraries should be the same as mine, so that should not be a problem. Try the following: 1) Get your code to compile (even if you comment out the offending code). 2) Copy and paste the following snippet. Including the '{' and '}'. 3) Try to compile it. This should isolate the pow function into a chunk of code with everything defined locally and no external resources being used with the exception of the pow function. 4) Let me know what happens. { uint16_t aTemp; double vTemp; double Temp; aTemp = 1; vTemp = ((aTemp/1024.0)*5.0); Temp = -0.494*pow(vTemp,5); } ``````{ uint16_t aTemp; double vTemp; double Temp; aTemp = 1; vTemp = ((aTemp/1024.0)*5.0); Temp = -0.494*pow(vTemp,5); } `````` That did compile. Since the code you just tried used the power of 5, we can assume the pow function is correct. The next step is to check your declarations of adc0, volts, and ctemp. adc0 should be a uint16_t. volts and ctemp should be double. ``````double ctemp; double volts; uint16_t adc0; ``````