Friday, December 25, 2009

Flash Loader for 8-Pin ZiLOG MCUs

Serial Port Flash Loader for 8-Pin Z8F Zilog Encore(XP)

One major problem for the ZiLOG 8-pin mcu's is that it needs an expensive usb smart cable in order for the program to be 'flashed'/'burned' to their memory. This application aims to address this problem, by using a common serial port for flash loading (reading and erasing as well) instead of using an expensive tool.



For now,it's only tested with 8-pin Z8F042A. Hopefully in the future, it can also support other ZiLOG MCUs, not only these 8-pins (those 20- and 28-pins should be easier to program).

download: Flash Loader for 8-Pin Z8F.rar

forum link for project progress: Serial Port Flash Loader for 8-Pin Zilog MCUs

update(123009):
already tested with 8-pin z8f0423 and 28-pin z8f082a (yes, soic-28 also)

update(010110):
Win32 Executable verion: Flash Loader for 8-Pin Z8F (WIN32 Executable).rar
it only requires msvcp90.dll - most Win32 OS already have this; if not yet installed, it can be downloaded from Microsoft.

Wednesday, December 16, 2009

Python for PIC MCUs

Python (pseudo) Compiler for PIC12/PIC16 Microcontrollers

It uses pyastra (python assembler translator) and gpasm assembler.
The PyQt GUI has a QScintilla-based editor for easy editing of the python scripts to be compiled.

main.py : (compatible with Portable Eric 4 Python IDE)
 #################################  
# Python (pseudo) Compiler for PIC12 and PIC16 devices
# using pyastra and gpasm
# PyQt GUI by yus
#################################

import sys, os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.Qsci import QsciScintilla, QsciLexerPython

class ScriptEditor(QsciScintilla):
def __init__(self):
QsciScintilla.__init__(self)
self.filename = None
self.filedialog = QFileDialog()
# font
font = QFont()
font.setPointSize(9.5)

# Choose python lexer
lexer = QsciLexerPython()
lexer.setDefaultFont(font)
self.setLexer(lexer)

# Folding visual : we will use boxes
self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
# Braces matching
self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
# Editing line color
self.setCaretLineVisible(True)
self.setCaretLineBackgroundColor(QColor(200, 240, 200))
# line numbers
self.setMarginWidth(0, QFontMetrics(font).width( "00000" ) )

def open(self):
self.filename = self.filedialog.getOpenFileName(None,
'Open Python Script', '.\\',
'python script(*.py);;text file(*.txt);;All files (*)', QString())
try:
f = open(self.filename)
self.setText(f.read())
f.close()
except:
print 'unable to open script.'

def save(self):
if self.filename == None:
self.save_as()
else:
try:
f = open(self.filename, "w")
f.write(str(self.text()))
f.close()
except:
print 'file not save.'

def save_as(self):
self.filename = self.filedialog.getSaveFileName(None,
'Save Python Script', '.\\',
'python script(*.py);;;text file(*.txt);;All files (*)', QString())
if self.filename != None:
self.save()

def get_filename(self):
return self.filename
class AppWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle('PIC12-PIC16 Python Compiler ( PyQt, PyAsTra and GPASM ) - yus ')
#self.setMinimumSize(700, 320)
#self.move(20, 20)

self.editor = ScriptEditor()
self.open_btn = QPushButton('Open')
self.save_btn = QPushButton('Save As')
self.device_label = QLabel('Select Device:')
self.status_info = QLabel('Select or create a python script first')
self.device_cbox = QComboBox()
self.compile_btn = QPushButton('Compile Script')
self.compile_btn.setEnabled(False) # initially disabled until a script is opened

self.editor_area = QDockWidget('(pic script here)')
self.editor_area.setWidget(self.editor)
self.addDockWidget(Qt.TopDockWidgetArea, self.editor_area)

self.output_info = QTextEdit()
self.output_info.setReadOnly(True) # read only information
self.output_info.setTextColor(Qt.darkBlue)
self.output_info_widget = QDockWidget('Output Information')
self.output_info_widget.setWidget(self.output_info)
self.addDockWidget(Qt.BottomDockWidgetArea, self.output_info_widget)

file_tbar = QToolBar()
file_tbar.addWidget(self.open_btn)
file_tbar.addWidget(self.save_btn)
compile_tbar = QToolBar()
compile_tbar.addWidget(self.device_label)
compile_tbar.addWidget(self.device_cbox)
compile_tbar.addWidget(self.compile_btn)

self.addToolBar(file_tbar)
self.addToolBar(compile_tbar)

self.status = QStatusBar()
self.status.addWidget(QLabel('\t')) # dummy widget
self.status.addWidget(self.status_info, 1)
self.setStatusBar(self.status)

self.update_device_list()
self.connect(self.save_btn, SIGNAL('clicked()'), self.save_script)
self.connect(self.open_btn, SIGNAL('clicked()'), self.open_script)
self.connect(self.compile_btn, SIGNAL('clicked()'), self.compile_script)

def open_script(self):
self.editor.open()
fname = str(self.editor.get_filename())
self.editor_area.setWindowTitle(fname)
if fname != 'None':
self.compile_btn.setEnabled(True)
def save_script(self):
self.editor.save_as()
fname = str(self.editor.get_filename())
self.editor_area.setWindowTitle(fname)
if fname != 'None':
self.compile_btn.setEnabled(True)
def compile_script(self):
self.editor.save() # save changes in the script before compiling
script = str(self.editor.get_filename())
device = str(self.device_cbox.currentText())
# PyAstra (python assymbly translator)
pyastra_command = '.\\pyastra_console.py -p'+device[3:] + ' -S --compile ' + script
msg = ' from pyastra console :\n'
try: # clean/delete previous output files
for ext in ('asm', 'hex', 'lst', 'cod'):
os.remove(script[:-2] + ext)
except:
pass #print 'one or more files not found'
try:
msg += os.popen(pyastra_command).read() # execute pyastra console
self.output_info.setText(msg) #pyastra.py info
except:
self.output_info.append('Error occured while translating the python script')
if msg.find('Program memory usage')>0:
# assemble the generated asm file using gpasm.exe
self.output_info.append('---------------\nExecuting gpasm.exe....')
file_asm = '%s'%self.editor.get_filename()
file_asm = file_asm[:file_asm.find('.py')] + '.asm'
#self.output_info.append( os.popen('.\\gpasm\\gpasm -v').read() ) # show gpasm version
msg = os.popen('.\\gpasm\\gpasm -I .\\gpasm\\header '+file_asm).read()
self.output_info.append(msg)
self.output_info.append('Finished.')
self.status_info.setText('Done')
else:
self.status_info.setText('Please verify the script')

def update_device_list(self):
for root, dirs, files in os.walk('.\\pyastra\\ports\\pic14\\procs'):
for name in files:
device = str(name)
if device[:1]=='1' and device.find('.pyc')<0 and device.find('i')<0:
device = device[:device.find('.')]
self.device_cbox.addItem('pic'+device)
self.device_cbox.setCurrentIndex(127) # initially set to PIC16F876A

if __name__ == '__main__':
app = QApplication(sys.argv)
form = AppWindow()
form.show()
sys.exit(app.exec_())




Complete Eric4 project : Python for PIC.rar
* already includes pyastra and gpasm

note: Python programming language is really NOT intended for platform/devices with very limited resources, such a microcontroller with a very small memory. For now, C language is still the widely used in microcontroller programming.

forum link: Python Compiler for PIC MCUs

Sunday, December 6, 2009

USB-based Oscilloscope (beta)

This is NOT considered as an oscilloscope yet. It's just a preparation of making a real PIC18F USB-based oscilloscope. For my initial testing, I used my PIC18F and PyUSB demo, same hardware and firmware for the 18F2550. The only difference is in the GUI, instead of PyQt QDial, I use PyQwt PlotCurve widget.

the Python script: (compatible with my Portable Eric 4 Python IDE (v2))
 #################################  
# USB-based oscillpscope (beta)
# using pyUSB and PyQt/PyQwt
#################################

import sys, usb
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.Qwt5 import *
from PyQt4.Qwt5.anynumpy import *

class UsbPic:
def __init__(self, vendor_id, product_id):
busses = usb.busses() # enumerate busses
self.handle = None
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.idVendor==vendor_id and dev.idProduct==product_id: # device matches
self.dev = dev
self.conf = self.dev.configurations[0]
self.intf = self.conf.interfaces[0][0]
self.endpoints = []
for endpoint in self.intf.endpoints:
self.endpoints.append(endpoint)
return

def open(self):
if self.handle:
self.handle = None
try:
self.handle = self.dev.open()
self.handle.detachKernelDriver(0)
self.handle.detachKernelDriver(1)
self.handle.setConfiguration(self.conf)
self.handle.claimInterface(self.intf)
self.handle.setAltInterface(self.intf)
return True
except:
return False

def write(self, ep, buff, timeout = 100):
try:
return self.handle.interruptWrite(ep, buff, timeout) #return bytes written
except:
return 0
def read(self, ep, size, timeout = 100):
try:
return self.handle.interruptRead(ep, size, timeout) # return data read
except:
return []
def getDeviceName(self):
return self.handle.getString(2, 40)

class AmplitudevsTime(QwtPlot):
def __init__(self):
QwtPlot.__init__(self)
self.setTitle("<font size=1 color=darkblue>Potentiometer Position ( 8-bit ADC value )</font>")
self.setCanvasBackground(Qt.black)
#grid
grid = QwtPlotGrid()
#grid.enableXMin(True)
#grid.enableYMin(True)
grid.setMajPen(QPen(Qt.darkGreen, 0, Qt.DotLine))
grid.setMinPen(QPen(Qt.darkGreen, 0 , Qt.DotLine))
grid.attach(self)
# x-axis
self.setAxisTitle(QwtPlot.xBottom, "<font size=1 color=darkred>time (seconds)</font>")
self.timerange = arange(0.0, 60, 0.2) #60 seconds, 200 ms interval
self.amplitudes = zeros(len(self.timerange), Float)
# curve
self.amplitude_plot = QwtPlotCurve('Amplitude')
self.setAxisScale(QwtPlot.yLeft, 0, 255) #amplitude range : 0 to 255
self.setAxisScale(QwtPlot.xBottom, 0, 60) #time range: 0 to 60 seconds
self.amplitude_plot.setPen(QPen(Qt.yellow))
self.amplitude_plot.attach(self)

def updatePlot(self, new_value=0):
# shift amplitude array left and assign new value to z[n-1].
self.amplitudes = concatenate((self.amplitudes[1:], self.amplitudes[:1]), 1)
self.amplitudes[-1] = new_value
self.amplitude_plot.setData(self.timerange, self.amplitudes)
self.replot()

class MyForm(QDialog):
def __init__(self, parent = None):
super(MyForm, self).__init__(parent)
self.setWindowTitle("USB-based Oscilloscope (Beta) - pYUSb + PIC18F2550")
self.setMinimumSize(560, 300)
# create widgets/controls
self.connect_btn = QPushButton('Connect')
self.toggle1_btn = QPushButton('Toggle LED1')
self.toggle2_btn = QPushButton('Toggle LED2')
self.status_label = QLabel('press "Connect" button')
self.update_timer = QTimer()

self.display = AmplitudevsTime()

layout = QGridLayout()
layout.addWidget(self.display, 0, 0, 10, 15)
layout.addWidget(self.toggle1_btn, 2, 15)
layout.addWidget(self.toggle2_btn, 2, 16)
layout.addWidget(self.connect_btn, 7, 15)
layout.addWidget(self.status_label, 4, 15, 2, 2)
self.setLayout(layout)
# widgets initial condition
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
# signals
self.connect(self.connect_btn, SIGNAL("clicked()"), self.DeviceConnect)
self.connect(self.toggle1_btn, SIGNAL("clicked()"), self.toggleLED1)
self.connect(self.toggle2_btn, SIGNAL("clicked()"), self.toggleLED2)
self.connect(self.update_timer, SIGNAL("timeout()"), self.updateDisplay)

def DeviceConnect(self):
self.device = UsbPic(0x04d8, 0x0204) # Microchip Vendor ID and Product ID
if self.device.open():
self.toggle1_btn.setEnabled(True)
self.toggle2_btn.setEnabled(True)
self.update_timer.start(200) # update every 200ms
self.status_label.setText('Connected to:\n %s' %self.device.getDeviceName())
else:
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
self.update_timer.stop()
self.status_label.setText('Warning:\n No Device Found!')
def toggleLED1(self):
self.device.write(1, [0x80], 1000)
def toggleLED2(self):
self.device.write(1, [0x82], 1000)
def updateDisplay(self):
self.device.write(1, [0x81])
byteread = self.device.read(0x81, 64)
if len(byteread)>1:
self.display.updatePlot(byteread[1])

if __name__ == "__main__":
app = QApplication(sys.argv)
form = MyForm()
form.show()
sys.exit(app.exec_())

