SKR v1.3 with AD8495 doesn't boot
Expected behavior: [What you expect to happen]
Read the AD8495 correctly
Actual behavior: [What actually happens]
Board will not boot
I've been working on this board for hours trying to figure out why the SD card doesn't get mounted to the host and the COM port doesn't respond. With the Marlin bugfix and smoothieware firmware from Bigtreetech's github it boots right up. As soon as I made changes to the 2.0.4.3 config and flash the firmware it would stop working. It would boot up for about 15-30 seconds with the COM port in device manager (which would not respond to prontorface) then the COM port would disappear and it would show up as a failed device with description "device descriptor not recognized". I must have changed every setting relating to LCD's, EEPROM, serial ports, SD cards, etc. Luckily I found #14006 which was similar problems to what I was getting and near the bottom mentioned thermal protection kicking in. I changed TEMP_SENSOR_0 from -4 to 1 and it booted straight up. It looked like there was a fix implemented but it apparently does not work with this sensor type. If you need any configs from me let me know but should be pretty easy to reproduce by just setting TEMP_SENSOR_0 to -4 with or without a sensor plugged in.
Try adding this to your Configuration and see if it helps with the AD8495…
// Ignore temp readings during initial startup
#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000
With the setting above I can confirm that the issue of the board "not booting" is thermal protection.
[ERROR] Error:Thermal Runaway, system stopped! Heater_ID: 0
I was debugging this further with MMcLure on discord tonight. I turned on the display of the RAW value for the formula in temperature.cpp with SHOW_TEMP_ADC_VALUES in Configuration_adv.h. 1648 seems to be a pretty common reading. After some manual calculations MMcLure decided that setting TEMP_SENSOR_AD8495_GAIN to 0.015625 in Configuration_adv.h should fix the issue, which it did. MMcLure says there's a problem with both OVERSAMPLENR (resulting in 16x multiplier) and HAL_ADC_RESOLUTION (resulting in a further 4x multiplier).
Interesting, and it makes sense. The ADC resolution determines how many bits to expect, and essentially the more bits there are the more the value gets re-doubled. Two extra bits (12 vs 10) would give you 4x the expected value, if your math expects 10 bits. So, ok, we just need to look at HAL_ADC_RESOLUTION when we resolve this.
In your testing did you also have an attached normal thermistor, and did that also give 4x the expected value?
I'll see if I can put together a quick patch for testing.
The thing is that with a regular thermistor there's a lookup in a table, while with the AD8495 it's all done via a formula with no lookup.
The formula is
#define TEMP_AD8495(RAW) ((RAW) * 6.6 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET)
@atsage was getting a raw value of 1647. If we use that in the formula with the default values we end up with a temperature of 1061C. If we adjust the formula to:
#define TEMP_AD8495(RAW) ((RAW) * 6.6 * 100.0 / 1024.0 / (OVERSAMPLENR) / (THERMISTOR_TABLE_SCALE) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET)
we end up with 265.38C which is still high.
However, if we divide that by 16 we get 16.58C which is very close to the correct temperature. So I think there's also a problem related to OVERSAMPLENR. The LPC1768 HAL sets OVERSAMPLENR to 1 (via HAL_ADC_FILTERED) while all other HALs set it to 16. This works fine for thermistors looking up in tables, but for some reason isn't working here.
Take a look at this issue: #14257. The comments towards the end are most correct. The formula we need is going to depend on the Reference Voltage and the "Transfer Function" that fits the device and the interface.
As you mentioned, the LPC1768 is unique in having a 12-bit ADC but that would only account for the result being off by 4x. But the other 16x can't be accounted for by OVERSAMPLENR because with the LPC1768 that value actually ends up being 1. So there is no oversampling at all. It's using the raw value as received.
So the question becomes, where is that other 16x actually coming from? That's a full extra 4 bits of resolution, and it can't be accounted for by the HAL ADC resolution. This means the reading coming from the sensor is actually 16x too large. But then, there aren't enough bits there….
Here is my config
config.zip
OK - the reason this works for the thermistor table lookup is because the thermistor table values are scaled at compile time by the OV() macro which takes into account both THERMISTOR_TABLE_SCALE and OVERSAMPLENR. So we definitely need to take THERMISTOR_TABLE_SCALE into account in the TEMP_AD8495() macro.
I just find it very coincidental that there's an exact 16x offset. Powers of 2 make me suspicious of a logic error.
I believe the / 1024.0 in those AD595 and AD8495 formulae refers to the ADC bit size.
So it should probably be replaced with / (1 << (HAL_ADC_RESOLUTION)). That would take care of the 4x part.
Or just use HAL_ADC_RANGE which is equivalent to (1 << (HAL_ADC_RESOLUTION)).
which takes into account both
THERMISTOR_TABLE_SCALEandOVERSAMPLENR…
THERMISTOR_TABLE_SCALE won't come into play. It simply refers to the fact that the numbers in the tables are based on 10 bit ADC. If you're not converting a table then there's nothing needing THERMISTOR_TABLE_SCALE.
Six of one... dividing by (1024 * THERMISTOR_TABLE_SCALE) has the same effect as dividing by HAL_ADC_RANGE (or (1 << (HAL_ADC_RESOLUTION)). But I agree that just using HAL_ADC_RANGE is clearer since we're not looking into a thermistor table.
(4095 * 5.0 * 100.0 / 4096.0 / 1.0 * 1.0 + 0.0) == 499.88
The AD8495's output is always 5 mV/°C. VCC for the chip can be from 2.7V to 36V. The output voltage is never bigger then VCC. If VCC is smaller than 5V the measurable temperature is limited by that - lower than 1000°C. (3.3V/5mV/°C = 660°C)
In
define TEMP_AD8495(RAW) ((RAW) * 6.6 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET)
The result is in (float) °C.
RAW is the addition of OVERSAMPLENR readings of the ADC.
6.6 is 2 times the reference voltage of the ADC. (3.3/5V)
100.0 is together with the above factor 2 the 5mV/°C scaling.
1024 is the ADC range. The number you get when 3.3/5V are applied to the ADC at 10bit. (4096 for 12bit)
OVERSAMPLENR the number of ADC readings what are averaged.
TEMP_SENSOR_AD8495_GAIN, narmally 1.
TEMP_SENSOR_AD8495_OFFSET, normally 0.
AD595 puts out 10mV/°C and is not specified for being used with VCC below 5V. (From 3.3V/10mv = 330°C on a 3.3V ADC is in danger to be destroyed.)
For the interested:
RAW / OVERSAMPLENR = average_ADC_value
ADC_Max_Voltage / ADC_RANGE = ADC_Volt_Per_Digit
average_ADC_value * ADC_Volt_Per_Digit = Volt
Volt * ADxxxx_Converter_Constant = °C
Shift the line in the coordinate system by self determined Calibration constants. °C_corrected = a*°C + b.
This is only true if ADxxxx, thermocuple and ADC behave strictly linear. Non of the components behaves really linear. With a table driven algorithm (like that for the thermistors) you could get a bit more exact results, if you have (and that's a problem) a much better reference thermometer to produce the table.
I'm still confused what the * 6.6 * 100.0 / 1024.0 part of the formula is for. The docs say that the reference voltage doesn't matter when calculating the value. Temperature = (Vout - 1.25) / 0.005 V
Documentation of what? The module?
Some modules apply a voltage to the REF-pin of the chip - here seemingly 1.25V. That enables the modules to measure negative temperatures, but cuts the maximum measurable temperature down by the same amount.
With the 1.25V offset the new temperature range is from -1.25V/5mv/°C = -250°C to (3.3V-1.25V)/5mV/°C = 410°C instead of the 0°C to 3.3V/5mV/°C = 660°C for what the formular was made for.
Simply set TEMP_SENSOR_AD8495_OFFSET to -250 ( -1.25V/5mv/°C = -250°C).
Yes, documentation for the module. https://www.adafruit.com/product/1778
I have the TEMP_SENSOR_AD8495_OFFSET set to 0 and I'm getting the correct values with the default formula. I dunno, doesn't make sense to me but I lost most of my algebra years ago.
* 6.6 * 100 / 1024 is
* 3.3 * 200 / 1024 is
* 3.3 / 0.005 / 1024 is
* 3.3 / 1024 / 0.005 is
* (ADC_reference_voltage / ADC_counts) / sensor_gain is
* Volt_per_ADC_digit / sensor_gain
It really does not matter if you are subtracting 1.25V from the voltage on the one or 250°C on the other side of the equation - that's the same.
If someone tries to use the AD8495 with a 5V-ADC the TEMP_SENSOR_AD8495_GAIN is (5.0/3.3).
If someone uses the AD595 with a 3.3V-ADC the TEMP_SENSOR_AD8495_GAIN is (3.3/5.0).
So the 16x is coincidental! I was stuck on it being a multiplication issue instead of a subtraction. So using HAL_ADC_RANGE and setting TEMP_SENSOR_AD8495_OFFSET to -250 should resolve the OP's problem.
If no one else gets to it first, I'll make a PR to replace the 1024.0 with (float)HAL_ADC_RANGE.
I made the changes in the PR and everything seems to be working now.
Also changed in Configuration_adv.h #define TEMP_SENSOR_AD8495_OFFSET -250.0 to account for my specific Adafruit module.
Thanks everyone, especially @atsage for hitting me up on Discord about this. The fix should help future-proof the firmware and it's one more area I'll be keeping in mind from now on!
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.