nanpy / nanpy

Use your Arduino board with Python.
http://nanpy.github.io/
MIT License
233 stars 79 forks source link

Extending nanpy with Adafruit's DotStar Library #95

Open jc78 opened 7 years ago

jc78 commented 7 years ago

I'm trying to extend nanpy by supporting Adafruit's DotStar LED strips and I'm running into a serial timeout when I'm trying to create an instance of the DotStar object I added.

I followed the instructions found here, and was able to get my sketch to compile and upload to my Uno board without any issues. I have run the blink.py test afterwards to ensure the nanpy firmware is working as expected and it is. I also tried running Adafruit's strandtest.ino to ensure that all of the hardware is functioning as expected, and it is.

My problem happens when I try to create a DotStar object in my python code. I'm assuming that the Adafruit_DotStar class I made is failing in some way. I'm not proficient in C++ so the best I could do was follow the documents and hope for the best. :-) I ensured that the actual Adafruit_Dotstar library is in my Arduino Sketchbook\Libraries folder so it can be included properly.

Your Python code

from nanpy import (ArduinoApi, SerialManager, dotstar)
import time
import logging
logging.basicConfig(level=logging.DEBUG)

connection = SerialManager()
arduino = ArduinoApi(connection=connection)

strip = dotstar.DotStar(3, 4, 5, connection=connection)

while True:
    for x in range(3):
        strip.setPixelColor(x, [0,0,0])
    time.sleep(0.5)

    for x in range(3):
        strip.setPixelColor(x, [255,0,0])
    time.sleep(0.5)

Your log messages

Python 2.7.9 (default, Sep 17 2016, 20:26:04) 
[GCC 4.9.2] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
DEBUG:nanpy.serialmanager:opening port:/dev/ttyACM0 [115200 baud]
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'count\x00'
DEBUG:nanpy.serialmanager:received:'8\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:received:'A\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:received:'RAM\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'2\x00'
DEBUG:nanpy.serialmanager:received:'D\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'3\x00'
DEBUG:nanpy.serialmanager:received:'Core\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'4\x00'
DEBUG:nanpy.serialmanager:received:'Info\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'5\x00'
DEBUG:nanpy.serialmanager:received:'DHT\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'6\x00'
DEBUG:nanpy.serialmanager:received:'Measure\r\n'
DEBUG:nanpy.serialmanager:sending:'Info\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'1\x00'
DEBUG:nanpy.serialmanager:sending:'name\x00'
DEBUG:nanpy.serialmanager:sending:'7\x00'
DEBUG:nanpy.serialmanager:received:'Adafruit_DotStar\r\n'
DEBUG:nanpy.serialmanager:sending:'DotStar\x00'
DEBUG:nanpy.serialmanager:sending:'0\x00'
DEBUG:nanpy.serialmanager:sending:'3\x00'
DEBUG:nanpy.serialmanager:sending:'new\x00'
DEBUG:nanpy.serialmanager:sending:'3\x00'
DEBUG:nanpy.serialmanager:sending:'4\x00'
DEBUG:nanpy.serialmanager:sending:'5\x00'
DEBUG:nanpy.serialmanager:received:''

Traceback (most recent call last):
  File "/home/pi/lumbercade/Tests & Examples/nanpy_dotstar_test.py", line 9, in <module>
    strip = dotstar.DotStar(3, 4, 5, connection=connection)
  File "/usr/local/lib/python2.7/dist-packages/nanpy/dotstar.py", line 7, in __init__
    self.id = self.call('new', numpixels, datapin, clockpin)
  File "/usr/local/lib/python2.7/dist-packages/nanpy/arduinoboard.py", line 150, in call
    return _call(self.namespace, self.id, args, self.connection)
  File "/usr/local/lib/python2.7/dist-packages/nanpy/arduinoboard.py", line 47, in _call
    ret = return_value(connection)
  File "/usr/local/lib/python2.7/dist-packages/nanpy/arduinoboard.py", line 16, in return_value
    return connection.readline().replace('\r\n', '')
  File "/usr/local/lib/python2.7/dist-packages/nanpy/serialmanager.py", line 101, in readline
    raise SerialManagerError('Serial timeout!')
SerialManagerError: Serial timeout!
>>> 

Your cfg.h

#pragma once

// only for ESP8266
#define USE_WIFI_CONNECTION                         0

// for WIFI connection
#define WIFI_SSID       "***"
#define WIFI_PASSWORD   "***"

// for serial connection
#define BAUDRATE 115200

// info about existence of other features
#define USE_Info                                    1

// definitions: MCU type, frequency, Arduino version,
// EEPROM size, RAM size, pin count, build time,..
#define USE_Define                                  1

// low level mapping of pins and ports
#define USE_ArduinoCore                             1

// read, write RAM
#define USE_RAM                                     1

// read, write EEPROM
#define USE_EEPROM                                  1

// read, write AVR registers
#define USE_Register                                0

// watchdog and reset
#define USE_Watchdog                                0

#define USE_Tone                                    0

#define USE_LiquidCrystal                           0