Right now, my problem is on the 18F2550 side. I still don't know how to use both the USB and ADC interrupts together. My first modification on PIC's firmware was no success. When I enabled the ADC interrupt routine, the whole program response slows down. I still have to read properly the datasheet(plus application notes), and ask for help of the 'masters'. What I'm currently doing on the code is reading a single byte of ADC value every 200ms (very slow!). From what I've understand, the PIC can (it should) send 64 bytes for every USB interrupt read request. I don't know how fast it is, but it will surely improve the PIC18F USB-based oscilloscope.

Thursday, December 3, 2009

Portable Eric 4 Python IDE (v2)


After my first portable Eric4 IDE, here comes another portable Development Environement for Python. It's still Eric4, but this time it's now equipped with SciPy scientific tool for python (open-source software for mathematics, science, and engineering). Together with NumPy and matplotlib, scipy turns Python into a powerful language for numerical computing.

Aside from matplotlib, I also added PyQwt. They both share the same purpose - plotting graphs in python. Although matplotlib graphs are more detailed than of PyQwt, I still prefer PyQwt because it can be easily integrated to PyQt GUIs, and it has also faster response(ideal for creating GUIs). Here is a good comparison between matplotlib vs PyQwt. Also, a possibility of embedding matplotlib plots into PyQt.

I also included pySerial, pyParallel and PyUSB. These three are great for learning PC interfacing. I wasn't able to test the pyparallel module, since my machine doesn't have any LPT ports. PySerial works fine, same with previous portable IDE. For PyUSB to work, LibUsb-Win32 has still need to be installed on the host machine.

download link: Eric4 IDE Python 2.6.rar
size: ~62MB RAR file (~250MB uncompressed EXE file), tested only on WinXP
view "readme.txt" (inside the RAR file) for more information.


some scripts run on this IDE:
Ruby and Python Programming Language Thread
DSP 0.01: A tutorial

Saturday, November 21, 2009

PIC18F and PyUSB

I finally got a clearer idea on how to use the PyUSB libray. PyUSB is simply a python binding/wrapper for libusb. There are only few examples of python scripts I found on the net regarding the use of PyUSB. Also, the documentation for PyUSB is not that comprehensive yet.

On the USB device side, fortunately, Microchip has provide a LibUSB example for their PICDEM Full Speed USB demo board. Aside from the firmware for the PIC18F4550 family (includes PIC18F2550), they also provided a simple demo (Windows) application (with source codes for MSVC++ and Qt). It's a good opportunity to study LibUSB library along its generic usb device driver.
After some trial&errors on my python script, I finally made my PyQt GUI program working. (Most of my mistakes on the PyUSB module usage were the incorrect types of arguments used in the pyusb functions).

Below is my proto circuit. Basically it's the same circuit I used in my PIC18F2550 USB HID Mouse project. I only added two LEDs on RB0 and RB1 pins of pic18f2550. I also included a 10k potentiometer on RA0 pin (ADC ANA0).

I made a minimal modification on the LibUSB example firmware by Microchip so that it will be compatible with PyUSB demo python script:
 /*   
Filename: main.c
*/

/** INCLUDES *********************/
#include "Compiler.h"
#include "HardwareProfile.h"
#include "GenericTypeDefs.h"
#include "USB/usb_device.h"
#include "USB/usb.h"
#include "USB/usb_function_generic.h"
#include "usb_config.h"

/** CONFIGURATION ****************/
#pragma config PLLDIV = 5 // (20 MHz crystal on PICDEM FS USB board)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = ON
#pragma config BORV = 3
#pragma config VREGEN = ON //USB Voltage Regulator
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config XINST = OFF // Extended Instruction Set
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CPB = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRTB = OFF // Boot Block Write Protection
#pragma config WRTC = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTRB = OFF

/** VARIABLES ******************************************************/
#pragma udata USB_VARIABLES=0x500

unsigned char OUTPacket[64]; //User application buffer for receiving and holding OUT packets sent from the host
unsigned char INPacket[64]; //User application buffer for sending IN packets to the host
#pragma udata

USB_HANDLE USBGenericOutHandle;
USB_HANDLE USBGenericInHandle;
#pragma udata

/** PRIVATE PROTOTYPES *********************************************/
static void InitializeSystem(void);
void USBDeviceTasks(void);
void YourHighPriorityISRCode(void);
void YourLowPriorityISRCode(void);
void ProcessIO(void);

/** VECTOR REMAPPING ***********************************************/
#define REMAPPED_RESET_VECTOR_ADDRESS 0x00
#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x08
#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x18

#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
_asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
_asm goto YourLowPriorityISRCode _endasm
}

#pragma code
//These are your actual interrupt handling routines.
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
USBDeviceTasks();
} //This return will be a "retfie fast", since this is in a #pragma interrupt section
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
}

/** DECLARATIONS ***************************************************/
#pragma code

//////////////////////////////////////////////////////////////////////
void main(void)
{
InitializeSystem();
USBDeviceAttach();
while(1)
{
ProcessIO();
}
}

static void InitializeSystem(void)
{
ADCON1 |= 0x0F; // Default all pins to digital

USBGenericOutHandle = 0;
USBGenericInHandle = 0;

InitLEDs();
InitPot();
USBDeviceInit(); //usb_device.c. Initializes USB module SFRs and firmware variables to known states.
}

////////////////////////////////////////////////////////////
void ProcessIO(void)
{
if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
if(!USBHandleBusy(USBGenericOutHandle)) //Check if the endpoint has received any data from the host.
{
switch(OUTPacket[0]) //Data arrived, check what kind of command might be in the packet of data.
{
case 0x80: // toggle LED1 (command from PC application)
LED1 = !LED1;
break;
case 0x82: // toggle LED2
LED2 = !LED2;
break;
case 0x81: //Get potentiometer position
adc_status = 1; // start a/d conversion
INPacket[0] = 0x81;
while(adc_status); // wait for the a/d conversion to complete (or use interrupt)
INPacket[1] = ADRESH; //read only 8-bit adc value (left justified)
if(!USBHandleBusy(USBGenericInHandle))
USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,USBGEN_EP_SIZE);
break;
}

USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
}
}//end ProcessIO


/*********** USB Callback Functions ****************/
void USBCBSuspend(void)
{
}

void USBCBWakeFromSuspend(void)
{
}

void USBCB_SOF_Handler(void)
{
}

void USBCBErrorHandler(void)
{
}

void USBCBCheckOtherReq(void)
{
}

void USBCBStdSetDscHandler(void)
{
}

void USBCBInitEP(void)
{
USBEnableEndpoint(USBGEN_EP_NUM,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
}

void USBCBSendResume(void)
{
static WORD delay_count;
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do{
delay_count--;
}while(delay_count);
USBResumeControl = 0;
}

BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER:
Nop();
break;
default:
break;
}
return TRUE;
}

then, the generated hex code for PIC18F2550 device using C18 compiler:
 :020000040000FA  
