Feature: Generic analog inputs

There’ve been a few discussions in the past about using temperature sensors as a hack to obtain analog inputs. I’d like to have a proper implementation that UIs can support, as printer I’m Klipperizing has voltage and current sensors connected to analog pins.

I’ve put together a minimal implementation, and I’m looking for feedback on what you’d want from it, or ideally some testing to see if if works for you before I put up a pull request:

At the moment all it supports is a linear transformation of the raw ADC reading and a unit. But this allows everything to be plumbed through to Mainsail (and, presumably, other UIs) with some fairly small changes there:

I could’ve sworn I’d seen abandoned pull requests with similar goals to this before, but I’ve been unable to find them again.

3 Likes

@mykepredko , @jhs : since you’ve expressed interest in this, perhaps you’d be able to give some input as to whether my implementation fulfills what you want? If you want, I can publish my Mainsail changes too for you to test.

2 Likes

Hey @rcloran

Looks nice - I’d love to give it a try. Please pass along the diff changes for Mainsail as well as for klippy (I presume there are no changes to the firmware).

I have implemented the Voltage Sensor hack (that you referenced in the original post) on all my printers as well as building it into the main controller boards and I have found it’s operation to be both interesting and useful. It will definitely flag marginal power supplies or situations where the power supply is loaded beyond its current specification.

At first glance at the code/Config_Reference.md you have the basics as to what I’m looking for but I’d like two additional features:

  1. The ability to set voltage limits that will flag an error when they’re exceeded. This is similar to a heater working outside its specified range
  2. A running graph (like what is produced by the temperature displays). As I said, if you have a power supply running at the limit, you will want to see the voltage sag when the heaters are on and the toolhead is moving

I can see two other issues that you may encounter going forward:

  1. What if the ADC sensor is something other than built into the MCU? I’m thinking of the work @garethky is doing with the strain gauges and he may want to monitor the output during normal operation
  2. What happens if the ADC value to display value is not linear? That was a concern when I designed my voltage monitor circuit and it’s not an issue mostly by luck than design

Please pass along the necessary changes and I’ll give your code a try.

Thanx!

Looks nice - I’d love to give it a try. Please pass along the diff changes for Mainsail as well as for klippy (I presume there are no changes to the firmware).

The klippy changes are in the branch I linked, you can just get the one extras file at klipper/klippy/extras/analog_input.py at analog-input · rcloran/klipper · GitHub

The mainsail branch is at GitHub - rcloran/mainsail at misc-sensor , and I’ve put up a build at Mainsail build with misc sensors · GitHub in case you don’t want to deal with running a node server to test.

  1. The ability to set voltage limits that will flag an error when they’re exceeded. This is similar to a heater working outside its specified range

My board has an overcurrent hardware pin, so I hadn’t thought about this. The obvious way to implement it would be allowing gcode to be run. My concern with that would be whether hysteresis is needed to deal with marginal values – how do you think that should be handled?

  1. A running graph (like what is produced by the temperature displays).

Definitely a frontend concern, though it looks like some changes to moonraker would also be needed to get some short history saved. I’m about at my limit for hacking frontend stuff for now, but I do also want charts, so I’ll look at it at some point for sure.

  1. What if the ADC sensor is something other than built into the MCU? I’m thinking of the work @garethky is doing with the strain gauges and he may want to monitor the output during normal operation

This is definitely on my radar, too, as I’m interested in using the secondary input of the ADC which reads my load cell.

What happens if the ADC value to display value is not linear?

I’m sure that will happen eventually, but I don’t think it’s worth designing it without a use case – having different “flavors” of configuration for a particular object is fairly common in Klipper, and splitting out the raw value manipulation into two (or more) separate helper classes won’t be hard.

When I looked at the Klippy code initially I only saw the one file but I wasn’t sure if there were any other changes that analog_input.py was dependent on - which is why I asked.

