2018년 4월 13일 금요일

Turn off power management of bluetooth mouse (i.e. Microsoft Designer Mouse)

/etc/bluetooth/input.conf

# Configuration file for the input service

# This section contains options which are not specific to any
# particular interface
[General]

# Set idle timeout (in minutes) before the connection will
# be disconnect (defaults to 0 for no timeout)
#IdleTimeout=30
IdleTimeout= 0

# Enable HID protocol handling in userspace input profile
# Defaults to false (HIDP handled in HIDP kernel module)
#UserspaceHID=true

reboot.

2018년 4월 11일 수요일

Install QTCreator in Debian

# apt install qtcreator qtbase5-dev libqt5serialport-dev


How to use USB4000 Spectrometer in Linux system (Debian)

There are two kinds of tools that cooperate USB4000 under GNU Debian distribution.
The first one is that C/C++ interface comes from OceanOptics Official, and the other is that the Python package was made as Open Source contribution.


1. Preliminary


The first thing to do before tools installation is to configure the system allowing any one to access the USB4000 without root premission.


1.1. Download SeaBreeze (i.e. OceanOptics Official tool for linux system).

https://sourceforge.net/projects/seabreeze/?source=typ_redirect





1.2. Extract *.zip file and copy the rules file into system.


With root permission,


# cp seabreeze-3.0.11/SeaBreeze/os-support/linux/10-oceanoptics.rules /etc/dev/rules.d/


1.3.  Plugin USB4000 and verify the connection.
 

You can see the USB4000 with Vendor ID: 0x2457 and Product ID: 0x1022.


2. OceanOptics' Offical Tool (i.e. SeaBreeze)


The tool contains C/C++ api, utilities and test codes.



2.1. Register the library path.


Before the compilation, load library path has to be registered.


# cd ~/seabreeze-3.0.11/SeaBreeze

#  export LD_LIBRARY_PATH="$PWD/lib"


2.2. Compilation with some errors and modification.


Once compiling the SeaBreeze, many errors are poped out that is actually kinds of warnings for c++11 deprecation.


This kinds of erros could be removed by comment out '-Werror' option.




2.3. Install dependencies.


# apt install libusb-dev, ....


2.4. Complete compilation.


# make


2.5. Execution of test code.

# ./test/seabreeze_test_posix




3. Open Sourced Toolkit (linux drivers for usb spectrometers)

This tool is open source tool that supports several usb spectrometers (i.e. avantes, hamamatsu, and OceanOptics). That is basically written by Python script, and internally using Kernel interface or Libusb. In otherwords, it do not requires any kinds of additional kernel driver.

3.1. Download python package.


Click Download Snapshot.

3.2. Install dependencies.

# pip install numpy, matlibplot, pyusb

3.3. Modification for visualizing live graph.

#!/usr/bin/env python3 -w

# python module to communicate with an Ocena Optics USB spectrometer
#
# Copyright (C) Wolfgang Schoenfeld (wolfgang.schoenfeld@hzg.de) and
#               Carsten Frank       (carsten.frank@hzg.de)
#
#       This program is free software; you can redistribute it and/or
#       modify it under the terms of the GNU General Public License as
#       published by the Free Software Foundation, version 2.
#
# This module is suitable to control a Avantes USB spectrometer. The following
# types are supported:
# - USB 4000
# - probably USB 2000

# C H A N G E S #
# 28. 07. 2012 Carsten Frank
# - created based on the Hamamatsu code
# - also based on the documentation given in the USB4000-OEM_Data-Sheet.pdf
#   which is publicly available (http://www.oceanoem.com/).

from __future__ import print_function

import os
import os.path
import re
import time
import sys
import numpy as np
import multiprocessing
import ctypes
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
#import cv2

#sys.path.append('/home/carsten/Programme/python/FiaSia')
#sys.path.append('/home/carsten/Programme/python')
#from findUSBserialDevice import getDeviceFileFromAddress, testAddress

import usb.core, usb.util

USB_USBSPEC_VENDOR_ID = 0x2457
USB_USBSPEC_PRODUCT_ID_USB4000 = 0x1022
USB_USBSPEC_PRODUCT_ID_USB650 = 0x1014   # not working, kept for future use
PIXEL_COUNT_USB4000 = 3840

class USB4000: ## GUI OoUSB4000 ## Adds this device to the spectrometers listed in the GUI
    '''Connect to a Ocean Optics mini spectrometer via USB. '''

    # device name should be either the USB-address or the serial numer
    def __init__(self, deviceName = None):
        # the device name would be the 'device' in the "/dev/" folder (linux)
        self.deviceName   = None
        self.serialNumber = None

        # Only needed for pyUSB. Checks if the configuration was already set.
        self.configurationSet = False

        # self.usedInterface is set in findAllConnectedSpectrometers
        # self.usedInterface equals None if no device is found
        devNotFound = True

        # If no spectrometer is foud this function complains and exits!
        self.specs = self._findAllConnectedSpectrometers()

        if self.usedInterface == 'pyusb':
                if  deviceName == None:
                        # use the 'first' spectrometer
                        self.serialNumber = self.specs.keys()[0]
                        self.deviceName   = None
                        self.basePath     = None
                        devNotFound = False
                else:
                        # only the serial number would be delivered as device name in this context (pyusb)
                        if self.specs.has_key(deviceName):
                                self.serialNumber = key
                                self.deviceName   = None
                                self.basePath     = None
                                devNotFound       = False

        elif self.usedInterface == 'kernel':
                if  deviceName == None:
                        # use random device (if more than one device is attached)
                        self.serialNumber = self.specs.keys()[0]
                        self.deviceName = self.specs[self.serialNumber][0]
                        self.basePath = os.path.join("/sys/bus/usb/drivers/usbhspec/", self.specs[self.serialNumber][1])
                        devNotFound = False
                else:
                        # if it is an valid usb address like '8-2:1.0'
                        if testAddress(deviceName):
                                for key, value in self.specs.iteritems():
                                        if value[1] == deviceName:
                                                self.deviceName = value[0]
                                                self.basePath = os.path.join("/sys/bus/usb/drivers/usbhspec/", value[1])
                                                devNotFound = False
                                                break
                        else:
                                for key, value in self.specs.iteritems():
                                        if value[0] == deviceName:
                                                self.deviceName = value[0]
                                                self.basePath = os.path.join("/sys/bus/usb/drivers/usbhspec/", value[1])
                                                devNotFound = False
                                                break
                                        if key == deviceName:
                                                self.deviceName = value[0]
                                                self.basePath = os.path.join("/sys/bus/usb/drivers/usbhspec/", value[1])
                                                devNotFound = False
                                                break

        if devNotFound == True:
                print('Device %s not found! Exiting ...'%(deviceName))
                sys.exit()

        if self.usedInterface == 'kernel':
                #: First calibration coefficient of the spectrometer. Pixel counting starts at 1!
                self.startWavelength = float(file(os.path.join(self.basePath,"a0")).read())
                #: Second calibration coefficient.
                self.firstKoeff      = float(file(os.path.join(self.basePath,"a1")).read())
                #: Third calibration coefficient.
                self.secondKoeff     = float(file(os.path.join(self.basePath,"a2")).read())
                #: Fourth calibration coefficient.
                self.thirdKoeff      = float(file(os.path.join(self.basePath,"a3")).read())
                #: Fifth calibration coefficient.
                self.fourthKoeff     = float(file(os.path.join(self.basePath,"a4")).read())
                #: Guess what!
                self.fifthKoeff      = float(file(os.path.join(self.basePath,"a5")).read())
                self.deviceName = file(os.path.join(self.basePath,"device_name")).read().strip()
                self.sensorName = file(os.path.join(self.basePath,"sensor_name")).read().strip()

                self.devicePath = "/dev/%s" % (self.deviceName)
        else: # self.usedInterface == 'pyusb'
                # we do know the serialNumber!

                value = self.specs[self.serialNumber]
                dev = value[3]

                # create endpoints

                cfg = dev.get_active_configuration()
                interface_number = cfg[(0,0)].bInterfaceNumber
                alternate_setting = usb.control.get_interface(dev, interface_number)
                intf = usb.util.find_descriptor(cfg, bInterfaceNumber = interface_number,bAlternateSetting = alternate_setting)

                self.ep1Out = usb.util.find_descriptor(intf, custom_match = lambda e: e.bEndpointAddress == 0x01)
                self.ep1In  = usb.util.find_descriptor(intf, custom_match = lambda e: e.bEndpointAddress == 0x81)
                self.ep2    = usb.util.find_descriptor(intf, custom_match = lambda e: e.bEndpointAddress == 0x82)
                self.ep6    = usb.util.find_descriptor(intf, custom_match = lambda e: e.bEndpointAddress == 0x86)

                #: Get start wavelength
                self.startWavelength = self._query(0x01, "num")
                #: Second calibration coefficient.
                self.firstKoeff      = self._query(0x02, "num")
                #: Third calibration coefficient.
                self.secondKoeff     = self._query(0x03, "num")
                #: Fourth calibration coefficient.
                self.thirdKoeff      = self._query(0x04, "num")
                #: Fifth calibration coefficient.
                self.fourthKoeff     = 0.0
                #: Guess what!
                self.fifthKoeff      = 0.0
                self.sensorName = ''

                self.deviceName = dev


        # Default
        self.pixelOffset = 0
        # S10420-1006/-1106 CCD image sensor see documentation (Device structure)
        if (self.sensorName == "S10420-1106") or (self.sensorName == "S10420-1006"):
                self.pixelOffset = 10
                print("Sensor '%s' means pixel offset of %d" % (self.sensorName, self.pixelOffset))
        elif (self.sensorName.find("S8377") > -1) or (self.sensorName.find("S8378") > -1):
                self.pixelOffset = 0
                print("Sensor '%s' means pixel offset of %d" % (self.sensorName, self.pixelOffset))



        # gereate wavelength array
        self.wlArr = np.zeros(PIXEL_COUNT_USB4000)
        for pix in range(PIXEL_COUNT_USB4000):
                self.wlArr[pix] = self.startWavelength       + \
                                   pix *   self.firstKoeff   + \
                                  (pix**2)*self.secondKoeff  + \
                                  (pix**3)*self.thirdKoeff   + \
                                  (pix**4)*self.fourthKoeff  + \
                                  (pix**5)*self.fifthKoeff
        print(self.wlArr)

    def findAllConnectedSpectrometers(self):
            return self.specs
    def _findAllConnectedSpectrometers(self):
        """Function to find all connected USB-spectrometers

        Returns a list/dictionary? with spectrometers containing:
        - device name
        - serial number
        - start wavelength
        """

        specs = {}
        self.usedInterface = "kernel"

        basePath = "/sys/bus/usb/drivers/usbhspec/"
        if not os.path.exists(basePath):
                self.usedInterface = "pyusb"
                print("No spectrometer found using the kernel module.")
                print("Now testing pyusb!")

        if self.usedInterface == "kernel":
                fList = os.listdir(basePath)

                for i in fList:
                        mtch = re.search("\d\-\d.*\:\d+\.\d+", i)
                        if mtch:
                                serNr = open(os.path.join(basePath, i, "serial_number"), "r").read().strip()
                                res = getDeviceFileFromAddress("usb", i)
                                if len(res) <> 1:
                                        print("Something went wrong. I found two USB devices with the same path!")
                                        for i in res:
                                                print(i)
                                        print("PLEASE call someone (Carsten) who knows what to do now!")
                                        sys.exit()

                                specs[serNr] = (res[0][0], i, "%.0f" % (float(file(os.path.join(basePath, i,"a0")).read())))
        elif self.usedInterface == "pyusb":
                # use the pyusb interface (only ONE of these interfaces WILL work)
                devs = list(usb.core.find(idVendor=USB_USBSPEC_VENDOR_ID, idProduct=USB_USBSPEC_PRODUCT_ID_USB4000, find_all=True))
                #devs = usb.core.find(idVendor=USB_USBSPEC_VENDOR_ID, idProduct=USB_USBSPEC_PRODUCT_ID_USB650, find_all=True)
                if len(devs) > 0:
                        print("Found %d spectrometer(s) via pyusb!" % (len(devs)))
                else:
                        print("Also no spectrometer found using pyusb.")

                # find alls connected devices
                for dev in devs:
                        #dev.set_configuration()
                        #cfg = dev.get_active_configuration()
                        #interface_number = cfg[(0,0)].bInterfaceNumber
                        #alternate_setting = usb.control.get_interface(dev, interface_number)
                        #intf = usb.util.find_descriptor(cfg, bInterfaceNumber = interface_number,bAlternateSetting = alternate_setting)

                        cfg=dev[0]
                        intf=cfg[(0, 0)]

                        self.ep1Out=intf[0]
                        self.ep1In =intf[3]

                        #self.ep1Out = usb.util.find_descriptor(intf, custom_match = lambda e: e.bEndpointAddress == 0x01)
                        #self.ep1In  = usb.util.find_descriptor(intf, custom_match = lambda e: e.bEndpointAddress == 0x81)

                        readSuccess = False
                        while not readSuccess:
                                # INITIALIZE
                                self.ep1Out.write(chr(0x01))
                                time.sleep(0.5)
                                readSuccess = True
                                # get integration time

                                #self.ep1Out.write(chr(0xfe))
                                #try:
                                        #res = self.ep1In.read(64)
                                        #readSuccess = True
                                #except usb.core.USBError:
                                        #print "Failed"
                                        #pass

                        #int_time = (res[5]<<24 br="" res="">                        #print int_time

                        # get necessary data for all devices {'510C2114': ('usbhspec0', '5-2:1.0', '324'  )}
                        #                                    { serialNo : ( 'pyusb'   ,  None    , firstWL)}
                        # get serial number
                        serNr = self._query(0x00, "str")
                        # get a0
                        a0 = self._query(0x01, "num")
                        del(self.ep1Out, self.ep1In)
                        specs[serNr] = ( 'pyusb'   ,  None    ,  "%.0f" % (float(a0)), dev)
        else:
                print("This point should never be reached!")
                sys.exit()

        if len(specs) == 0:
                self.usedInterface = None

        return specs

    def _query(self, byte, decode=None):
        self.ep1Out.write(chr(0x05) + chr(byte))
        res = self.ep1In.read(64)
        if   decode == 'str':
            s   = ''.join(map(chr,res[2:])).rstrip()
            res = s.replace('\x00','')
            res = res.replace('\xa4','')
        elif decode == 'num':
            s   = ''.join(map(chr,res[2:])).rstrip()
            res = s.replace('\x00','')
            res = res.replace('\xa4','')  #FIXME: ??
            res = float(res)
        return res

    def setIntegrationTime(self, intTime, test=True):
        # integration_time possible values between 10 - 65535000 (in usec)
        if (intTime < 10) or  (intTime > 65535000):
                print("USB4000.setIntegrationTime : Integration Time not allowed! please use vaues between")
                print("10 and 65535000 us")
                return False
        while True:
                if   self.usedInterface == 'pyusb':
                        c = []
                        c.append( intTime        & 0xFF )
                        c.append((intTime >>  8) & 0xFF )
                        c.append((intTime >> 16) & 0xFF )
                        c.append((intTime >> 24) & 0xFF )
                        self.ep1Out.write(chr(0x02) + bytearray(c))
                else:
                        print("Interface not yet implemented")
                        sys.exit()

                if not test:
                        break
                time.sleep(.01)
                devIT = self.getIntegrationTime()
                print("setIntTime : %d  ----  deviceIntTime : %d" % (devIT, intTime))
                if devIT == intTime:
                        break
                if (time.time() - startT) > 1.0:
                        return False
        self.integrationTime = intTime
        return True

    def getIntegrationTime(self):
        # integration_time possible values between 10000 and 10000000 (in usec)
        if   self.usedInterface == 'pyusb':

                startT = time.time()
                self.ep1Out.write(chr(0xfe))
                res    = self.ep1In.read(64)
                #while len(res) <> 4:
                        #print("--------------------------------- getIntegrationTime -- Answer incorrect (too long or too short)!")
                        #time.sleep(.01)
                        #res    = self.deviceName.ctrl_transfer(bmRequestType = 0xc0, bRequest = 0x0b, wValue = 0x01, wIndex = 0x00, data_or_wLength = 4, timeout = 2000)
                        #if (time.time() - startT) > .5:
                                #raise
                intTime = (res[5] << 24) + (res[4] << 16) + (res[3] << 8) + res[2]
        elif self.usedInterface == 'kernel':
                print("Interface not yet implemented")
                sys.exit()
        return intTime

    def getSensorName(self):
        return self.sensorName

    def getSerialNumber(self):
        return self.serialNumber

    def getSpectrum(self, timeout = None):
        """This function grabs spectral data from the spectrometer. Addidtional
        information is also encoded in the data read from the interface so
        take nothing for granted!

        I've got two different spectrometers from which I tried to conclude
        what to do with the data. I may have made invalid assumptions!

        You have to read 0x1040 bytes of data. These are 16bit numbers so it does
        make sense to calculate these numbers from the data and the only use those
        integers.

        The first number (16 bit in this context) was alwas 2. That only changes
        if you read data if the spectrometer is not yet ready (integration time).
        If the spectrometer isn't ready all numers are zero.

        The second number is an index which is 0,1 or 2 and just counts up.

        Third is the amount of active pixels (in contrast to the amount of pixels
        sixth number (index 5)). Please see the documentation to your image sensor
        (e.g. S10420-1106 from Hamamtsu).

        Forth (index 3) is the most important number because it says where to find
        the first pixel in the whole dataset of 0x1040/2 = 0x820 16bit numbers.

        The fifth seems to be the end index because startIndex + amountOfPixels = endIndex
        HOWEVER in my case the end index is higer than 0x820 which means that I can be
        very wrong with my interpretation.

        In my case and using the S10420-1106 sensor I found that the first four numbers
        of the spectrum (starting with startIndex) seem to be darkened pixels. You can
        increase the integration time as much as you wish these numbers stay (more or less)
        the same. Use at your own risc!

        Actually the spectrum seems to start at startIndex + 10 pixels/numbers which was
        veryfied for MY spectrometer with a really good and freshly checked laboratory
        spectrometer from Perkin Elmer (wavelength correctness was checkt with the aid of
        special filters).
        So I calculate the start of the spectrum unsing
        startSpectrum = startIndex + (amountOfPixels - amountOfActivePixels) / 2
        which seems to make sense.

        The wavelength correctness was VERY good compared to spectrometers from avantes,
        ocean optics and trios. We estimat an offset of about .4 nm over the whole spectrum
        which lies in the tolerance of of our measurement setup.
        """

        if timeout == None:
                timeout = self.integrationTime / 1000000.0 * 2.1
        startT = time.time()
        while 1:
                #: Grab data from the interface
                if self.usedInterface == 'pyusb':
                        # ask for the data
                        self.ep1Out.write(chr(0x09))
                        resArr = np.zeros(256 * 15)
                        resArrIndex = 0
                        # read four times from endpoint 6 an four times from ep2
                        while 1:
                                try:
                                        res = self.ep6.read(512)
                                except usb.core.USBError:
                                        if (time.time() - startT) > timeout:
                                                raise usb.core.USBError("Timeout")
                                        time.sleep(.01)
                                        continue
                                else:
                                        break

                        for i in range(0,len(res),2):
                                resArr[resArrIndex] = (res[i+1] << 8) + res[i]
                                resArrIndex += 1


                        for i in range(3):
                            res = self.ep6.read(512)
                            for i in range(0,len(res),2):
                                resArr[resArrIndex] = (res[i+1] << 8) + res[i]
                                resArrIndex += 1
                        for i in range(4,15):
                            res = self.ep2.read(512)
                            for i in range(0,len(res),2):
                                resArr[resArrIndex] = (res[i+1] << 8) + res[i]
                                resArrIndex += 1
                        sync_packet = self.ep2.read(1)
                        return resArr
                else:
                        return None

        return resArr

