What did we just measure?
The potentiometer is hooked up between ground and Vdd. We turn the knob and get a voltage between 0 - 3.3 V, which we measured with the meter at AN0 where it goes* into the PIC.
The PIC's built in ADC converts this analog voltage to a digital signal. The ADC is in 12-bit mode, so this digital signal is 0x000 when voltage is 0, and 0xFFF (4095) when voltage = Vdd.
This line of code gets the output of the ADC and stores it in u16_adcVal:
u16_adcVal = convertADC1(); //get ADC value
This variable contains an integer between 0-4095. This is the hex number that the program outputs as "ADC in".
To store a voltage value between 0 and 3.3, we need a float:
f_adcVal = u16_adcVal;
f_adcVal now contains a number between 0.0 and 4095.0. We can think of it like a fraction: "n/4096ths of Vdd". So this line of code converts it into a voltage we can read:
f_adcVal = f_adcVal/4096.0 * VREF; //convert to float 0.0 to VREF
f_adcVal is the decimal number output in Bully as "ADC in"
So the ADC converts the analog voltage to digital and then sends it to the DAC, which converts it back to analog?
Not exactly. The ADC just takes in voltage and gives us a 12-bit number. The program converts this number to 8 bits, then sends the new 8-bit number to the DAC. In Task 1, the numbers are approximately the same because they represent the same thing - voltage at AN0.
Why 8 bits?
The MAX548A is an 8-bit DAC. If we send it the digital signal 0x00 it will output 0 V. If we send it 0xFF (255) it outputs Vdd. We can think of it like a fraction: "n/256ths of Vdd".
How do we convert 12 bits to 8?
This line of code lops off the least significant four bits: For example, 0xABC would become 0xAB.
u8_dacVal = (u16_adcVal>>4) & 0x00FF; //upper 8 bits to DAC value
u8_dacVal is the hex value for "To DAC" in the program.
How do we make the DAC output?
The following line of code sends the value to the DAC:
writeDAC(u8_dacVal);
Note that writeDAC takes a uint8_t as an argument.
To get the decimal value of what we are sending the DAC, we do need a float variable:
f_dacVal = u8_dacVal;
And we multiply by 256 (2^8 bc 8 bits). This is what is output in the program as the decimal number next to "To DAC"
f_dacVal = f_dacVal/256.0 * VREF;
We see approximately this value being output at OUTA (pin 2) of the DAC when we measure with the meter.
Why do you keep saying "approximately"?
The loss of precision caused by lopping off the last four bits is where most of your percent error comes from and why (unless you're using absolute value) this error is usually negative: DAC Out is always rounded down from ADC In.
How do I find the temperature?
The formula for the LM60 is:
From Texas Instruments SNIS119F - May 2004 - Revised August 2017
What is "the LM60 output voltage"?
In the program, it is f_adcVal.
So f_adcVal =...?
No, solve for T. Make a float variable like "f_tempC".
How do I convert to Farenheit?
Make another float variable. To convert Celsius to Fahrenheit, multiply degrees Celsius by 9/5 then add 32.
My fingers are 8000 degrees?!
mV = millivolts
My fingers are 50 degrees?!
In integer math, 9/5 = 1. Try (9.0/5.0).
My fingers are 72, no 83, no -12, no...
Check your wiring, in particular that:
pin 7 of PIC is connected to pin 3 of DAC
pin 17 of PIC is connected to pin 4 of DAC
pin 16 of PIC is connected to pin 5 of DAC
your potentiometer is not still connected to pin 2 of PIC
What are we supposed to be doing?
In Task 1, you got 0 - 3.3V from the potentiometer and made the DAC output the same thing. Then you hooked up your temperature sensor instead of the pot. The LM60 outputs 0 V at -40 C, and Vdd at 125 C. Since the range of temperatures you can generate by squeezing the sensor is a tiny fraction of that (unless you are very ill or have superpowers), the voltage output by the DAC will probably be something boring like 0.590 - 0.700 V. We want to make the DAC output almost the full range of voltages (0 - 3.3 V), so that our "midpoint" temperature is ~1.65 V.
Why?
Because when you get checked off you can go home.
What is my range? My midpoint? My percentage?
For your new low temperature, take the lowest temperature you saw (after you got the program working correctly) and subtract 2. Round down. For your new high temperature, squeeze the LM60 until you get bored and add 2. Round up.
range = new high - new low
midpoint = (new high - new low) / 2
In the code, make a float variable called f_percent or something like that.
f_percent = (f_tempF - new low) / range
Use whatever you called your Farenheit float variable. For new low and range don't use variables; just type in the numbers.
Now what?
You want to make u8_dacVal = 0 when the temperature = "new low", and u8_dacVal = 256 when the temperature = "new high", so multiply 256 by the percent:
f_dacVal = 256 * f_percent;
Then writeDAC(f_dacVal)?
You can, since it will automatically round down for you. However I would make u8_dacVal = f_dacVal, since you need to print both the 8-bit code and the float. Write u8_dacVal. Then set f_dacVal to the desired voltage by making it equal to VREF * percent. Finally, remove the initial writeDAC line: Do not write to the DAC twice.
Is it working?
When you squeeze the LM60 and make temperature = midpoint, does "DAC Out" (change the printf statement) = ~1.65? Does it say approximately the same thing on your voltmeter? Then it is working, and you can get the final checkoff of your Micro career.
*Voltage technically doesn't "go" anywhere and isn't "taken in", "sent", or "output" either. It is actually a measure of the number of tiny elves who inhabit that part of your circuit.