adafruit / Adafruit_DotStar_Pi

DotStar module for Python on Raspberry Pi
GNU General Public License v3.0
60 stars 30 forks source link

Python 3 compatibility #24

Closed colorchestra closed 5 years ago

colorchestra commented 6 years ago

This has been asked before, but the issue was closed without a resolution: has anyone used this library with Python 3 and/or can it easily be made compatible? That would be great.

retroj commented 6 years ago

I have. Here is a patch:

diff --git a/dotstar.c b/dotstar.c
index 7d46bb2..7c34b3b 100644
--- a/dotstar.c
+++ b/dotstar.c
@@ -54,7 +54,7 @@
   License along with NeoPixel.  If not, see <http://www.gnu.org/licenses/>.
   ------------------------------------------------------------------------*/

-#include <python2.7/Python.h>
+#include <python3.5/Python.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/ioctl.h>
@@ -226,7 +226,7 @@ static PyObject *DotStar_new(
    // "order='rgb'" or similar (switch r/g/b around to match strip).
    // Order string isn't much validated; nonsense may occur.
    if(kw && (string = PyDict_GetItemString(kw, "order")) &&
-     (order = PyString_AsString(string))) {
+     (order = PyBytes_AsString(string))) {
        for(i=0; order[i]; i++) order[i] = tolower(order[i]);
        if((c = strchr(order, 'r'))) rOffset = c - order + 1;
        if((c = strchr(order, 'g'))) gOffset = c - order + 1;
@@ -654,7 +654,7 @@ static void DotStar_dealloc(DotStarObject *self) {
    _close(self);
    if(self->pBuf)   free(self->pBuf);
    if(self->pixels) free(self->pixels);
-   self->ob_type->tp_free((PyObject *)self);
+   Py_TYPE(self)->tp_free((PyObject *)self);
 }

 // Method names are silly and inconsistent, but following NeoPixel
@@ -675,8 +675,8 @@ static PyMethodDef methods[] = {
 };

 static PyTypeObject DotStarObjectType = {
-   PyObject_HEAD_INIT(NULL)
-   0,                           // ob_size (not used, always set to 0)
+        PyVarObject_HEAD_INIT(NULL, 0)
+   //0,                           // ob_size (not used, always set to 0)
    "dotstar.Adafruit_DotStar",  // tp_name (module name, object name)
    sizeof(DotStarObject),       // tp_basicsize
    0,                           // tp_itemsize
@@ -717,13 +717,27 @@ static PyTypeObject DotStarObjectType = {
    0,                           // tp_free
 };

-PyMODINIT_FUNC initdotstar(void) { // Module initialization function
+PyMODINIT_FUNC PyInit_dotstar(void) { // Module initialization function
    PyObject* m;

-   if((m = Py_InitModule("dotstar", methods)) &&
+   static struct PyModuleDef moduledef = {
+     PyModuleDef_HEAD_INIT,
+     "dotstar",     /* m_name */
+     "DotStar",     /* m_doc */
+     -1,            /* m_size */
+     methods,       /* m_methods */
+     NULL,          /* m_reload */
+     NULL,          /* m_traverse */
+     NULL,          /* m_clear */
+     NULL,          /* m_free */
+   };
+
+   if((m = PyModule_Create(&moduledef)) &&
       (PyType_Ready(&DotStarObjectType) >= 0)) {
        Py_INCREF(&DotStarObjectType);
        PyModule_AddObject(m, "Adafruit_DotStar",
          (PyObject *)&DotStarObjectType);
+       return m;
    }
+   return NULL;
 }

Here is the guide that I followed: http://python3porting.com/cextensions.html

It also gives information on how to make an extension compatible with both python 2 and 3, but I was in a hurry so I didn't do that yet.

jsheedy commented 6 years ago

Thanks for the patch, it is working great for me. My Pi currently has Python 3.4, so I had to change the include to #include <python3.4/Python.h> also added `python3.4-config --libs` to the gcc link in the Makefile.

dhocker commented 5 years ago

I've got a forked version of Adafruit_DotStar_Pi that works on Python 3.5 and 3.6 on an RPi running Raspbian Stretch. Adafruit_DotStar_pi_fork. This fork contains the two pull requests that are open against Adafruit_DotStar_Pi.

ladyada commented 5 years ago

thanks we're thinking of maybe just moving to straight circuitpython - not sure if we really need the ultra speed of this repo (and the attendant code support nightmare of C!)

524248 commented 5 years ago

I'd like to use dotstar.so with my RPi3B SPI1 pins (MOSI->GPIO20 board pin 38, SCLK->GPIO21 board pin 40) instead of the default SPI0 pins. I see that the default pins are DEFINE'd in the source code, and are used in multiple locations to check if bit-bang pins chosen overlap to force hardware SPI.

I didn't see a commandline arg to input user preferred hardware SPI pins ... so I guess short of poking new values into those memory locations there's no way to use the dotstar.so library with SPI1.

I can recompile after changing those two DEFINE statements, but not sure what I need to do so. For instance, I don't appear to have the libdotstar.so file on my Pi3. Can you give me a nudge in the right direction?

ladyada commented 5 years ago

yeah we're definitely only going to be supporting https://learn.adafruit.com/adafruit-dotstar-leds/python-circuitpython going forward!

524248 commented 5 years ago

Hi ladyada ... BIG fan. BIG!!

Um ... was that an answer to my question, or to someone else's? are you saying that you don't plan to support dotstars controlled by RPi3 going forward? I suspect I've misunderstood.

dhocker commented 5 years ago

You might take a look at the CircuitPython driver I wrote for DotStars (and other SPI based LEDs).

https://github.com/dhocker/CircuitPython_DotStarAPA102

If you look at the example below you should be able to easily see how to use it with alternate pins for the SPI clock and data lines.

https://github.com/dhocker/CircuitPython_DotStarAPA102/blob/master/examples/dotstarapa102_test.py

Look at line 56 of the test file to see where the data and clock lines are specified. I think this change would get what you need.

spi_bus = busio.SPI(board.SCLK_1, MOSI=board.MOSI_1, MISO=board.MISO_1)

On Thu, Dec 20, 2018 at 1:20 PM Rod notifications@github.com wrote:

I'd like to use SPI1 (MOSI->GPIO20 board pin 38, SCLK->GPIO21 board pin 40) instead of the default SPI0 pins. I see that the default pins are DEFINE'd in the source code, and are used to check if bit-bang pins chosen overlap to force hardware SPI. I didn't see a commandline arg to input user preferred hardware SPI pins ... so I guess short of poking new values into those memory locations there's no way to use the dotstar.so library with SPI1.I can recompile after changing those two DEFINE statements, but not sure what I need to do so. For instance, I don't appear to have the libdotstar.so file on my Pi3.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adafruit/Adafruit_DotStar_Pi/issues/24#issuecomment-449107419, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpZ7qJVgKXsYMbOrsQAnXWzQDuW4k4pks5u6-LqgaJpZM4TjsUC .

-- [dh]

524248 commented 5 years ago

dhocker - your response and nudges :) greatly appreciated.

Not sure I understand what you mean about CircuitPython for DotStars ... is CircuitPython an AdaFruit version of python for their products, or a hardware product? Are you saying I can use CircuitPython to write code for my DotStars on the RPi? If so, that works for me !!

Sorry if I seem dense - my main association to AdaFruit DotStars has been through the RPi3 python interpreter.

dhocker commented 5 years ago

As far as I am aware, DotStars are Adafruit's branding/version of APA102 based LED strings. An APA102 driver should work for DotStars or any other APA102 based LED string (as the APA102 uses SPI). My CircuitPython driver was tested using an RPi v3 B+ on a DotStar LED string that I purchased from Adafruit. However, it should work with any APA102 based LED string driven by an RPi.

If you are unfamiliar with addressable LED strings there really only seems to be two types. There is a set of WS281X (WS2811/WS2812/...) based LED strings (I have several of these). These use PWM as their protocol (3 wire). The APA102 based LED strings use SPI for their protocol (4 wire) (and I have a number of these, too). There are pros and cons of each, but the biggest advantage of the APA102 based strings is that they can be driven much faster (meaning the transitions are smoother).

Not to get too far into the weeds, but here is what my virtual env looks like (check the requirements.txt file).

Adafruit-Blinka adafruit-circuitpython-busdevice RPi.GPIO

You might consider pulling my CircuitPython_DotStarAPA102 repo and using the test program to get things working. Be sure to go through the README.rst file first.

CircuitPython is mostly seems to be a standard environment to write hardware oriented Python code against. The idea is to put it on minimalist hardware thus providing an inexpensive way for experimenters to get going.

On Thu, Dec 20, 2018 at 2:11 PM Rod notifications@github.com wrote:

dhocker - your response and nudges :) greatly appreciated.

Not sure I understand what you mean about CircuitPython for DotStars ... is CircuitPython an AdaFruit version of python for their products, or a hardware product? Are you saying I can use CircuitPython to write code for my DotStars on the RPi? If so, that works for me !!

Sorry if I seem dense - my main association to AdaFruit DotStars has been through the RPi3 python interpreter.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adafruit/Adafruit_DotStar_Pi/issues/24#issuecomment-449121607, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpZ7r8tuRpE05wlCoaPPydlJJw7B0r4ks5u6-8MgaJpZM4TjsUC .

-- [dh]

524248 commented 5 years ago

Thanks, Dave ... you're being extra patient with me, I suspect :). I've been building LED displays with the DotStar strips controlled by a Pi2/3 for a year off and on, so quite familiar with the APA102 addressable color LEDs. I've accumulated about 27m of strips over that time for Halloween and Christmas displays. I was just thrown off by the numerous references in the last few posts to CircuitPython, which I thought was a hardware/software product of the teeny-tiny sort AdaFruit is constantly releasing. I didn't realize (until you linked in the references) that it could be loaded and run on a Pi to replace the basic python coding environment I've been using on the Pi3's.

I'm not a big fan of virtual environments on a resource-limited device like the Pi, even with its 1GB of RAM. But if that's the direction AdaFruit is going with DotStar/APA102 based LED products, then I'll have to adjust. My investment in DotStars is too large now to get picky about the environment in which I do the coding.

I checked line 56 of your test file - and it would indeed do what I want, if my Pi3B will allow me to run both the default and 2nd SPI channels simultaneously. So I guess the next thing I need to do is dive into this CircuitPython world and get working !

ladyada commented 5 years ago

ok a lot going on here

1) yes you can enable the second SPI port and use it https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices 2) APA102 and dotstars are the same (altho, we use dotstar because some SK68 chips work as well, so the actual chip name varies but the protocol is the same) 3) you should be able to follow https://learn.adafruit.com/adafruit-dotstar-leds/python-circuitpython and get it working