:060000008AEF0AF0120075
:0600080073EF08F0120086
:06001800BEEF08F012002B
:02002A000000D4
:04002C00D9CFE6FF43
:10003000E1CFD9FFE6526A6A686A160E6F6E9F0EAC
:100040006B6E7B0E696E6D8C6E6A000EE66EE66AF4
:10005000E66A710EE66E0F0EE66E70EC0AF00B6E3D
:10006000050EE15E0B506D9CDF6ADF500B6E0C6A73
:10007000080E0B5C000E0C5810E2DF50040DF3CF9D
:10008000E9FFF4CFEAFF000EE926040EEA22EE6A49
:10009000EE6AEE6AEE6ADF2AE8D7160E706E68A680
:1000A0000CD0030EE66E680EE66E0F0EE66E39ECAF
:1000B00008F0E552E552E552F2D70001736B786B18
:1000C000796B7A6B6D98080E6B6F040E6C6F616BB9
:1000D000606BE552E552E7CFD9FF1200D9CFE6FFBA
:1000E000E1CFD9FFE6520001600507E16DBA05D006
:1000F000686A69806988020E606F6850040B0FE0BF
:100100006950040B0CE0020EE66E680EE66E0F0EF0
:10011000E66E39EC08F0E552E552E552E9D86DA2F9
:1001200002D0A19AA1D06850010B1BE06950010BCD
:1001300018E07CDF0001040E606F0401200E026FE6
:10014000040E036F080E016F006B8C0E0013E66A3D
:10015000680EE66E0F0EE66E39EC08F0E552E552D9
:10016000E5526850100B0FE06950100B0CE0A4D85A
:10017000040EE66E680EE66E0F0EE66E39EC08F0C1
:10018000E552E552E5526850400B1DE06950400BC6
:100190001AE0010EE66EE66A000EE66EE66A020EF0
:1001A000E66EE66A7DEC09F00B6E060EE15E0B5022
:1001B000060EE66E680EE66E0F0EE66E39EC08F07F
:1001C000E552E552E5526850200B04E06950200BDF
:1001D00001E04FD86850020B12E06950020B0FE0AB
:1001E000010EE66EE66A000EE66EE66AE668E6680E
:1001F0007DEC09F00B6E060EE15E0B506A6A040E90
:100200000001605D02E2A19A2FD069A62CD0DF6ABE
:10021000040EDF5C28E268A625D06CCF80F0030EC8
:10022000E66E680EE66E0F0EE66E39EC08F0E552EB
:10023000E552E552780E0001801502E178D810D021
:10024000000EE66EE66A800EE66E000EE66E010EA9
:10025000E66EE66A7DEC09F00B6E060EE15E0B5071
:10026000DF2AD6D700D0A19AE552E552E7CFD9FFD1
:10027000120070A015D063C0E9FF64C0EAFFEF5020
:1002800080080DE16BC0E9FF6CC0EAFFEF50840805
:1002900006E163C0E9FF64C0EAFF8C0EEF6E709068
:1002A000050EE66E680EE66E0F0EE66E39EC08F08F
:1002B000E552E552E55212006984040EE66E680EBE
:1002C000E66E0F0EE66E39EC08F0E552E552E552A7
:1002D0006D82000EE66EE66AE66EE66A040EE66E73
:1002E000E66A7DEC09F00B6E060EE15E0B50120023
:1002F000000EE66EE66AE66EE66A030EE66EE66AF3
:100300007DEC09F00B6E060EE15E0B506D92699468
:1003100068A40CD0020EE66E680EE66E0F0EE66E56
:1003200039EC08F0E552E552E552F2D71200D9CF88
:10033000E6FFE1CFD9FFE652FD0E000180155AE13C
:100340007E0E8015E8407F0B040DF3CF63F0F4CFF1
:1003500064F0000E6327040E642363C065F064C07C
:1003600066F0657563C0E9FF64C0EAFFEF503C0BBF
:10037000E842E8420D083CE163C0E9FF64C0EAFFDF
:10038000020EE926000EEA22EECF0BF0EFCF0CF0C2
:10039000280E0B1802E1040E0C1828E163C0E9FFD7
:1003A00064C0EAFF020EE926000EEA22200EEE6E7D
:1003B000040EED6EDF6ADF500B6E0C6A080E0B5CEC
:1003C000000E0C5813E2DF50EA6A280FE96E040EA3
:1003D000EA22EF50E66EDF50EA6A200FE96E040E63
:1003E000EA22E552E750EF6EDF2AE5D70DD801D0BB
:1003F0002ED805D0FD0E8015040801E14ED8E55237
:10040000E552E7CFD9FF12006BC0E9FF6CC0EAFFED
:10041000EF50800B05E06BC0E9FF6CC0EAFFEF6AAC
:1004200000016F6B706B746B756B736BB6D8000EDD
:10043000E66EE66AE66EE66A170EE66EE66A7DEC42
:1004400009F00B6E060EE15E0B5079EF04F0020E20
:100450000001705D02E1ADDB1FD06CD8000181515D
:100460001AE165C0E9FF66C0EAFFEE52080EEF6EC2
:1004700065C0E9FF66C0EAFF020EE926000EEA2227
:10048000200EEE6E040EED6E65C0E9FF66C0EAFF59
:100490008C0EEF6E01D0816B1200D9CFE6FFE1CF59
:1004A000D9FFE6526BC0E9FF6CC0EAFFEF50400B8A
:1004B00001E0010EDF6E00016B75080E605D0AE160
:1004C00022C46EFF6E50000803E2100E606F02D06F
:1004D000040E606F700528E16BC0E9FF6CC0EAFF95
:1004E000020EE926000EEA22280EEE6E040EED6ED4
:1004F000D5DA020E00016F5D07E16BC0E9FF6CC049
:10050000EAFF840EEF6E0FD0DF5007E16BC0E9FF0A
:100510006CC0EAFFC80EEF6E06D06BC0E9FF6CC07E
:10052000EAFF880EEF6E01D005D8E552E552E7CF1D
:10053000D9FF1200D9CFE6FFE1CFD9FF020EE126A5
:100540000001706B6BC0E9FF6CC0EAFFEF6A040E3C
:100550006B190B6E6CC00CF00BC0DEFF0CC0DDFF26
:10056000DECFE9FFDDCFEAFFEF6A78AF0CD07B5139
:100570007C1107E005D07CC0FAFF00017B51F96EC9
:10058000FADF0001789F020EE15C02E2E16AE552C7
:10059000E16EE552E7CFD9FF120004012051600B54
:1005A000E842E842E842E842E842000901E058D067
:1005B00021510C0A54E00B0A43E00C0A35E0010A11
:1005C00026E00B0A22E0020A20E0030A1CE0080AE7
:1005D00010E0010A0CE00F0A08E0030A01E03FD036
:1005E0000001738F080E606F3BD0C8D839D07FDB15
:1005F00037D00001610E716F000E726F7381010EB2
:10060000746F738F2DD014D92BD02BD829D02451AF
:100610000001716F726B620E7127000E722373817D
:10062000010E746F738F1CD00001738F040124516D
:10063000EA6A620FE96E000EEA2222C4EFFF10D0D0
:10064000000EE66EE66AE66EE66A160EE66EE66A8C
:100650007DEC09F00B6E060EE15E0B5001D000D070
:100660001200D9CFE6FFE1CFD9FF040EE126040145
:10067000220510E120511F0B00090CE10001738FCE
:10068000030E0401215D04E10001010E7F6F02D021
:1006900000017F6B0401225167E120511F0B02080A
:1006A00063E124510F0B00095FE00001738F040127
:1006B00024BF10D024510F0BE96EEA6AD890E936B6
:1006C000EA36670EE926000EEA22EECFDEFFEDCF16
:1006D000DDFF0FD024510F0BE96EEA6AD890E9369E
:1006E000EA366B0EE926000EEA22EECFDEFFEDCFF2
:1006F000DDFF030E215D07E1DECFE9FFDDCFEAFF7D
:10070000840EEF6E31D024510F0B0C6A700F0B6EFC
:100710000F0E0C22020E0BC0DBFF030E0CC0DBFF22
:10072000020EDBCFE9FF030EDBCFEAFFEE90ED52C6
:1007300024AF0DD0DECFE9FFDDCFEAFFEF6ADF7433
:10074000DECFE9FFDDCFEAFF400EEF6E0DD0DECF4A
:10075000E9FFDDCFEAFF880EEF6EDF74DECFE9FF41
:10076000DDCFEAFFC80EEF6E040EE15C02E2E16A43
:10077000E552E16EE552E7CFD9FF1200800E040189
:10078000205D55E10001C00E736F04012351030A7F
:100790002EE0010A0EE0030A03E00001736B47D06C
:1007A0000001900E716F130E726F120E746F756BE5
:1007B0003ED02251F66EF76AD890F636F7363A0EEA
:1007C000F626140EF7220900F5CF71F00A00F5CFD6
:1007D00072F0020E0001F76A7125F66E7251F7226F
:1007E0000900F5CF74F00A00F5CF75F020D0030EA4
:1007F000225D1AE22251F66EF76AD890F636F73685
:100800003C0EF626140EF7220900F5CF71F00A000F
:10081000F5CF72F071C0F6FF72C0F7FF0800F55017
:100820000001746F756B02D00001736B00D0120071
:10083000D9CFE6FFE1CFD9FF020EE1260401286BF4
:10084000296B20511F0B020A12E0030A0DE0010A76
:1008500001E03BD00001738F0401288100017F0576
:1008600002E10401288331D00001738F2ED00001F2
:10087000738F040124BF10D024510F0BE96EEA6A74
:10088000D890E936EA36670EE926000EEA22EECF66
:10089000DEFFEDCFDDFF0FD024510F0BE96EEA6ACA
:1008A000D890E936EA366B0EE926000EEA22EECF42
:1008B000DEFFEDCFDDFFDECFE9FFDDCFEAFFEF505A
:1008C000040B02E0010E286F00D0000173AF07D0C7
:1008D000280E716F040E726F7381020E746F020E18
:1008E000E15C02E2E16AE552E16EE552E7CFD9FF51
:1008F00012006D98000173BF4AD078AF28D0020E65
:10090000706F6BC0E9FF6CC0EAFFEE52EF6A6BC01C
:10091000E9FF6CC0EAFFC80EEF6E65C0E9FF66C074
:10092000EAFFEE52080EEF6E65C0E9FF66C0EAFF0F
:10093000020EE926000EEA22280EEE6E040EED6E7F
:1009400065C0E9FF66C0EAFFC80EEF6E1FD065C044
:10095000E9FF66C0EAFFEE52080EEF6E65C0E9FFE0
:1009600066C0EAFF020EE926000EEA22200EEE6EB5
:10097000040EED6E65C0E9FF66C0EAFF8C0EEF6EF7
:100980006BC0E9FF6CC0EAFF840EEF6E86D078BFC3
:1009900084D0040120AF59D0000174510401265DB8
:1009A000000175510401275904E226C474F027C4DC
:1009B00075F074D80001010E706F65C0E9FF66C064
:1009C000EAFFEE52080EEF6E65C0E9FF66C0EAFF6F
:1009D000020EE926000EEA22200EEE6E040EED6EE7
:1009E00065C0E9FF66C0EAFF800EEF6E816B63C0F1
:1009F000E9FF64C0EAFFEE52080EEF6E63C0E9FF44
:100A000064C0EAFF020EE926000EEA22200EEE6E16
:100A1000040EED6E63C0E9FF64C0EAFF840EEF6E62
:100A2000010E816F6BC0E9FF6CC0EAFF020EE92680
:100A3000000EEA22280EEE6E040EED6E6BC0E9FF8A
:100A40006CC0EAFFC80EEF6E28D00001020E706F76
:100A50006BC0E9FF6CC0EAFFEE52EF6A6BC0E9FFC2
:100A60006CC0EAFFC80EEF6E65C0E9FF66C0EAFF22
:100A7000EE52080EEF6E65C0E9FF66C0EAFF020E97
:100A8000E926000EEA22280EEE6E040EED6E65C019
:100A9000E9FF66C0EAFFC80EEF6E1200D9CFE6FF8D
:100AA000E1CFD9FF020EE1260001080E745D000EB1
:100AB00075590EE274C0DEFF75C0DDFF6F5103E1B2
:100AC000010E6F6F04D06F0502E1020E6F6F03D04D
:100AD000080EDE6EDD6A6BC0E9FF6CC0EAFFEF92C4
:100AE0006BC0E9FF6CC0EAFFEF906BC0E9FF6CC020
:100AF000EAFF010EDB50EF126BC0E9FF6CC0EAFFAA
:100B0000EE52DFCFEFFF000EDB50745F010EDB50C3
:100B1000755B280E7D6F040E7E6F73B121D0D9CF27
:100B2000E9FFDACFEAFFEE50ED1019E071C0F6FFF1
:100B300072C0F7FF712B000E72230800F550E66EAD
:100B40007DC0E9FF7EC0EAFF7D2B000E7E23E552CB
:100B5000E750EF6EDF06010E01E2DB06E0D71FD0A3
:100B6000D9CFE9FFDACFEAFFEE50ED1018E071C0FF
:100B7000E9FF72C0EAFF712B000E7223EF50E66EA0
:100B80007DC0E9FF7EC0EAFF7D2B000E7E23E5528B
:100B9000E750EF6EDF06010E01E2DB06E1D7020E41
:100BA000E15C02E2E16AE552E16EE552E7CFD9FF8E
:100BB0001200D9CFE6FFE1CFD9FF020EE12663C0D4
:100BC000E9FF64C0EAFFEE52EFCFDFFFDFCF0BF0AB
:100BD0000B500001795D000E7A5903E279C0DFFF06
:100BE00009D0DF500B6E0C6A0B50795D796F0C5099
:100BF0007A597A6F010EDB6ADF50F36E010EDBCF9C
:100C0000F4FFF350F45C16E2010EDB50EA6A280FA1
:100C1000E96E040EEA22EF50E66E76C0E9FF77C077
:100C2000EAFF762B000E7723E552E750EF6E010EB8
:100C3000DB2AE2D7000ED8807955000E7A5528E2DB
:100C400065C0E9FF66C0EAFFEE52080EEF6E65C0B0
:100C5000E9FF66C0EAFF020EE926000EEA22280E2E
:100C6000EE6E040EED6E63C0E9FF64C0EAFFEF5064
:100C7000400B07E165C0E9FF66C0EAFFC80EEF6EF2
:100C800006D065C0E9FF66C0EAFF880EEF6E25D08A
:100C900065C0E9FF66C0EAFFEE52080EEF6E65C060
:100CA000E9FF66C0EAFF020EE926000EEA22200EE6
:100CB000EE6E040EED6E65C0E9FF66C0EAFF840EBD
:100CC000EF6E7B517C1107E005D07CC0FAFF00017C
:100CD0007B51F96EFADF0001789F020EE15C02E2BF
:100CE000E16AE552E16EE552E7CFD9FF120000015B
:100CF000738F000EE66EE66AE66A710EE66E0F0E00
:100D0000E66E70EC0AF00B6E050EE15E0B50010E04
:100D1000E66EE66AE66A620EE66E000EE66E70EC5D
:100D20000AF00B6E050EE15E0B5022C461F0040167
:100D3000225104E10001100E606F11D00001200E5D
:100D4000606F000EE66EE66AE66EE66A150EE66E07
:100D5000E66A7DEC09F00B6E060EE15E0B501200A8
:100D6000D9CFE6FFE1CFD9FF020EE126000EDE6EFD
:100D7000040EDD6EFD0EDB50E8240D6EFE0EDB5022
:100D8000040DF3500D24040DF3500B6E0C6A020E8B
:100D90000F0B05E0D8900C320B32E806FBE1D8903F
:100DA0000B360C36D8900B360C36D9CFE9FFDACF9C
:100DB000EAFF0B50EE260C50ED22DECFE9FFDDCF2F
:100DC000EAFFEF9EFD0EDB500FE1FE0EEA6ADB3418
:100DD000FE0BEA36E96E670EE926000EEA22DECF48
:100DE000EEFFDDCFEDFF0ED0FE0EEA6ADB34FE0B28
:100DF000EA36E96E6B0EE926000EEA22DECFEEFF40
:100E0000DDCFEDFFDECFE9FFDDCFEAFFEF9CDECFE8
:100E1000E9FFDDCFEAFF040EE926000EEA22EF8C9F
:100E2000020EE15C02E2E16AE552E16EE552E7CFD3
:100E3000D9FF1200D9CFE6FFE1CFD9FF020EE1269C
:100E4000FE0EDB500C6A700F0B6E0F0E0C220BC0E7
:100E5000DEFF0CC0DDFFDECFE9FFDDCFEAFFFD0ED8
:100E6000DBCFEFFFDBA407D0E66AFE0EDBCFE6FFA9
:100E700077DFE552E552FD0EDBA208D0010EE66EEB
:100E8000FE0EDBCFE6FF6CDFE552E552020EE15CC1
:100E900002E2E16AE552E16EE552E7CFD9FF1200C6
:100EA000D9CFE6FFE1CFD9FF020EE126FE0EDB50DF
:100EB00020E165C0E9FF66C0EAFFEE52080EEF6E62
:100EC00065C0E9FF66C0EAFF020EE926000EEA22CD
:100ED000200EEE6E040EED6E65C0E9FF66C0EAFFFF
:100EE0008C0EEF6E6BC0E9FF6CC0EAFF840EEF6EF4
:100EF0003DD0FD0EDB50E8240D6EFE0EDB50040DE0
:100F0000F3500D24040DF3CF0BF0F4CF0CF0000ED2
:100F10000B26040E0C220BC0DEFF0CC0DDFF840E7E
:100F20000B6EDECFE9FFDDCFEAFF0B50EF12FD0EB7
:100F3000DB50E8240D6EFE0EDB50040DF3500D2443
:100F4000010F040DF3CF0BF0F4CF0CF0000E0B26C5
:100F5000040E0C220BC0DEFF0CC0DDFF840E0B6EF6
:100F6000DECFE9FFDDCFEAFF0B50EF12020EE15CAE
:100F700002E2E16AE552E16EE552E7CFD9FF1200E5
:100F8000D9CFE6FFE1CFD9FF020EE126FD0EDB50FF
:100F90000FE0FE0EEA6ADB34FE0BEA36E96E6B0EFA
:100FA000E926000EEA22EECFDEFFEDCFDDFF0ED008
:100FB000FE0EEA6ADB34FE0BEA36E96E670EE926BE
:100FC000000EEA22EECFDEFFEDCFDDFFDECFE9FF40
:100FD000DDCFEAFF020EE926000EEA22FB0EDBCF90
:100FE000EEFFFC0EDBCFEDFFDECFE9FFDDCFEAFF4A
:100FF000EE52FA0EDBCFEFFF400E0B6EDECFE9FFB5
:10100000DDCFEAFF0B50EF16880E0B6EDECFE9FF47
:10101000DDCFEAFF0B50EF12FD0EDB500CE0FE0EB1
:10102000EA6ADB34FE0BEA36E96E6B0EE926000E47
:10103000EA22EF740BD0FE0EEA6ADB34FE0BEA36CE
:10104000E96E670EE926000EEA22EF74DECF0BF0A0
:10105000DDCF0CF00BC0F3FF0CC0F4FF020EE15C1F
:1010600003E200D0E16AE552E16EE552E7CFD9FF35
:101070001200D9CFE6FFE1CFD9FF010EF36EFC0ECF
:10108000DB5004E0D890F336E806FCE1F350E81CAE
:101090000B6EFD0EDBCFE9FFFE0EDBCFEAFF0B5040
:1010A000EF16E552E7CFD9FF120005D06D6A696AE5
:1010B0000001606B00D012000001605113E16D6A05
:1010C000696A160E6F6E9F0E6B6E7B0E696ED08E08
:1010D000A28AA08AF28E6DB602D06D86FCD700017E
:0610E000010E606F12001A
:0A10E600DACFE4FFE2CFDAFFE9CF32
:1010F000E4FFEACFE4FFF6CFE4FFF7CFE4FFF5CF5C
:10110000E4FFF3CFE4FFF4CFE4FFFACFE4FF00EE17
:1011100000F00B0EE80403E3EECFE4FFFBD700EE94
:101120000BF0030EE80403E3EECFE4FFFBD7E65237
:101130006EEC00F0E55200EE0DF0030EE80403E360
:10114000E5CFEDFFFBD700EE0AF00B0EE80403E35A
:10115000E5CFEDFFFBD7E5CFFAFFE5CFF4FFE5CF15
:10116000F3FFE5CFF5FFE5CFF7FFE5CFF6FFE5CFDE
:10117000EAFFE5CFE9FFE5CFDAFF1100D8CFE4FFC2
:10118000E0CFE4FFE46EDACFE4FFE2CFDAFFE6522D
:10119000E552E5CFDAFFE550E5CFE0FFE5CFD8FF38
:1011A000100005D85CEC08F014D8FED712000F0E22
:1011B000C1120001906B916B926B936BFC0E8A16BF
:1011C000931692800E0EC16EC06E010EC26E16EFA7
:1011D00000F0200E0001605D03E36D50020B01E0A2
:1011E0005BD000019051911102E1000E08D090C037
:1011F000E9FF91C0EAFFEF50800B01E0010E00090A
:101200004BE105010051810A09E0030A05E0020AE9
:1012100001E02FD08A702DD08A722BD0C282810E2D
:10122000406FC2B2FED7C4CF41F500019251931175
:1012300002E1000E08D092C0E9FF93C0EAFFEF5030
:10124000800B01E0010E000913E1400EE66E400E36
:10125000E66E050EE66E010EE66EE66EC0EC07F079
:101260000B6E050EE15E0B50F3CF92F0F4CF93F0CE
:1012700000D0400EE66E000EE66E050EE66EE66AE3
:10128000010EE66EC0EC07F00B6E050EE15E0B5032
:10129000F3CF90F0F4CF91F0120012001200120080
:1012A0001200120012001E0EE66E010EE66E1AEC1F
:1012B00007F0E552E552400EE66E000EE66E050EB2
:1012C000E66EE66A010EE66EC0EC07F00B6E050EE8
:1012D000E15E0B50F3CF90F0F4CF91F012006D84EB
:1012E0000001080E946F070E956F9407000E955B32
:1012F00094519511FAE16D941200D9CFE6FFE1CF38
:10130000D9FFFD0EDBCF06F0FE0EDBCF07F0010E9E
:10131000061801E1075033E0E868061802E1E868C2
:1013200007182BE0030E061801E1075024E0040E15
:10133000061801E107501DE0020E061801E10750F2
:1013400016E0170E061801E107500FE0160E0618FA
:1013500001E1075008E0150E061801E1075001E011
:1013600010D0A1DF0FD09EDF0DD09BDF0BD097DF19
:1013700009D093DF07D092DF05D092DF03D00000C1
:1013800001D000D0010E00D0E552E7CFD9FF120006
:101390001201000200000008D8040402000001024B
:1013A000000109022000010100C03209040000020E
:1013B000FFFFFF0007050102400001070581024011
:1013C00000010403090434034D0069006300720046
:1013D0006F00630068006900700020005400650021
:1013E000630068006E006F006C006F00670079009A
:1013F000200049006E0063002E0040034D0069008C
:10140000630072006F0063006800690070002000D4
:101410004C00690062007500730062002000450006
:10142000780061006D0070006C00650020004400D1
:1014300065007600690063006500A213C213C6133D
:02144000FA139D
:0E1442002A0EF66E000EF76E000EF86E000118
:101450000900F5508B6F0900F5508C6F03E18B6725
:1014600001D03DD00900F550866F0900F550876F17
:101470000900F550886F09000900F550E96E090070
:10148000F550EA6E090009000900F550896F09005E
:10149000F5508A6F09000900F6CF8DF0F7CF8EF076
:1014A000F8CF8FF086C0F6FF87C0F7FF88C0F8FF3F
:1014B0000001895302E18A5307E00900F550EE6EFE
:1014C0008907F8E28A07F9D78DC0F6FF8EC0F7FFCB
:1014D0008FC0F8FF00018B07000E8C5BBFD7120096
:1014E000FE0EE3CFE9FFFF0EE3CFEAFFE9CFF3FF04
:1014F000EACFF4FFFB0EE35003E1FC0EE35009E0FA
:10150000FB0EE30602E2FC0EE306FD0EE350EE6E78
:04151000F1D71200FD
:0C15140013EE00F023EE00F0F86A0A9CD1
:1015200021EC0AF098EC0AF0D1EC08F0FBD712009D
:021530001200A7
:020000040030CA
:0100000024DB
:010001000EF0
:010002003FBE
:010003001EDE
:010005008179
:010006008178
:010008000FE8
:01000900C036
:01000A000FE6
:01000B00E014
:01000C000FE4
:01000D0040B2
:00000001FF