As for the Mainsail, just copy the contents of the .zip into the Mainsail folder on the host and reboot?

Personally, I would go with a limit value that definitely indicates a problem and could not be close to normal operating levels. Going back to my original post with Kevin’s comments, this is not something that will probably catch transients.

What board are you running? I don’t think I’ve seen one that monitors current - I’m curious to see how it does that.


Once you confirm how to update Mainsail, I’ll give this a try and let you know how it works.

Thanx again!

1 Like

As for the Mainsail, just copy the contents of the .zip into the Mainsail folder on the host and reboot?

Yes, but you shouldn’t need to reboot, probably just refresh your Mainsail tab (mainsail is just static content served by a web server).

:+1:

Prusa xBuddy (MK4).

Thermistors implement curves, so there is precedent for a module that ingests the ADC data and then transforms it into something else.

No joy in first attempt:

I added analog_input.py to klipper/klippy/extras and put in the information as specified in your Config_reference.md and got the error above.

Trying it again, I modified it to include a label in the [analog_input ...] statement and the failure went away.

I suggest that you add that to your documentation.


Now, I don’t see any value for this in Mainsail:

I copied in your version of Mainsail into the host and I do not see the “VIN” analog_input value on the dashboard (see above).

Here is the system’s: klippy (2).log (94.5 KB)


Now, you’ve made changes to the editor in Mainsail - when I tried to edit printer.cfg I get the screen:

With no way to edit the file - I edited it using SSH (and I could have done it using Notepad++) but I was expecting to be still able to use the Mainsail editor.


Finally, you’re going to need to rethink how you do your maths.

I didn’t take a deep look at how you calculate the values for display but it’s more awkward/difficult and, I think, quite prone to rounding errors.

For my circuit, I have the following two points I use for calculations: the ADC Value of 0.151V indicates 2V input to the system and an ADC Value of 3.049V indicates that there is a 70V input.

For three decimal places of accuracy, this works out to an Offset of -0.066 and a Scale of 25.529

Plugging these values into your formula, the displayed values will be 2.17V and 76.15V ==> Each having a higher error than I would think is appropriate: 8.5% and 8.8%, respectively.

Could I suggest that your calculation take a slope and Y intercept in the standard format:

Y = mX + b

The calculations are more straightforward and rounding errors in the offset won’t be multiplied by the scale (which also has rounding errors).


Sorry for the poor first results.

I definitely think you have something here but there are a few bugs to straighten out.

Thanks for testing. I’ve just pushed an update …

Added – hopefully the documentation update is clear on how to use it.

Derp, fixed the docs.

Have you disabled the “Miscellaneous” panel? It should be in that… There is some logic in Mainsail to show or not show that panel, but I thought I’d got it right, since I did test with no other optional extras other than these sensors (Since I can never find that setting, it’s at Gears icon on top right → Dashboard → Desktop).

I’m sorry, but I’m not going to be putting work into trying to figure out why crazy-fancy UI features don’t work in quick once-off builds. Perhaps it’d be more sensible to not provide a frontend build to test.

Thanks again for testing.

I don’t believe your error is to do with any accuracy errors in the calculation, but rather in how you calculated the slope and measurement values. It looks to me like a linear regression would give you a slope of 23.46 and a y intercept of -1.543 for the provided values.

$ python3 -c 'x = 3.049; print((x-(1.543/23.46)) * 23.46)'
69.98654
$ python3 -c 'x = 0.151; print((x-(1.543/23.46)) * 23.46)'
1.9994600000000002

Also it looks like your scale should be more in the order of 115 – the raw value is in the range 0…1 (as reported by QUERY_ADC), not 0…5. If the docs I wrote aren’t clear on that, please let me know.

I’ve re-organized into the standard form, and pushed the update. The only reason I put it in the order I did was because I assumed -0.5 would be a common case (it is for one of my sensors). There’s nothing stopping you using arbitrarily long precision in your config, in case you have a sensor with a scale < 1 one day.