@dhocker is there a difference between your library and https://github.com/adafruit/Adafruit_CircuitPython_DotStar ? maybe we could join forces so only one library is needed?

524248 commented 5 years ago

Thanks to both of you for your help !! You've given me a lot of homework, so I better get after it.

BTW, I use "DotStars" to differentiate them from NeoPixels LED strings. I understand references to APA102 is basically the same thing, the chip on which the DotStar was orginally based - didn't know there were alternate chips that function similarily, but then that doesn't concern me much. Sorry if my generic use of DotStars is confusing.

dhocker commented 5 years ago

Rod, you seem to have more LED strings than I do, by quite a bit. I have 3 different RPi controllers. One is an RPi Zero W and the other two are RPi v2B's. Two controllers drive short WS281X strings and the third drives an APA102 string of 150 LEDs. I run Raspbian Lite on all of them and I use virtual envs exclusively. I have never noticed a resource issue. In fact, the whole SDCard image is typically less than 2GB. My light controller programs typically only consume a few percent CPU. I think if you get into virtual envs you will find that they have little impact on RAM, storage or CPU. And, they provide a lot of benefits.

Good luck!

On Thu, Dec 20, 2018 at 3:00 PM ladyada notifications@github.com wrote:

ok a lot going on here

  1. yes you can enable the second SPI port and use it https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices
  2. APA102 and dotstars are the same (altho, we use dotstar because some SK68 chips work as well, so the actual chip name varies but the protocol is the same)
  3. you should be able to follow https://learn.adafruit.com/adafruit-dotstar-leds/python-circuitpython and get it working