here's my python script for PyUSB (also uses PyQt for the GUI):
 ###########################################  
# PyUSB and PIC18F2550 demo (first revision) #
# Julius 'yus' Constante Nov. 21, 2009 #
###########################################

import sys, usb
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class UsbPic:
def __init__(self, vendor_id, product_id):
busses = usb.busses() # enumerate busses
self.handle = None
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.idVendor==vendor_id and dev.idProduct==product_id: # device matches
self.dev = dev
self.conf = self.dev.configurations[0]
self.intf = self.conf.interfaces[0][0]
self.endpoints = []
for endpoint in self.intf.endpoints:
self.endpoints.append(endpoint)
return

def open(self):
if self.handle:
self.handle = None
try:
self.handle = self.dev.open()
self.handle.detachKernelDriver(0)
self.handle.detachKernelDriver(1)
self.handle.setConfiguration(self.conf)
self.handle.claimInterface(self.intf)
self.handle.setAltInterface(self.intf)
return True
except:
return False

def write(self, ep, buff, timeout = 100):
try:
return self.handle.interruptWrite(ep, buff, timeout) #return bytes written
except:
return 0
def read(self, ep, size, timeout = 100):
try:
return self.handle.interruptRead(ep, size, timeout) # return data read
except:
return []
def getDeviceName(self):
return self.handle.getString(2, 40)

class SimpleForm(QDialog):
def __init__(self, parent = None):
super(SimpleForm, self).__init__(parent)
self.setWindowTitle('PIC18F and PyUSB')
self.setMinimumSize(270, 180)
# create widgets/controls
self.connect_btn = QPushButton('Connect')
self.toggle1_btn = QPushButton('Toggle LED1')
self.toggle2_btn = QPushButton('Toggle LED2')
self.pot_position = QDial()
self.pot_label = QLabel('Potentiometer Position')
self.status_label = QLabel(' press "Connect" button')
self.update_timer = QTimer()
# form layout and widgets location
layout = QGridLayout()
layout.addWidget(self.connect_btn, 9, 0, 2, 1)
layout.addWidget(self.pot_position, 0, 0, 8, 7)
layout.addWidget(self.pot_label, 8, 0, 1, 7)
layout.addWidget(self.toggle1_btn, 4, 7)
layout.addWidget(self.toggle2_btn, 5, 7)
layout.addWidget(self.status_label, 9, 1, 2, 7)
self.setLayout(layout)
# widgets initial condition
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
self.pot_position.setEnabled(False) #read only
self.pot_position.setNotchesVisible(True)
self.pot_position.setRange(0, 255) # for PIC 8-bit ADC value
self.pot_label.setAlignment(Qt.AlignHCenter)
# signals
self.connect(self.connect_btn, SIGNAL("clicked()"), self.DeviceConnect)
self.connect(self.toggle1_btn, SIGNAL("clicked()"), self.toggleLED1)
self.connect(self.toggle2_btn, SIGNAL("clicked()"), self.toggleLED2)
self.connect(self.update_timer, SIGNAL("timeout()"), self.updatePotPosition)

def DeviceConnect(self):
self.device = UsbPic(0x04d8, 0x0204) # Microchip Vendor ID and Product ID
if self.device.open():
self.toggle1_btn.setEnabled(True)
self.toggle2_btn.setEnabled(True)
self.update_timer.start(200) # update every 200ms
self.status_label.setText('Connected to:\n %s' %self.device.getDeviceName())
else:
self.toggle1_btn.setEnabled(False)
self.toggle2_btn.setEnabled(False)
self.update_timer.stop()
self.status_label.setText('Warning:\n No Device Found!')

def toggleLED1(self):
self.device.write(1, [0x80], 1000)

def toggleLED2(self):
self.device.write(1, [0x82], 1000)

def updatePotPosition(self):
self.device.write(1, [0x81])
byteread = self.device.read(0x81, 64)
if len(byteread)>1:
self.pot_position.setValue(byteread[1])

if __name__ == '__main__':
app = QApplication(sys.argv)
form = SimpleForm()
form.show()
sys.exit(app.exec_())



And finally, the actual circuit in action:


additional useful links:
Microchip USB Framework for PIC18, PIC24 & PIC32
LibUSB Win32

Sunday, November 15, 2009

PIC18F2550 USB HID Mouse

As my first step in learning on how to interface on PC USB ports, I copied the example source code for usb hid mouse by CCS C compiler. It's just a simple demo, moving the mouse pointer into a circular pattern, but it already gave me enough confidence because this example code works on my simple circuit. Since there's no problem with the circuit, I've continued with the next step which is the familiarization with the code routines/functions by modifying them (i.e. experimenting with the example code).

CCS C uses the usb_put_packet() command to send one packet to the usb host(PC), e.g. usb_put_packet(1, out_data, 4, USB_DTS_TOGGLE). The out_data parameter is an array of 4 elements (i.e. int8 out_data[4]). The first byte of out_data correspond to the state of mouse buttons, the second and third are for the x and y directions, while the last byte is for mouse wheel.

After experimenting with the usb_put_packet() function, I came up with this modified demo code for usb hib mouse. Instead of only moving the mouse pointer, I've configured it to 'draw some lines' on Microsoft Paint. And this was the result:


Here's the code used in that demo video:
 // USB HID Mouse draws "usb pic18F2550" on MS Paint
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

#define USB_HID_DEVICE TRUE
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT
#define USB_EP1_TX_SIZE 8
#include <pic18_usb.h>
#include <usb_desc_mouse.h>
#include <usb.c>

