kizniche / Mycodo

An environmental monitoring and regulation system
http://kylegabriel.com/projects/
GNU General Public License v3.0
2.95k stars 494 forks source link

NON-SPI NeoPixel Custom Output (adafruit-circuitpython-neopixel library) #1217

Closed LucidEye closed 2 years ago

LucidEye commented 2 years ago

The attached txt file is a copy of the Mycodo NeoPixel-SPI Output that has been edited to use the 'regular' non-SPI library to fix a problem I was having using 'off-brand' NeoPixel strips from Amazon. For some reason the SPI library would only light 7 pixels in an 8 pixel (or longer) strip. Any attempt to address pixel positions above 0-6 would result in erratic behavior from the pixel strip and/or errors from Mycodo.

Lines 205 and 220 in the attached file are the main code differences from the original SPI NeoPixel Output. Everything was tested using a 16 pixel strip and works just like the original SPI Output, except the data pin is now changed to GPIO 18, and the SPI interface does not need to be enabled on the Pi (tested and working with SPI disabled). Unfortunately I can not figure out how to edit the Output code to allow for changing the GPIO pin through the web interface. Attempts to do so resulted in no response from the LEDs and the following errors from Mycodo in the Web Log...

2022-07-23 02:07:40,906 Adding endpoint past (/past////). Jul 23 02:07:41 Mycodo-test python[389]: 2022-07-23 02:07:41,600 URL for 'daemon_active' raised and error: cannot connect to ('127.0.0.1', 9080): [Errno 111] Connection refused Jul 23 02:07:41 Mycodo-test python[389]: 2022-07-23 02:07:41,638 Exception on /outputstate [GET] Jul 23 02:07:41 Mycodo-test python[389]: Traceback (most recent call last): Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/Pyro5/client.py", line 278, in connect_and_handshake Jul 23 02:07:41 Mycodo-test python[389]: sock = socketutil.create_socket(connect=connect_location, Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/Pyro5/socketutil.py", line 283, in create_socket Jul 23 02:07:41 Mycodo-test python[389]: sock.connect(connect) Jul 23 02:07:41 Mycodo-test python[389]: ConnectionRefusedError: [Errno 111] Connection refused Jul 23 02:07:41 Mycodo-test python[389]: The above exception was the direct cause of the following exception: Jul 23 02:07:41 Mycodo-test python[389]: Traceback (most recent call last): Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/flask/app.py", line 2077, in wsgi_app Jul 23 02:07:41 Mycodo-test python[389]: response = self.full_dispatch_request() Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/flask/app.py", line 1525, in full_dispatch_request Jul 23 02:07:41 Mycodo-test python[389]: rv = self.handle_user_exception(e) Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/flask_restx/api.py", line 672, in error_router Jul 23 02:07:41 Mycodo-test python[389]: return original_handler(e) Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/flask/app.py", line 1523, in full_dispatch_request Jul 23 02:07:41 Mycodo-test python[389]: rv = self.dispatch_request() Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/flask/app.py", line 1509, in dispatch_request Jul 23 02:07:41 Mycodo-test python[389]: return self.ensure_sync(self.view_functions[rule.endpoint])(*req.view_args) Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/flask_login/utils.py", line 277, in decorated_view Jul 23 02:07:41 Mycodo-test python[389]: return current_app.ensure_sync(func)(args, **kwargs) Jul 23 02:07:41 Mycodo-test python[389]: File "/home/pi/Mycodo/mycodo/mycodo_flask/routes_general.py", line 218, in gpio_state Jul 23 02:07:41 Mycodo-test python[389]: return jsonify(get_all_output_states()) Jul 23 02:07:41 Mycodo-test python[389]: File "/home/pi/Mycodo/mycodo/mycodo_flask/utils/utils_output.py", line 427, in get_all_output_states Jul 23 02:07:41 Mycodo-test python[389]: return daemon_control.output_states_all() Jul 23 02:07:41 Mycodo-test python[389]: File "/home/pi/Mycodo/mycodo/mycodo_client.py", line 233, in output_states_all Jul 23 02:07:41 Mycodo-test python[389]: return self.proxy().output_states_all() Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/Pyro5/client.py", line 92, in getattr Jul 23 02:07:41 Mycodo-test python[389]: self._pyroGetMetadata() Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/Pyro5/client.py", line 358, in _pyroGetMetadata Jul 23 02:07:41 Mycodo-test python[389]: self.pyroCreateConnection() Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/Pyro5/client.py", line 342, in pyroCreateConnection Jul 23 02:07:41 Mycodo-test python[389]: connect_and_handshake(conn) Jul 23 02:07:41 Mycodo-test python[389]: File "/var/mycodo-root/env/lib/python3.9/site-packages/Pyro5/client.py", line 304, in connect_and_handshake Jul 23 02:07:41 Mycodo-test python[389]: raise errors.CommunicationError(err) from x Jul 23 02:07:41 Mycodo-test python[389]: Pyro5.errors.CommunicationError: cannot connect to ('127.0.0.1', 9080): [Errno 111] Connection refused Jul 23 02:07:41 Mycodo-test python[570]: /bin/sh: 1: /opt/vc/bin/vcgencmd: not found Jul 23 02:07:49 Mycodo-test python[389]: 2022-07-23 02:07:49,700 URL for 'daemon_active' raised and error: cannot connect to ('127.0.0.1', 9080): [Errno 111] Connection refused

So it works, but it still needs work.
I'm assuming the GPIO issue is my lack of understanding of the webhooks and what needs to be changed in that regard... I think? Kyle, when you have the opportunity, can you please take a look at this and see what you think.

Thank you JCL

Change file extension from .txt to .py custom_output_neopixel_rgb_test01.txt

kizniche commented 2 years ago

I just committed the module with changes that should allow it to work with any GPIO pin. Let me know if this works if you decide to test it.

LucidEye commented 2 years ago

Non-SPI NeoPixel Output - I added the following to the output message...

USE WITH CAUTION: This library uses the Hardware-PWM0 bus. Only GPIO pins 12 or 18 will work. If you use one of these pins for a NeoPixel strip, you can not use the other for Hardware-PWM control of another output or there will be conflicts that can cause the Mycodo Daemon to crash and the Pi to become unresponsive. If you need to control another PWM output like a servo, fan, or dimable grow lights, you will need to use the Software-PWM by setting the Output PWM: Raspberry Pi GPIO--> "Library" field to "Any Pin, <=40kHz". If you use the "Hardware Pin, <=30MHz" setting, it will cause conflicts as well.

Testing Notes:

I tested all pins capable of generating the 800kHz signaling required to drive the NeoPixels. I was able to drive an 8 and 16 neopixel strip directly from the Pi 3.3v signal without needing to level shift the signal up to 5v I am using a 350 ohm resistor on the data line between the Pi and the pixel strip to protect the strip from possible voltage spikes. I am also using a 600uf 10v capacitor across the VCC and Ground pins on the pixel strip to help prevent "glitching" from abrupt brightness changes. The only pins that worked without causing conflicts are PWM0 bus GPIO 12 & 18.
I tried enabling PWM1 bus GPIO 13 & 19 in /boot/config.txt using "dtoverlay=pwm-2chan", but was not able to get Mycodo to use that PWM channel. This may be something in the output code that needs to be changed to use that channel. Not sure if this is worth the effort since most PWM devices like servos, fans, or dimable grow lights don't require high frequency hardware PWM signal like NeoPixels do. Although this output can cause major conflicts if not careful, it does give users more options for pins to drive pixel strips from, and seems to work with the newer WS2812B NeoPixels.

on_off_neopixel_rgb.txt .