def frange(start, end=None, inc=None):
    "A range function, that does accept float increments..."

    if end == None:
        end = start + 0.0
        start = 0.0

    if inc == None:
        inc = 1.0

    L = []
    while 1:
        next = start + len(L) * inc
        if inc > 0 and next >= end:
            break
        elif inc < 0 and next <= end:
            break
        L.append(next)

    return L

pauseEvent = False
animationHandle = None

def main(argv):
    global animationHandle
    
    ham = USB4000()
    #print ham.findAllConnectedSpectrometers()
    ham.setIntegrationTime(100000)
    res = ham.getSpectrum()
    print(res, len(res), max(res))
    
    fig = plt.figure()
    fig.suptitle('Demo. of Spectrometer')

    ax = fig.add_subplot(1, 1, 1)
    #plt.axis([0, len(res), 0, 40000])
    
    '''
    li, = ax.plot(ham.wlArr, res, c='r')
    #ax.relim()
    #ax.autoscale_view(True, True, True)
    #fig.canvas.draw()
    plt.show(block=False)

    while True:
        try:
            res = ham.getSpectrum()
            li.set_ydata(res)
            fig.canvas.draw()
        except KeyboardInterrupt:
            break

    '''
    def draw_spectrum(i):
        res = ham.getSpectrum()
        ax.clear()
        ax.set_title('USB4000')
        #ax.set_xlim(ham.wlArr.min(), ham.wlArr.max())
        #ax.set_ylim(0, 36000)
        ax.set_xlabel('Wavelength')
        ax.set_ylabel('Intensity')
        ax.plot(ham.wlArr, res, c='r')
        
    ax.relim()
    ax.autoscale_view(True, True, True)
    animationHandle = animation.FuncAnimation(fig, draw_spectrum, blit=False, interval=1, repeat=True)
    
    def on_click(event):
        global pauseEvent
        global animationaHandle
        #print('clicked')
        pauseEvent ^= True
        if pauseEvent:
            animationHandle.event_source.stop()
        else:
            animationHandle.event_source.start()

    fig.canvas.mpl_connect('button_press_event', on_click)

    plt.show()
    
    return 0
    
if __name__ == '__main__':
    sys.exit(main(sys.argv))


3.4. Execution.




4. References

https://sourceforge.net/projects/seabreeze/?source=typ_redirect

https://sourceforge.net/p/usbspecdrivers/wiki/Installation/



2017년 2월 28일 화요일

BeagleBone Green Wireless

Preparing external SD Card

Install udev rule

Connect to the board

Plug in USB port of host PC

Using ssh terminal, connect to the board

WiFi connection

Update Debian packages


2016년 4월 20일 수요일

조명 장치의 조사 영역 분포도 검사 시뮬레이션