#define delay 20
#define scale 17
void draw_vertical(int8 direction)
{
int8 data[4], count = 0;
data[0] = 1;
data[1] = 0;
data[2] = direction;
data[3] = 0;
while(count<scale){
 if(usb_put_packet(1, data,4,USB_DTS_TOGGLE)) count++;
 delay_ms(delay);
}
}
void draw_horizontal(int8 direction)
{
int8 data[4], count = 0;
data[0] = 1;
data[1] = direction;
data[2] = 0;
data[3] = 0;
while(count<scale){
 if(usb_put_packet(1, data,4,USB_DTS_TOGGLE)) count++;
 delay_ms(delay);
}
}
void move_pointer(int8 x_direction, int8 y_direction)
{
int8 data[4], count = 0;
data[0] = 0;
data[1] = x_direction;
data[2] = y_direction;
data[3] = 0;
while(count<scale){
 if(usb_put_packet(1, data,4,USB_DTS_TOGGLE)) count++;
 delay_ms(delay);
}
}
void main(void)
{
usb_init_cs();

while (TRUE) {
 usb_task();
 if (usb_enumerated())
 {
   // 'u'
   draw_vertical(5);
   draw_horizontal(4);
   draw_vertical(-5);
   // 's'
   move_pointer(1,5);
   draw_horizontal(5);
   draw_vertical(-3);
   draw_horizontal(-4);
   draw_vertical(-3);
   draw_horizontal(4);
   // 'b'
   move_pointer(2,-4);
   draw_vertical(8);
   draw_horizontal(4);
   draw_vertical(-5);
   draw_horizontal(-4);
   // 'p'
   move_pointer(7,4);
   draw_horizontal(4);
   draw_vertical(-3);
   draw_horizontal(-4);
   draw_vertical(6);
   // 'i'
   move_pointer(5,-3);
   draw_vertical(-4);
   // 'c'
   move_pointer(4,3);
   draw_horizontal(-3);
   draw_vertical(-3);
   draw_horizontal(3);
   // '1'
   move_pointer(2,-4);
   draw_vertical(6);
   // '8'
   move_pointer(2,-3);
   draw_vertical(-3);
   draw_horizontal(3);
   draw_vertical(3);
   draw_horizontal(-3);
   draw_vertical(3);
   draw_horizontal(3);
   draw_vertical(-3);
   // 'F'
   move_pointer(2,4);
   draw_vertical(-7);
   draw_horizontal(4);
   move_pointer(-1,3);
   draw_horizontal(-3);
   // '2'
   move_pointer(4,-1);
   draw_horizontal(3);
   draw_vertical(3);
   draw_horizontal(-3);
   draw_vertical(3);
   draw_horizontal(3);
   // '5'
   move_pointer(2,0);
   draw_horizontal(3);
   draw_vertical(-3);
   draw_horizontal(-3);
   draw_vertical(-3);
   draw_horizontal(3);
   // '5'
   move_pointer(5,0);
   draw_horizontal(-3);
   draw_vertical(3);
   draw_horizontal(3);
   draw_vertical(3);
   draw_horizontal(-3);
   // '0'
   move_pointer(5,0);
   draw_vertical(-5);
   draw_horizontal(3);
   draw_vertical(5);
   draw_horizontal(-3);
   // line
   move_pointer(0,7);
   draw_horizontal(-22);
   draw_vertical(2);
   draw_horizontal(22);
  
  
   delay_ms(5000);
 }
}
}

then the HEX file generated using CCS Microchip C PCH v4.088 compiler:
 :020000040000FA  
 :040000005EEF07F0B8  
 :08000800056ED8CF06F0E0CF31  
 :1000100007F00001E9CF0DF0EACF08F0E1CF09F0D9  
 :10002000E2CF0AF0D9CF0BF0DACF0CF0F3CF14F017  
 :10003000F4CF15F0FACF16F000C00FF001C010F0A9  
 :1000400002C011F003C012F004C013F0A0AA2CEFFC  
 :1000500000F0A1BA2EEF06F00FC000F010C001F0C2  
 :1000600011C002F012C003F013C004F00DC0E9FF8C  
 :1000700008C0EAFF088E09C0E1FF0AC0E2FF0BC01A  
 :10008000D9FF0CC0DAFF14C0F3FF15C0F4FF16C08F  
 :10009000FAFF055007C0E0FF06C0D8FF1000F76A5E  
 :1000A000AE0FF66E000EF7220900F55012000403A1  
 :1000B0000000000000000000000000000000F76ADF  
 :1000C000CE0FF66E000EF7220900F5501200040064  
 :1000D0000000000000000000000000000000F76ABF  
 :1000E000EE0FF66E000EF7220900F55012004000E8  
 :1000F00008000000000000000000000000000000F8  
 :100100000000000000000000000000000000F76A8E  
 :100110001E0FF66E010EF7220900F5501200400086  
 :1001200000000000000000000000000000000000CF  
 :100130000000000000000000000000000000F76A5E  
 :100140004E0FF66E010EF7220900F5501200050160  
 :100150000902A1010901A1000509190129031500DE  
 :100160002501950375018102950175058101050140  
 :100170000930093109381581257F750895038106F5  
 :10018000C0C0F76A920FF66E010EF7220900F55013  
 :1001900012000000F76AA40FF66E010EF7220900A4  
 :1001A000F55012003400F76AB60FF66E010EF72212  
 :1001B0000900F550120009022200010100C03209B5  
 :1001C00004000001030102000921000100012234A2  
 :1001D000000705810308000AF76AE80FF66E010EB2  
 :1001E000F7220900F55012000100F76AFA0FF66EC7  
 :1001F000010EF7220900F550120012011001000053  
 :10020000004061042200000101020001F76A1C0F96  
 :10021000F66E020EF7220900F550120000040C00E1  
 :10022000F76A300FF66E020EF7220900F550120041  
 :100230000403090408034300430053001C03430064  
 :1002400043005300200055005300420020004D00A1  
 :100250006F007500730065006D926994689439EFC2  
 :1002600006F06A6A689242EF06F03E6A3E520AE180  
 :10027000036A3E50240FE96E000E0320EA6EEF6A17  
 :100280003E2AF4D71A6A010E1B6E196A000C010E81  
 :10029000476E47500F080EE3700E4724016E0F0E95  
 :1002A000036ED8B0032A01C0E9FF03C0EAFFEF6A7A  
 :1002B000472AEFD71E6A1D6A000C400E0401016F29  
 :1002C000050E036F026B880E006F046B050E076F3F  
 :1002D000400E066F0001000C6A6A686A9F0E6B6E22  
 :1002E000390E696E6E6AC1DFD2DF160E706E68A6B7  
 :1002F00002D06896FCD76D98E0DF030E1F6E48EFC2  
 :1003000006F0698468986D824EEF06F0689C54EFA1  
 :1003100006F070A002D0D1DF7090689A5AEF06F014  
 :1003200042C020F0000CFF0E206E000C406A2352E9  
 :100330003EE040503F083BE31C50FC0F2BE2040F13  
 :10034000E1EF01F0036A2250F2CF42F0F29E2BDF80  
 :1003500042BEF28E416E1ED0036A2250F2CF42F0AE  
 :10036000F29EEDDE42BEF28E416E14D0036A225040  
 :10037000F2CF42F0F29E54DF42BEF28E416E0AD0BE  
 :10038000036A2250F2CF42F0F29E2FDF42BEF28E7D  
 :10039000416E00D0222A23064050402A036A400FB3  
 :1003A000E96E050E0320EA6E41C0EFFFC0D723526D  
 :1003B00004E14050400801E0196A40C042F0B0DF5B  
 :1003C000000CE824F76AF736DD0FF66E030EF7220D  
 :1003D0000A00F550FA6E0800F550F96E4403580310  
 :1003E0006C038003226A1C6A05010351010A0001A3  
 :1003F00009E0030A0CE0010A0DE0220A22E0030AE8  
 :1004000032E058D0120E236E030E1C6E55D0220E11  
 :10041000236E52D0020E1C6E036A05010251F2CF08  
 :1004200040F0F29E0001F2DE40BEF28E226E036AC0  
 :100430002250F2CF40F0F29EF3DE40BEF28E236EE9  
 :100440003BD0120E226E223C01D00BD0036A225008  
 :10045000F2CF40F0F29EA7DE40BEF28E236E2CD08B  
 :1004600002D061DF35D0D89005010435036AF2CFA0  
 :1004700040F0F29E000185DE0900F5CF03F040BE9A  
 :10048000F28E226E223C01D013D0010E1C6ED89049  
 :1004900005010435036AF2CF40F0F29E00017ADED6  
 :1004A0000900F5CF03F040BEF28E236E05D002D0D6  
 :1004B0003ADF0ED038DF0CD00501075305E1235099  
 :1004C000065D02E206C523F0010E196E00012EDF63  
 :1004D000000C3F5204E1040E1F6ED9DEC1D0050EA0  
 :1004E0001F6E426E800E416E010E406E40500F082E  
 :1004F000D8A0B6D0436A036A4050F2CF47F0F29ECC  
 :10050000DEDD47BEF28E000A51E0040E436ED89045  
 :100510004034036AF2CF47F0F29EF9DD0900F5CFCF  
 :1005200003F047BEF28E446E03C045F04050080D04  
 :10053000F350010F016E040E036ED8B0032A01C000  
 :10054000E9FF03C0EAFF44C0EFFF4050080DF3503D  
 :10055000020F016E040E036ED8B0032A01C0E9FF3A  
 :1005600003C0EAFF42C0ECFFED5241C0EFFFD8905C  
 :100570004034036AF2CF47F0F29EC9DD0900F5CF9F  
 :1005800003F047BEF28E412603504222880E466E8B  
 :1005900045B0468045B246824050080DF3CF01F089  
 :1005A000040E01C0E9FFEA6E46C0EFFF036A405047  
 :1005B000F2CF47F0F29E73DD47BEF28E000A31E0C3  
 :1005C00043824050080DF350060F016E040E036E77  
 :1005D000D8B0032A01C0E9FF03C0EAFF42C0ECFF24  
 :1005E000ED5241C0EFFFD8904034036AF2CF47F09C  
 :1005F000F29E75DD0900F5CF03F047BEF28E41266D  
 :10060000035042224050080DF350040F016E040EB7  
 :10061000036ED8B0032A01C0E9FF03C0EAFF400E11  
 :10062000EF6E4350060802E10E0E436E036A40501F  
 :10063000F2CF47F0F29E33DD47BEF28E020801E0B2  
 :100640004388700E4024016E0F0E036ED8B0032A4B  
 :1006500001C0E9FF03C0EAFF43C0EFFF402A46D7CD  
 :100660007CEF03F00501015100010DE0010A14E0E7  
 :10067000020A1EE0060A27E0030A2CE00E0A2CE01C  
 :10068000010A30E03DD01BC040F50501416B020E70  
 :10069000426E000145DE36D00501022D06D0010E66  
 :1006A0001B16426A00013CDE02D000013CDE2AD06B  
 :1006B0000501022D05D01B82426A000131DE02D005  
 :1006C000000131DE1FD0020E196E02C521F0426A10  
 :1006D00027DE18D087DE16D01AC040F5010E426E14  
 :1006E0001FDE10D005010251010808E302C51AF00F  
 :1006F00002C53FF00001EDD6426A12DE000102D0D1  
 :1007000012DE00D0B2EF04F01AC03FF00501015133  
 :10071000000107E00A0A0DE0010A2DE00D0A3DE0A4  
 :100720003ED00501406B416B020E426E0001F8DDC8  
 :1007300038D03F521EE0010E3F5C036AF2CF40F01A  
 :10074000F29E4ADD40BEF28E016E0501045DD8A026  
 :1007500002D000010ED0036A0451240FE96E000E8E  
 :100760000320EA6EEFCF40F5010E426E0001D8DDA6  
 :1007700001D0D9DD16D03F520EE0036A05010451C5  
 :10078000240FE96E000E0320EA6E02C5EFFF426AF5  
 :100790000001C6DD01D0C7DD04D024DE02D0C3DDF8  
 :1007A00000D0B2EF04F040903FBE40803F9E40A09A  
 :1007B00010D0036A3F50F2CF41F0F29E70DC41BE90  
 :1007C000F28E000A02E1000E01D0010E016E10D07F  
 :1007D0000FD0036A3F50F2CF41F0F29E70DC41BE71  
 :1007E000F28E000A02E1000E01D0010E016E00D06F  
 :1007F0006AEF04F040903FBE40803F9E40A010D082  
 :100800003F50080DF350040F016E040E036ED8B074  
 :10081000032A01C0E9FF03C0EAFF880EEF6E09D08A  
 :100820003F50080DF3CF01F0040E01C0E9FFEA6E5E  
 :10083000EF6A79EF04F040903FBE40803F9E40A0B9  
 :1008400010D03F50080DF350040F016E040E036EDC  
 :10085000D8B0032A01C0E9FF03C0EAFF840EEF6E9F  
 :100860000AD03F50080DF3CF01F0040E01C0E9FF9C  
 :10087000EA6E840EEF6E7FEF04F040903FBE408042  
 :100880003F9E40A010D03F50080DF350040F016E62  
 :10089000040E036ED8B0032A01C0E9FF03C0EAFFCB  
 :1008A000EFCF41F00AD03F50080DF3CF01F0040E16  
 :1008B00001C0E9FFEA6EEFCF41F041AE02D041B492  
 :1008C00002D0000E01D0010E016E89EF04F004C5C4  
 :1008D0003FF069D7015229E005010151010A0001E9  
 :1008E00005E0020A09E0030A0DE01DD004C53FF04F  
 :1008F00081D7426A15DD19D004C53FF09CD7426A02  
 :100900000FDD13D00501406B416B04C53FF00001C2  
 :10091000B4D7015204E0010E0501406F0001020E40  
 :10092000426EFEDC02D0FFDC00D0B2EF04F0050125  
 :10093000015100D00001F7DC00D0B2EF04F0196AD9  
 :10094000050100517F0B000107E0010A06E0030AE0  
 :1009500005E0230A04E004D085D6D6D6B8D7E7D779  
 :10096000E2DC00D0D9EF05F03F50080DF3CF01F0E5  
 :10097000040E01C0E9FFEA6EEFCF41F040500208DB  
 :1009800006E141AC02D0406A02D0010E406E4050F8  
 :10099000030812E1840E416E3F50080DF350040F1E  
 :1009A000016E040E036ED8B0032A01C0E9FF03C034  
 :1009B000EAFF840EEF6E09D0402C03D0C80E416EC2  
 :1009C00004D0405202E1880E416E036A010E026EAD  
 :1009D0003F50006E05E0D89002360336002EFBD75C  
 :1009E0000250FF0A006EFF0E031A00501D1603503E  
 :1009F0001E16D8903F34036AF2CF44F0F29E87EC83  
 :100A000000F00900F5CF03F044BEF28E426E03C041  
 :100A100043F03F50080DF350010F016E040E036EBA  
 :100A2000D8B0032A01C0E9FF03C0EAFF42C0EFFFCC  
 :100A300043B0418043B241823F50080DF3CF01F0F3  
 :100A4000040E01C0E9FFEA6E41C0EFFF000C3F5009  
 :100A5000080DF350040F016E040E036ED8B0032A84  
 :100A600001C0E9FF03C0EAFFEFCF43F043BE5BD014  
 :100A70003F50080DF350050F016E040E036ED8B001  
 :100A8000032A01C0E9FF03C0EAFF40C0EFFF425064  
 :100A9000020816E13F50080DF350040F016E040EDA  
 :100AA000036ED8B0032A01C0E9FF03C0EAFFEFCF0D  
 :100AB00043F043AC02D0426A02D0010E426E13D022  
 :100AC0004250040810E13F50080DF3CF01F0040E2E  
 :100AD00001C0E9FFEA6EEFCF43F043AC03D0010E53  
 :100AE000426E01D0426A422C03D0C80E436E04D03D  
 :100AF000425202E1880E436E41B0438041B24382CC  
 :100B00003F50080DF350040F016E040E036ED8B071  
 :100B1000032A01C0E9FF03C0EAFF43C0EFFF010E53  
 :100B2000016E03D000D0000E016E000C3F5203E1B5  
 :100B30005DEC01F00FD0036A010E026E3F50006EB3  
 :100B400005E0D89002360336002EFBD702501D1266  
 :100B500003501E12000C40C06EFF405203E0040E12  
 :100B60001F6E02D0020E1F6EBBEF05F01A6A196AE3  
 :100B700021C040F0F0D7C8EF05F03F5209E1192C31  
 :100B800003D096EC01F004D01950020801E1EED731  
 :100B9000000C6C303E6E3E323E321F0E3E166C52E2  
 :100BA0003BE1040100513C0B34081BE1046B0001E4  
 :100BB000C6D6203C05D03F6A030E406ED5DE0ED06F  
 :100BC0003F6A020E406ED0DE2050FE0807E03F6A0A  
 :100BD000416A20C040F0040E426E39DF6D9819D092  
 :100BE000040100513C0B040815E13F6A00019EDF3F  
 :100BF0003F6A020E406EB8DE2050FE080AE0203C3C  
 :100C000001D007D03F6A416A20C040F0010E426E19  
 :100C10001EDF040120D000016C50040812E1FF0E19  
 :100C2000206E3F6AAADF203C01D008D03F6A416AAB  
 :100C300020C040F0020E426E0ADF02D05DEC01F0EF  
 :100C400009D06CB404D03EC03FF070DF03D03EC08A  
 :100C50003FF093DF040100015FEF06F01F5201E156  
 :100C60002FD068522DE068A404D069A402D02CEFE4  
 :100C700001F06DA201D024D068A204D069A202D0F4  
 :100C800031EF01F068A004D069A002D06CEF01F050  
 :100C900068A804D069A802D081EF01F068AC04D044  
 :100CA00069AC02D086EF01F068AA04D069AA02D02C  
 :100CB00089EF01F068A604D069A602D06AD76896C9  
 :100CC000A19A2CEF00F06D6A696A080E6F6E94505D  
 :100CD0003009946E1F6A186AF2BE188EF29E35ECC7  
 :100CE00001F018BEF28E1E6A1D6A6CEF07F0186ADA  
 :100CF000F2BE188EF29E35EC01F018BEF28E6D6ACF  
 :100D0000140E6F6E696A6D86010E1F6E8BEF06F012  
 :100D10006DB601D0ECD71F2C0BD06DBA09D0686A24  
 :100D2000696AA08AC00EF212110E696E020E1F6E61  
 :100D30006DEF07F02C50080DF350040F016E040EF8  
 :100D4000036ED8B0032A01C0E9FF03C0EAFFEFCF6A  
 :100D500034F034BE45D02C50080DF350060F016E10  
 :100D6000040E036ED8B0032A01C0E9FF03C0EAFFF6  
 :100D7000ECCF03F0ED52EFCF35F003C036F0336A1D  
 :100D8000326A3350305C1AE303E12F50325C16E2D2  
 :100D90002DC0E9FF2EC0EAFFEFCF39F036C0EAFFE1  
 :100DA00035C0E9FF39C0EFFF352AD8B4362A2D2ADD  
 :100DB000D8B42E2A322AD8B4332AE3D7186AF2BE1E  
 :100DC000188EF29E2CC03FF030C041F02FC040F092  
 :100DD00031C042F03CDE18BEF28E015003D000D08C  
 :100DE000000E016E000CEA6A2C0EE96EEF500EE068  
 :100DF0000F0E016E006A002EFED7012EFBD78F0E5C  
 :100E0000006E002EFED70000EF2EF2D7000C2A6AEB  
 :100E1000010E266E276A25C028F0296A2A5010087C  
 :100E200012E3010E2C6E2E6A260E2D6E306A040E11  
 :100E30002F6E020E316E7EDF0152D8A42A2A140EC4  
 :100E40002C6ED1DFEBD7000C2A6A010E266E25C06E  
 :100E500027F0286A296A2A50100812E3010E2C6E26  
 :100E60002E6A260E2D6E306A040E2F6E020E316E23  
 :100E700061DF0152D8A42A2A140E2C6EB4DFEBD7FE  
 :100E8000000C2B6A276A25C028F026C029F02A6AA0  
 :100E90002B50100812E3010E2C6E2E6A270E2D6EB9  
 :100EA000306A040E2F6E020E316E44DF0152D8A458  
 :100EB0002B2A140E2C6E97DFEBD7000CF86AD09E0D  
 :100EC000088EEA6AE96AC150C00B0F09C16E070EAD  
 :100ED000B46E1F6A236AF7D61BD71A52D8B4E8D06B  
 :100EE000050E256E94DF040E256EAEDFFB0E256E1B  
 :100EF0008EDF010E256E050E266EC3DF050E256EF4  
 :100F0000A3DFFD0E256E83DFFC0E256E9DDFFD0E3B  
 :100F1000256E7DDF040E256E97DF020E256EFC0E1A  
 :100F2000266EAFDF080E256E72DF040E256E8CDF95  
 :100F3000FB0E256E6CDFFC0E256E86DF070E256E20  
 :100F4000040E266E9EDF040E256E7EDFFD0E256EDE  
 :100F50005EDFFC0E256E78DF060E256E58DF050E6F  
 :100F6000256EFD0E266E8DDFFC0E256E50DF040E05  
 :100F7000256E030E266E85DFFD0E256E65DFFD0EE8  
 :100F8000256E45DF030E256E5FDF020E256EFC0E1B  
 :100F9000266E77DF060E256E3ADF020E256EFD0EF9  
 :100FA000266E6FDFFD0E256E32DF030E256E4CDFE1  
 :100FB000030E256E2CDFFD0E256E46DF030E256E1B  
 :100FC00026DF030E256E40DFFD0E256E20DF020EAC  
 :100FD000256E040E266E55DFF90E256E18DF040E01  
 :100FE000256E32DFFF0E256E030E266E4ADFFD0EE4  
 :100FF000256E2ADF040E256EFF0E266E42DF030EDD  
 :10100000256E22DF030E256E02DFFD0E256E1CDF2E  
 :10101000030E256EFCDE030E256E16DF020E256E16  
 :10102000266A2FDF030E256E0FDFFD0E256EEFDE25  
 :10103000FD0E256E09DFFD0E256EE9DE030E256E21  
 :1010400003DF050E256E266A1CDFFD0E256EFCDE15  
 :10105000030E256EDCDE030E256EF6DE030E256E16  
 :10106000D6DEFD0E256EF0DE050E256E266A09DF42  
 :10107000FB0E256ECCDE030E256EE6DE050E256E1C  
 :10108000C6DEFD0E256EE0DE256A070E266EF9DE51  
 :10109000EA0E256ED9DE020E256EB9DE160E256E1D  
 :1010A000D3DE140E256EFA0E2C6E9DDE252EFBD798  
 :0410B00013D703004F  
 :020000040030CA  
 :0E000000240E3E1E008381000FC00FE00F4053  
 :00000001FF  
 ;PIC18F2550  
 ;CRC=1458 CREATED="15-Nov-09 13:45"  