“Miscellaneous” is enabled and I don’t see the analog_input value:


The formula I used followed your documentation (now deleted/changed) which was:

x = (value + offset) * scale

The formula you are using above is:

x = (value + (offset/scale)) * scale

Both calculations are equally accurate, provided you use the appropriate number of significant digits. If I go to six digits (-0.065764 for the offset and 23.529411 for scale), I get 2.0056 and 70.1938, which is a considerable improvement in accuracy.

Personally, I’m going to be suspicious if I have to go beyond three decimal places (two would be ideal). Don’t forget that for Voltage/Current, that we’re working to three digits of accuracy (tesn, ones and one tenths) - you won’t have any better accuracy working with the hardware (ie MCU ADCs) that are used in 3D printers.

I still recommend that you change the conversion to use:

Y = mX + b

Much easier to calculate the slope followed by the Y intercept; if you passed Grade 9 math, then you can do it.


Now, looking at the Reference_config.md and analog_input.py, you’ve made considerable changes to the Klipper/Mainsail code base since I tested them and you appear to be making more.

I’m happy to help debug your code and help characterize it but I’m not willing to work with a moving target with other features modified/broken.

Please provide me with code modified to support analog_input ONLY and , if there are any features that don’t work, please let me know in advance.

I have, as mentioned in my previous post – hopefully it’ll help make things more clear.

What changes do you mean? The only commit in the Klipper codebase on top of the current Klipper master branch is to support analog inputs. You can see its contents at analog_input: Add support for generic analog inputs · rcloran/klipper@8831e61 · GitHub … as before, just grabbing the analog_input.py and putting that in your extras should be sufficient. Are the changes you’re referring to the gcode triggers on going over/under a threshold? I added that because you asked for it.

The Mainsail build is based on top of their develop branch, which probably is quite different to what you normally run. If you’d like to test my changes on top of master, you’re welcome to cherry pick my change on top of their master branch and run that. As I’ve tried to imply before, I’m not that focused on the UI at the moment; I’ve put it together as a proof of concept. I’m not a frontend developer. If you need the frontend changes, perhaps it’s best not to try this all out, which would be unfortunate, as I need to get the Klipper changes landed before I can even begin suggesting enhancements to the Mainsail folks.

As I write this, my last posting was 3 hours ago:

Now, when I look at your GitHub repos, the changes you’re referencing seem to have been made two hours ago:

This is different from a) what I tried originally and b) what I saw when I looked at the repo when I wrote my email three hours ago. I’ve seen three versions of the code in the past 8 hours or so.

This is what I’m talking about trying to work with a moving target.


As for Mainsail, I’ll try whatever you want me to but with your version as well as the latest main branch (I just reverted back to it), I don’t see anything relating to an analog_input and, yes, the “Miscellaneous” display options are enabled, as I showed above.


So, what do you want me to do?

Ah, I see.

I thought you meant you thought I’d been making considerable changes to the Klipper/Mainsail code base.

Thanks for the feedback, I think the changes you’ve suggested have been worthwhile, but I now somehow regret implementing them. I probably created confusion by force-pushing over the same commit, which is usually how I do things while I’m preparing something to be merged to another project, so that it gets a clean succinct history.

I didn’t realize that you were working with the development branch - that wasn’t clear.

Is there anything you want me to do/test?

I don’t recommend you test the Mainsail changes. I’ve removed them so that nobody else tries out what was a quick proof of concept implementation. If you’d like to test the Klipper code, please go ahead – testing and feedback will help towards being able to getting it merged, which will allow work on stuff further up the stack (Moonraker, Mainsail) to start. As it stands the gcode thresholds work OK for me, and you should be able to get data out of the Klipper or Moonraker APIs. It’s still just the one file, so you can place that in the extras folder of whatever version of Klipper you prefer to run.