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

Saturday, October 3, 2009

USB-based Loader circuit for DS89C4x0

Here's an alternative flash loader/programmer circuit for Maxim's DS89C4x0 microcontrollers. Most of the circuit parts came from a cheap Nokia data cable bought at CDR-King.

from the conventional "Serial Load Hardware Configuration":
to this one:*uses PL2303 from this cable: CHEAP USB-serial interface cable for our MCU projects!
*completely USB-powered
*no other addtional IC (e.g 74xx125)
**but still need to place the external crystal on the DS89C4x0


inside the cdrking's nokia data cable:
connections (tapping of wires):
actual circuit:*has a pull-up on P3.7 pin (only for some batches of ds89c420 as indicated in their errata)

the 40-pin DIP DS89C420 (obsolete part):
the MTK (Loader software):*the actual hardware is not working with version 2.4.10
*works also with Loader420 and hyperterminal..
dalsemi.com/microcontroller/dev_tool_software/mtk/obsolete/

demo ("classic" LED blinker program): video

SDCC code:Compiled using M-IDE with SDCC

Friday, October 2, 2009

Goertzel Algorithm for PIC16F

Here's an experimental circuit(actual and simulation) of Goertzel algorithm using Microchip's PIC16F876A @20MHz crystal.

mathematical proof using MathCad:
initial simulation using Proteus ISIS:
code excerpt:
 #define SAMPLING_RATE    2003.21  
#define MAX_BINS 6
#define GOERTZEL_N 96
#define pi 3.141592654
#define threshold 2E4
#define true 1
#define false 0
const float freqs[MAX_BINS] = { 83, 110, 147, 196, 247, 330 };
unsigned int sample_count = 0;
unsigned char levels[ MAX_BINS];
unsigned char samples[GOERTZEL_N];
unsigned char sample_complete = false;
float prev1[ MAX_BINS ];
float prev2[ MAX_BINS ];
float magnitude[ MAX_BINS ];
float coeffs[ MAX_BINS ];
void interrupt isr() // Interrupt Handler
{
if(ADIF)// A/D conversion complete interrupt
{
samples[++sample_count] = ADRESH; // Read 8-bit ADC result
if (sample_count == GOERTZEL_N)
{
TMR0IE = 0; //disable TMR0 interrupt
sample_complete = true;
}
ADIF = 0; // clear the flag
}
if (TMR0IF) // Timer0 Interrupt
{
ADGO = 1; // initiate ADC conversion
TMR0 = 100; // reset the timer0 preset count
TMR0IF = 0; // clear the flag
}
}
void calc_coeffs() // calculate coefficients
{
unsigned int k, n;
for(n = 0; n < MAX_BINS; n++)
{
k = (unsigned int)(0.5 + (float)GOERTZEL_N * freqs[n] / SAMPLING_RATE);
coeffs[n] = 2.0 * cos(2.0 * pi * (float)k/GOERTZEL_N);
}
}
void main(void)
{
unsigned int i;
float val, max;
calc_coeffs();
// initializations
init_display(); // initialize LCD
init_adc(); // initialize PIC ADC module
init_timer(); // initialize Timer0
while(1)
{
if( sample_complete == true )
{
for(i = 0; i < MAX_BINS; i++) {
prev2[i] = prev1[i] = 0.0;
}
for(sample_count=0; sample_count < GOERTZEL_N; sample_count ++)
{
//GOERTZEL Algorithm
for ( i = 0; i < MAX_BINS; i++ )
{
val = coeffs[i] * prev1[i] - prev2[i] + (float)samples[sample_count];
prev2[i] = prev1[i];
prev1[i] = val;
}
}
sample_count = 0;
sample_complete = false;
TMR0IE = 1; // enable TMR0 interrupt, restart storing samples
max = threshold;
for ( i=0; i<MAX_BINS; i++ ) // compute the amplitudes/magnitudes
{
magnitude[i] = (prev1[i] * prev1[i]) + (prev2[i] * prev2[i]) - (coeffs[i] * prev1[i] * prev2[i]);
if (magnitude[i] > max) max = magnitude[i];
}
/*for ( i=0; i<MAX_BINS; i++ )
{
levels[i] = (unsigned char)(magnitude[i] / max);
}
display_spectrum();*/
}
}
}

then, build the actual circuit with this schematic:
the actual testing using a guitar(two strings pick):
another simulation (simple spectrum analyzer):

forum link: PIC-based Guitar Tuner