Also, the first hex code that worked on my circuit
(mouse pointer in circular movement):
 :020000040000FA
:040000001EEF07F0F8
:08000800056ED8CF06F0E0CF31
:1000100007F00001E9CF0DF0EACF08F0E1CF09F0D9
:10002000E2CF0AF0D9CF0BF0DACF0CF0F3CF14F017
:10003000F4CF15F0FACF16F000C00FF001C010F0A9
:1000400002C011F003C012F004C013F0A0AA2CEFFC
:1000500000F0A1BA43EF06F00FC000F010C001F0AD
:1000600011C002F012C003F013C004F00DC0E9FF8C
:1000700008C0EAFF088E09C0E1FF0AC0E2FF0BC01A
:10008000D9FF0CC0DAFF14C0F3FF15C0F4FF16C08F
:10009000FAFF055007C0E0FF06C0D8FF1000F76A5E
:1000A000AE0FF66E000EF7220900F55012000403A1
:1000B0000000000000000000000000000000F76ADF
:1000C000CE0FF66E000EF7220900F5501200040064
:1000D0000000000000000000000000000000F76ABF
:1000E000EE0FF66E000EF7220900F55012004000E8
:1000F00008000000000000000000000000000000F8
:100100000000000000000000000000000000F76A8E
:100110001E0FF66E010EF7220900F5501200400086
:1001200000000000000000000000000000000000CF
:100130000000000000000000000000000000F76A5E
:100140004E0FF66E010EF7220900F5501200050160
:100150000902A1010901A1000509190129031500DE
:100160002501950375018102950175058101050140
:100170000930093109381581257F750895038106F5
:10018000C0C0F76A920FF66E010EF7220900F55013
:1001900012000000F76AA40FF66E010EF7220900A4
:1001A000F55012003400F76AB60FF66E010EF72212
:1001B0000900F550120009022200010100C03209B5
:1001C00004000001030102000921000100012234A2
:1001D000000705810308000AF76AE80FF66E010EB2
:1001E000F7220900F55012000100F76AFA0FF66EC7
:1001F000010EF7220900F550120012011001000053
:10020000004061042200000101020001F76A1C0F96
:10021000F66E020EF7220900F550120000040C00E1
:10022000F76A300FF66E020EF7220900F550120041
:100230000403090408034300430053001C03430064
:1002400043005300200055005300420020004D00A1
:100250006F00750073006500F2CF0EF0F29EF76A32
:10026000720FF66E020EF7220900F5500EBEF28EE6
:100270001200000103040404030100FFFDFCFCFC68
:10028000FDFF6D92699468944EEF06F06A6A689279
:1002900057EF06F03E6A3E520AE1036A3E50240FD1
:1002A000E96E000E0320EA6EEF6A3E2AF4D71A6A5E
:1002B000010E1B6E196A000C010E476E47500F08A5
:1002C0000EE3700E4724016E0F0E036ED8B0032AA2
:1002D00001C0E9FF03C0EAFFEF6A472AEFD71E6AB1
:1002E0001D6A000C400E0401016F050E036F026BC6
:1002F000880E006F046B050E076F400E066F00013D
:10030000000C6A6A686A9F0E6B6E390E696E6E6ABF
:10031000C1DFD2DF160E706E68A602D06896FCD7D9
:100320006D98E0DF030E1F6E5DEF06F0698468983C
:100330006D8263EF06F0689C69EF06F070A002D052
:10034000D1DF7090689A6FEF06F042C020F0000C89
:10035000FF0E206E000C406A23523EE040503F08E2
:100360003BE31C50FC0F2BE2040FF6EF01F0036A95
:100370002250F2CF42F0F29E16DF42BEF28E416E64
:100380001ED0036A2250F2CF42F0F29ED8DE42BE67
:10039000F28E416E14D0036A2250F2CF42F0F29EE8
:1003A0003FDF42BEF28E416E0AD0036A2250F2CF86
:1003B00042F0F29E1ADF42BEF28E416E00D0222A37
:1003C00023064050402A036A400FE96E050E0320C1
:1003D000EA6E41C0EFFFC0D7235204E1405040080D
:1003E00001E0196A40C042F0B0DF000CE824F76A6F
:1003F000F736070FF66E040EF7220A00F550FA6E74
:100400000800F550F96E6E0382039603AA03226A70
:100410001C6A05010351010A000109E0030A0CE00E
:10042000010A0DE0220A22E0030A32E058D0120E3F
:10043000236E030E1C6E55D0220E236E52D0020E78
:100440001C6E036A05010251F2CF40F0F29E0001DA
:10045000DDDE40BEF28E226E036A2250F2CF40F003
:10046000F29EDEDE40BEF28E236E3BD0120E226E76
:10047000223C01D00BD0036A2250F2CF40F0F29E12
:1004800092DE40BEF28E236E2CD002D061DF35D0DA
:10049000D89005010435036AF2CF40F0F29E0001C6
:1004A00070DE0900F5CF03F040BEF28E226E223CD2
:1004B00001D013D0010E1C6ED89005010435036ADB
:1004C000F2CF40F0F29E000165DE0900F5CF03F0A7
:1004D00040BEF28E236E05D002D03ADF0ED038DF58
:1004E0000CD00501075305E12350065D02E206C565
:1004F00023F0010E196E00012EDF000C3F5204E1C3
:10050000040E1F6ED9DEC1D0050E1F6E426E800E26
:10051000416E010E406E40500F08D8A0B6D0436A1D
:10052000036A4050F2CF47F0F29EC9DD47BEF28E1B
:10053000000A51E0040E436ED8904034036AF2CFB3
:1005400047F0F29EE4DD0900F5CF03F047BEF28EDE
:10055000446E03C045F04050080DF350010F016E8A
:10056000040E036ED8B0032A01C0E9FF03C0EAFFFE
:1005700044C0EFFF4050080DF350020F016E040E0F
:10058000036ED8B0032A01C0E9FF03C0EAFF42C0EE
:10059000ECFFED5241C0EFFFD8904034036AF2CF38
:1005A00047F0F29EB4DD0900F5CF03F047BEF28EAE
:1005B000412603504222880E466E45B0468045B221
:1005C00046824050080DF3CF01F0040E01C0E9FF50
:1005D000EA6E46C0EFFF036A4050F2CF47F0F29E4A
:1005E0005EDD47BEF28E000A31E043824050080DC6
:1005F000F350060F016E040E036ED8B0032A01C03B
:10060000E9FF03C0EAFF42C0ECFFED5241C0EFFF3B
:10061000D8904034036AF2CF47F0F29E60DD0900C3
:10062000F5CF03F047BEF28E4126035042224050E0
:10063000080DF350040F016E040E036ED8B0032AA8
:1006400001C0E9FF03C0EAFF400EEF6E4350060809
:1006500002E10E0E436E036A4050F2CF47F0F29E65
:100660001EDD47BEF28E020801E04388700E402472
:10067000016E0F0E036ED8B0032A01C0E9FF03C05C
:10068000EAFF43C0EFFF402A46D791EF03F0050190
:10069000015100010DE0010A14E0020A1EE0060A01
:1006A00027E0030A2CE00E0A2CE0010A30E03DD0DE
:1006B0001BC040F50501416B020E426E000145DE94
:1006C00036D00501022D06D0010E1B16426A00012C
:1006D0003CDE02D000013CDE2AD00501022D05D00F
:1006E0001B82426A000131DE02D0000131DE1FD0E0
:1006F000020E196E02C521F0426A27DE18D087DE8D
:1007000016D01AC040F5010E426E1FDE10D0050152
:100710000251010808E302C51AF002C53FF00001CA
:10072000EDD6426A12DE000102D012DE00D0C7EF21
:1007300004F01AC03FF005010151000107E00A0A68
:100740000DE0010A2DE00D0A3DE03ED00501406BB1
:10075000416B020E426E0001F8DD38D03F521EE0C0
:10076000010E3F5C036AF2CF40F0F29E35DD40BEE1
:10077000F28E016E0501045DD8A002D000010ED0FA
:10078000036A0451240FE96E000E0320EA6EEFCFD6
:1007900040F5010E426E0001D8DD01D0D9DD16D042
:1007A0003F520EE0036A05010451240FE96E000E6A
:1007B0000320EA6E02C5EFFF426A0001C6DD01D0E8
:1007C000C7DD04D024DE02D0C3DD00D0C7EF04F0C3
:1007D00040903FBE40803F9E40A010D0036A3F50F3
:1007E000F2CF41F0F29E5BDC41BEF28E000A02E1E4
:1007F000000E01D0010E016E10D00FD0036A3F50E1
:10080000F2CF41F0F29E5BDC41BEF28E000A02E1C3
:10081000000E01D0010E016E00D07FEF04F0409079
:100820003FBE40803F9E40A010D03F50080DF35087
:10083000040F016E040E036ED8B0032A01C0E9FF55
:1008400003C0EAFF880EEF6E09D03F50080DF3CFCA
:1008500001F0040E01C0E9FFEA6EEF6A8EEF04F0CA
:1008600040903FBE40803F9E40A010D03F50080DBA
:10087000F350040F016E040E036ED8B0032A01C0BA
:10088000E9FF03C0EAFF840EEF6E0AD03F50080D67
:10089000F3CF01F0040E01C0E9FFEA6E840EEF6EA3
:1008A00094EF04F040903FBE40803F9E40A010D0A7
:1008B0003F50080DF350040F016E040E036ED8B0C4
:1008C000032A01C0E9FF03C0EAFFEFCF41F00AD0DD
:1008D0003F50080DF3CF01F0040E01C0E9FFEA6EAE
:1008E000EFCF41F041AE02D041B402D0000E01D0B2
:1008F000010E016E9EEF04F004C53FF069D701526E
:1009000029E005010151010A000105E0020A09E0A0
:10091000030A0DE01DD004C53FF081D7426A15DD02
:1009200019D004C53FF09CD7426A0FDD13D00501F2
:10093000406B416B04C53FF00001B4D7015204E0A5
:10094000010E0501406F0001020E426EFEDC02D076
:10095000FFDC00D0C7EF04F00501015100D0000119
:10096000F7DC00D0C7EF04F0196A050100517F0BD6
:10097000000107E0010A06E0030A05E0230A04E09B
:1009800004D085D6D6D6B8D7E7D7E2DC00D0EEEFD4
:1009900005F03F50080DF3CF01F0040E01C0E9FF50
:1009A000EA6EEFCF41F04050020806E141AC02D0C0
:1009B000406A02D0010E406E4050030812E1840EDE
:1009C000416E3F50080DF350040F016E040E036E8C
:1009D000D8B0032A01C0E9FF03C0EAFF840EEF6E1E
:1009E00009D0402C03D0C80E416E04D0405202E121
:1009F000880E416E036A010E026E3F50006E05E0E4
:100A0000D89002360336002EFBD70250FF0A006E44
:100A1000FF0E031A00501D1603501E16D8903F34C7
:100A2000036AF2CF44F0F29E87EC00F00900F5CFA4
:100A300003F044BEF28E426E03C043F03F50080DF7
:100A4000F350010F016E040E036ED8B0032A01C0EB
:100A5000E9FF03C0EAFF42C0EFFF43B0418043B269
:100A600041823F50080DF3CF01F0040E01C0E9FFB1
:100A7000EA6E41C0EFFF000C3F50080DF350040F29
:100A8000016E040E036ED8B0032A01C0E9FF03C053
:100A9000EAFFEFCF43F043BE5BD03F50080DF35069
:100AA000050F016E040E036ED8B0032A01C0E9FFE2
:100AB00003C0EAFF40C0EFFF4250020816E13F507A
:100AC000080DF350040F016E040E036ED8B0032A14
:100AD00001C0E9FF03C0EAFFEFCF43F043AC02D00F
:100AE000426A02D0010E426E13D04250040810E157
:100AF0003F50080DF3CF01F0040E01C0E9FFEA6E8C
:100B0000EFCF43F043AC03D0010E426E01D0426AF6
:100B1000422C03D0C80E436E04D0425202E1880E2C
:100B2000436E41B0438041B243823F50080DF350C1
:100B3000040F016E040E036ED8B0032A01C0E9FF52
:100B400003C0EAFF43C0EFFF010E016E03D000D0E7
:100B5000000E016E000C3F5203E172EC01F00FD069
:100B6000036A010E026E3F50006E05E0D890023617
:100B70000336002EFBD702501D1203501E12000C2C
:100B800040C06EFF405203E0040E1F6E02D0020E02
:100B90001F6ED0EF05F01A6A196A21C040F0F0D735
:100BA000DDEF05F03F5209E1192C03D0ABEC01F069
:100BB00004D01950020801E1EED7000C6C303E6EF3
:100BC0003E323E321F0E3E166C523BE10401005194
:100BD0003C0B34081BE1046B0001C6D6203C05D059
:100BE0003F6A030E406ED5DE0ED03F6A020E406EA5
:100BF000D0DE2050FE0807E03F6A416A20C040F086
:100C0000040E426E39DF6D9819D0040100513C0B7F
:100C1000040815E13F6A00019EDF3F6A020E406E44
:100C2000B8DE2050FE080AE0203C01D007D03F6A21
:100C3000416A20C040F0010E426E1EDF040120D048
:100C400000016C50040812E1FF0E206E3F6AAADF1B
:100C5000203C01D008D03F6A416A20C040F0020E1B
:100C6000426E0ADF02D072EC01F009D06CB404D0FD
:100C70003EC03FF070DF03D03EC03FF093DF040181
:100C8000000174EF06F01F5201E12FD068522DE0F1
:100C900068A404D069A402D041EF01F06DA201D094
:100CA00024D068A204D069A202D046EF01F068A067
:100CB00004D069A002D081EF01F068A804D069A82F
:100CC00002D096EF01F068AC04D069AC02D09BEF83
:100CD00001F068AA04D069AA02D09EEF01F068A6CC
:100CE00004D069A602D06AD76896A19A2CEF00F0CA
:100CF0006D6A696A080E6F6E94503009946E1F6AAF
:100D0000186AF2BE188EF29E4AEC01F018BEF28EFE
:100D10001E6A1D6A30EF07F0186AF2BE188EF29E46
:100D20004AEC01F018BEF28E6D6A140E6F6E696A9D
:100D30006D86010E1F6EA0EF06F06DB601D0ECD7E8
:100D40001F2C0BD06DBA09D0686A696AA08AC00EE0
:100D5000F212110E696E020E1F6E31EF07F02C5069
:100D6000080DF350040F016E040E036ED8B0032A71
:100D700001C0E9FF03C0EAFFEFCF34F034BE45D035
:100D80002C50080DF350060F016E040E036ED8B000
:100D9000032A01C0E9FF03C0EAFFECCF03F0ED52E4
:100DA000EFCF35F003C036F0336A326A3350305C2F
:100DB0001AE303E12F50325C16E22DC0E9FF2EC08A
:100DC000EAFFEFCF39F036C0EAFF35C0E9FF39C09E
:100DD000EFFF352AD8B4362A2D2AD8B42E2A322A43
:100DE000D8B4332AE3D7186AF2BE188EF29E2CC00C
:100DF0003FF030C041F02FC040F031C042F03CDE47
:100E000018BEF28E015003D000D0000E016E54EFD8
:100E100007F0EA6A2C0EE96EEF500EE00F0E016E3D
:100E2000006A002EFED7012EFBD78F0E006E002E1B
:100E3000FED70000EF2EF2D768EF07F0F86AD09ED9
:100E4000088EEA6AE96AC150C00B0F09C16E070E2D
:100E5000B46E1F6A236A296A2A6A040E2B6E48D769
:100E60006CD71A5235E0256A036A2A50F2CF2CF06B
:100E7000F29E2CEC01F02CBEF28E266E036A2B50F3
:100E8000F2CF2CF0F29E2CEC01F02CBEF28E276EED
:100E9000286A010E2C6E2E6A250E2D6E306A040E05
:100EA0002F6E020E316E5BD7015201E0292A2950C4
:100EB0000A080BE22A2A2A500F08D8A02A6A2B2AED
:100EC0002B500F08D8A02B6A296A0A0E2C6EA1D7C6
:040ED000C7D703007D
:020000040030CA
:0E000000240E3E1E008381000FC00FE00F4053
:00000001FF
;PIC18F2550
;CRC=A06D CREATED="15-Nov-09 11:02"

