Add i2c gpio support #390
Reference in New Issue
Block a user
Delete Branch "master"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implement support for i2c gpio devices (GPIO outputs and temp/humidity inputs)
I am using octoprint on a raspberry with a hyperpixel4 screen which is using all the GPIO of the raspi. The only way to have IO is to use the I2C bus. This commit allows to interact with an i2c slave within the enclosure plugin. You can create regular GPIO with the i2c option and choose the register to read/write from for that pin.
You can also add temperature or humidity sensor using the same mechanism.
A simple i2c slave based on an arduino mini pro that I use is available here: https://github.com/raoulh/arduino_i2c_gpio_slave
related issue #323
Just want to upvote this pull request. Would be extremely useful for a project I'm working on!
Same for me. I would like to connect relay for PSU, through i2c and arduino.
Is the implementation flexible enough for the Enclosure plugin to directly control I2C "regular" outputs (i.e., without the need for an I2C proxy)? For example, I'm using three SparkFun Qwiic I2C Quad Relays (12 relays total). Of course, each board has a unique I2C address. You turn on and off the combination of board (I2C address) + relay (1 - 4). Along the same lines, you'd referenced @JaredC01's feature request to support an I2C GPIO expander (MCP23017). Will your implementation directly control an I2C GPIO expander?
Is the implementation flexible enough for the Enclosure plugin to directly monitor I2C temperature and humidity sensors via an I2C mux? For example, I'm using an 8-channel SparkFun Qwiic I2C Mux (TCA9548A) Breakout board in order to leverage five SparkFun BME280 temperature and humidity Atmospheric Sensor Breakout boards (the SparkFun BME280 board only supports two different I2C addresses).
With the master branch, rpi_outputs with an output_type of temp_hum_control
can only control "native" GPIO (i.e., you can only specify a specific GPIO number). With your implementation, can a cooler, heater or dehumidifer controller control I2C GPIO?
I have submitted Enclosure plugin feature requests for,
@wickedbeernut
I quickly went through the doc of the Sparkfun doc, it seems that the relays would work as they seems standard i2c outputs.
About the temp/hum boards, I fear it will not be compatible. The TCA9548A chip is not a simple read operation on a i2c register (like I did in this PR) but rather multiple read/writes with calibrations values and such. It would be better to implement that a different way.
Here is a screenshot of the config screen in my PR. You are free to configure the data written, read, register, etc...