파이선 소스 코드


 #!/usr/bin/python  
 import Image  
 import numpy  
 import math  
 palette=((0, 0, 0), (0, 0, 10), (0, 0, 20), (0, 0, 30), (0, 0, 37), (0, 0, 42), (0, 0, 46), (0, 0, 50), (0, 0, 54), (0, 0, 58), (0, 0, 62), (0, 0, 66), (0, 0, 70), (0, 0, 74), (0, 0, 79), (0, 0, 82), (1, 0, 85), (1, 0, 87), (2, 0, 89), (2, 0, 92), (3, 0, 94), (4, 0, 97), (4, 0, 99), (5, 0, 101), (6, 0, 103), (7, 0, 105), (8, 0, 107), (9, 0, 110), (10, 0, 112), (11, 0, 115), (12, 0, 116), (13, 0, 117), (13, 0, 118), (14, 0, 119), (16, 0, 120), (18, 0, 121), (19, 0, 123), (21, 0, 124), (23, 0, 125), (25, 0, 126), (27, 0, 128), (28, 0, 129), (30, 0, 131), (32, 0, 132), (34, 0, 133), (36, 0, 134), (38, 0, 135), (40, 0, 137), (42, 0, 137), (44, 0, 138), (46, 0, 139), (48, 0, 140), (50, 0, 141), (52, 0, 142), (54, 0, 142), (56, 0, 143), (57, 0, 144), (59, 0, 145), (60, 0, 146), (62, 0, 147), (63, 0, 147), (65, 0, 148), (66, 0, 149), (68, 0, 149), (69, 0, 150), (71, 0, 150), (73, 0, 150), (74, 0, 150), (76, 0, 151), (78, 0, 151), (79, 0, 151), (81, 0, 151), (82, 0, 152), (84, 0, 152), (86, 0, 152), (88, 0, 153), (90, 0, 153), (92, 0, 153), (93, 0, 154), (95, 0, 154), (97, 0, 155), (99, 0, 155), (100, 0, 155), (102, 0, 155), (104, 0, 155), (106, 0, 155), (108, 0, 156), (109, 0, 156), (111, 0, 156), (112, 0, 156), (113, 0, 157), (115, 0, 157), (117, 0, 157), (119, 0, 157), (120, 0, 157), (122, 0, 157), (124, 0, 157), (126, 0, 157), (127, 0, 157), (129, 0, 157), (131, 0, 157), (132, 0, 157), (134, 0, 157), (135, 0, 157), (137, 0, 157), (138, 0, 157), (139, 0, 157), (141, 0, 157), (143, 0, 156), (145, 0, 156), (147, 0, 156), (149, 0, 156), (150, 0, 155), (152, 0, 155),  (153, 0, 155),  (155, 0, 155),  (156, 0, 155),  (157, 0, 155),  (159, 0, 155),  (160, 0, 155),  (162, 0, 155),  (163, 0, 155),  (164, 0, 155),  (166, 0, 154),  (167, 0, 154),  (168, 0, 154),  (169, 0, 153),  (170, 0, 153),  (171, 0, 153),  (173, 0, 153),  (174, 1, 152),  (175, 1, 152),  (176, 1, 152),  (176, 1, 152),  (177, 1, 151),  (178, 1, 151),  (179, 1, 150),  (180, 2, 150),  (181, 2, 149),  (182, 2, 149),  (183, 3, 149),  (184, 3, 149),  (185, 4, 149),  (186, 4, 149),  (186, 4, 148),  (187, 5, 147),  (188, 5, 147),  (189, 5, 147),  (190, 6, 146),  (191, 6, 146),  (191, 6, 146),  (192, 7, 145),  (192, 7, 145),  (193, 8, 144),  (193, 9, 144),  (194, 10, 143),  (195, 10, 142),  (195, 11, 142),  (196, 12, 141),  (197, 12, 140),  (198, 13, 139),  (198, 14, 138),  (199, 15, 137),  (200, 16, 136),  (201, 17, 135),  (202, 18, 134),  (202, 19, 133),  (203, 19, 133),  (203, 20, 132),  (204, 21, 130),  (205, 22, 129),  (206, 23, 128),  (206, 24, 126),  (207, 24, 124),  (207, 25, 123),  (208, 26, 121),  (209, 27, 120),  (209, 28, 118),  (210, 28, 117),  (210, 29, 116),  (211, 30, 114),  (211, 32, 113),  (212, 33, 111),  (212, 34, 110),  (213, 35, 107),  (213, 36, 105),  (214, 37, 103),  (215, 38, 101),  (216, 39, 100),  (216, 40, 98),  (217, 42, 96),  (218, 43, 94),  (218, 44, 92),  (219, 46, 90),  (219, 47, 87),  (220, 47, 84),  (221, 48, 81),  (221, 49, 78),  (222, 50, 74),  (222, 51, 71),  (223, 52, 68),  (223, 53, 65),  (223, 54, 61),  (224, 55, 58),  (224, 56, 55),  (224, 57, 51),  (225, 58, 48),  (226, 59, 45),  (226, 60, 42),  (227, 61, 38),  (227, 62, 35),  (228, 63, 32),  (228, 65, 29),  (228, 66, 28),  (229, 67, 27),  (229, 68, 25),  (229, 69, 24),  (230, 70, 22),  (231, 71, 21),  (231, 72, 20),  (231, 73, 19),  (232, 74, 18),  (232, 76, 16),  (232, 76, 15),  (233, 77, 14),  (233, 77, 13),  (234, 78, 12),  (234, 79, 12),  (235, 80, 11),  (235, 81, 10),  (235, 82, 10),  (235, 83, 9),  (236, 84, 9),  (236, 86, 8),  (236, 87, 8),  (236, 88, 8),  (237, 89, 7),  (237, 90, 7),  (237, 91, 6),  (238, 92, 6),  (238, 92, 5),  (238, 93, 5),  (238, 94, 5),  (239, 95, 4),  (239, 96, 4),  (239, 97, 4),  (239, 98, 4),  (240, 99, 3),  (240, 100, 3),  (240, 101, 3),  (241, 102, 3),  (241, 102, 3),  (241, 103, 3),  (241, 104, 3),  (241, 105, 2),  (241, 106, 2),  (241, 107, 2),  (241, 107, 2),  (242, 108, 1),  (242, 109, 1),  (242, 110, 1),  (243, 111, 1),  (243, 112, 1),  (243, 113, 1),  (243, 114, 1),  (244, 115, 0),  (244, 116, 0),  (244, 117, 0),  (244, 118, 0),  (244, 119, 0),  (244, 120, 0),  (244, 122, 0),  (245, 123, 0),  (245, 124, 0),  (245, 126, 0),  (245, 127, 0),  (246, 128, 0),  (246, 129, 0),  (246, 130, 0),  (247, 131, 0),  (247, 132, 0),  (247, 133, 0),  (247, 134, 0),  (248, 135, 0),  (248, 136, 0),  (248, 136, 0),  (248, 137, 0),  (248, 138, 0),  (248, 139, 0),  (248, 140, 0),  (249, 141, 0),  (249, 141, 0),  (249, 142, 0),  (249, 143, 0),  (249, 144, 0),  (249, 145, 0),  (249, 146, 0),  (249, 147, 0),  (250, 148, 0),  (250, 149, 0),  (250, 150, 0),  (251, 152, 0),  (251, 153, 0),  (251, 154, 0),  (251, 156, 0),  (252, 157, 0),  (252, 159, 0),  (252, 160, 0),  (252, 161, 0),  (253, 162, 0),  (253, 163, 0),  (253, 164, 0),  (253, 166, 0),  (253, 167, 0),  (253, 168, 0),  (253, 170, 0),  (253, 171, 0),  (253, 172, 0),  (253, 173, 0),  (253, 174, 0),  (254, 175, 0),  (254, 176, 0),  (254, 177, 0),  (254, 178, 0),  (254, 179, 0),  (254, 180, 0),  (254, 181, 0),  (254, 182, 0),  (254, 184, 0),  (254, 185, 0),  (254, 185, 0),  (254, 186, 0),  (254, 187, 0),  (254, 188, 0),  (254, 189, 0),  (254, 190, 0),  (254, 192, 0),  (254, 193, 0),  (254, 194, 0),  (254, 195, 0),  (254, 196, 0),  (254, 197, 0),  (254, 198, 0),  (254, 199, 0),  (254, 200, 0),  (254, 201, 1),  (254, 202, 1),  (254, 202, 1),  (254, 203, 1),  (254, 204, 2),  (254, 205, 2),  (254, 206, 3),  (254, 207, 4),  (254, 207, 4),  (254, 208, 5),  (254, 209, 6),  (254, 211, 8),  (254, 212, 9),  (254, 213, 10),  (254, 214, 10),  (254, 215, 11),  (254, 216, 12),  (254, 217, 13),  (255, 218, 14),  (255, 218, 14),  (255, 219, 16),  (255, 220, 18),  (255, 220, 20),  (255, 221, 22),  (255, 222, 25),  (255, 222, 27),  (255, 223, 30),  (255, 224, 32),  (255, 225, 34),  (255, 226, 36),  (255, 226, 38),  (255, 227, 40),  (255, 228, 43),  (255, 228, 46),  (255, 229, 49),  (255, 230, 53),  (255, 230, 56),  (255, 231, 60),  (255, 232, 63),  (255, 233, 67),  (255, 234, 70),  (255, 235, 73),  (255, 235, 77),  (255, 236, 80),  (255, 237, 84),  (255, 238, 87),  (255, 238, 91),  (255, 238, 95),  (255, 239, 99),  (255, 239, 103),  (255, 240, 106),  (255, 240, 110),  (255, 241, 114),  (255, 241, 119),  (255, 241, 123),  (255, 242, 128),  (255, 242, 133),  (255, 242, 138),  (255, 243, 142),  (255, 244, 146),  (255, 244, 150),  (255, 244, 154),  (255, 245, 158),  (255, 245, 162),  (255, 245, 166),  (255, 246, 170),  (255, 246, 175),  (255, 247, 179),  (255, 247, 182),  (255, 248, 186),  (255, 248, 189),  (255, 248, 193),  (255, 248, 196),  (255, 249, 199),  (255, 249, 202),  (255, 249, 205),  (255, 250, 209),  (255, 250, 212),  (255, 251, 216),  (255, 252, 219),  (255, 252, 223),  (255, 253, 226),  (255, 253, 229),  (255, 253, 232),  (255, 254, 235),  (255, 254, 238),  (255, 254, 241),  (255, 254, 244),  (255, 255, 246))    
 LEDs_on_head = 4  
 LED_interval = 60  
 shift_on_head = 30   
 head_angle = 30  
 distance_to_head = 200  
 #user_FOV_width  
 #user_FOV_height  
 #45 degree -> 0  
 #22.5 degree -> 400  
 #0 degree -> 2000  
 LED_FOV_dy = int(round(distance_to_head * math.tan(math.radians(45)) * 1.25))  
 LED_FOV_dx1 = int(round(distance_to_head * math.cos(math.radians(head_angle)) * math.tan(math.radians(45 + head_angle)) - distance_to_head * math.sin(math.radians(head_angle))))  
 LED_FOV_dx2 = int(round(distance_to_head * math.sin(math.radians(head_angle)) - distance_to_head * math.cos(math.radians(head_angle)) * math.tan(math.radians(head_angle - 45))))  
 LED_FOV_xcenter = LED_FOV_dx1  
 LED_FOV_ycenter = LED_FOV_dy  
 LED_FOV_width = LED_FOV_dx1 + LED_FOV_dx2  
 LED_FOV_height = 2 * LED_FOV_dy  
 print LED_FOV_width  
 print LED_FOV_height  
 def py_ang(v1, v2):  
   """ Returns the angle in radians between vectors 'v1' and 'v2'  """  
   cosang = numpy.dot(v1, v2)  
   sinang = numpy.linalg.norm(numpy.cross(v1, v2))  
   return numpy.arctan2(sinang, cosang)  
 LED_FOV_map = numpy.zeros((LED_FOV_height, LED_FOV_width))  
 v1 = numpy.array([-distance_to_head * math.sin(math.radians(head_angle)), 0, -distance_to_head * math.cos(math.radians(head_angle))])  
 for y in range(LED_FOV_height):  
   for x in range(LED_FOV_width):  
     dv = numpy.array([x - LED_FOV_xcenter, y - LED_FOV_ycenter, 0])  
     v2 = v1 + dv  
     ang = abs(math.degrees(py_ang(v1, v2)))  
     if ang > 45.0:  
       intensity = 0  
     elif ang > 22.5:  
       intensity = -400.0 / (45.0 - 22.5) * (ang - 45.0)  
     elif ang > 11.2:  
       intensity = (400.0 - 1600.0) / (22.5 - 11.2) * (ang - 22.5) + 400.0  
     else:  
       intensity = (1600.0 - 2000.0) / (11.2 - 0) * (ang - 11.2) + 1600.0  
     LED_FOV_map[y][x] = intensity * numpy.power(numpy.dot(v1, v2), 2) / numpy.power(numpy.linalg.norm(v2), 4)  
 head_FOV_width = 2 * max(LED_FOV_dx1, LED_FOV_dx2)  
 head_FOV_height = LED_FOV_height + (LEDs_on_head - 1) * LED_interval + shift_on_head  
 head_FOV_map = numpy.zeros((head_FOV_height, head_FOV_width))  
 print head_FOV_width  
 print head_FOV_height  
 for y in range(LED_FOV_height):  
   for x in range(LED_FOV_width):  
     for i in range(LEDs_on_head):  
       head_FOV_map[y + i * LED_interval][x] += LED_FOV_map[y][x]  
       head_FOV_map[y + i * LED_interval + shift_on_head][(head_FOV_width -1) - x] += LED_FOV_map[y][x]  
 # 380 nm to 780 nm -> RGB  
 def wave2rgb(wavelength):  
   GAMMA = 1.0  
   # ITYPE=1 - PLAIN SPECTUM  
   # ITYPE=2 - MARK SPECTRUM AT 100 nm INTEVALS  
   # ITYPE=3 - HYDROGEN BALMER EMISSION SPECTRA  
   # ITYPE=4 - HYDROGEN BALMER ABSORPTION SPECTRA  
   ITYPE = 1  
   if wavelength < 440:  
     r = -1.0 * (wavelength - 440.0) / (440.0 - 380.0)  
     g = 0  
     b = 1  
   elif wavelength < 490.0:  
     r = 0.0  
     g = (wavelength - 440.0) / (490.0 - 440.0)  
     b = 1.0  
   elif wavelength < 510.0:  
     r = 0.0  
     g = 1.0  
     b = -1.0 * (wavelength - 510.0) / (510.0 - 490.0)  
   elif wavelength < 580:  
     r = (wavelength - 510.0) / (580.0 - 510.0)  
     g = 1.0  
     b = 0.0  
   elif wavelength < 645:  
     r = 1.0  
     g = -1.0 * (wavelength - 645.0) / (645.0 - 580.0)  
     b = 0.0  
   else:  
     r = 1.0  
     g = 0.0  
     b = 0.0  
   if wavelength > 700.0:  
     sss = 0.3 + 0.7 * (780.0 - wavelength) / (780.0 - 700.0)  
   elif wavelength < 420.0:  
     sss = 0.3 + 0.7 * (wavelength - 380.0) / (420.0 - 380.0)  
   else:  
     sss = 1.0  
   # Gamma adjust and write image to an array  
   r = int(255.0 * math.pow(sss * r, GAMMA))  
   g = int(255.0 * math.pow(sss * g, GAMMA))  
   b = int(255.0 * math.pow(sss * b, GAMMA))  
   if ITYPE == 2:  
     if abs(wavelength - 400) < 1 or abs(wavelength - 500) < 1 or abs(wavelength - 600) < 1 or abs(wavelength - 700) < 1:  
       r = 255  
       g = 255  
       b = 255  
   elif ITYPE == 3:  
     if abs(wavelength-656.0) > 1.0 and abs(wavelength-486.0) > 1.0 and abs(wavelength-433.0) > 1.0 and abs(wavelength-410.0) > 1.0 and abs(wavelength-396.0) > 1.0:  
       r = 0  
       g = 0  
       b = 0  
   elif ITYPE == 4:  
     if abs(wavelength-656.0) < 1.1 or abs(wavelength-486.0) < 1.1 or abs(wavelength-433.0) < 1.1 or abs(wavelength-410.0) < 1.1 or abs(wavelength-396.0) < 1.1:  
       r = 0  
       g = 0  
       b = 0  
   return (r, g, b)  
 minvalue = maxvalue = head_FOV_map[0][0]  
 for i in range(head_FOV_height):  
   for j in range(head_FOV_width):  
     if head_FOV_map[i][j] > maxvalue:  
       maxvalue = head_FOV_map[i][j]  
     elif head_FOV_map[i][j] < minvalue:  
       minvalue = head_FOV_map[i][j]  
 print minvalue  
 print maxvalue  
 print "profile"  
 for i in range(head_FOV_height):  
   print head_FOV_map[i][head_FOV_width / 2]  
 img = Image.new('RGB', (head_FOV_width, head_FOV_height), "black")  
 #img = Image.new('L', (head_FOV_width, head_FOV_height))  
 pixels = img.load()  
 for i in range(img.size[1]):  
   for j in range(img.size[0]):  
     #pixels[j, i] = wave2rgb(head_FOV_map[i][j] / 8000.0 * 400.0 + 380.0)  
     pixels[j, i] = palette[int(round((head_FOV_map[i][j] - minvalue) / (maxvalue - minvalue) * (len(palette) - 1)))]  
     #pixels[j, i] = int(round((head_FOV_map[i][j] - minvalue) / (maxvalue - minvalue) * 255.0))  
 img.show()  