Saturday, November 7, 2009

Scrolling Message Display on a DMM

Recently, I came across this Python package for GPIB interfacing. It's called PyVISA, and it's relatively easy to use even if you don't have backgrounds on Python programming language. As part of my experiments on Python PC interfacing, I managed to borrow an equiptment having a GPIB port.The Agilent (HP)34410A Digital Multimeter (DMM), it's one of the commonly used equipments in our workplace. While reading the 'remote programming' manual of this DMM, I found out that it is capable of displaying text (e.g. alphanumerics) on its front panel display. The GPIB command is fairly simple, just send DISPlay:TEXT + the qouted message. (e.g. DISP:TEXT "hello" ). The message to be displayed is up to 12 characters long.


the PyVISA python script for scrolling message:
 import visa, time  

hp = visa.Instrument('GPIB::2')

def display(msg):
hp.write('DISP:TEXT ' + '"' + msg + '"')

message = ' scrolling message display on Agilent HP34410A using Python PyVISA. by yus Electronicslab.ph'

for count in range(100):
for i in range( len(message)):
#display(message[i:(i+12)])
display(message[i:(i+12)].upper())
time.sleep(0.3)


demo:


forum link: GPIB (General Purpose Interface Bus, IEEE-488)

Monday, November 2, 2009

PySerial DTR and RTS Manipulation

