Saturday, February 6, 2010

MSI Wind 12 Bluetooth Mod

It's been more than a year since I made my own BT modding on U100. I made that a month later after I bought my first wind netbook. Then recently (a week ago), I bought a new netbook notebook - MSI Wind u230. It's one of the Wind12 series and its specs (i.e. processor and graphics) are far way better than the early wind netbooks.
However, the locally available Wind12 notebooks in the country also don't have the built-in bluetooth module. The good news is, according to the msi forum, the bluetooth module for the U100 will also work on U210. So, without hesitation (since I've already verified the other features of my unit), I opened my less-than-a-week old U230 and found out that there's also readily available connector for the bluetooth.

For this modding I chose a slim-type USB bluetooth dongle (worth Php220), so that it will be easy to disassemble and also easy to fit inside my U230.

Checking first the voltage supply for the bluetooth module.
(showing 5V across pin1/red and pin2/orange)


The electrical connection is the same as for the U100 BT mod, except for the connector's wire colors (not the typical BBROYGBVGW arrangement).

The finished 'product':
(I use the same part number of MosFET for the 'enable switch'. It's IRFR5505 P-channel MosFET.)


Initial testing:

Putting some insulation (kapton tape)first before placing inside the unit:


Finally, SCM already detects the new hardware by pressing Fn+F9.
The bluetooth LED indicator is now also working.


And that's the do-it-yourself bluetooth module for MSI U230, costing only less than 300 pesos... =)
Hopefully I could also mod a usb hsdpa modem to fit inside the vacant mini-pcie slot of my U230.

Wednesday, January 13, 2010

Z8 on-chip Temperature Sensor


It is basically based on technical note (TN004201-0905) by ZiLOG: Technique for Measuring System Temperature Using the On-chip Temperature Sensor of the Z8 Encore! XP®. I just copied the routine for measuring the temperature. The main difference is, in stead of sending the result through the UART of Z8F042A (i.e. using Hyperterminal), I used Nokia 5110 LCD to display the temperature reading. N5110 LCD has the same LCD controller with that of N3310 LCD (so, N3310 LCD can also be used with this project).

The equation used for temperature reading is:
integrated on-chip temperature sensor (ITS) temperature:
T = (25/128)*ADC – 77
where,
T is the temperature in C
ADC represents the 10-bit compensated ADC register value



I was also able to implement a different approach in computing the temperature of the on-chip sensor using the sample code from this application note AN019102-0708 also by ZiLOG: Reading Temperature Using the F082A Series MCUs. Unfortunately, I don't know why the result is different from the previous approach. And I don't have the time (and an accurate thermometer) to test which one is correct (although both of them are not accurate enough compared to of using external temperature sensor). Also, in the datasheet of F082A series, there's a parameter called TSCAL (Temperature Sensor Calibration Data) which I never noticed in the sample codes of the two. I also tried doing my own code starting from 'scratch' (using the datasheet as the only reference), but I always failed. The hardest part is on the compensating of the ADC results.

Download:
source code (w/ HEX) and schematic: Z8042A temperature sensor.rar

edited (Jan 16, 2009):
uses this equation from the datasheet in stead of the previous one:
V = 0.01 * T + 0.65 (where T is the temperature in C; V is the sensor output in Volts)


forum link: digital thermometer using 8-pin Z8F042A

Nokia LCD Interfacing

Due to their wide availability in the local markets, old Nokia LCDs are the best alternatives for those expensive GLCDs. They can be bought cheaply at many cellphone parts shops (N3310 lcds usually cost only around Php100 each). Interfacing them with microcontrollers can easily be done using serial communication (e.g. SPI protocol).

Nokia 3530/3510i LCD
98x67 pixels , 4096 colors








Nokia 6610/6100 LCD
132x132 pixels, 4096 colors
(good backlights,
but the connector is difficult to use)







Nokia 3310/5110 LCD
84x48 pixels, monochrome
(very common and relatively cheap)








some links for N3310/N5110 LCDs:
Using Nokia 3310 LCD as Display for PIC Projects
Nokia 3310 LCD LPH7779
Nokia 3310 LCD Image Encoder
DIY scope using Z8F0823 and N3310 LCD

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