Thank you for pointing this out. You are absolutely right, the two methods yield different values.I will change to use the file, but I see it returns slightly different results which are not simply rounding issues
The following script makes this fact explicit, and shows more. It takes exactly 2 minutes to run:
Code:
import subprocessfrom time import monotonicdef get_temp(): with open("/sys/class/thermal/thermal_zone0/temp") as f: cputemp = f.readline() return int(cputemp.strip("\n")) / 1000def get_temp_slow(): ''' prerequisite: package raspi-utils is installed ''' ret = subprocess.run(["vcgencmd", "measure_temp"], capture_output=True) retstring = ret.stdout.decode() return float(retstring.lstrip("temp=").rstrip("'C\n"))def get_temp_slow2(): ''' prerequisite: package lm-sensors is installed ''' ret = subprocess.run(["sensors"], capture_output=True) lines = ret.stdout.decode().splitlines() for line in lines: if line.endswith("C)"): return float(line.split()[1].lstrip("+").rstrip("°C"))def unique_values(): print("acquiring temperature samples for one minute (sysfs method) ...") s = set() c = 0 stop = monotonic() + 60 while monotonic() < stop: temp = get_temp() s.add(temp) c += 1 print("... unique values observed:") print(sorted(s)) print(f"{c} samples acquired\n") print("acquiring temperature samples for one minute (vcgencmd method) ...") s = set() c = 0 stop = monotonic() + 60 while monotonic() < stop: temp = get_temp_slow() s.add(temp) c += 1 print("... unique values observed:") print(sorted(s)) print(f"{c} samples acquired") ''' # optional, uncomment if the package lm-sensors is installed print("\nacquiring temperature samples for one minute (sensors method) ...") s = set() c = 0 stop = monotonic() + 60 while monotonic() < stop: temp = get_temp_slow2() s.add(temp) c += 1 print("... unique values observed:") print(sorted(s)) print(f"{c} samples acquired") '''if __name__ == '__main__': unique_values()
Code:
acquiring temperature samples for one minute (sysfs method) ...... unique values observed:[48.5, 49.05, 49.6, 50.15, 50.7, 51.25, 51.8, 52.35, 52.9, 53.45, 54.0, 54.55, 55.1, 55.65, 56.2, 56.75]2983110 samples acquiredacquiring temperature samples for one minute (vcgencmd method) ...... unique values observed:[49.4, 49.9, 50.5, 51.0, 51.6, 52.1, 52.7, 53.2, 53.8, 54.3, 54.9, 55.4, 56.0, 56.5]33029 samples acquired
These are outputs from the ADC cleverca22 was talking about.
There were already visual clues in the temperature charts showing the digital nature of the noise.
The step increment in these values is 0.55°C, i.e. 1 LSB = 0.55°C
This is mediocre for human psychology but good enough for temperature control in the range considered.
The two decimals in the values have nothing to do with accuracy, they are here for consistency's sake.
In /sys/class/thermal/thermal_zone0 there are 2 files used for linear scaling. On my RPi5 I have these values:
slope = -550
offset = 450000
Most probably, these values are the same on every RPi5.
The scaling is: temp = slope * ADCval + offset
As an example, for 52.35°C we have temp = 52350 and ADCval = 723
Because the slope is negative, temperatures decrease as ADC outputs increase.
I've seen that the ADC has 10-bit resolution. So, assuming linearity over the whole range, the limits of the ADC are:
Code:
ADCval = 1023 -> -112.65°CADCval = 0 -> 450.00°C
But we would see even more noise though...
The discrete values observed with vcgencmd are peculiar.
There's definitely no rounding involved, instead notice the alternation of increments: 0.5, 0.6, 0.5 ...
As far as I know, the temperature is retrieved with IOCTL calls to /dev/vcio
I'm confused at this point, is it the same sensor to begin with?
Why do we have to ask the gpu to tell us about the cpu's temperature?
If you have lm-sensors installed, modify the script to make it a 3 minute run.
You'll see that values observed with the command sensors look like values from sysfs rounded to 1 decimal.
I'd agree with you that most of the time in Python, profiling is futile. However in some occurrences it can make sense.Much as I like Python, if speed is at all important, why not use C ?
I used a digital filter for noise rejection a few days ago, where the sampling period is cooked with time.sleep()
So I had to make sure that the duration of the routine was negligible compared to the shortest of the sampling periods I could be using.
Bottomline: it is, and the routines based on command spawning... are not.
Statistics: Posted by pragma — Sun Jan 14, 2024 12:50 pm