Another application using (Python) PyQt and PySerial: a simple serial port LED blinker program.

two LEDs connected to DTR and RTS of a COM port (pins 4 and 7 of DB9):

simple python py script:
 import sys, serial  
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MyForm(QDialog):
def __init__(self, parent = None):
super(MyForm, self).__init__(parent)
self.setWindowTitle('PySerial DTR and RTS Manipulation')
self.setMinimumSize(300, 100)
# widgets
DTRlabel, RTSlabel = QLabel(), QLabel()
self.DTRbutton = QPushButton('set to Logic "True"')
self.RTSbutton = QPushButton('set to Logic "True"')
self.DTRcheckbox = QCheckBox('continuous toggle')
self.RTScheckbox = QCheckBox('continuous toggle')
# layout
layout = QGridLayout()
layout.addWidget(DTRlabel, 0, 0)
layout.addWidget(RTSlabel, 0, 1)
layout.addWidget(self.DTRbutton, 1, 0)
layout.addWidget(self.RTSbutton, 1, 1)
layout.addWidget(self.DTRcheckbox, 2, 0)
layout.addWidget(self.RTScheckbox, 2, 1)
self.setLayout(layout)
# serial port
self.port = serial.Serial('COM1')
DTRlabel.setText("<font size = 5 color = darkred><b> " +self.port.name + " DTR pin:</b></font>")
RTSlabel.setText("<font size = 5 color = darkred><b> " +self.port.name + " RTS pin:</b></font>")
self.DTRlogic, self.RTSlogic = False, False
self.port.setDTR(self.DTRlogic)
self.port.setRTS(self.RTSlogic)
# events
self.connect(self.DTRbutton, SIGNAL('clicked()'), self.toggleDTR)
self.connect(self.RTSbutton, SIGNAL('clicked()'), self.toggleRTS)
self.DTRtimer , self.RTStimer = QTimer(), QTimer()
self.connect(self.DTRtimer, SIGNAL('timeout()'), self.eventDTRtimer)
self.DTRtimer.start(250) # in milliseconds
self.connect(self.RTStimer, SIGNAL('timeout()'), self.eventRTStimer)
self.RTStimer.start(100) # in milliseconds

def toggleDTR(self):
self.DTRbutton.setText('set to Logic "' + str(self.DTRlogic) + '"')
self.DTRlogic = not self.DTRlogic # invert logic
self.port.setDTR(self.DTRlogic)
def toggleRTS(self):
self.RTSbutton.setText('set to Logic "' + str(self.RTSlogic) + '"')
self.RTSlogic = not self.RTSlogic # invert logic
self.port.setRTS(self.RTSlogic)
def eventDTRtimer(self):
if self.DTRcheckbox.isChecked():
self.toggleDTR()
def eventRTStimer(self):
if self.RTScheckbox.isChecked():
self.toggleRTS()

if __name__ == '__main__':
app = QApplication(sys.argv)
form = MyForm()
form.show()
sys.exit(app.exec_())


demo:

*the 'blink' rate depends on QTimer timeout period

forum link: serial port LED blinker

Saturday, October 24, 2009

Portable Eric 4 Python IDE

Portable ERIC Integrated Development Environment for the Python programming language. Eric 4.3.8 (r3477)

What is Eric?
Eric is a full featured Python and Ruby editor and IDE, written in python. It is based on the cross platform Qt gui toolkit, integrating the highly flexible Scintilla editor control. It is designed to be usable as everdays' quick and dirty editor as well as being usable as a professional project management tool integrating many advanced features Python offers the professional coder. eric4 includes a plugin system, which allows easy extension of the IDE functionality with plugins downloadable from the net.




download link: Portable Eric 4 Python IDE
*includes Eric 4 (w/ necessary plugins) + Python 2.6.3 + PyQt (Qt v4.5.2) + pyserial 2.5
*tested on Windows XP SP3


sample usage: PyCute Timer (PyQt + PySerial example)

Wednesday, October 7, 2009

Parallel Two Resistors

I made a small and simple application for finding a pair of resistors (with standard values) together having an equivalent resistance (to be connected in parallel) with the desired resistance value.

This one is created in Python S60 language. I'm using a Nokia 6120c operating at Symbian OS (S60v3).

Python S60 source code (PyS60 script):
 ####################################  
# parallel two resistors v1.05 #
# yus projectproto.blogspot.com/ #
####################################
import appuifw
from appuifw import *
import e32
from graphics import *
decades_E24 = u"1.0,1.1,1.2,1.3,1.5,1.6,1.8,2.0,2.2,2.4,2.7,3.0,3.3,3.6,3.9,4.3,4.7,5.1,5.6,6.2,6.8,7.5,8.2,9.1"
decades_E12 = u"1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2"
decades = decades_E12 #initial, set to E12 series
excluded_parts = u"" #initial, no excluded parts
#define colors: black, brown, red, orange, yellow, green, blue, violet, grey, white, gold, silver
colors = [0x000000, 0x804040, 0xff0000, 0xff8000, 0xffff00, 0x008000, 0x0000ff, 0x800080, 0xc0c0c0, 0xffffff,
0x808040, 0x808080]
Rdesired = u"12.3" #initial desired value
excludeds = appuifw.Text()
excludeds.font = (None, 20, None)
excludeds.add(excluded_parts)
base = appuifw.Text()
base.font = (None, 20, None)
base.set(decades)
# define an initial image (white)
img = Image.new((240,320)) #(horizontal, vertical)
# define your redraw function (that redraws the picture on and on)
def main_handle_redraw(rect):
main_canvas.blit(img) # redraw the image named img using the blit function
# define the canvas, include the redraw callback function
main_canvas = appuifw.Canvas(event_callback=None, redraw_callback=main_handle_redraw)
def initialize():
appuifw.app.screen='normal' # set the screen size to large
main_canvas_setup()
appuifw.app.exit_key_handler = quit
main_canvas_setup()
img.clear(0x0080f0)
appuifw.app.menu = [] #create the menu
appuifw.app.menu.append((u"input resistance",get_desired_resistance))
appuifw.app.menu.append((u"select decades set", decades_setup))
appuifw.app.menu.append((u"add excluded parts", excluded_parts_setup))
appuifw.app.menu.append((u"about", about))
appuifw.app.menu.append((u"exit", quit))
img.text((5,70), u"press 'options'->'input resistance'", 0xfff000, font=(None,12,FONT_BOLD))
img.text((5,90), u"then, type the desired resistance value", 0xfff000, font=(None,12,FONT_BOLD))
img.text((170,200), u"'yus 09", 0xff8040, font=(None,18,FONT_BOLD))
main_canvas.blit(img)
def about():
appuifw.note(u"Parallel 2R v1.04\n by: 'yus", 'info')
def main_canvas_setup():
appuifw.app.title = u"Parallel 2R"
appuifw.app.body = main_canvas
appuifw.app.exit_key_handler = quit
def decades_setup():
global decades
appuifw.app.title = u"decade values"
options = [u"E12 series", u"E24 series", u"customize"]
decades_select = appuifw.popup_menu(options, u"Select decade series:")
if decades_select == 0:
decades = decades_E12
if decades_select == 1:
decades = decades_E24
if decades_select == 2:
appuifw.app.body = base
decades = base.get()
appuifw.app.exit_key_handler = main_canvas_setup
base.set(decades)
def excluded_parts_setup():
global excluded_parts
global excludeds
appuifw.app.title = u"excuded parts"
appuifw.app.body = excludeds
excluded_parts = excludeds.get()
appuifw.app.exit_key_handler = main_canvas_setup
def get_desired_resistance():
global Rdesired
global decades
global excluded_parts
global ex_parts
global excludeds
decades = base.get()
excluded_parts = excludeds.get()
ex_parts = (u"0,0" + excluded_parts).split(",")
main_canvas_setup()
Rdesired = appuifw.query(u"desired resistance (\u03A9)", 'text', Rdesired) # u"\u03A9" -> ohm symbol
R1_base, R1_multiplier, R2_base, R2_multiplier = find_equivalent_2R()
R1 = float(R1_base)* float(10**int(R1_multiplier))
img.clear(0x0080f0)
img.text((10,40), u"desired R = " + Rdesired + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
img.text((20,65), u"R1 = " + u"%.1f" % R1 + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
color_code(0, R1_base, R1_multiplier)
if R2_base == u"open":
R_equivalent = R1
error = compute_error(R1*2, R1*2)*100
else:
R2 = float(R2_base)* float(10**int(R2_multiplier))
R_equivalent = (R1*R2)/(R1+R2)
error = compute_error(R1, R2)*100
img.text((20,135), u"R2 = " + u"%.1f" % R2 + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
color_code(1, R2_base, R2_multiplier)
img.text((10,200), u"Req = " + u"%.5f" % R_equivalent + u" \u03A9", 0xfff000, font=(None,18,FONT_BOLD))
img.text((10,225), u"error = " + u"%.7f" % error + u" %", 0xfff000, font=(None,18,FONT_BOLD))
def find_equivalent_2R():
global Rdesired
global decades
ex_parts = (u"0,0" + excluded_parts).split(",")
r1_base = r2_base = u"1.0" #initial values
r1_multiplier = r2_multiplier = u"-2"
r1 = r2 = 0.0001
e = compute_error(r1, r2)
decade_values = decades.split(",")
for i in decade_values:
for j in range(-2,7):
r1 = float(i) * float(10**j) # i * (10^j)
if pwede(r1) == False:
continue
elif r1 == float(Rdesired):
r1_base, r1_multiplier, r2_base, r2_multiplier = i, j, u"open", u"open"
return r1_base, r1_multiplier, r2_base, r2_multiplier # _r2 is open
elif compute_error(r1*2, r1*2) < e:
r1_base, r1_multiplier, r2_base, r2_multiplier = i, j, u"open", u"open"
e = compute_error(r1*2, r1*2)
for m in decade_values:
for n in range(-2,7):
r2 = float(m) * float(10**n) # m * (10^n)
if r2 < r1:
continue
elif compute_error(r1, r2) < e and pwede(r2):
r1_base, r1_multiplier, r2_base, r2_multiplier = i, j, m, n
e = compute_error(r1, r2)
return r1_base, r1_multiplier, r2_base, r2_multiplier
def compute_error(R1, R2):
global Rdesired
Rin = float(Rdesired)
Req = (R1 * R2)/(R1 + R2)
error = (Req - Rin)/Rin
if error < 0:
error *= -1 #absolute value
return (error)
def pwede(value):
global ex_parts
valid = True
for i in ex_parts:
#if value == float(i): #having problems with "float" variables precision
diff = (float(i)-value)/value
if diff < 0:
diff *= -1 #absolute value
if diff < 0.0000000001: #tolerance for precision error
valid = False
return (valid)
def color_code(pos, base, multiplier):
global colors
digits = base.split(".")
band1 = colors[int(digits[0])]
band2 = colors[int(digits[1])]
multiplier -= 1
if multiplier == -3:
band3 = None
elif multiplier == -2:
band3 = colors[11]
elif multiplier == -1:
band3 = colors [10]
else:
band3 = colors[int(multiplier)]
band4 = colors[10] # gold (default tolerance)
#'draw' a typical resistor
img.rectangle((40,85 +pos*70,210,95 +pos*70), fill=colors[8]) # terminals
img.rectangle((100,70 +pos*70,160,110 +pos*70), fill=(250,200,120)) # body
img.ellipse((75,67 +pos*70,110,113 +pos*70), fill=(250,200,120)) # left edge
img.ellipse((147,67 +pos*70,182,113 +pos*70), fill=(250,200,120)) # right edge
#color bands
img.rectangle((100,70 +pos*70,110,110 +pos*70), fill=band1) # 1st digit
img.rectangle((113,70 +pos*70,123,110 +pos*70), fill=band2) # 2nd digit
img.rectangle((126,70 +pos*70,136,110 +pos*70), fill=band3) # 'zeroes'
img.rectangle((148,70 +pos*70,158,110 +pos*70), fill=band4) # tolerance
# create an exit handler
def quit():
app_lock.signal()
initialize()
app_lock = e32.Ao_lock()
app_lock.wait()


.. don't have a symbian phone? try an S60 Emulator:

I also have a PC(Windows) version created in MS Visual C# (*requires dotNET Framework):
download: parallel 2R.rar
forum link: parallel two resistors