// I2C
#define USE_Wire                                    0

#define USE_Servo                                   0

#define USE_Stepper                                 0

// frequency counter,  USE_Tone should be off!
#define USE_Counter                                 0

///////////////////////////////////////////////////////////////////////
// external libraries should be installed for the following features:
///////////////////////////////////////////////////////////////////////

// https://github.com/PaulStoffregen/OneWire
#define USE_OneWire                                 0

// https://github.com/milesburton/Arduino-Temperature-Control-Library
#define USE_DallasTemperature                       0

#define USE_CapacitiveSensor                        0

// https://github.com/adafruit/DHT-sensor-library
#define USE_DHT                                     1

// https://bitbucket.org/fmalpartida/new-liquidcrystal
#define USE_LiquidCrystal_I2C                       0

// https://www.adafruit.com/products/1429
#define USE_TLC5947                                 0

// ???
#define USE_MCP41xxx                                0

// Add the custome HC-SR04 distance measure class
#define USE_Measure                                 1

// Add the Adafruit DotStar LED class
#define USE_DotStar                                 1

Output of examples/firmware_check.py

Python 2.7.9 (default, Sep 17 2016, 20:26:04) 
[GCC 4.9.2] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
Firmware classes enabled in cfg.h:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/nanpy/examples/firmware_check.py", line 19, in <module>
    fw_check()
  File "/usr/local/lib/python2.7/dist-packages/nanpy/examples/firmware_check.py", line 10, in fw_check
    print('  ' + '\n  '.join(a.connection.classinfo.firmware_name_list))
AttributeError: 'ClassInfo' object has no attribute 'firmware_name_list'
>>> 

Extended Python module (dotstar.py)

(saved at: ..\python2.7\dist-packages\nanpy\dotstar.py)

from nanpy.arduinoboard import ArduinoObject
from nanpy.arduinoboard import (arduinoobjectmethod, returns)

class DotStar(ArduinoObject):
    def __init__(self, numpixels, datapin, clockpin, connection=None):
        ArduinoObject.__init__(self, connection=connection)
        self.id = self.call('new', numpixels, datapin, clockpin)

    @arduinoobjectmethod
    def begin(self):
        pass

    @arduinoobjectmethod
    def show(self):
        pass

    @arduinoobjectmethod
    def setPixelColor(self, pixel, color):
        pass

    @returns(int)
    @arduinoobjectmethod
    def numPixels(self):
        pass

C++ Files (DotStarClass.cpp & DotStarClass.h)

(saved at: ..\sketchbook\libraries\nanpyfirmware\nanpy)

.cpp

#include "cfg.h"

#if USE_DotStar

#include <Arduino.h>
#include <Adafruit_DotStar.h> //!!!Your real DotStar Library!!!!
#include "DotStarClass.h"
#include <stdlib.h>

const char* nanpy::DotStarClass::get_firmware_id()
{
    return "Adafruit_DotStar";
}

void nanpy::DotStarClass::elaborate( MethodDescriptor* m ) {
    ObjectsManager<Adafruit_DotStar>::elaborate(m);

    if (strcmp(m->getName(),"new") == 0) {
        Adafruit_DotStar* ds;
        ds = new Adafruit_DotStar(m->getInt(0), m->getInt(1), m->getInt(2));
        v.insert(ds);
        m->returns(v.getLastIndex());
    }

    if (strcmp(m->getName(), "begin") == 0) {
        //m->returns(v[m->getObjectId()]->begin());
        v[m->getObjectId()]->begin();
    }

    if (strcmp(m->getName(), "show") == 0) {
        //m->returns(v[m->getObjectId()]->show());
        v[m->getObjectId()]->show();
    }

    if (strcmp(m->getName(), "setPixelColor") == 0) {
        //m->returns(v[m->getObjectId()]->setPixelColor(m->getInt(0), m->getInt(1)));
        v[m->getObjectId()]->setPixelColor(m->getInt(0), m->getInt(1));
    }

    if (strcmp(m->getName(), "numPixels") == 0) {
        m->returns(v[m->getObjectId()]->numPixels());
    }
};

#endif

.h

#ifndef DOTSTAR_CLASS
#define DOTSTAR_CLASS

#include "BaseClass.h"
#include "MethodDescriptor.h"

class Adafruit_DotStar;

namespace nanpy {
    class DotStarClass: public ObjectsManager<Adafruit_DotStar> {
        public:
            void elaborate( nanpy::MethodDescriptor* m );
            const char* get_firmware_id();
    };
}

#endif

nanpy.ino

#include "cfg_all.h"
#include <SPI.h>

#if USE_MCP41xxx
#include <MCP41xxx.h>
#endif

#if USE_EEPROM
#include <EEPROM.h>
#endif

#if USE_Servo
#include <Servo.h>
#endif

#if USE_LiquidCrystal
#include <LiquidCrystal.h>
#endif

#if USE_LiquidCrystal_I2C
#include <LiquidCrystal_I2C.h>
#endif

#if USE_Stepper
#include <Stepper.h>
#endif

