New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
module: DS18B20, new module for 1-wire temperature sensor (WIP) #3462
module: DS18B20, new module for 1-wire temperature sensor (WIP) #3462
Conversation
Initial commit of code to support 1-wire (Dallas) sensors such as the DS18B20. requires Linux kernel drivers to create a file in /sysfs which is read by this module, and temperature typically returned to a temperature_fan. This code purely for testing/revew. No documentation as yet. Signed-off-by: Alan Lord <alanslists@gmail.com>
Thanks. As we discussed on IRC, I think the file reading should really be done in the "linux mcu" code. Performing the IO from the MCU allows us to keep portability, permissions, and timing consistent. It would also be worthwhile to only perform the -Kevin |
@KevinOConnor Thanks. I made a comment on IRC about the linux/mcu code part. As this reads from a file, a user doesn't actually need to have the Linux MCU configured. The target fan's pin could be on any mcu, but the file read is not reliant on having the RPi configured as an MCU at all. Secondly, I thought I had updated my code so open is only called once and I am using seek(0)... See line 51. |
I still feel this should be implemented from the "linux mcu" code. Handling just this one device differently from all the others is not something I'm comfortable with (it would have less reliable timing, require host code privileges, use a different update thread, be constrained to only support devices directly connected to the host, etc.).
I missed that - thanks. -Kevin |
NP - I guess I'd better start learning how to write C then. Can you point me to a good example of how the python code interfaces with some mcu code? I tried to look for something the other day but I failed to see how, for example, bus.py actually interfaces to the i2c.c code... Sorry for being dense. |
You'll want to look at src/thermocouple.c and klippy/extras/spi_temperature.py . That code does something very similar. I put together some demo code to show what the C code would look like - it's on the work-ds18b20-20201024 branch (see 7ac3eef). It is totally untested. -Kevin |
That's awesome. Thanks Kevin. |
Any further updates on this? -Kevin |
I've not had much time of late but did mention something on irc last Sunday... Am getting a "Rescheduled timer in the past" error, but can't understand from the logs the root cause. |
Ah, okay. If you update your latest code and attach the log, I'll try to take a look. Cheers, |
Thanks very much Kevin - I have pushed the current code onto this branch. Attached is the klippy.log. the error always happens after the first read. You can see the value from the sensor is being returned. I'm guessing it's something to do with the clocks but I don't "grok" the logs well enough to really work out what's going on. FWIW, I'm in no rush. |
Odd. If you change ds18_read() to:
What does the output() call report? -Kevin |
lol - was just about to hit the sack but caught your message - have separated your output message for clarity: `Configured MCU 'mcu' (1024 moves) #output: read timing t1=2150002040 t2=2150003126 t3=2150003142 t4=2195569798 got {'#receive_time': 16049.048920544, u'next_clock': 2400000000L, u'oid': 0, u'value': 20750000, '#name': u'ds18_result', '#sent_time': 0.0} |
The value should be val / 1000 by and not * 1000 on this line I believe:
|
If i change that to / 1000 then the log prints: ` #output: read timing t1=750002225 t2=750003399 t3=750003409 t4=793569068 got {'#receive_time': 16286.010951027, u'next_clock': 1000000000, u'oid': 0, u'value': 21, '#name': u'ds18_result', '#sent_time': 0.0} |
Unfortunately, in both examples, it took ~900ms to read from the file. That isn't going to work in Klipper (neither in the mcu code nor in the host python code). We can't stop processing everything for that long. Do you know if there is a way to read from that linux device in such a way that it doesn't force a pause? If we have to do it manually, it would require starting a new thread just to be able to read without blocking, which would be a bit of work. -Kevin |
Oh - what is the format of the file? If you just |
I knew it was slow - but that is very slow... I read something about it taking ~1/2 second after "opening" the file to read from. I'll do some research and come back if I can find anything. I guess maybe that just 1-wire is too slow? Or maybe this kernel module itself is the delay? There are a few 1-wire C libraries on github (gpl or compatible) which are portable - I did have a thought about trying to integrate one so the 1-wire protocol was available on more MCUs than just the RPi, but my C knowldege is way too light for that right now. I'll update in a day or two on what I find. Thanks for the help. |
This kernel module outputs ascii. If I read the "temperature" file (rather than w1_slave), then it ONLY sends a 5 digit integer. e.g. 23750 which I guess is milli-Celsius and means 23.750'C |
It's definitely in the kernel logic. One simple test would be to run the read() first and then do the lseek().
Ah, okay. Then we don't want to multiply or divide in the C code at all. We should just send the integer as it is and the python host code should do the divide by 1000 (and multiply by 1000 when calculating the min/max range). Something like the following:
|
Alas, I think it's the sensor... In the data sheet there's a discussion about the resolution:
And the later on in the datasheet it discusses the conversion time... At 12bit it says 750ms! See below. So unless the resolution is changed (9-bit is < 100ms) maybe this is never going to be that suitable inside Klipper? Some background: I have been using these sensors with other Arduino & RPi projects for years - they are reliable, cheap and accurate. I added one to my printer which was then read and used by an Octoprint plugin to (pwm) control some fans in the electronics bay. Once I'd moved to mainsail/moonraker that is when this idea to integrate it into Klipper came about... Maybe another approach could be to use a standalone python script and poke the moonraker API? Would it be possible to control a temperature_fan via the API? |
FWIW, I did some more investigations. I came across a thread[1] that referenced this bit of code to change the register: https://github.com/blogmotion/BitBangingDS18B20/blob/master/configDS18B20.c I compiled it on my RPi and when I run it, it returns the temperature much faster than 750ms (see gif, when I hit enter it comes back pretty much instantly - and I've not changed the resolution). [1] https://raspberrypi.stackexchange.com/questions/14278/how-to-change-ds18b20-reading-resolution |
Changing the code as you suggested (move the read before seek) the output statement shows:
|
Even a pause of a couple of milliseconds would not work well. So, I don't think this can be fixed by changing the sampling resolution. FWIW, the issue isn't how long the sensor takes - a 1 second delay would be fine. The issue is that we can't stop processing to wait for that temperature result. Ideally the code could instruct Linux to take the measurement, and then pickup the result when it's ready. (Or, alternatively, after reading a result, start the next sample so that it is ready the next time we read the sensor.) I'm not sure how one can go about doing that with the ds18b20 Linux kernel module, but it should be possible as it's a pretty common requirement. -Kevin |
Alas I don't think I have enough knowledge or experience to do this kind of thing. Please feel free to close this PR. If I find time I may try and review this again in the future, but I can live without it :-) |
One thing that comes to my mind that could be improved is error reporting when the temp id is not found -- ends up with exception |
Thanks. What do you mean by the "temp id"? I miss configured my sensor's serial number and I'm not sure the error is that bad actually. It seems to be doing what I would expect and you do get a sensible message:
This is what other sensors will do if they can't be found. It seems that shutting down the MCU is the right thing to do if a temperature sensor isn't available?
|
I'm sorry for not being specific enough... Yes, that was the issue I was
thinking about. I agree with you shutting down makes sense/is preferable
in this context. Maybe I was just confused by the klippy log, all seems
fine now when I experiment with it.
y.
…On Sun, Jan 31, 2021 at 10:07 AM Alan Lord ***@***.***> wrote:
@jtrmal <https://github.com/jtrmal>
One thing that comes to my mind that could be improved is error reporting
when the temp id is not found -- ends up with exception
Thanks.
What do you mean by the "temnp id"?
I miss configured mt sensor's serial number and I'm not sure the error is
that bad actually. It seems to be doing what I would expect and you do get
a sensible message:
Invalid DS18B20 serial id 2
This is what other sensors will do if they can't be found. It seems that
shutting down the MCU is the right thing to do if a temperature sensor
isn't available?
Transition to shutdown state: MCU 'mcu' shutdown: Invalid DS18B20 serial id 2
Reactor garbage collection: (5435.858255113, 0.0, 0.0)
MCU error during connect
Traceback (most recent call last):
File "/home/pi/klipper/klippy/klippy.py", line 151, in _connect
cb()
File "/home/pi/klipper/klippy/mcu.py", line 582, in _connect
config_params = self._send_get_config()
File "/home/pi/klipper/klippy/mcu.py", line 560, in _send_get_config
self._name, self._shutdown_msg))
error: MCU 'mcu' error during config: Invalid DS18B20 serial id 2
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3462 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACUKYX6ORBCRDCIY67EIFQTS4VW33ANCNFSM4S4JPTWQ>
.
|
Oops. I deleted the declaration in a "cleanup" commit which I didn't test. Sorry about that. 74de4f8#diff-f525538b58518a4f67b54bb6fbdafbc28d1091e230c1ab03b0ee88ae14b85ff5L153 |
@joshhead I've merged your work into this branch now so the pull request is now up-to-date. I have had it running on my printer for a few hours and no problems at all. The sensor is working well and my electronics bay is being kept nice and cool :-) |
ditto... so far so good, didn't notice anything peculiar...
y.
…On Sun, Jan 31, 2021 at 10:45 AM Alan Lord ***@***.***> wrote:
@joshhead <https://github.com/joshhead> I've merged your work into this
branch now so the pull request is now up-to-date.
I have had it running on my printer for a few hours and no problems at
all. The sensor is working well and my electronics bay is being kept nice
and cool :-)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3462 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACUKYX6XAVDHNTLPSC53KYDS4V3ILANCNFSM4S4JPTWQ>
.
|
Thanks. In general it looks fine to me. One question - can you confirm that on a FIRMWARE_RESTART command that the thread is properly killed? (That is, that the code doesn't leak threads in that case.) I don't think it would be a problem, but worth double checking. -Kevin |
FWIW, I got this error, when I messed up configuration of something
completely different (for mesh bed leveling, I wrote "mean" instead of
"average")
Exception in serial callback
Traceback (most recent call last):
File "/home/pi/klipper/klippy/serialhdl.py", line 59, in _bg_thread
hdl(params)
File "/home/pi/klipper/klippy/extras/ds18b20.py", line 46, in
_handle_ds18b20_response
last_read_clock = next_clock - self._report_clock
AttributeError: DS18B20 instance has no attribute '_report_clock'
Exception in serial callback
Traceback (most recent call last):
File "/home/pi/klipper/klippy/serialhdl.py", line 59, in _bg_thread
hdl(params)
File "/home/pi/klipper/klippy/extras/ds18b20.py", line 46, in
_handle_ds18b20_response
last_read_clock = next_clock - self._report_clock
AttributeError: DS18B20 instance has no attribute '_report_clock'
Exception in serial callback
Traceback (most recent call last):
File "/home/pi/klipper/klippy/serialhdl.py", line 59, in _bg_thread
hdl(params)
File "/home/pi/klipper/klippy/extras/ds18b20.py", line 46, in
_handle_ds18b20_response
last_read_clock = next_clock - self._report_clock
AttributeError: DS18B20 instance has no attribute '_report_clock'
…On Sun, Jan 31, 2021 at 8:50 PM KevinOConnor ***@***.***> wrote:
Thanks. In general it looks fine to me. One question - can you confirm
that on a FIRMWARE_RESTART command that the thread is properly killed?
(That is, that the code doesn't leak threads in that case.) I don't think
it would be a problem, but worth double checking.
-Kevin
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3462 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACUKYX5RX3YOOHKI2WY3UELS4YCHJANCNFSM4S4JPTWQ>
.
|
@KevinOConnor They should be killed since the linux klipper_mcu program is restarted with
|
To double check, I started Klipper, opened HTOP and filtered for "klipper_mcu". I edited printer.cfg and sent "FIRMWARE_RESTART" a few times, with 2, 1 or 0 temperature sensors configured. The number of threads changed to match the number of configured sensors (plus the main thread). |
@jtrmal, @joshhead @KevinOConnor
This is interesting... I saw the exact same error on my bench RPi yesterday evening after a complete OS reboot. I only had one So I'm beginning to wonder if this could be a timing issue? Maybe the w1 module and/or the |
FYI I've tried "breaking" my test klipper and now I can't get that error to reappear. |
Best to assign all values in the Separately, it would also be good to implement the min_temp/max_temp checks in this PR. For reference, I recently added the checks to the LM75 code (commit 333f8c2). -Kevin |
Signed-off-by: Alan Lord <alanslists@gmail.com>
Thanks. Have updated the PR. |
Thanks. -Kevin |
congrats Josh and Alan! And thanks a lot for your time on it.
y.
…On Tue, Feb 2, 2021 at 2:35 PM KevinOConnor ***@***.***> wrote:
Thanks.
-Kevin
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3462 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACUKYX2S33XSU7E4BAQIB7LS5BHXTANCNFSM4S4JPTWQ>
.
|
W00t! Thanks Josh, Kevin. |
Thanks all! |
Initial commit of code to support 1-wire (Dallas) sensors such as the DS18B20. Requires Linux kernel drivers to create a file in /sysfs which is read by this module, and temperature typically returned to a temperature_fan. Signed-off-by: Alan Lord <alanslists@gmail.com> Signed-off-by: Josh Headapohl <joshhead@gmail.com>
Initial commit of code to support 1-wire (Dallas) sensors such
as the DS18B20. requires Linux kernel drivers to create a file
in /sysfs which is read by this module, and temperature
typically returned to a temperature_fan.
This code purely for testing/revew. No documentation as yet.
Signed-off-by: Alan Lord alanslists@gmail.com