All of my vitormhenrique / OctoPrint-Enclosure plugin inputs and outputs are I2C. At the moment, I have 10 I2C outputs (relays),
and ten I2C inputs,
I’ve been forced to incorporate the I2C mux support into the Enclosure plugin BME280.py script. It’s only half a dozen lines, but I’m forced to own it.
I assume the screenshot you shared is of an output (on the “Raspberry Pi Outputs” settings page) with an output type of “Regular IO”.
As I mentioned, all of my I2C outputs are controlled using Enclosure plugin heater and cooler controllers (i.e., rpi_outputs of output_type ‘temp_hum_control’ with control_type ‘heater’ or ‘cooler’). In the master branch, “Raspberry Pi Outputs” with output type “Temperature / Humidity Control” only accept GPIO numbers. Are you planning to add I2C support to “Temperature / Humidity Control” outputs or only “Regular IO” outputs?
I’m currently using my own OctoPrint plugin that maps GPIO outputs to I2C outputs and I2C inputs (buttons and switches) to GPIO inputs. It’s completely transparent to the Enclosure plugin. The Enclosure plugin thinks it’s monitoring and controlling GPIO input and output devices when in fact they’re I2C. This works fine, however, it “wastes” GPIO pins. It won’t help guys like you and @JaredC01 that burned all of the GPIO pins on a Hyperpixel 4.0 display.
I’m not sure if you’re familiar with blynk.io. In addition to analog and digital input / output pins, blynk.io supports the notion of “virtual pins”. I think this may be the cleanest approach to supporting my I2C inputs and outputs. For example, let’s assume the Enclosure plugin recognizes pins 32 – 63 as “virtual”. The idea is the Enclosure plugin would treat virtual pins exactly like physical pins except at the lowest (hardware) level.
For example, consider the
write_gpiofunction,def write_gpio(self, gpio, value, queue_id=None):For GPIO pin numbers less than 32, the
write_gpiofunction would invokeGPIO.output(gpio, value)as is the case today. However, for virtual pins 32 – 63, thewrite_gpiofunction might invoke a user-supplied Python script, passing the pin and value. The underlying Python script would apply the appropriate I2C logic. In most cases, this would involve leveraging existing user-friendly Python libraries for the I2C device being controlled or monitored (rather than performing raw register reads and writes). The simplest approach would be for the user-supplied Python script to hardcode the mapping between the virtual pin and the corresponding I2C address / syntax. The Python script should be able to interface with just about any I2C device. Of course, a Python script may not be as efficient as a more "built-in" solution.Using virtual pins frees up GPIO pins. In theory, treating the virtual pins like GPIO pins (at all but the hardware level) should minimize the changes to the Enclosure plugin.
I’ll probably stick with my GPIO <-> I2C mapper plugin for now. However, if I run out of GPIO pins, I’ll pursue the virtual pin approach. Please let me know if you plan to support I2C outputs in conjunction with temperature and humidity controllers. That may be an option as well.
Here's the
set_relay_onfunction of the sparkfun / Qwiic_Relay_Py Python library. It would appear you can only toggle an individual output of a quad relay. Therefore, you must first read the current state of the output. If the current state doesn't match the target state, you then toggle (write) the output. I assume this won't work with your I2C GPIO support?Hi guys
Well done! Before I start to spend hours and days and finally find out that it is not going to work without hudge coding, I prefer to ask your advice or who knows perhaps somebody got it working.
@ Victor made absolutly a great practical and useful Enclosure plug in, no doupt. and to read that your recovered from your unluck last year... Thanks... for your enclosure....
I really need the temp and humidity gettting into Octoprint to be able to set up a PWM to my External SolidState Relay. I followed allmost as the issues DMT 11 /22 but didn`t get it working in my octoprint.
So my question: if I add a Arduino over I2C where all the Sensors are connected. might I have a chance to get it working? I`ve never done it but I think I should be able to get that communication running up.
What`s your opinion.
Thanks
By "DMT 11 /22", I assume you mean DHT11 and DHT22. You're saying you were never able to successfully integrate a DHT11 or DHT22 temperature and humidity sensor with the Enclosure plugin?
It sounds like you're looking to leverage an Enclosure plugin temperature controller. I had asked @raoulh whether he planned to add I2C support to outputs of type “Temperature / Humidity Control”. I don't see where I received an answer. I'm assuming the answer is no.
Then there's the question of PWM. Even if @raoulh were to integrate his I2C support with outputs of type “Temperature / Humidity Control”, I don't believe an Enclosure plugin temperature controller currently supports PWM. I believe @raoulh's I2C support is focused on regular (i.e., binary) GPIO. This could be modified to pass a PWM value (rather than binary), however again, an Enclosure plugin temperature controller currently doesn't have the logic to derive (and pass) the PWM value.
Is there a particular reason why you're using I2C, rather than Raspberry Pi GPIO? And are you sure you need PWM? Have you tried to leverage the existing Enclosure plugin temperature controller functionality? This would require you to directly integrate a temperature sensor with the Enclosure plugin. The Enclosure plugin temperature controller would then simply turn your relay on or off (via regular GPIO) based on the target and actual temperature (and an optional deadband).
@hartmannf My PR fully support what you want to do. I do exactly that. I have an arduino with temp/humidity + relays on it, and Enclosure plugin controls them using i2c.
@wickedbeernut Temp&hum are supported with my code, but using a specific format, only the value is sent over the i2c bus and all the calibration/configuration of the chip has to be done in the arduino code.
See my example code here https://github.com/raoulh/arduino_i2c_gpio_slave
@raoulh Where is your temperature controller logic (i.e., the code that compares the configurable target temperature and the actual temperature)? Are you leveraging an Enclosure plugin output of type "Temperature / Humidity Control" (shown below)?
@wickedbeernut
Did you even try my PR??
No. I had asked you twice (now three times) whether your PR supported I2C in conjunction with Enclosure plugin outputs of type "Temperature / Humidity Control". I never received an answer (until now). I had assumed the answer was no. Clearly, from your screenshot, this is supported. As soon as your PR is folded into the master branch, I will give it shot.
It's written in the main comment of my PR...
Thank you very much for your answer. At the moment I don
t really got time but Ill try that out.You assume absolutely Right of course DHT11/22. I was able to get values on *.py level, so hardware was is working fine.
I read the followed message, and now at least it is answerd ;) Yeah hard times for everybody ....
I would already be happy to get the actValue to octopi, and send setpoint value out from Octopi to *.py level or arduino over I2C. What and how I am going to control the SolidState Relaiy, is not decided yet. At the moment I got an "old" external Ero Electronic temp controller that controls a SolidState Relay 12V or 24V and as I saw on the osci it is using a PWM. But of course a bit level control might be working as well. On the moment I got the SP value on out of octo I think I am able to get something controling the SolidRelay.
Of course it would be also my favor solution to get Gpio directly to in and out to Pi.
Let
s say that way, I tried so many things according #368 to get the enclosure plugin to get Read temp an humidity from the sensor (the only thing I missed is that what makes it work bäääääääää). I was only able to get the hardware signal on terminal mode als read the value. I am not so knowledged to get deep into python code to see where it hangs. And honestly also dont have that much time... I am more used to PLC programming and sometimes also some c+ but there is more coping then really writing codes..@raoulh and @wickedbeernut Thanks guys for work and reply. first test looked promising and i2c worked. once I got coding done I puplish the code for arduino. I got an idee how to regulate the PWM signal
Couple of questions.
What format does the i2c humidity sensor need to return (currently, I'm returning a float but it shows 0)? It also shows with the degrees celsius symbol instead of a percent; can I change this?
How would I add an i2c input for a door sensor (opened/closed)? Currently, I have it as an output but it shows up as a button.
@qtemp The format is simple as sending the raw 4 bytes of a float. Example arduino code here:
https://github.com/raoulh/arduino_i2c_gpio_slave/blob/master/Prusa3d.ino#L136
About the celcius/percent symbol, you are right, that's a issue I did not see. I need to figure this out...
For i2c inputs, it's not supported by my PR... You have 2 ways of doing it, polling for the i2c inputs at regular interval (not recommended as you will miss some edge changes at some point), or you need an other pin for an Interrupt pin to tell the code that "something" changed. As I do not have any PIN left to use as an interrupt, I did not implement that...
Are you using a stand-alone, dedicated I2C switch?
You might want to check out a SparkFun Qwiic I2C switch (or button). The SparkFun I2C switch has a built-in FIFO queue. It stores up to 15 switch presses (or clicks) along with the corresponding timestamp. This way you can significantly increase the polling interval without having to worry about missing a switch press. The SparkFun I2C switch is also capable of generating an interrupt if you want to go that route. And, of course, the switch has built-in debounce logic.
If you go the SparkFun Qwiic I2C switch route, make sure the switch has the latest firmware. There was a bug in the queue logic that I fixed. SparkFun has incorporated the fix into the master branch, however, you need to ensure the switch ships with the latest firmware.
I have my own OctoPrint plugin that maps I2C inputs (buttons and switches) to GPIO inputs. It’s completely transparent to the Enclosure plugin. The Enclosure plugin thinks it’s monitoring GPIO inputs when in fact they’re I2C.
I'm using an Arduino nano (via https://www.thingiverse.com/thing:2862044) with DHT22 sensors.
I'm using the same floatBytes for returning temperature and humidity. Temperature works.
However, the humidity is always sitting at zero (using the readHumidity function). My temperature stopped responding as well earlier and I had to restart the nano. I'll dig into the values that are getting returned when I get a chance to see what it's trying to send from the arduino.
I was hoping to eventually get into controlling the fan as well as LED lighting from the pi rather than having to open my enclosure door and letting possible fumes escape.
So, if I change from "Raw I2C Humidity" to "Raw I2C Temperature" for pulling the humidity it works...other than just displaying the temperature symbol.
I cobbled my way through it and have it working somewhat in my repository.
I added both 'temp_raw_i2c' and 'hum_raw_i2c' to the list of humidityCapableSensor in enclosure.js.
In init.py changed read_raw_i2c_temp to receive a two floats and return them both to the caller.
In my arduino code I build the array of two floats and return them as a byte array.
This really eliminates the need for the hum_raw_i2c, at least for me. Since hum_raw_i2c and temp_raw_i2c shared the same read i2c code, I made the 'humidity' version expect the humidity first and then temp...this of course requires the slave to return the humidity and then zero for the second value if there is no temperature to return.
@qtemp Nice 👍 You need to to a new PR as mine was merged in master ;-)
Hi all,
short question regarding integration of TI PCF8547 i2c I/O expander. Unfortuntly , this chip is not working against the current enclosure implemention. This is mainly caused by calling write_block_data and read_block_data methods.
This chip does not make use of registers and has a very simple i2c layout. As checked, it can easily driven by the use of write_byte and read_byte methods of smbus2 module.
As second attempt, the integration via the kernel module gpio_pcf853x didn't succeed within the enclosure plugin.
The chip is recognized via the kernel driver and the standard gpio interface is exported via sysfs. Since enclosure uses RPi.GPIO library for gpio access this solution fails also. The RPi.GPIO library accesses gpios over memory mapping via /dev/gpiomem. So external memory/registers are not mapped accordingly.
In my view, best approach would be the usage of WiringPi lib instead of RPi.GPIO to support the standard gpio interface via sysfs. Is this support planned?
Do you see any other option for the integration of PCF8547?
For us, it would be great, we the integratin of the chip goes upstream.
So long
Is it fair to say that I2C binary inputs (ie buttons, switches) are not yet supported?
@daveharnett Yes, that is not supported by this PR
Thanks @raoulh . Do you know if this already on the agenda, or should I make a new feature request?
I'm not conversant with python, but it looks like your PR here should make it a lot easier?
@daveharnett, @raoulh, @Mcarbuhn . Many thanks for the discussion, what is the current state here? Is a new FR planned?
@daveharnett Actually it's not on my agenda, I don't have time to work on this
@raoulh I have no plan. Enclosure plugin is working the way I need for now