결과물


 FOV_simulation_assign_60mm_30mm



 FOV_simulation_assign_90mm_45mm


 시각적 변화를 위한 몇 가지 프로파일들


Yellow gradient

 palette=((0, 0, 0), (53, 2, 0), (53, 2, 0), (53, 3, 0), (53, 3, 0), (53, 4, 0), (52, 4, 0), (52, 5, 0), (52, 6, 0), (52, 6, 0), (51, 7, 0), (51, 8, 0), (51, 9, 0), (51, 9, 0), (51, 10, 0), (51, 10, 0), (51, 11, 0), (51, 11, 0), (51, 12, 0), (51, 12, 0), (51, 13, 0), (50, 14, 0), (50, 14, 0), (50, 15, 0), (50, 15, 0), (50, 16, 0), (50, 16, 0), (50, 17, 0), (50, 17, 0), (50, 18, 0), (50, 18, 0), (50, 19, 0), (50, 20, 0), (50, 20, 0), (50, 21, 0), (51, 21, 0), (51, 22, 0), (51, 22, 0), (51, 23, 0), (51, 24, 0), (51, 25, 0), (51, 25, 0), (52, 26, 0), (52, 27, 0), (52, 27, 0), (52, 28, 0), (52, 28, 0), (52, 29, 0), (52, 29, 0), (52, 30, 0), (53, 30, 0), (53, 31, 0), (53, 32, 0), (54, 32, 0), (54, 33, 0), (54, 33, 0), (54, 34, 0), (55, 34, 0), (55, 35, 0), (55, 35, 0), (55, 36, 0), (56, 36, 0), (56, 37, 0), (56, 38, 0), (57, 39, 0), (57, 39, 0), (57, 40, 0), (58, 41, 0), (58, 41, 0), (59, 42, 0), (59, 42, 0), (59, 43, 0), (60, 43, 0), (60, 44, 0), (61, 45, 0), (61, 45, 0), (62, 46, 0), (62, 46, 0), (63, 47, 0), (63, 47, 0), (64, 48, 0), (64, 48, 0), (64, 49, 0), (65, 50, 0), (65, 50, 0), (66, 51, 0), (66, 51, 0), (67, 52, 0), (67, 52, 0), (68, 53, 0), (69, 53, 0), (70, 54, 0), (71, 55, 0), (72, 56, 0), (72, 56, 0), (73, 57, 0), (74, 58, 0), (74, 58, 0), (75, 59, 0), (75, 59, 0), (76, 60, 0), (77, 60, 0), (78, 61, 0), (78, 61, 0), (79, 62, 0), (80, 63, 0), (80, 63, 0), (81, 64, 0), (82, 64, 0), (83, 65, 0), (84, 65, 0), (84, 66, 0), (85, 66, 0), (86, 67, 0), (87, 68, 0), (88, 68, 0), (88, 69, 0), (89, 69, 0), (90, 70, 0), (92, 71, 0), (93, 72, 0), (94, 72, 0), (94, 73, 0), (95, 73, 0), (96, 74, 0), (97, 75, 0), (98, 75, 0), (98, 76, 0), (99, 76, 0), (101, 77, 0), (102, 77, 0), (103, 78, 0), (104, 78, 0), (104, 79, 0), (105, 79, 0), (106, 80, 0), (107, 81, 0), (108, 81, 0), (109, 82, 0), (110, 82, 0), (111, 83, 0), (112, 83, 0), (114, 84, 0), (115, 84, 0), (115, 85, 0), (116, 86, 0), (117, 86, 0), (118, 87, 0), (119, 88, 0), (120, 89, 0), (122, 89, 0), (123, 90, 0), (124, 90, 0), (125, 91, 0), (126, 91, 0), (127, 92, 0), (128, 93, 0), (129, 93, 0), (130, 94, 0), (131, 94, 0), (133, 95, 0), (134, 95, 0), (135, 96, 0), (136, 96, 0), (137, 97, 0), (138, 98, 0), (139, 98, 0), (140, 99, 0), (141, 99, 0), (142, 100, 0), (143, 100, 0), (145, 101, 0), (146, 102, 0), (147, 102, 0), (148, 103, 0), (149, 104, 0), (150, 105, 0), (151, 105, 0), (152, 106, 0), (153, 106, 0), (155, 107, 0), (156, 107, 0), (158, 108, 0), (159, 108, 0), (160, 109, 0), (161, 109, 0), (162, 110, 0), (163, 111, 0), (164, 111, 0), (164, 112, 0), (165, 112, 0), (167, 113, 0), (168, 113, 0), (169, 114, 0), (170, 114, 0), (171, 115, 0), (173, 116, 0), (174, 116, 0), (175, 117, 0), (176, 117, 0), (177, 118, 0), (178, 118, 0), (179, 119, 0), (180, 120, 0), (181, 121, 0), (182, 121, 0), (183, 122, 0), (184, 123, 0), (185, 123, 0), (186, 124, 0), (187, 124, 0), (188, 125, 0), (190, 125, 0), (191, 126, 0), (192, 126, 0), (193, 127, 0), (194, 127, 0), (195, 128, 0), (195, 129, 0), (196, 129, 0), (197, 130, 0), (198, 130, 0), (200, 131, 0), (201, 131, 0), (202, 132, 0), (203, 132, 0), (204, 133, 0), (205, 134, 0), (206, 135, 0), (206, 135, 0), (207, 136, 0), (208, 137, 0), (209, 137, 0), (210, 138, 0), (211, 138, 0), (212, 139, 0), (213, 139, 0), (214, 140, 0), (215, 141, 0), (216, 141, 0), (216, 142, 0), (217, 142, 0), (218, 143, 0), (219, 143, 0), (220, 144, 0), (221, 144, 0), (221, 145, 0), (222, 145, 0), (223, 146, 0), (224, 147, 0), (224, 147, 0), (225, 148, 0), (225, 148, 0), (226, 149, 0), (227, 149, 0), (228, 150, 0), (229, 151, 0), (229, 151, 0), (230, 152, 0), (231, 153, 0), (232, 154, 0), (232, 154, 0), (233, 155, 0), (233, 155, 0), (234, 156, 0), (235, 156, 0), (236, 157, 0), (236, 157, 0), (237, 158, 0), (238, 159, 0), (238, 159, 0), (239, 160, 0), (239, 160, 0), (240, 161, 0), (240, 161, 0), (240, 162, 0), (241, 162, 0), (241, 163, 0), (241, 163, 0), (242, 164, 0), (243, 165, 0), (243, 165, 0), (244, 166, 0), (244, 167, 0), (245, 168, 0), (245, 168, 0), (246, 169, 0), (246, 169, 0), (247, 170, 0), (247, 171, 0), (248, 171, 0), (248, 172, 0), (248, 172, 0), (248, 173, 0), (249, 173, 0), (249, 174, 0), (249, 174, 0), (249, 175, 0), (250, 175, 0), (250, 176, 0), (250, 177, 0), (251, 177, 0), (251, 178, 0), (251, 178, 0), (251, 179, 0), (252, 179, 0), (252, 180, 0), (252, 180, 0), (252, 181, 0), (252, 181, 0), (252, 182, 0), (252, 183, 0), (253, 184, 0), (253, 184, 0), (253, 185, 0), (253, 186, 0), (253, 186, 0), (253, 187, 0), (253, 187, 0), (253, 188, 0), (254, 189, 0), (254, 189, 0), (254, 190, 0), (254, 190, 0), (254, 191, 0), (254, 191, 0), (254, 192, 0), (254, 192, 0), (254, 193, 0), (254, 193, 0), (254, 194, 0), (254, 195, 0), (254, 195, 0), (254, 196, 0), (254, 196, 0), (254, 197, 0), (254, 197, 0), (254, 198, 0), (253, 199, 0), (253, 200, 0), (253, 200, 0), (253, 201, 0), (253, 202, 0), (253, 202, 0), (253, 203, 0), (252, 203, 0), (252, 204, 0), (252, 204, 0), (252, 205, 0), (252, 205, 0), (252, 206, 0), (252, 207, 0), (251, 207, 0), (251, 208, 0), (251, 208, 0), (251, 209, 0), (250, 209, 0), (250, 210, 0), (250, 210, 0), (250, 211, 0), (250, 211, 0), (250, 212, 0), (250, 213, 0), (249, 213, 0), (249, 214, 0), (249, 214, 0), (249, 215, 0), (248, 216, 0), (248, 217, 0), (248, 217, 0), (248, 218, 0), (247, 218, 0), (247, 219, 0), (247, 220, 0), (246, 220, 0), (246, 221, 0), (246, 221, 0), (246, 222, 0), (245, 222, 0), (245, 223, 0), (245, 223, 0), (245, 224, 0), (244, 225, 0), (244, 225, 0), (244, 226, 0), (243, 226, 0), (243, 227, 0), (243, 227, 0), (242, 228, 0), (242, 228, 0), (241, 229, 0), (241, 230, 0), (241, 230, 0), (240, 231, 0), (240, 232, 0), (240, 233, 0), (239, 233, 0), (239, 234, 0), (239, 234, 0), (239, 235, 0), (238, 235, 0), (238, 236, 0), (238, 236, 0), (237, 237, 0), (237, 238, 0), (237, 238, 0), (237, 239, 0), (236, 239, 0), (236, 240, 0), (236, 240, 0), (235, 241, 0), (235, 241, 0), (234, 242, 0), (234, 243, 0), (233, 243, 0), (233, 244, 0), (233, 244, 0), (233, 245, 0), (232, 245, 0), (232, 246, 0), (232, 247, 0), (232, 247, 0), (231, 248, 0), (231, 249, 0), (231, 250, 0), (230, 250, 0), (230, 251, 0), (230, 251, 0), (230, 252, 0), (229, 252, 0), (229, 253, 0), (229, 253, 0), (229, 254, 0), (229, 254, 0)) 