@dhocker https://github.com/dhocker is there a difference between your library and https://github.com/adafruit/Adafruit_CircuitPython_DotStar ? maybe we could join forces so only one library is needed?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/adafruit/Adafruit_DotStar_Pi/issues/24#issuecomment-449133882, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpZ7igbY9WAInGBRkXNo5tFpxL7jz8Tks5u6_p5gaJpZM4TjsUC .

-- [dh]

dhocker commented 5 years ago

ladyada,

My CircuitPython driver is modeled more off of the https://github.com/adafruit/Adafruit_DotStar_Pi package. The driver model I implemented can functionally do what the https://github.com/adafruit/Adafruit_CircuitPython_DotStar package can do (and, then some), but the API is different. Neither of the drivers is API "compatible", although with work you could migrate a program from one to the other. Assuming, you want to keep your API, the most benefit I could see would be to adapt the extra functionality in my driver into the AdaFruit driver (right now I'm not exactly sure how significant that would be).

If you would like to discuss this further, I'd suggest emailing me at the email address on my main GitHub account https://github.com/dhocker.

On Thu, Dec 20, 2018 at 3:29 PM Dave Hocker dghocker@gmail.com wrote:

Rod, you seem to have more LED strings than I do, by quite a bit. I have 3 different RPi controllers. One is an RPi Zero W and the other two are RPi v2B's. Two controllers drive short WS281X strings and the third drives an APA102 string of 150 LEDs. I run Raspbian Lite on all of them and I use virtual envs exclusively. I have never noticed a resource issue. In fact, the whole SDCard image is typically less than 2GB. My light controller programs typically only consume a few percent CPU. I think if you get into virtual envs you will find that they have little impact on RAM, storage or CPU. And, they provide a lot of benefits.

