This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

I released a small python interface for the lightcrafter 6500

Other Parts Discussed in Thread: DLPC900

Hi to all Lightcrafter 6500 users!

I thought it would be nice to share the small library i wrote in Python for controlling the lightcrafter 6500 evaluation module (dlplcr6500evm). It is not feature complete, as it only does what i need in my application, but it can be used to set up "on the fly" sequences of binary patterns, with independently controllable exposures, triggers and dark times.

If you are into Python programming you can check out the source and use it as a base for your own needs, it's definitely better than starting from the dlpc900 programmer's guide.

In order to use it, you will need a python environment with pyusb 1.0 and numpy installed. The small test code attached requires PIL for importing an image, but you can use any Numpy array of size (1080,1920) containing only ones and zeros.

You can find the code at https://github.com/csi-dcsc/Pycrafter6500. The readme has short instructions on how to use it, and there is a small sample code, projecting a binary image of a cat. I of course decline any responsibility on any consequence of the use of the library, just know it worked for me, and i hope it helps you too.

Let me know if you nee any help with it! Enjoy!

  • Paolo,

    Thank you for your valuable contribution to this community!

    Paul
  • HI Paolo,

    I came across your python package while looking for a programmable interface for the LightCrafter 6500 GUI. The chip I'm trying to program is a DLPC900ZPC, that I usually load images on with the LightCrafter 6500 GUI, and I've installed python, numpy, libusb, pyusb, and Pillow in order to run the test script you include. When I do so, I get the error

    Traceback (most recent call last):
      File "test_code.py", line 10, in <module>
        dlp=pycrafter6500.dmd()
      File "C:\Users\Jeremy\Desktop\Pycrafter6500-master\pycrafter6500.py", line 221, in __init__
        self.dev.set_configuration()
    AttributeError: 'NoneType' object has no attribute 'set_configuration'

    Any idea on what could be causing this error?

  • Hi Jeremy,

    at the moment i am not in the lab, so i can not try to reproduce your error, but it seems to me that libusb does not "see" the device connected to the computer. I assume the device already works through the Texas instruments GUI, if not you could have some drivere problem or something like that.
    Also, you may need to install libusb drivers for your device. You can easily do it through Zadig ( http://zadig.akeo.ie/ ), selecting your device, the libusb-win32 driver, and pressing "install driver". The device will still work through the TI interface if you need it.

    If this does not solve the problem, it could be some device id mismatch. I used the evaluation module for Lightcrafter 6500, which, according to the datasheet, has a DLPC900 controller. I don't know if it is an abbreviation, or if DLPC900 and DLPC900ZPC are actually two different devices with different usb IDs.
    The IDs my script looks for are idVendor=0x0451 ,idProduct=0xc900. You can check yours by going to control panel-> system ->device manager, find the usb device corresponding to the controller, and select properties->details->hardware ids. If they are different, but you are very sure that the usb commands for controlling the device are the same, you can just change the values of the IDs at line 219 of the file pycrafter6500.py.

    I hope some of this help, let me know how it goes, so i can update the documentation if necessary.

    Bests

    Paolo
  • Hi Paolo,

    It did end up being a libusb issue. The DLPC900 and DLPC900ZPC differences don't actually come into play in your code, and it works just fine for both. The difficulties for me were, like I said, getting the libusb stuff installed correctly. If I were to offer any suggestion for the documentation, it would be some simple installation instructions for things needed on the backend to run the code. Just for people like me who aren't familiar with libusb, or even much about python. Other than that issue, the code works great.

    On additional question, though. Is there any way to speed up loading images? I have a set of 5 or so images and that's pretty much all I'm going to ever need to load, and I've been loading them like you did the kitten test image, from image files. Not that it takes forever, but it does take 5 or so seconds between running the script and the images appearing. Is there any way to speed that up? Something I can pre-compute for each of the 5 images perhaps? Thanks again for your code. It really does the trick.

  • Hi Jeremy,

    glad to know my code helps! I will try to write a small guide to libusb installation, but it varies wildly with operating systems, and i am definitely not an expert myself, even for me the setup was very much a trial and error procedure.

    As for the upload speed, unfortunately it is limited by the usb protocol the device works with (it is a usb 1.1 hid, if i am not mistaken). My code is a bit slower than the interface from TI, mostly due to the fact that the RLE compression is done through a for loop on all pixels of the images, which in Python is quite slow compared to C (or whatever the interface is written in), but the upload of the images themselves can not be speeded up in any way.
    If the images you intend to use are always the same, your best bet is loading them in the non volatile memory of the device, and use the pre-stored patterns mode.
    My software does not support uploading of new images, as it requires modifying the firmware information, so an unskilled programmer like myself would risk bricking the device during testing. That said, you can use the official TI GUI to upload the images once, and then use my code setting the mode to pre-stored patterns mode, and the images will be always available, so you can define the sequence and start right away.

    Let me know if it works, good luck!
  • Hi Jeremy,

    I'm testing DLPC900 and I think that I'm also having the libusb issue, the error says "NoBackendError: No backend available". May I ask how did you install the "libusb"? I tried Zadig but it couldn't find any device on my laptop so I couldn't modify things like "Driver""USB ID" etc. they are all blank. All I could do is to install WCID Driver, and it didn't solve the problem. Could you give me some suggestions ? Thank you.

  • Hi Paolo,

    Thank you so much for your code. May I ask that how does your code communicate with DLPC900? Is it  through TCP connection? Do you know what's the IP address of the DLPC900? Thank you.

  • Hi Bow,
    the only connection available for the DLPC900 is a HID protocol through a usb 1.1 connection. You can find a detailed programmer's guide on the DLPC900 webpage. My library is a Python implementation of most of the basic USB commands needed to operate the device.

    Cheer

    Paolo
  • Hi Paolo,

    Got it. Thank you, that's very helpful. I have another question, when I run your python program, I got this error, may I know what can I do to solve it? I'm using Python 2.7. Thank you.


    File "pycrafter6500.py", line 221, in __init__

    self.dev.set_configuration()

    AttributeError: 'NoneType' object has no attribute 'set_configuration'


    Sincerely,

    Bow

  • Hi Paolo,

    Thank you for your reply, I finally solved the driver problem but ran into another error when running your code, it says "Invalid endpoint address 0x1" (screenshot attached below), where I believe the "0x1" comes from line 258 in "pycrafter6500": "self.dev.write(1, buffer)". May I ask what could have caused this problem? Is it my "usb.core" version is not correct ? I would really appreciate it if you could give me some advice. Thank you.

    Thanks,

    Bow

  • Hi bow,

    that is a strange problem indeed. May i ask if the device works with the official TI software?
    As the error is, it seems that the configuration automatically set by the device is not correct,which is a weird issue.

  • Hi Paolo,

    Yes, it works with the official TI software. May I ask what exactly is the error? Can I get some help from TI ? Should I try to set the configuration back to the default setting ?

    Also, I tried several other values on the write line, only 2 shows a different error, I don't know if that means anything (And I'm not sure if this errors happens before or after the "endpoint address" line now). Thank you very much for your help.

    Thanks,

    Bow

  • I guess TI can not help you with that, since this is not their code.
    The good news is that the new error you get seems unrelated to my code, but more to the IDE you are using for your python coding. I would suggest to try and run the sample code from the basic IDLE interface. You will find it in "your_python_installation_folder\Lib\idlelib\idle.bat". It is a very basic python shell, you can open my sample code with it and try to run it.
    If it runs the problem is with your IDE, and i am afraid in that case i can not help you further.
  • Hi Paolo,

    Thank you, I tried using python shell but the problem persists. Only address 2 gives a different error (attached below). But telling from the timeout error of address 2, I suspect that 2 is a wrong address. May I ask what other solutions could there be? What does this endpoint address mean? Can I manually configure it? Thank you.

    Thanks,

    Bow

  • Hi Paolo,

    I did some searching online and found that generally endpoint 2 is for OUT, meaning writing into USB device,as the "invalid endpoint address" error happens at "self.dev.write(2, buffer)", so I think we should use address 2 right? Am I understanding it wrong? Thank you.
  • Hi Bow,


    sorry for the late reply, i don't know why, but i didn't receive email notifications for your latest responses. In theory you should not manually specify the endpoint, in the line "self.dev.set_configuration" the pyusb library should automatically select the correct writing endpoint . What error is return from the python console using endpoint 1? Still "invalid endpoint adress"?

    In alternative, you can obtain the first working endpoint address from the configuration, you can find an alternative version of the source code for the library, which i successfully tested on my system. Let me know if it works, and i will upgrade the version on the github repository.

    As a final test, can you please run the whole thing from a folder that does not have chinese characters in the path? That is the only difference i can think between your system and mine, i doubt it causes the problem, but you never know.

    New code for pycrafter6500.py :

    import usb.core
    import usb.util
    import time
    import numpy
    import sys
    
    
    
    
    ##function that converts a number into a bit string of given length
    
    def convlen(a,l):
        b=bin(a)[2:]
        padding=l-len(b)
        b='0'*padding+b
    
        return b
    
    ##function that converts a bit string into a given number of bytes
    
    def bitstobytes(a):
        bytelist=[]
        if len(a)%8!=0:
            padding=8-len(a)%8
            a='0'*padding+a
        for i in range(len(a)/8):
            bytelist.append(int(a[8*i:8*(i+1)],2))
    
        bytelist.reverse()
    
        return bytelist
    
    ##function that encodes a 8 bit numpy array matrix as a enhanced run lenght encoded string of bits
    
    def mergeimages(images):
        mergedimage=numpy.zeros((1080,1920,3),dtype='uint8')
    
        for i in range(len(images)):
            if i<8:
                mergedimage[:,:,2]=mergedimage[:,:,2]+images[i]*(2**i)
            if i>7 and i<16:
                mergedimage[:,:,1]=mergedimage[:,:,1]+images[i]*(2**(i-8))
            if i>15 and i<24:
                mergedimage[:,:,0]=mergedimage[:,:,0]+images[i]*(2**(i-16))
    
        return mergedimage
    
    def encode(image): 
    
    
    ## header creation
        bytecount=48    
        bitstring=[]
    
        bitstring.append(0x53)
        bitstring.append(0x70)
        bitstring.append(0x6c)
        bitstring.append(0x64)
        
        width=convlen(1920,16)
        width=bitstobytes(width)
        for i in range(len(width)):
            bitstring.append(width[i])
    
        height=convlen(1080,16)
        height=bitstobytes(height)
        for i in range(len(height)):
            bitstring.append(height[i])
    
    
        total=convlen(0,32)
        total=bitstobytes(total)
        for i in range(len(total)):
            bitstring.append(total[i])        
    
        for i in range(8):
            bitstring.append(0xff)
    
        for i in range(4):    ## black curtain
            bitstring.append(0x00)
    
        bitstring.append(0x00)
    
        bitstring.append(0x02) ## enhanced rle
    
        bitstring.append(0x01)
    
        for i in range(21):
            bitstring.append(0x00)
    
    
    
        n=0
        i=0
        j=0
    
        while i <1080:
            while j <1920:
                if i>0 and numpy.all(image[i,j,:]==image[i-1,j,:]):
                    while j<1920 and numpy.all(image[i,j,:]==image[i-1,j,:]):
                        n=n+1
                        j=j+1
    
                    bitstring.append(0x00)
                    bitstring.append(0x01)
                    bytecount+=2
                    
                    if n>=128:
                        byte1=(n & 0x7f)|0x80
                        byte2=(n >> 7)
                        bitstring.append(byte1)
                        bitstring.append(byte2)
                        bytecount+=2
                        
                    else:
                        bitstring.append(n)
                        bytecount+=1
                    n=0
    
                
                else:
                    if j<1919 and numpy.all(image[i,j,:]==image[i,j+1,:]):
                        n=n+1
                        while j<1919 and numpy.all(image[i,j,:]==image[i,j+1,:]):
                            n=n+1
                            j=j+1
                        if n>=128:
                            byte1=(n & 0x7f)|0x80
                            byte2=(n >> 7)
                            bitstring.append(byte1)
                            bitstring.append(byte2)
                            bytecount+=2
                            
                        else:
                            bitstring.append(n)
                            bytecount+=1
    
                        bitstring.append(image[i,j-1,0])
                        bitstring.append(image[i,j-1,1])
                        bitstring.append(image[i,j-1,2])
                        bytecount+=3
                        
                        j=j+1
                        n=0
    
                    else:
                        if j>1917 or numpy.all(image[i,j+1,:]==image[i,j+2,:]) or numpy.all(image[i,j+1,:]==image[i-1,j+1,:]):
                            bitstring.append(0x01)
                            bytecount+=1
                            bitstring.append(image[i,j,0])
                            bitstring.append(image[i,j,1])
                            bitstring.append(image[i,j,2])
                            bytecount+=3
                            
                            j=j+1
                            n=0
    
                        else:
                            bitstring.append(0x00)
                            bytecount+=1
    
                            toappend=[]
    
                            
                            while numpy.any(image[i,j,:]!=image[i,j+1,:]) and numpy.any(image[i,j,:]!=image[i-1,j,:]) and j<1919:
                                n=n+1
                                toappend.append(image[i,j,0])
                                toappend.append(image[i,j,1])
                                toappend.append(image[i,j,2])
                                j=j+1
    
                            if n>=128:
                                byte1=(n & 0x7f)|0x80
                                byte2=(n >> 7)
                                bitstring.append(byte1)
                                bitstring.append(byte2)
                                bytecount+=2
                                    
                            else:
                                bitstring.append(n)
                                bytecount+=1
    
                            for k in toappend:
                                bitstring.append(k)
                                bytecount+=1
                            n=0
            j=0
            i=i+1
            bitstring.append(0x00)
            bitstring.append(0x00)
            bytecount+=2
        bitstring.append(0x00)
        bitstring.append(0x01)
        bitstring.append(0x00)
        bytecount+=3
    
    
        while (bytecount)%4!=0:
            bitstring.append(0x00)
            bytecount+=1        
    
        size=bytecount
    
        print size
    
        total=convlen(size,32)
        total=bitstobytes(total)
        for i in range(len(total)):
            bitstring[i+8]=total[i]    
    
        return bitstring, bytecount
    
    
    
    ##a dmd controller class
    
    class dmd():
        def __init__(self):
            self.dev=usb.core.find(idVendor=0x0451 ,idProduct=0xc900 )
    
            self.dev.set_configuration()
    
            cfg = self.dev.get_active_configuration()
            intf = cfg[(0,0)]
    
            self.ep = usb.util.find_descriptor(
                intf,
                # match the first OUT endpoint
                custom_match = \
                lambda e: \
                    usb.util.endpoint_direction(e.bEndpointAddress) == \
                    usb.util.ENDPOINT_OUT)
    
            assert self.ep is not None
    
    
            self.ans=[]
    
    ## standard usb command function
    
        def command(self,mode,sequencebyte,com1,com2,data=None):
            buffer = []
    
            flagstring=''
            if mode=='r':
                flagstring+='1'
            else:
                flagstring+='0'        
            flagstring+='1000000'
            buffer.append(bitstobytes(flagstring)[0])
            buffer.append(sequencebyte)
            temp=bitstobytes(convlen(len(data)+2,16))
            buffer.append(temp[0])
            buffer.append(temp[1])
            buffer.append(com2)
            buffer.append(com1)
    
            if len(buffer)+len(data)<65:
            
                for i in range(len(data)):
                    buffer.append(data[i])
    
                for i in range(64-len(buffer)):
                    buffer.append(0x00)
    
    
                self.ep.write(buffer)
    
            else:
                for i in range(64-len(buffer)):
                    buffer.append(data[i])
    
                self.ep.write(buffer)
    
                buffer = []
    
                j=0
                while j<len(data)-58:
                    buffer.append(data[j+58])
                    j=j+1
                    if j%64==0:
                        self.ep.write(buffer)
    
                        buffer = []
    
                if j%64!=0:
    
                    while j%64!=0:
                        buffer.append(0x00)
                        j=j+1
    
    
                    self.ep.write(buffer)               
                    
    
    
    
    
    
            self.ans=self.dev.read(0x81,64)
    
    ## functions for checking error reports in the dlp answer
    
        def checkforerrors(self):
            self.command('r',0x22,0x01,0x00,[])
            if self.ans[6]!=0:
                print self.ans[6]    
    
    ## function printing all of the dlp answer
    
        def readreply(self):
            for i in self.ans:
                print hex(i)
    
    ## functions for idle mode activation
    
        def idle_on(self):
            self.command('w',0x00,0x02,0x01,[int('00000001',2)])
            self.checkforerrors()
    
        def idle_off(self):
            self.command('w',0x00,0x02,0x01,[int('00000000',2)])
            self.checkforerrors()
    
    ## functions for power management
    
        def standby(self):
            self.command('w',0x00,0x02,0x00,[int('00000001',2)])
            self.checkforerrors()
    
        def wakeup(self):
            self.command('w',0x00,0x02,0x00,[int('00000000',2)])
            self.checkforerrors()
    
        def reset(self):
            self.command('w',0x00,0x02,0x00,[int('00000010',2)])
            self.checkforerrors()
    
    ## test write and read operations, as reported in the dlpc900 programmer's guide
    
        def testread(self):
            self.command('r',0xff,0x11,0x00,[])
            self.readreply()
    
        def testwrite(self):
            self.command('w',0x22,0x11,0x00,[0xff,0x01,0xff,0x01,0xff,0x01])
            self.checkforerrors()
    
    ## some self explaining functions
    
        def changemode(self,mode):
            self.command('w',0x00,0x1a,0x1b,[mode])
            self.checkforerrors()
    
        def startsequence(self):
            self.command('w',0x00,0x1a,0x24,[2])
            self.checkforerrors()
    
        def pausesequence(self):
            self.command('w',0x00,0x1a,0x24,[1])
            self.checkforerrors()
    
        def stopsequence(self):
            self.command('w',0x00,0x1a,0x24,[0])
            self.checkforerrors()
    
    
        def configurelut(self,imgnum,repeatnum):
            img=convlen(imgnum,11)
            repeat=convlen(repeatnum,32)
    
            string=repeat+'00000'+img
    
            bytes=bitstobytes(string)
    
            self.command('w',0x00,0x1a,0x31,bytes)
            self.checkforerrors()
            
    
        def definepattern(self,index,exposure,bitdepth,color,triggerin,darktime,triggerout,patind,bitpos):
            payload=[]
            index=convlen(index,16)
            index=bitstobytes(index)
            for i in range(len(index)):
                payload.append(index[i])
    
            exposure=convlen(exposure,24)
            exposure=bitstobytes(exposure)
            for i in range(len(exposure)):
                payload.append(exposure[i])
            optionsbyte=''
            optionsbyte+='1'
            bitdepth=convlen(bitdepth-1,3)
            optionsbyte=bitdepth+optionsbyte
            optionsbyte=color+optionsbyte
            if triggerin:
                optionsbyte='1'+optionsbyte
            else:
                optionsbyte='0'+optionsbyte
    
            payload.append(bitstobytes(optionsbyte)[0])
    
            darktime=convlen(darktime,24)
            darktime=bitstobytes(darktime)
            for i in range(len(darktime)):
                payload.append(darktime[i])
    
            triggerout=convlen(triggerout,8)
            triggerout=bitstobytes(triggerout)
            payload.append(triggerout[0])
    
            patind=convlen(patind,11)
            bitpos=convlen(bitpos,5)
            lastbits=bitpos+patind
            lastbits=bitstobytes(lastbits)
            for i in range(len(lastbits)):
                payload.append(lastbits[i])
    
    
    
            self.command('w',0x00,0x1a,0x34,payload)
            self.checkforerrors()
            
    
    
        def setbmp(self,index,size):
            payload=[]
    
            index=convlen(index,5)
            index='0'*11+index
            index=bitstobytes(index)
            for i in range(len(index)):
                payload.append(index[i]) 
    
    
            total=convlen(size,32)
            total=bitstobytes(total)
            for i in range(len(total)):
                payload.append(total[i])         
            
            self.command('w',0x00,0x1a,0x2a,payload)
            self.checkforerrors()
    
    ## bmp loading function, divided in 56 bytes packages
    ## max  hid package size=64, flag bytes=4, usb command bytes=2
    ## size of package description bytes=2. 64-4-2-2=56
    
        def bmpload(self,image,size):
    
            t=time.clock()
    
            packnum=size/504+1
    
            counter=0
    
            for i in range(packnum):
                if i %100==0:
                    print i,packnum
                payload=[]
                if i<packnum-1:
                    leng=convlen(504,16)
                    bits=504
                else:
                    leng=convlen(size%504,16)
                    bits=size%504
                leng=bitstobytes(leng)
                for j in range(2):
                    payload.append(leng[j])
                for j in range(bits):
                    payload.append(image[counter])
                    counter+=1
                self.command('w',0x11,0x1a,0x2b,payload)
    
    
                self.checkforerrors()
            print time.clock()-t
    
    
        def defsequence(self,images,exp,ti,dt,to,rep):
    
            self.stopsequence()
    
            arr=[]
    
            for i in images:
                arr.append(i)
    
    ##        arr.append(numpy.ones((1080,1920),dtype='uint8'))
    
            num=len(arr)
    
            encodedimages=[]
            sizes=[]
    
            for i in range((num-1)/24+1):
                print 'merging...'
                if i<((num-1)/24):
                    imagedata=mergeimages(arr[i*24:(i+1)*24])
                else:
                    imagedata=mergeimages(arr[i*24:])
                print 'encoding...'
                imagedata,size=encode(imagedata)
    
                encodedimages.append(imagedata)
                sizes.append(size)
    
                if i<((num-1)/24):
                    for j in range(i*24,(i+1)*24):
                        self.definepattern(j,exp[j],1,'111',ti[j],dt[j],to[j],i,j-i*24)
                else:
                    for j in range(i*24,num):
                        self.definepattern(j,exp[j],1,'111',ti[j],dt[j],to[j],i,j-i*24)
    
            self.configurelut(num,rep)
    
            for i in range((num-1)/24+1):
            
    
                self.setbmp((num-1)/24-i,sizes[(num-1)/24-i])
    
    
    
                print 'uploading...'
                self.bmpload(encodedimages[(num-1)/24-i],sizes[(num-1)/24-i])
    
    
    
    
    
    
    

  • Hi Paolo,

    Thank you so much for your help, I really appreciate it. Yes, when I run code in Python console using "1" as endpoint address, it gives "Invalid endpoint address 0x1" error.  I just want to double-check if our hardware match, I'm using Lightcraft 6500 with dlpc900, windows10.

    I tried your new code in a different folder, but the error persists. I extended the timeout time,but still didn't get anything.

    From my understanding, the error happens in the "write" step, it could because of:

    1. the device couldn't read the command string sent from the laptop,so there's no response back. But I tried to modify the buffer to be some sample commands on "dlpc900 programmer guide", it still doesn't work.

    2. the command string is not able to reach th device, or the response doesn't reach the laptop. But I think there shouldn't be problem for the device to receive the commands because it works with TI software.

    I'm wondering what do you think the problem could be ? Thank you.

    Thanks,

    Bow

  • Hi Bow,

    we indeed have the same hardware, the only difference is that i am using Windows 7. I will later try with my Windows 10 laptop, but i doubt it will be a problem. The persistence of the problem is very strange, as if it was unable to find a working endpoint it would now return a different error. It appears the software finds an endpoint, sends a message, but the device does not react.
    Just to be perfectly sure, the TI software is not open when you are running the Python script, right?

    As i said, i will alter try to operate the device from my Windows 10 laptop, and document all the steps i take for the driver installation, in case something went wrong for you there.

  • Hi Paolo,

    Thank you for your time. I'll keep testing as well. Looking forward to hearing from you.

  • Hi Bow,

    i tried on my Windows 10 pc. It worked without problems. The procedure is:

    -plugged in the usb cable
    -opened Zadig
    -Selected "show all devices"
    -Selected the "libusb-win32" driver
    -Pressed the "install driver" button
    -run the Python script

    One thingh i just noticed is that, in your errors, the Pyusb library seems to be using the libusb0 backend, while, in case i get an error, it seems i am using the libusb1 backend. In theory the device should work with both, but please check that you are using the latest version of Zadig, and you are selecting the correct driver.

    Good luck!

    Paolo

  • Hi Paolo,

    Thank you so much for the kind remainder! It's working now! I double-checked the driver and I noticed that there are two interfaces for DLPC900, one is "C900(interface 1)", the other is "DLPC900(interface 0)", I think previously I might have only replaced one of them with libusb-win32.

    But I when I run the code on my IDE (Spyder), it gives me "UnicodeDecodeError: 'ascii' codec can't decode byte 0xc7 in position 87: ordinal not in range(128)" I'm wondering if there's a way to solve this problem? Or what IDE do you use that doesn't have this problem?

    I'm also trying to upload a sequence of images and to speed up the upload process, the same as Jeremy who posted before. I'll read your reply to him and try to figure out how to do it. Thank you again for your help, I really appreciate it !
  • Hi Bow, 

    great to hear that it works! And thank you for your patience in testing the code without giving up.

    I will try, based on your feedback, to create better driver installation instructions for the library.
    Again, i can not help you for the IDE specific problems, you should probably contact the IDE developers. My guess is that the text editor for a Chinese language operating system creates some problems with the use of hexadecimal notation in the code, but i could be very wrong.

    I hope you enjoy using your DLP with Python!

    Cheers

    Paolo

  • Hi Paolo,

    Got it, thank you. Just one small question, I found out that I can't use the TI software to control the device right now, is it also the case for you? I'm wondering if there is an easy way to uninstall the libusb driver? I tried uninstalling the device from "Device manager " and reboot, also unplug the device, but the libusb driver is still there.
  • Hi Bow,

    that is strange, i can use both the TI software and my python software with the same driver. Maybe try to reinstall the TI software?

  • Hi Paolo,

    Thank you for the suggestion. But it really confuses me that why you could run TI software by using libusb-win32 driver. I had a test on another computer, the TI software runs fine at first, but after installing the libusb-win32 driver from Zadig, the TI software doesn't work anymore. Are you using And the problem persists even after uninstalling the libusb-win32 driver. (I found a way to uninstall it) I'm wondering that are you using 3.0.0 version of the TI software? And what's the firmware version on your DLPC900? Thank you!
  • Hi Bow,

    I've run into the same issue. After install the driver from Zadig, the TI software no longer connects. Were you able to get it working again? Any help is appreciated.

    Thanks,

    Alex

  • Hi Alex,

    No, I've been only using the Python code since then. I tried to remove all the drivers but the TI software never worked since the Zadig driver was installed.

    Sincerely,

    Bow

  • Hi Bow,
    Thanks for the update. That is unfortunate to hear. If I find a solution I will let you know.
    Alex
  • Hi Bow,
    I came back to this problem and managed to get the GUI working again. The way to do was, with the projector connected over USB, to go to device manager and uninstall the libusb driver, but when the confirmation window comes up, to make sure to check the box to also remove driver software. Afterwards, unplugging and replugging the USB cable properly installed the USB driver to work with LCR4500 GUI.
  • Hey Paolo,

    I encountered a problem with your Python interface. I display different moving lattices on the DMD, which is why I wanted to use your interface so I could generate them and load them onto the DMD fully automated. Otherwise I would have to load them by hand with the TI interface. For good compressible images your interface works fine but my lattices are very fine, in the worst case a checkerboard pattern. I came to this conclusion because for the big lattices the TI interface transfers the images very fast, but for the fine ones and espacially for the checkerboard it takes very long. When I try to transfer those images with your interface I get an error for a lattice depandent amount of images. If I use big lattices I can transfer many images and in the case of the case of the checkerboard I can't even transfer only this one.

    The exact error message I get in the command window reads:

    C:\Users\username\Documents\DMD\Python\Pycrafter>test_code.py
    merging...
    encoding...
    Traceback (most recent call last):
      File "C:\Users\username\Documents\DMD\Python\Pycrafter\test_code.py", line 23, in
    <module>
        dlp.defsequence(images,exposure,trigger_in,dark_time,trigger_out,0)
      File "C:\Users\username\Documents\DMD\Python\Pycrafter\pycrafter6500.py", line 488
    , in defsequence
        imagedata,size=encode(imagedata)
      File "C:\Users\username\Documents\DMD\Python\Pycrafter\pycrafter6500.py", line 165
    , in encode
        while numpy.any(image[i,j,:]!=image[i,j+1,:]) and numpy.any(image[i,j,:]!=im
    age[i-1,j,:]) and j<1919:
    IndexError: index 1920 is out of bounds for axis 1 with size 1920

    Here are two of the images I use:

  • Hey David,

    interesting, clearly my compression function breaks down pretty badly with this very thin checkerboard patterns. At the moment i am not using my DMD, but i should introduce it in my new setup in the next few days. As soon as it's online again i will try to reproduce your problem, and hopefully fix the code to solve it. I'll keep you posted!

    Bests

    Paolo