Glowbow gradient


 palette =((0, 0, 0), (2, 0, 0), (4, 1, 1), (6, 1, 1), (8, 1, 1), (10, 1, 2), (12, 2, 2), (13, 2, 3), (15, 2, 3), (17, 2, 3), (19, 2, 4), (21, 2, 4), (23, 2, 4), (24, 3, 5), (26, 3, 5), (28, 3, 5), (30, 3, 6), (32, 4, 6), (34, 4, 7), (35, 4, 7), (37, 4, 7), (39, 5, 8), (41, 5, 8), (43, 5, 8), (45, 5, 9), (47, 5, 9), (49, 5, 9), (51, 5, 9), (53, 6, 10), (55, 6, 10), (57, 6, 10), (59, 7, 11), (60, 7, 12), (62, 7, 12), (64, 7, 12), (66, 8, 13), (67, 8, 13), (69, 8, 13), (71, 8, 13), (73, 8, 14), (75, 8, 14), (77, 8, 14), (79, 9, 15), (81, 9, 16), (83, 9, 16), (85, 9, 16), (88, 10, 17), (91, 10, 17), (94, 10, 17), (97, 11, 18), (100, 11, 19), (103, 12, 20), (105, 12, 20), (106, 12, 21), (108, 12, 21), (110, 12, 21), (112, 12, 21), (113, 13, 22), (115, 13, 22), (117, 13, 22), (119, 13, 22), (121, 14, 23), (123, 14, 23), (125, 14, 24), (127, 15, 24), (129, 15, 25), (131, 15, 25), (133, 15, 25), (135, 15, 26), (136, 15, 26), (138, 15, 26), (140, 15, 26), (142, 16, 27), (144, 16, 27), (146, 16, 28), (147, 17, 28), (149, 17, 29), (151, 17, 29), (153, 17, 29), (155, 18, 30), (157, 18, 30), (159, 18, 30), (160, 18, 30), (162, 18, 31), (164, 18, 31), (166, 18, 32), (168, 19, 32), (170, 19, 33), (172, 19, 33), (174, 19, 33), (176, 20, 34), (178, 20, 34), (180, 20, 34), (182, 21, 35), (183, 21, 35), (185, 21, 35), (187, 21, 35), (189, 21, 36), (190, 21, 36), (192, 21, 36), (194, 21, 37), (196, 22, 37), (198, 22, 38), (200, 22, 38), (202, 23, 39), (204, 23, 39), (205, 23, 39), (206, 24, 39), (206, 24, 38), (207, 25, 38), (207, 26, 38), (207, 26, 37), (208, 27, 37), (208, 28, 36), (209, 29, 36), (209, 29, 35), (210, 30, 35), (210, 30, 35), (211, 31, 35), (211, 31, 34), (212, 32, 34), (212, 33, 34), (212, 33, 33), (213, 34, 33), (213, 35, 32), (214, 36, 32), (214, 36, 31), (215, 37, 31), (215, 37, 31), (216, 38, 31), (216, 38, 30), (217, 39, 30), (217, 39, 30), (217, 40, 30), (218, 40, 29), (218, 41, 29), (219, 42, 28), (219, 43, 28), (220, 44, 27), (220, 44, 27), (221, 45, 27), (221, 45, 26), (222, 46, 26), (222, 46, 26), (222, 47, 26), (223, 48, 25), (223, 48, 25), (224, 49, 24), (224, 50, 24), (225, 51, 23), (225, 51, 23), (226, 52, 23), (226, 52, 22), (227, 53, 22), (227, 53, 22), (228, 54, 21), (228, 55, 21), (228, 55, 21), (229, 56, 21), (229, 57, 20), (230, 58, 20), (230, 58, 20), (231, 59, 19), (231, 59, 19), (232, 60, 18), (232, 61, 18), (233, 61, 17), (233, 62, 17), (233, 62, 17), (234, 63, 17), (234, 63, 16), (235, 64, 16), (235, 65, 16), (236, 65, 15), (236, 66, 15), (237, 67, 14), (237, 68, 14), (238, 68, 13), (238, 69, 13), (238, 69, 13), (239, 70, 13), (239, 70, 12), (240, 71, 12), (240, 72, 12), (241, 72, 11), (241, 73, 11), (242, 74, 10), (242, 75, 10), (243, 75, 9), (243, 76, 9), (243, 76, 9), (244, 77, 9), (244, 77, 8), (245, 78, 8), (245, 78, 8), (246, 79, 8), (247, 80, 7), (247, 80, 7), (247, 81, 6), (248, 82, 6), (248, 83, 5), (248, 83, 5), (249, 84, 5), (249, 84, 4), (250, 85, 4), (250, 85, 4), (251, 86, 4), (252, 87, 3), (252, 87, 3), (252, 88, 2), (253, 89, 2), (253, 90, 1), (253, 90, 1), (254, 91, 1), (254, 91, 0), (255, 92, 0), (255, 93, 0), (255, 94, 0), (255, 95, 0), (255, 96, 0), (255, 97, 0), (255, 98, 0), (255, 100, 0), (255, 101, 0), (255, 102, 0), (255, 103, 0), (255, 105, 0), (255, 106, 0), (255, 107, 0), (255, 108, 0), (255, 109, 0), (255, 110, 0), (255, 111, 0), (255, 113, 0), (255, 114, 0), (255, 115, 0), (255, 116, 0), (255, 117, 0), (255, 118, 0), (255, 119, 0), (255, 120, 0), (255, 121, 0), (255, 123, 0), (255, 124, 0), (255, 126, 0), (255, 127, 0), (255, 128, 0), (255, 129, 0), (255, 130, 0), (255, 131, 0), (255, 132, 0), (255, 133, 0), (255, 134, 0), (255, 136, 0), (255, 137, 0), (255, 138, 0), (255, 139, 0), (255, 140, 0), (255, 141, 0), (255, 142, 0), (255, 143, 0), (255, 145, 0), (255, 146, 0), (255, 147, 0), (255, 149, 0), (255, 150, 0), (255, 151, 0), (255, 152, 0), (255, 153, 0), (255, 154, 0), (255, 155, 0), (255, 156, 0), (255, 157, 0), (255, 158, 0), (255, 160, 0), (255, 161, 0), (255, 162, 0), (255, 163, 0), (255, 164, 0), (255, 166, 0), (255, 167, 0), (255, 168, 0), (255, 169, 0), (255, 170, 0), (255, 172, 0), (255, 173, 0), (255, 174, 0), (255, 175, 0), (255, 176, 0), (255, 177, 0), (255, 178, 0), (255, 179, 0), (255, 180, 0), (255, 181, 0), (255, 182, 0), (255, 184, 0), (255, 185, 0), (255, 186, 0), (255, 188, 0), (255, 189, 0), (255, 190, 0), (255, 191, 0), (255, 192, 0), (255, 193, 0), (255, 194, 0), (255, 196, 0), (255, 197, 0), (255, 198, 0), (255, 199, 0), (255, 200, 0), (255, 201, 0), (255, 202, 0), (255, 203, 0), (255, 204, 0), (255, 206, 0), (255, 207, 0), (255, 208, 0), (255, 210, 0), (255, 211, 0), (255, 212, 0), (255, 213, 0), (255, 214, 0), (255, 215, 0), (255, 216, 0), (255, 217, 0), (255, 218, 1), (255, 218, 3), (255, 219, 5), (255, 219, 8), (255, 219, 10), (255, 219, 12), (255, 220, 15), (255, 220, 17), (255, 221, 20), (255, 221, 22), (255, 222, 24), (255, 222, 26), (255, 222, 29), (255, 223, 31), (255, 223, 34), (255, 223, 36), (255, 224, 38), (255, 224, 40), (255, 224, 43), (255, 224, 45), (255, 225, 47), (255, 225, 50), (255, 225, 52), (255, 226, 55), (255, 226, 57), (255, 227, 60), (255, 227, 62), (255, 228, 64), (255, 228, 66), (255, 228, 69), (255, 228, 71), (255, 229, 73), (255, 229, 75), (255, 229, 78), (255, 229, 80), (255, 230, 82), (255, 230, 85), (255, 231, 87), (255, 231, 90), (255, 232, 92), (255, 232, 95), (255, 232, 97), (255, 233, 99), (255, 233, 101), (255, 233, 104), (255, 233, 106), (255, 234, 109), (255, 234, 111), (255, 234, 113), (255, 235, 115), (255, 235, 118), (255, 235, 120), (255, 236, 122), (255, 236, 125), (255, 237, 127), (255, 237, 130), (255, 237, 132), (255, 238, 134), (255, 238, 136), (255, 238, 138), (255, 239, 141), (255, 239, 143), (255, 239, 145), (255, 239, 148), (255, 240, 150), (255, 240, 153), (255, 240, 155), (255, 240, 157), (255, 241, 159), (255, 241, 161), (255, 242, 164), (255, 242, 166), (255, 243, 169), (255, 243, 171), (255, 243, 174), (255, 244, 176), (255, 244, 179), (255, 244, 181), (255, 245, 183), (255, 245, 185), (255, 245, 187), (255, 245, 190), (255, 246, 192), (255, 246, 194), (255, 246, 196), (255, 247, 199), (255, 247, 201), (255, 248, 204), (255, 248, 206), (255, 249, 209), (255, 249, 211), (255, 249, 214), (255, 249, 216), (255, 250, 218), (255, 250, 220), (255, 250, 223), (255, 250, 225), (255, 251, 228), (255, 251, 230), (255, 252, 232), (255, 252, 234), (255, 253, 237), (255, 253, 239), (255, 253, 241), (255, 254, 244), (255, 254, 246), (255, 254, 249), (255, 254, 251), (255, 255, 253)) 