Good luck!

On Thu, Dec 20, 2018 at 3:00 PM ladyada notifications@github.com wrote:

ok a lot going on here

  1. yes you can enable the second SPI port and use it https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices
  2. APA102 and dotstars are the same (altho, we use dotstar because some SK68 chips work as well, so the actual chip name varies but the protocol is the same)
  3. you should be able to follow https://learn.adafruit.com/adafruit-dotstar-leds/python-circuitpython and get it working

@dhocker https://github.com/dhocker is there a difference between your library and https://github.com/adafruit/Adafruit_CircuitPython_DotStar ? maybe we could join forces so only one library is needed?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/adafruit/Adafruit_DotStar_Pi/issues/24#issuecomment-449133882, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpZ7igbY9WAInGBRkXNo5tFpxL7jz8Tks5u6_p5gaJpZM4TjsUC .

-- [dh]

-- [dh]

524248 commented 5 years ago

Now that I've absorbed a fair amount of that "homework", I can see the attraction of using CircuitPython to control my DotStars through my Pi: using the "virtual CS" approach, I can run multiple devices (DotStar strips) on the SPI0 bus, and ALSO enable SPI1 to run several more devices on a separate SPI bus. As long as I stay away from the defined CE0 pin for CS, it gives me lots of options. No need for my current applications to use multiple Pi's for multiple DotStar strips!

I determined last night that by using the standard python threading library, I can "multi-task" (time-slice really) on SPI0 by running programs for segments of my single long strip inside threads that are launched independently. So far, that has also worked.

So I have a few options depending on my physical LED layout and the program needs. I'm going to setup a CircuitPython test rig next to see if adding the second SPI1 channel gives me better performance or extends how much I can realistically do in one Pi3B.

Thanks again to both of you for your explanations, links, and for giving me the push in the CP direction !!

ladyada commented 5 years ago

circuitpython dotstar code has bitbang support - not incredibly fast but probably good enough - you can use any two pins, try it!

524248 commented 5 years ago

I just remembered - you folks sent me a GEMMA MO and a Trinket MO with my first order a year ago. If I recall, they both have CP built into them.

Can I use them with DotStar strips to play around and get comfortable with CP?

Is there a 3.3V-5V level shifter built into these little guys, and if not can I hook them to the same level shifter I use for my Pi3's to drive the strips with 5V 10A PS's? IOW, could I drive 1 or more DotStar 60 LED strips hooked to a 5V PS with a Trinket or Gemma?

Man, I forgot all about those things ... talk about having a senior moment :/

ladyada commented 5 years ago

yes, see that guide for info on how to do it

PaintYourDragon commented 5 years ago

As we're deprecating this library in favor of CircuitPython (which requires Python 3), the issue is implicitly resolved there. Please check out the Adafruit CircuitPython DotStar library: https://github.com/adafruit/Adafruit_CircuitPython_DotStar