Monday, February 22, 2010

MSI Wind 12 Internal HSDPA (3.5G) Modem Mod

Ever since Wind12 series was introduced in the market, I always see in most of the reviews for these products announcing that these units have SIM card slot found underneath the battery pack. Yes I'm also aware that the 3G modules are only optional, but when I checked my Wind U230 I noticed that the SIM slot actually has no SIM connector inside. Nevertheless, it is true that there's an extra PCIe-mini card slot (intended for 3G modem module) found beside the harddisk. This is a great candidate for circuit modding on which I've already made one. =)

I've dissected my Smart Bro (Huawei E1553) modem for the sake of this mod. Anyway, these USB dongles are relatively cheap nowadays. AFAIK, pcie-mini card-type modems cost 3-4 times more compared to usb-types. Before doing the actual mod, I was still not sure whether this will work on 3.3V supply instead of the common 5V of USB ports. Since I cannot find its electrical specs, I just test it on actual. And, fortunately, it works!


I'm using pins 36 and 38 of PCIE mini card connector for the USB functionality of this port. And for the USB supply, I tapped 3.3V and GND on capacitor C236.This 3.3V supply for the pcie-mini card is automatically turned off during system standby.

There's also a disable pin function for the host to disable the pcie-mini card. It is W_DISABLE# on pin 20. It is held low during boot up of the unit. Also during boot-up, the BIOS will check if there's a load on the pcie-mini's 3V3 output. If it doesn't see any load on the 3V3 bus, the unit will cut-off the 3.3V supply all throughout. Therefor, pressing Fn+F10 keys combination without "load" on the 3V3 will not cause this pin to go to logic high. For now, I'm not utilizing this pin since my "enable circuit" is not yet working. The enable circuit is basically using a p-channel mosfet, which is the same with the bluetooth mod. However, the mosfet I currently have doesn't operate well with only -3.3V Vgs (i.e. doesn't turn on properly). BTW, the enable logic for this pin 20 is opposite of what the previous mod have. Meaning, low (0V) on pin 20 corresponds to "module disabled", and high (3.3V) is "enabled".

I was also got bothered of whether the internal antenna of the modem may not be able to get a good signal strength since Wind12 chassis has metal backbones and the plastic cover itself has conductive coatings. But, there was a U210-lite user who ask me to solder his usb hsdpa modem inside his unit. And I'm quite satisfied with the result even if we didn't wire and reposition the antenna of his modem.
I managed to get coaxial wires (hoping that these wires are similar to what WiFi adapters and actual 3G modems are using). Unfortunately, after finishing the mod and testing the modem, from the usual RSSI of -85dBm (before placing the modem inside the unit) it drops to -90dBm(sometimes -95dBm to -100dBm with SUN network) =( . I'm already anticipating this result. The important is that I can still surf the net (and other online stuffs) without the unexpected disconnection.
Actually, I'm not sure if the second one is really another antenna of this modem but assumed it is since it's not connected directly to GND. We even tested hsdpa modem without this and still works surprisingly.

I've placed the two antennas in between the touch pad and the right speaker, and put some spaced in between the two. I've also repositioned the modem in such a way that SIM card can easily be accessed by just removing the upgrade panel of this unit.

Finally, the complete internal hsdpa modem mod (somewhat "messy").

Fn+F10 combination is now working (the symbol appears on the bottom right of the screen). The LED indicator, which is shared with WiFi, turns yellow. It turns to blue for WiFi and light-blue when both are enabled. (note: my hsdpa modem is always enabled in my present mod)


----------------------
03/01/10 update:
Now I have the extra time to revisit this mod. It seems that it's better (in term of signal reception) for the second antenna(?) to be soldered directly to usb modem instead of using coax wire. Below is my latest adjustment. It looks "presentable" now compared to the previous circuit.
I also tried using different mosfet (IRLML5103 SOT23 package) for the enable/disable function. Although I can now toggle the whole circuit by Fn+F10 keys, it's not a full success yet since my U230 encounters frequent usb disconnection of this modem. I'm not sure of the exact reason of this problem, so I just put back the previous hardware (i.e. Vcc supply) configuration.

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.