#if USE_OneWire
#include <OneWire.h>
#endif

#if USE_DallasTemperature
#include <DallasTemperature.h>
#endif

#if USE_CapacitiveSensor
#include <CapacitiveSensor.h>
#endif

#if USE_DHT
#include <DHT.h>
#endif

#if USE_Wire
#include <Wire.h>
#endif

#if USE_TLC5947
#include <Adafruit_TLC5947.h>
#endif

#if USE_DotStar
#include <Adafruit_DotStar.h>
#endif

#include "MCP41xxxClass.h"
#include "BaseClass.h"
#include "ArduinoClass.h"
#include "OneWireClass.h"
#include "StepperClass.h"
#include "ServoClass.h"
#include "DallasTemperatureClass.h"
#include "LiquidCrystalClass.h"
#include "LiquidCrystalClass_I2C.h"
#include "CapacitiveSensorClass.h"
#include "ToneClass.h"
#include "MethodDescriptor.h"
#include "ComChannel.h"
#include "EEPROMClass.h"
#include "RAMClass.h"
#include "DHTClass.h"

#include "DefineClass.h"
#include "ArduinoCoreClass.h"
#include "WatchdogClass.h"
#include "RegisterClass.h"
#include "CounterClass.h"
#include "InfoClass.h"
#include "WireClass.h"

#include "TLC5947Class.h"
#include "EspClass.h"

#include "MeasureClass.h"
#include "DotStarClass.h"

using namespace nanpy;

MethodDescriptor *m = NULL;

void setup() {
    disable_watchdog_at_startup();

    REGISTER_CLASS(ArduinoClass);                                                   // 0.8 k
//
    REGISTER_CLASS_CONDITIONAL(MCP41xxxClass, USE_MCP41xxx);
    REGISTER_CLASS_CONDITIONAL(nanpy::EEPROMClass, USE_EEPROM);                     // 0.3 k
    REGISTER_CLASS_CONDITIONAL(nanpy::RAMClass, USE_RAM);                           // 
    REGISTER_CLASS_CONDITIONAL(LiquidCrystalClass, USE_LiquidCrystal);              //  2.3 k
    REGISTER_CLASS_CONDITIONAL(LiquidCrystalClass_I2C, USE_LiquidCrystal_I2C);
    REGISTER_CLASS_CONDITIONAL(OneWireClass, USE_OneWire);                          // 1.7 k
    REGISTER_CLASS_CONDITIONAL(DallasTemperatureClass, USE_DallasTemperature);      // 6.1 k
    REGISTER_CLASS_CONDITIONAL(StepperClass, USE_Stepper);                          // 0.8 k
    REGISTER_CLASS_CONDITIONAL(ServoClass, USE_Servo);                              // 2.5 k
    REGISTER_CLASS_CONDITIONAL(ToneClass, USE_Tone);                                // 2.2 k
    REGISTER_CLASS_CONDITIONAL(CapacitiveSensorClass, USE_CapacitiveSensor);        // 2.2 k
    REGISTER_CLASS_CONDITIONAL(DefineClass, USE_Define);                            // 0.6 k
    REGISTER_CLASS_CONDITIONAL(ArduinoCoreClass, USE_ArduinoCore);                  // 
    REGISTER_CLASS_CONDITIONAL(WatchdogClass, USE_Watchdog);                        // 0.2 k
    REGISTER_CLASS_CONDITIONAL(RegisterClass, USE_Register);                        // 1.5 k

    REGISTER_CLASS_CONDITIONAL(CounterClass, USE_Counter);                          // 
    REGISTER_CLASS_CONDITIONAL(InfoClass, USE_Info);                          // 
    REGISTER_CLASS_CONDITIONAL(DHTClass, USE_DHT);
    REGISTER_CLASS_CONDITIONAL(WireClass, USE_Wire);

    REGISTER_CLASS_CONDITIONAL(TLC5947Class, USE_TLC5947);

    REGISTER_CLASS_CONDITIONAL(nanpy::EspClass, USE_ESP);

    REGISTER_CLASS_CONDITIONAL(MeasureClass, USE_Measure);
    REGISTER_CLASS_CONDITIONAL(DotStarClass, USE_DotStar);

    ComChannel::connect();
}

void loop() {
    if(ComChannel::available()) {
        m = new MethodDescriptor();
        Register::elaborate(m);
    }
}

Your hardware

jc78 commented 7 years ago

Beuller? Beuller?

Anyone here have any ideas or suggestions?

jc78 commented 7 years ago

Are there any nanpy devs in here that can help out? I've been trying in vein to make this work but with no success.

@astagi @ponty

ponty commented 7 years ago

You use different identifier in Python and C++ code: C++: Adafruit_DotStar Python: DotStar

You can see it in the log.

Ekram-B commented 6 years ago

Hi,

I was wondering if @jc78 has their issue resolved. I'm trying to extend nanpy to accomodate Marten Lamer's NMEA library to nanpy. I'm running into a similar issue where I experience a SerialManager timeout.