gray gradient


 palette=((1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (4, 4, 4), (4, 4, 4), (5, 5, 5), (5, 5, 5), (6, 6, 6), (7, 7, 7), (8, 8, 8), (9, 9, 9), (9, 9, 9), (10, 10, 10), (10, 10, 10), (11, 11, 11), (11, 11, 11), (12, 12, 12), (13, 13, 13), (13, 13, 13), (14, 14, 14), (14, 14, 14), (15, 15, 15), (15, 15, 15), (16, 16, 16), (16, 16, 16), (17, 17, 17), (17, 17, 17), (18, 18, 18), (19, 19, 19), (19, 19, 19), (20, 20, 20), (21, 21, 21), (22, 22, 22), (22, 22, 22), (23, 23, 23), (23, 23, 23), (24, 24, 24), (24, 24, 24), (25, 25, 25), (26, 26, 26), (26, 26, 26), (27, 27, 27), (27, 27, 27), (28, 28, 28), (28, 28, 28), (29, 29, 29), (29, 29, 29), (30, 30, 30), (31, 31, 31), (31, 31, 31), (32, 32, 32), (32, 32, 32), (33, 33, 33), (33, 33, 33), (34, 34, 34), (35, 35, 35), (35, 35, 35), (36, 36, 36), (37, 37, 37), (38, 38, 38), (38, 38, 38), (39, 39, 39), (39, 39, 39), (40, 40, 40), (40, 40, 40), (41, 41, 41), (41, 41, 41), (42, 42, 42), (42, 42, 42), (43, 43, 43), (44, 44, 44), (44, 44, 44), (45, 45, 45), (45, 45, 45), (46, 46, 46), (46, 46, 46), (47, 47, 47), (47, 47, 47), (48, 48, 48), (49, 49, 49), (49, 49, 49), (50, 50, 50), (51, 51, 51), (52, 52, 52), (52, 52, 52), (53, 53, 53), (53, 53, 53), (54, 54, 54), (54, 54, 54), (55, 55, 55), (56, 56, 56), (56, 56, 56), (57, 57, 57), (57, 57, 57), (58, 58, 58), (58, 58, 58), (59, 59, 59), (59, 59, 59), (60, 60, 60), (60, 60, 60), (61, 61, 61), (62, 62, 62), (62, 62, 62), (63, 63, 63), (64, 64, 64), (65, 65, 65), (65, 65, 65), (66, 66, 66), (66, 66, 66), (67, 67, 67), (68, 68, 68), (68, 68, 68), (69, 69, 69), (69, 69, 69), (70, 70, 70), (70, 70, 70), (71, 71, 71), (71, 71, 71), (72, 72, 72), (72, 72, 72), (73, 73, 73), (74, 74, 74), (74, 74, 74), (75, 75, 75), (75, 75, 75), (76, 76, 76), (76, 76, 76), (77, 77, 77), (78, 78, 78), (78, 78, 78), (79, 79, 79), (80, 80, 80), (81, 81, 81), (81, 81, 81), (82, 82, 82), (82, 82, 82), (83, 83, 83), (83, 83, 83), (84, 84, 84), (84, 84, 84), (85, 85, 85), (86, 86, 86), (86, 86, 86), (87, 87, 87), (87, 87, 87), (88, 88, 88), (88, 88, 88), (89, 89, 89), (89, 89, 89), (90, 90, 90), (91, 91, 91), (92, 92, 92), (92, 92, 92), (93, 93, 93), (94, 94, 94), (94, 94, 94), (95, 95, 95), (95, 95, 95), (96, 96, 96), (96, 96, 96), (97, 97, 97), (98, 98, 98), (98, 98, 98), (99, 99, 99), (99, 99, 99), (100, 100, 100), (100, 100, 100), (101, 101, 101), (101, 101, 101), (102, 102, 102), (102, 102, 102), (103, 103, 103), (104, 104, 104), (104, 104, 104), (105, 105, 105), (105, 105, 105), (106, 106, 106), (107, 107, 107), (108, 108, 108), (108, 108, 108), (109, 109, 109), (109, 109, 109), (110, 110, 110), (111, 111, 111), (111, 111, 111), (112, 112, 112), (112, 112, 112), (113, 113, 113), (113, 113, 113), (114, 114, 114), (114, 114, 114), (115, 115, 115), (116, 116, 116), (116, 116, 116), (117, 117, 117), (117, 117, 117), (118, 118, 118), (118, 118, 118), (119, 119, 119), (119, 119, 119), (120, 120, 120), (121, 121, 121), (121, 121, 121), (122, 122, 122), (123, 123, 123), (124, 124, 124), (124, 124, 124), (125, 125, 125), (125, 125, 125), (126, 126, 126), (126, 126, 126), (127, 127, 127), (127, 127, 127), (128, 128, 128), (129, 129, 129), (129, 129, 129), (130, 130, 130), (130, 130, 130), (131, 131, 131), (131, 131, 131), (132, 132, 132), (132, 132, 132), (133, 133, 133), (134, 134, 134), (135, 135, 135), (135, 135, 135), (136, 136, 136), (137, 137, 137), (137, 137, 137), (138, 138, 138), (138, 138, 138), (139, 139, 139), (139, 139, 139), (140, 140, 140), (141, 141, 141), (141, 141, 141), (142, 142, 142), (142, 142, 142), (143, 143, 143), (143, 143, 143), (144, 144, 144), (144, 144, 144), (145, 145, 145), (145, 145, 145), (146, 146, 146), (147, 147, 147), (147, 147, 147), (148, 148, 148), (148, 148, 148), (149, 149, 149), (150, 150, 150), (151, 151, 151), (151, 151, 151), (152, 152, 152), (153, 153, 153), (153, 153, 153), (154, 154, 154), (154, 154, 154), (155, 155, 155), (155, 155, 155), (156, 156, 156), (156, 156, 156), (157, 157, 157), (157, 157, 157), (158, 158, 158), (159, 159, 159), (159, 159, 159), (160, 160, 160), (160, 160, 160), (161, 161, 161), (161, 161, 161), (162, 162, 162), (162, 162, 162), (163, 163, 163), (164, 164, 164), (165, 165, 165), (165, 165, 165), (166, 166, 166), (167, 167, 167), (167, 167, 167), (168, 168, 168), (168, 168, 168), (169, 169, 169), (169, 169, 169), (170, 170, 170), (171, 171, 171), (171, 171, 171), (172, 172, 172), (172, 172, 172), (173, 173, 173), (173, 173, 173), (174, 174, 174), (174, 174, 174), (175, 175, 175), (175, 175, 175), (176, 176, 176), (177, 177, 177), (178, 178, 178), (178, 178, 178), (179, 179, 179), (180, 180, 180), (180, 180, 180), (181, 181, 181), (181, 181, 181), (182, 182, 182), (182, 182, 182), (183, 183, 183), (184, 184, 184), (184, 184, 184), (185, 185, 185), (185, 185, 185), (186, 186, 186), (186, 186, 186), (187, 187, 187), (187, 187, 187), (188, 188, 188), (189, 189, 189), (189, 189, 189), (190, 190, 190), (190, 190, 190), (191, 191, 191), (191, 191, 191), (192, 192, 192), (193, 193, 193), (194, 194, 194), (194, 194, 194), (195, 195, 195), (196, 196, 196), (196, 196, 196), (197, 197, 197), (197, 197, 197), (198, 198, 198), (198, 198, 198), (199, 199, 199), (199, 199, 199), (200, 200, 200), (200, 200, 200), (201, 201, 201), (202, 202, 202), (202, 202, 202), (203, 203, 203), (203, 203, 203), (204, 204, 204), (204, 204, 204), (205, 205, 205), (206, 206, 206), (207, 207, 207), (208, 208, 208), (208, 208, 208), (209, 209, 209), (209, 209, 209), (210, 210, 210), (210, 210, 210), (211, 211, 211), (211, 211, 211), (212, 212, 212), (212, 212, 212), (213, 213, 213), (214, 214, 214), (214, 214, 214), (215, 215, 215), (215, 215, 215), (216, 216, 216), (216, 216, 216), (217, 217, 217), (217, 217, 217), (218, 218, 218), (218, 218, 218), (219, 219, 219), (220, 220, 220), (221, 221, 221), (221, 221, 221), (222, 222, 222), (223, 223, 223), (223, 223, 223), (224, 224, 224), (224, 224, 224), (225, 225, 225), (226, 226, 226), (226, 226, 226), (227, 227, 227), (227, 227, 227), (228, 228, 228), (228, 228, 228), (229, 229, 229), (229, 229, 229), (230, 230, 230), (230, 230, 230), (231, 231, 231), (232, 232, 232), (232, 232, 232), (233, 233, 233), (233, 233, 233), (234, 234, 234), (234, 234, 234), (235, 235, 235), (236, 236, 236), (237, 237, 237), (237, 237, 237), (238, 238, 238), (239, 239, 239), (239, 239, 239), (240, 240, 240), (240, 240, 240), (241, 241, 241), (241, 241, 241), (242, 242, 242), (242, 242, 242), (243, 243, 243), (244, 244, 244), (244, 244, 244), (245, 245, 245), (245, 245, 245), (246, 246, 246), (246, 246, 246), (247, 247, 247), (248, 248, 248), (248, 248, 248), (249, 249, 249), (250, 250, 250), (251, 251, 251), (251, 251, 251), (252, 252, 252), (252, 252, 252), (253, 253, 253), (253, 253, 253), (254, 254, 254), (254, 254, 254), (254, 254, 254), (255, 255, 255)) 


Iron gradient




 palette=((0, 0, 0), (0, 0, 10), (0, 0, 20), (0, 0, 30), (0, 0, 37), (0, 0, 42), (0, 0, 46), (0, 0, 50), (0, 0, 54), (0, 0, 58), (0, 0, 62), (0, 0, 66), (0, 0, 70), (0, 0, 74), (0, 0, 79), (0, 0, 82), (1, 0, 85), (1, 0, 87), (2, 0, 89), (2, 0, 92), (3, 0, 94), (4, 0, 97), (4, 0, 99), (5, 0, 101), (6, 0, 103), (7, 0, 105), (8, 0, 107), (9, 0, 110), (10, 0, 112), (11, 0, 115), (12, 0, 116), (13, 0, 117), (13, 0, 118), (14, 0, 119), (16, 0, 120), (18, 0, 121), (19, 0, 123), (21, 0, 124), (23, 0, 125), (25, 0, 126), (27, 0, 128), (28, 0, 129), (30, 0, 131), (32, 0, 132), (34, 0, 133), (36, 0, 134), (38, 0, 135), (40, 0, 137), (42, 0, 137), (44, 0, 138), (46, 0, 139), (48, 0, 140), (50, 0, 141), (52, 0, 142), (54, 0, 142), (56, 0, 143), (57, 0, 144), (59, 0, 145), (60, 0, 146), (62, 0, 147), (63, 0, 147), (65, 0, 148), (66, 0, 149), (68, 0, 149), (69, 0, 150), (71, 0, 150), (73, 0, 150), (74, 0, 150), (76, 0, 151), (78, 0, 151), (79, 0, 151), (81, 0, 151), (82, 0, 152), (84, 0, 152), (86, 0, 152), (88, 0, 153), (90, 0, 153), (92, 0, 153), (93, 0, 154), (95, 0, 154), (97, 0, 155), (99, 0, 155), (100, 0, 155), (102, 0, 155), (104, 0, 155), (106, 0, 155), (108, 0, 156), (109, 0, 156), (111, 0, 156), (112, 0, 156), (113, 0, 157), (115, 0, 157), (117, 0, 157), (119, 0, 157), (120, 0, 157), (122, 0, 157), (124, 0, 157), (126, 0, 157), (127, 0, 157), (129, 0, 157), (131, 0, 157), (132, 0, 157), (134, 0, 157), (135, 0, 157), (137, 0, 157), (138, 0, 157), (139, 0, 157), (141, 0, 157), (143, 0, 156), (145, 0, 156), (147, 0, 156), (149, 0, 156), (150, 0, 155), (152, 0, 155), (153, 0, 155), (155, 0, 155), (156, 0, 155), (157, 0, 155), (159, 0, 155), (160, 0, 155), (162, 0, 155), (163, 0, 155), (164, 0, 155), (166, 0, 154), (167, 0, 154), (168, 0, 154), (169, 0, 153), (170, 0, 153), (171, 0, 153), (173, 0, 153), (174, 1, 152), (175, 1, 152), (176, 1, 152), (176, 1, 152), (177, 1, 151), (178, 1, 151), (179, 1, 150), (180, 2, 150), (181, 2, 149), (182, 2, 149), (183, 3, 149), (184, 3, 149), (185, 4, 149), (186, 4, 149), (186, 4, 148), (187, 5, 147), (188, 5, 147), (189, 5, 147), (190, 6, 146), (191, 6, 146), (191, 6, 146), (192, 7, 145), (192, 7, 145), (193, 8, 144), (193, 9, 144), (194, 10, 143), (195, 10, 142), (195, 11, 142), (196, 12, 141), (197, 12, 140), (198, 13, 139), (198, 14, 138), (199, 15, 137), (200, 16, 136), (201, 17, 135), (202, 18, 134), (202, 19, 133), (203, 19, 133), (203, 20, 132), (204, 21, 130), (205, 22, 129), (206, 23, 128), (206, 24, 126), (207, 24, 124), (207, 25, 123), (208, 26, 121), (209, 27, 120), (209, 28, 118), (210, 28, 117), (210, 29, 116), (211, 30, 114), (211, 32, 113), (212, 33, 111), (212, 34, 110), (213, 35, 107), (213, 36, 105), (214, 37, 103), (215, 38, 101), (216, 39, 100), (216, 40, 98), (217, 42, 96), (218, 43, 94), (218, 44, 92), (219, 46, 90), (219, 47, 87), (220, 47, 84), (221, 48, 81), (221, 49, 78), (222, 50, 74), (222, 51, 71), (223, 52, 68), (223, 53, 65), (223, 54, 61), (224, 55, 58), (224, 56, 55), (224, 57, 51), (225, 58, 48), (226, 59, 45), (226, 60, 42), (227, 61, 38), (227, 62, 35), (228, 63, 32), (228, 65, 29), (228, 66, 28), (229, 67, 27), (229, 68, 25), (229, 69, 24), (230, 70, 22), (231, 71, 21), (231, 72, 20), (231, 73, 19), (232, 74, 18), (232, 76, 16), (232, 76, 15), (233, 77, 14), (233, 77, 13), (234, 78, 12), (234, 79, 12), (235, 80, 11), (235, 81, 10), (235, 82, 10), (235, 83, 9), (236, 84, 9), (236, 86, 8), (236, 87, 8), (236, 88, 8), (237, 89, 7), (237, 90, 7), (237, 91, 6), (238, 92, 6), (238, 92, 5), (238, 93, 5), (238, 94, 5), (239, 95, 4), (239, 96, 4), (239, 97, 4), (239, 98, 4), (240, 99, 3), (240, 100, 3), (240, 101, 3), (241, 102, 3), (241, 102, 3), (241, 103, 3), (241, 104, 3), (241, 105, 2), (241, 106, 2), (241, 107, 2), (241, 107, 2), (242, 108, 1), (242, 109, 1), (242, 110, 1), (243, 111, 1), (243, 112, 1), (243, 113, 1), (243, 114, 1), (244, 115, 0), (244, 116, 0), (244, 117, 0), (244, 118, 0), (244, 119, 0), (244, 120, 0), (244, 122, 0), (245, 123, 0), (245, 124, 0), (245, 126, 0), (245, 127, 0), (246, 128, 0), (246, 129, 0), (246, 130, 0), (247, 131, 0), (247, 132, 0), (247, 133, 0), (247, 134, 0), (248, 135, 0), (248, 136, 0), (248, 136, 0), (248, 137, 0), (248, 138, 0), (248, 139, 0), (248, 140, 0), (249, 141, 0), (249, 141, 0), (249, 142, 0), (249, 143, 0), (249, 144, 0), (249, 145, 0), (249, 146, 0), (249, 147, 0), (250, 148, 0), (250, 149, 0), (250, 150, 0), (251, 152, 0), (251, 153, 0), (251, 154, 0), (251, 156, 0), (252, 157, 0), (252, 159, 0), (252, 160, 0), (252, 161, 0), (253, 162, 0), (253, 163, 0), (253, 164, 0), (253, 166, 0), (253, 167, 0), (253, 168, 0), (253, 170, 0), (253, 171, 0), (253, 172, 0), (253, 173, 0), (253, 174, 0), (254, 175, 0), (254, 176, 0), (254, 177, 0), (254, 178, 0), (254, 179, 0), (254, 180, 0), (254, 181, 0), (254, 182, 0), (254, 184, 0), (254, 185, 0), (254, 185, 0), (254, 186, 0), (254, 187, 0), (254, 188, 0), (254, 189, 0), (254, 190, 0), (254, 192, 0), (254, 193, 0), (254, 194, 0), (254, 195, 0), (254, 196, 0), (254, 197, 0), (254, 198, 0), (254, 199, 0), (254, 200, 0), (254, 201, 1), (254, 202, 1), (254, 202, 1), (254, 203, 1), (254, 204, 2), (254, 205, 2), (254, 206, 3), (254, 207, 4), (254, 207, 4), (254, 208, 5), (254, 209, 6), (254, 211, 8), (254, 212, 9), (254, 213, 10), (254, 214, 10), (254, 215, 11), (254, 216, 12), (254, 217, 13), (255, 218, 14), (255, 218, 14), (255, 219, 16), (255, 220, 18), (255, 220, 20), (255, 221, 22), (255, 222, 25), (255, 222, 27), (255, 223, 30), (255, 224, 32), (255, 225, 34), (255, 226, 36), (255, 226, 38), (255, 227, 40), (255, 228, 43), (255, 228, 46), (255, 229, 49), (255, 230, 53), (255, 230, 56), (255, 231, 60), (255, 232, 63), (255, 233, 67), (255, 234, 70), (255, 235, 73), (255, 235, 77), (255, 236, 80), (255, 237, 84), (255, 238, 87), (255, 238, 91), (255, 238, 95), (255, 239, 99), (255, 239, 103), (255, 240, 106), (255, 240, 110), (255, 241, 114), (255, 241, 119), (255, 241, 123), (255, 242, 128), (255, 242, 133), (255, 242, 138), (255, 243, 142), (255, 244, 146), (255, 244, 150), (255, 244, 154), (255, 245, 158), (255, 245, 162), (255, 245, 166), (255, 246, 170), (255, 246, 175), (255, 247, 179), (255, 247, 182), (255, 248, 186), (255, 248, 189), (255, 248, 193), (255, 248, 196), (255, 249, 199), (255, 249, 202), (255, 249, 205), (255, 250, 209), (255, 250, 212), (255, 251, 216), (255, 252, 219), (255, 252, 223), (255, 253, 226), (255, 253, 229), (255, 253, 232), (255, 254, 235), (255, 254, 238), (255, 254, 241), (255, 254, 244), (255, 255, 246)) 


Rainbow gradient


 palette=((0, 0, 0), (4, 0, 4), (8, 0, 8), (12, 0, 12), (17, 0, 17), (21, 0, 21), (25, 0, 25), (30, 0, 30), (34, 0, 34), (39, 0, 39), (43, 0, 43), (47, 0, 47), (52, 0, 52), (56, 0, 56), (60, 0, 60), (65, 0, 65), (69, 0, 69), (74, 0, 74), (78, 0, 78), (82, 0, 82), (87, 0, 87), (91, 0, 91), (96, 0, 96), (100, 0, 100), (104, 0, 104), (109, 0, 109), (113, 0, 113), (118, 0, 118), (122, 0, 122), (126, 0, 126), (131, 0, 131), (135, 0, 135), (139, 0, 139), (144, 0, 144), (148, 0, 148), (153, 0, 153), (157, 0, 157), (161, 0, 161), (166, 0, 166), (170, 0, 170), (175, 0, 175), (179, 0, 179), (183, 0, 183), (188, 0, 188), (192, 0, 192), (197, 0, 197), (201, 0, 201), (205, 0, 205), (210, 0, 210), (214, 0, 214), (218, 0, 218), (223, 0, 223), (227, 0, 227), (232, 0, 232), (236, 0, 236), (240, 0, 240), (245, 0, 245), (249, 0, 249), (254, 0, 254), (252, 0, 254), (248, 0, 253), (243, 0, 251), (239, 0, 250), (235, 0, 249), (230, 0, 247), (226, 0, 246), (221, 0, 244), (217, 0, 243), (213, 0, 242), (208, 0, 240), (204, 0, 239), (199, 0, 238), (195, 0, 237), (191, 0, 236), (186, 0, 235), (182, 0, 233), (178, 0, 232), (173, 0, 230), (169, 0, 229), (164, 0, 228), (160, 0, 226), (156, 0, 225), (151, 0, 224), (147, 0, 223), (142, 0, 222), (138, 0, 220), (134, 0, 219), (129, 0, 218), (125, 0, 216), (121, 0, 215), (116, 0, 214), (112, 0, 212), (107, 0, 211), (103, 0, 210), (99, 0, 209), (94, 0, 208), (90, 0, 206), (85, 0, 205), (81, 0, 204), (77, 0, 202), (72, 0, 201), (68, 0, 200), (63, 0, 198), (59, 0, 197), (55, 0, 196), (50, 0, 195), (46, 0, 194), (42, 0, 192), (37, 0, 191), (33, 0, 190), (28, 0, 188), (24, 0, 187), (20, 0, 185), (15, 0, 184), (11, 0, 183), (7, 0, 182), (3, 0, 181), (0, 1, 180), (0, 5, 181), (0, 9, 183), (0, 14, 184), (0, 18, 185), (0, 22, 186), (0, 27, 188), (0, 31, 189), (0, 36, 190), (0, 40, 192), (0, 44, 193), (0, 49, 194), (0, 53, 196), (0, 57, 197), (0, 62, 198), (0, 66, 199), (0, 71, 200), (0, 75, 202), (0, 79, 203), (0, 84, 204), (0, 88, 206), (0, 93, 207), (0, 97, 208), (0, 101, 210), (0, 106, 211), (0, 110, 212), (0, 114, 213), (0, 119, 214), (0, 123, 216), (0, 128, 217), (0, 132, 219), (0, 136, 220), (0, 141, 221), (0, 145, 223), (0, 150, 224), (0, 154, 225), (0, 158, 226), (0, 163, 227), (0, 167, 229), (0, 172, 230), (0, 176, 231), (0, 180, 233), (0, 185, 234), (0, 189, 235), (0, 193, 237), (0, 198, 238), (0, 202, 239), (0, 207, 240), (0, 211, 241), (0, 215, 243), (0, 220, 244), (0, 224, 245), (0, 229, 247), (0, 233, 248), (0, 237, 249), (0, 242, 251), (0, 246, 252), (0, 250, 254), (0, 255, 255), (0, 252, 251), (0, 250, 246), (0, 247, 242), (0, 244, 238), (0, 242, 233), (0, 239, 229), (0, 237, 224), (0, 234, 220), (0, 232, 216), (0, 229, 211), (0, 227, 207), (0, 224, 203), (0, 222, 198), (0, 220, 194), (0, 217, 189), (0, 215, 185), (0, 212, 181), (0, 210, 176), (0, 207, 172), (0, 205, 167), (0, 202, 163), (0, 200, 159), (0, 197, 154), (0, 195, 150), (0, 192, 146), (0, 190, 141), (0, 187, 137), (0, 185, 132), (0, 183, 128), (0, 180, 124), (0, 178, 119), (0, 175, 115), (0, 173, 110), (0, 170, 106), (0, 168, 102), (0, 165, 97), (0, 163, 93), (0, 160, 88), (0, 158, 84), (0, 155, 80), (0, 153, 75), (0, 150, 71), (0, 148, 67), (0, 146, 62), (0, 143, 58), (0, 141, 53), (0, 138, 49), (0, 136, 45), (0, 133, 40), (0, 131, 36), (0, 128, 31), (0, 126, 27), (0, 123, 23), (0, 121, 18), (0, 118, 14), (0, 116, 10), (0, 113, 6), (0, 111, 2), (3, 111, 0), (7, 114, 0), (11, 116, 0), (15, 118, 0), (19, 120, 0), (23, 123, 0), (27, 125, 0), (31, 128, 0), (35, 130, 0), (40, 132, 0), (44, 134, 0), (48, 137, 0), (52, 139, 0), (56, 142, 0), (60, 144, 0), (64, 146, 0), (68, 148, 0), (72, 151, 0), (77, 153, 0), (81, 155, 0), (85, 158, 0), (89, 160, 0), (93, 163, 0), (97, 165, 0), (101, 167, 0), (105, 169, 0), (109, 172, 0), (114, 174, 0), (118, 177, 0), (122, 179, 0), (126, 181, 0), (130, 183, 0), (134, 186, 0), (138, 188, 0), (142, 190, 0), (146, 193, 0), (151, 195, 0), (155, 198, 0), (159, 200, 0), (163, 202, 0), (167, 204, 0), (171, 207, 0), (175, 209, 0), (179, 212, 0), (184, 214, 0), (188, 216, 0), (192, 218, 0), (196, 221, 0), (200, 223, 0), (204, 225, 0), (208, 228, 0), (212, 230, 0), (216, 232, 0), (221, 235, 0), (225, 237, 0), (229, 239, 0), (233, 242, 0), (237, 244, 0), (241, 247, 0), (245, 249, 0), (249, 252, 0), (253, 254, 0), (254, 252, 0), (253, 248, 0), (252, 244, 0), (251, 240, 0), (250, 236, 0), (249, 232, 0), (249, 228, 0), (248, 224, 0), (247, 220, 0), (246, 215, 0), (245, 211, 0), (244, 207, 0), (244, 203, 0), (243, 199, 0), (242, 195, 0), (241, 191, 0), (240, 187, 0), (239, 183, 0), (238, 178, 0), (237, 174, 0), (236, 170, 0), (235, 166, 0), (234, 162, 0), (234, 158, 0), (233, 154, 0), (232, 150, 0), (231, 145, 0), (230, 141, 0), (229, 137, 0), (229, 133, 0), (227, 129, 0), (226, 125, 0), (225, 121, 0), (224, 117, 0), (224, 113, 0), (223, 108, 0), (222, 104, 0), (221, 100, 0), (220, 96, 0), (219, 92, 0), (219, 88, 0), (218, 84, 0), (217, 80, 0), (216, 76, 0), (215, 71, 0), (214, 67, 0), (213, 63, 0), (212, 59, 0), (211, 55, 0), (210, 51, 0), (209, 47, 0), (209, 43, 0), (208, 39, 0), (207, 34, 0), (206, 30, 0), (205, 26, 0), (204, 22, 0), (204, 18, 0), (203, 14, 0), (202, 10, 0), (201, 6, 0), (200, 2, 0), (200, 2, 2), (201, 5, 5), (201, 8, 8), (202, 11, 11), (203, 14, 14), (204, 18, 18), (204, 21, 21), (205, 24, 24), (206, 27, 27), (206, 30, 30), (207, 33, 33), (208, 36, 36), (208, 40, 40), (209, 43, 43), (210, 46, 46), (211, 49, 49), (211, 52, 52), (212, 55, 55), (212, 58, 58), (213, 62, 62), (214, 65, 65), (215, 68, 68), (215, 71, 71), (216, 75, 75), (217, 78, 78), (217, 81, 81), (218, 84, 84), (219, 87, 87), (220, 90, 90), (220, 94, 94), (221, 97, 97), (221, 100, 100), (222, 103, 103), (223, 106, 106), (223, 109, 109), (224, 112, 112), (225, 116, 116), (226, 119, 119), (226, 122, 122), (227, 125, 125), (227, 129, 129), (228, 132, 132), (229, 135, 135), (230, 139, 139), (230, 142, 142), (231, 145, 145), (232, 148, 148), (232, 151, 151), (233, 154, 154), (234, 157, 157), (235, 161, 161), (235, 164, 164), (236, 167, 167), (236, 170, 170), (237, 173, 173), (238, 176, 176), (239, 179, 179), (239, 183, 183), (240, 186, 186), (241, 189, 189), (241, 193, 193), (242, 196, 196), (243, 199, 199), (243, 202, 202), (244, 205, 205), (245, 208, 208), (246, 211, 211), (246, 215, 215), (247, 218, 218), (247, 221, 221), (248, 224, 224), (249, 227, 227), (250, 230, 230), (250, 233, 233), (251, 237, 237), (251, 240, 240)) 



2015년 11월 20일 금요일

[번역] 16x32 RGB LED 매트릭스의 기술적인 해설

Curtis@HobbyPCB.com에 의해서 작성됨

16x32 RGB LED 매트릭스의 블로그 연재물에서 첫 번째 사안은 디스플레이 모듈을 소개하고 어떻게 동작하는지 설명하는 것이다. 우리는 보드에 있는 모든 부품에 대해서 살펴 볼 것이고, 그곳에서 벌어지는 일들을 이해하기 쉽게 풀어 해쳐갈 것이다.

이런 설명을 위해서 우리는 3-in-1 Pixel들을 가지고 있는 16x32 P7.62 RGB LED 매트릭스를 사용할 것이다. 이게 모두 뭘 의미하느냐 하면, 16x32는 512개의 각각의 픽셀을 가지고 있는 16열과 32 행을 의미하고 P7.62는 피치가 7.62mm 혹은 픽셀 간의 거리가 7.62mm를 의미한다. 일반적인 실내 디스플레이는 P6이나 P7.62이다. 좀 더 작은 값을 갖으며, 여러분은 좀 더 실제 이미지에 가까운 디스플레이를 볼 수 있다. P6와 P7.62의 실내 디스플레이들은 3.5m 혹은 4m 정도의 시청 거리를 가지고 있다. 일반적인 실외 디스플레이들은 최소 시청 거리가 15-20m인 P16 혹은 P20이다. 3-in-1은 각 픽셀이 같은 패키지에 3개의 색상의 LED 모아놓은 것을 의미한다. (우리의 모듈은 3528 패키지이다.) 보드에 하나의 픽셀을 형성하는데 3개의 각각의 SMD LED (보통 0805)들이 같이 납땜된 3-in-3형태도 존재한다. 나는 아직 어떤 것도 테스트 해보지 못했지만, 다음에 반드시 해볼 것이다.

다음의 그림은 P6(위)와 P7.62(아래) LED 매트릭스를 보여준다. 여러분은 1.62mm가 크기에 얼마나 큰 차이를 어떻게 가져오는지 볼 수 있다.



 내가 아는한 크지 않은 320x240 디스플레이를 보여줄 수 있는 큰 Jumbo Tron 디스플레이를 상상해보자. 이 모듈을 가지고 150의 모듈이 8 inch x 6 inch 정도 크기를 만들 수 있다. 640X480 디스플레이는 이 크기의 두배가 되고 600개의 모듈이 소요된다.

자 충분히 상상 가능할 것이다. 나는 Arduino 나 EasyPIC6 (아마도 나중에) 같은 마이크로 개발 보드를 가지고 이들을 구동하기 위해서 어떻게 동작하는지 설명하고 싶다.

나의 돋보기를 가지고 되돌아 보면, 나는 다음 칩들을 손꼽을 수 있다.

74HC245D - Bus Tranciever (Non-Inverting)
CYT62726B - Constant Current LED Driver
APM4953 - Dual P-Channel Mosfet
74HC138 - 3to8 Line Decoder (ABC)
74HC04D - HEX Inverter

나는 이 칩들은 개개별로 다음 그림에서 찾아 볼 수 있다.




이제, 이들 각각의 무엇을 하고 있는지 보자. 나는 이 설명서를 세 개의 섹션으로 구분해 놓을 것이고 모듈의 enable, rows, 그리고 columns을 분리해서 이야기 할 것이다.

커넥터에 가장 가까운 칩은 Non-Inverting Bus Transceiver 인 74HC245D (빨간색)이다. 이것이 뭐냐하면, 이 경우에는 74HC245D는 parallel bus Transceiver로 동작해서, 왼쪽 핀으로 전송된 데이터를 오른쪽 핀으로 전달되도록 한다. 때때로 bus transceiver는 신호 분리 요구를 맞추어줄 뿐 아니라 bus상의 신호를 배가시키는데 사용되곤 한다. 이 경우에 나는 그져 신호를 배가하는데 사용되고 회로에 다른 곳으로 신호를 분배 시켜주는데 사용되고 있다고 생각한다.

이 모듈의 하나의 중요한 기능이고 전혀 동작하지 않는 것처럼 모듈을 만드는 것은 Output Enable (OE)이다. 여러분은 커넥터의 왼쪽 모퉁이 바닥에서 이것을 찾을 수 있다. OE는 모듈이 어떤 것을 디스플레이하기 위해서 LOW 레벨을 유지해야 한다. 기본적으로 여러분이 OE을 변경할때, 신호가 A6/B6에 있는 74HC245를 통해서 전달되고 enable 기능을 가지고 있는 74HC138의 핀 4번과 5번 (G2A/G2B)에 연결된다. G2가 high를 띄게 될때, 74HC138의 모든 출력을 끄게 된다. 이것은  활성화된 열이 없다는 것을 의미한다.

row로 관점을 바꿔보자. 이 장치의 row들은 LED의 anode (양 극)들을 선택한다. 우리는 이 모듈을 구매한 공급자로 부터 이것이 8:1 scan 모듈이라는 것을 알았다. 이것은 여러분이 영상을 출력하기 위해서 8 rows를 단위로 스캔해야 한다는 것을 의미한다. 그러나 살펴보면 모듈은 16개의 row들로 되어 있다. 우리는 2개의 row를 동시에 불 밝혀야 한다고 예상할 수 있을 것이다. 커넥터 부분을 좀 더 살펴보자. A, B, 그리고 C로 표시된 3개의 핀들을 보자. 이것들이 뭘 하는 것인지 구글 검색을 해보면 row 스캐닝을 위한 제어 핀이라는 것을 알려 준다. 이 3개의 핀들은 3to8 디코더인 74HC138을 제어한다. 의미인 즉슨 효과적으로 3개 입력이 8개의 출력 중 하나는 선택하는 것이다. 여러분이 3 비트 바이너리 조합을 전송할때, 그에 알맞은 라인이 활성화 된다. 그래서 '000'는 0번째 row를 불 밝히고 '100'은 4번째 row를 불 밝히고, '111'는 7번째 row를 불 밝히게된다. 그래서 총 8개의 조합이 가능하다. 좀 더 살펴보면, 우리는 APM4953 Dual P-Channel Mosfet을 볼 수 있다. 이것은 순차적으로 LED에 전류를 공급하도록 74HC138에 의해서 제어된다.

마지막으로, 우리는 실제의 데이터인 Column에 대해서 이야기 할 필요가 있다. row는 그져 안보이게 하나하나씩 선택되고 다시 계속 반복된다. 하나의 row에 있는 각각의 픽셀에 해당하는 column은 데이터를 수행하는 것이다. 각 row는 각각 3개의 색상을 가지고 있는 32 픽셀들로 구성된다. 우리는 두 개의 row들을 동시에 불 밝힐 것이라는 것을 안다. 칩 리스트를 살펴보면, 우리는 CYT62726(녹색)이 있는 것을 볼 수 있다. 이건 또 뭐지. 이것은 16 비트 정전류 LED 드라이버이다. 이 드라이버는 LED의 cathode (음극) 에서 적절한 총 전류를 유지하도록 한다. 이 총 전류는 여러분이 선택한 LED의 지속성을 위해서 저항으로 조절 가능하다. 보드를 살펴보면, 우리는 보드의 각 코너에 3개의 칩을 볼 수 있다. (그림에서 여러분은 단지 왼쪽의 2개만 볼 수 있고 오른쪽은 사진의 앵글때문에 그렇지 못하다.) 이 칩들은 각각 16x8를 위한 (동시에 하나의 row에 해당하는) 색상을 표현한다. CYT62726B는 MBI5026과 TB62726과 호환되는 기능과 핀아웃을 가지고 있다. 여러분은 이런 다른 칩들을 이용하는 유사한 보드를 찾아 볼 수 있지만, 모두다 동일한 기능을 한다. 입력 커넥터에 있는 R1, R2, G1, G2, U1, U2 핀들은 각 색상에 대한 데이터 라인이다. (U는 파란색이다.) 1은 위쪽 반 rows들을 의미하고 2는 아랫쪽 반 rows들을 의미한다ㅏ. 윗쪽과 아랫쪽의 칩들을 각 모음은 수평적으로 32 비트의 라인을 형성하도록 중첩되어 있다. 나는 어떻게 클럭 데이터가 입력되는지를 좀 더 이야기 할 것이다. 나의 다음 블로그에서 이 프로토콜에 대해서 다룰 것이다.

[출처 : http://www.hobbypcb.com/blog/item/3-16x32-rgb-led-matrix-technical-details.html
cached at
https://web.archive.org/web/20121201205905/http://www.hobbypcb.com/blog/item/3-16x32-rgb-led-matrix-technical-details.html ]

[번역] 16 x 32 매트릭스 구동하기

나는 최종적으로 Adafruit에서 16 x 32 매트릭스 패널을 구매했다. - 가격이 비쌌지만, 아주 많은 LED들이 있었다. 가능한 한 빨리 시도해 보기 위해서, 나는 디지탈 파형 발생기 (DWG)에 전선으로 연결했다. JaySisson에 의해서 만들어진 다음의 타이밍도는 내가 16 x 32 의 영상을 생성하기 위해서 스크립트를 작성한 것이다. 여기에 매트릭스의 한 라인을 생성하는 (LED의 2번째 열에 해당하는) CLK (파란색), OE (핑크), 그리고 LAT (녹색) 신호들을 포착한 오실로스코프이다.

LED-Matrix-Scope-1Line

Flying lead connection

나는 DWG를 flying 리드 선으로 패널에 연결했고, 총 12개의 연결로 6개의 데이터 선, 3개의 어드레스선, 그리고 CLK, OE, LAT으로 구성된다.

다음의 것은 우리가 알고 있는 것이다.

LED Panel Blue

모두 같은 색을 띄는 색상들은 아주 단순하지만 VHDL 코드를 작성하기 전에 PWM을 조절하고 테스트하기에 훌룡하다. PWM 코드를 실행하고 설정하는 몇 개의 비디오가 있다. 나는 Favicons (16x 16 웹브라우져 아이콘)을 사용했다. 자 보시라.




다음 과정은 얼마나 빠른 클럭을 적용할 수 있는지이다.그리고 다른 조건 하에서 패널이 얼마나 많은 전력을 소비하는지를 측정하는 것이다.


[출처 : rhb.me/blog/2012/05/led-matrix-bringup+&cd=1&hl=ko&ct=clnk
cached at
 http://webcache.googleusercontent.com/search?q=cache:gUDee4-3LOAJ:rhb.me/blog/2012/05/led-matrix-bringup+&cd=1&hl=ko&ct=clnk ]