Posts tagged Embedded

January 06th, 2012

Telit GM862-GPS hex() bug

Written by Dave BarkerTopics: Code, News, Python, Embedded

My SHA1 code was returning a different hex digest when run on my Telit GM862 GPS. I eventually tracked the problem down to the hex() function. Simply put hex(3181490320L) does not return the right result!

Run this test script and post your results below.

import sys, SER, MDM

# Set up printing to serial
SER.set_speed('115200', '8N1')
class SerWriter:
  def write(self, s):
    SER.send(s + "\r")
sys.stdout = sys.stderr = SerWriter()

# Simplistic AT command function
def at_command(command):
  # Clear the command interface buffer
  MDM.read()
  # Send the command
  MDM.send(command + '\r', 0)
  # Create a buffer
  buffer = ''
  while 1:
    # Listen to serial port for click
    incoming = MDM.receive(1)
    # If we got some data handle it
    if incoming:
      buffer = buffer + incoming
      if buffer.find("OK") > -1:
        return buffer
      elif buffer.find("ERROR") > -1:
        return ''

# Run the tests
print at_command("AT+CGMM")
print at_command("AT+CGMR")
i = 3181490320L
print i
print long(hex(i), 16)

# Restore standard out
sys.stdout = sys.stderr = sys.__stdout__

My output was:

OK

GM862-GPS

OK


07.03.402

OK

3181490320
2376183952

Cheers, Dave.

Edit: In case anyone's interested here's my hex() replacement. It's probably much slower but it works and can pad the hex string to x bytes.

def write_hex(x, bytes=1):
  h = ['0'] * bytes * 2
  i = 0
  while x > 0:
    if i < bytes * 2:
      h[i] = '0123456789abcdef'[x & 0xf]
    else:
      h.append('0123456789abcdef'[x & 0xf])
    x = x >> 4
    i = i + 1
  h.reverse()
  return ''.join(h)

May 14th, 2011

Embedded development setup with Macbook

Written by Dave BarkerTopics: Python, Howto, Embedded

I've been put onto an interesting project recently, doing some embedded Python development for a Telit GM862-GPS unit. Being new to this type of thing it took me a while to get a development enviroment set up that I was happy with. In an effort to share what I've learned, here's my setup:

(To be clear I'm using the Roundsolutions development starter kit for the Telit GM862-GPS with my Macbook pro.)

Roundsolutions dev board

First of all I had to install the usb-serial driver (PL2303_1.2.1r2.dmg) to get the serial port working. Once that's installed and it's connected the serial device /dev/tty.usbserial appeared for use.

Next I followed this guide and connected to the device using the GNU Screen command that's included with Snowleopard. This command worked nicely:

screen -S telit -T vt100 /dev/tty.usbserial 115200,crtcts,-parity,-cstopb

Typing AT returned OK and I knew I was in business!

I soon found that deploying code over serial manually was pretty tedious, it's easy to mess up the AT commands. I wrote this script to automate the process, making deployment as easy as

telit-send-python.py telit example.py

The next issue I hit was that my code was sometimes being crapped up during transfer. I eventually figured out I was using the wrong line terminators for my files, Unix style just uses \n where as the Telit module demands \n\r (DOS style). To convert my files in Emacs I used the buffer-file-coding-system command, so

M-x set buffer-file-coding-system undecided dos

Next I realised backspace wasn't being transmitted properly across Screen, there's an option in the Advanced section of Terminal preferences "Delete sends Cntrl-H" which resolved it for me. Unfortunately I found it messed up my normal SSH sessions, a better solution is to have this fixed in GNU Screen, add these lines to your ~/.screenrc:

 
bindkey -d ^? stuff ^H
bindkey -d ^@ stuff ^H

Another annoyance with Screen was that I wasn't able to scroll up like normal in my Terminal windows. Luckily fixing that was pretty easy, I added this to my ~/.screenrc :

termcapinfo xterm* ti@:te@

Messing with SMS at commands I realised that the body of a SMS needs to be terminated with 0x1a, it bit tricky to type but there's a solution, Screen's "digraph" feature. To send 0x1a here's what I did:

C-a C-v 0x1a

So the next thing I really wanted to was to get the Telit version of Python running locally, allowing me to test things interactively at a 'REPL'. The units run a modified version of Python 1.5.2 and unfortunately I had no luck compiling or installing a version that old under Snowleopard. My solution in the end was to install the Windows version TelitPy1.5.2+_V4.1.exe using Wine. I then set up a little shell-script shortcut to launch it easily. (It installs to ~/.wine/drive_c/Program\ Files/Python/python.exe )

Now I've got a pretty sweet set up, but having the PCB dangling off the side of my Macbook in Starbucks isn't really an option. So I plugged it into my Linux server at home and then I can SSH in and deploy code / interact with the Terminal. (Using Emacs' tramp feature I can edit the code directly over SSH too.)

Only thing worth noting is that the naming convention for serial devices seems different in Linux. Also I found that sometimes the LANG environment variable ended up corrupting the binary transfer. Here's the Screen command I ended up using:

unset LANG && screen -S telit -T vt100 /dev/ttyUSB0 115200,crtcts,-parity,-cstopb

Read the Stty man page for details about those serial options at the end.

I also sometimes needed to check what Screen's _really_ sending out, helpful for debugging problems with transmitting binary data. It's not hard though, just start a Screen session and run this command inside it:

stty raw; cat > binary-file-name

(Just make sure to exit using the C-a :quit screen command rather, most special keys will be sent directly through into your file.)

Finaly while I'm waiting for the Python debugging board to arrive I needed to have some way of getting output through to the serial port. Otherwise t's hard to know if your code even ran at all. Turns out it's not too hard, here's a (noddy) example:

import SER, MOD, MDM, GPS, sys

# Set the baud rate
SER.set_speed('115200', '8N1')

# Send stout and stderr over serial
# http://forum.sparkfun.com/viewtopic.php?t=6289
class SerWriter:
  def write(self, s):
    SER.send(s + '\r')
sys.stdout = sys.stderr = SerWriter()

# You get the idea...
print "Lovely stuff"

Thanks for reading, I'd be interested to hear how any tips you've got in the comments. Also if anyone knows a better support forum / community than the Roundsolutions one let me know.

Cheers, Dave.

Edit: I've just discovered Sparkfun's evaluation board. The board looks a lot nicer, it's cheaper and Sparkfun actually list prices and stock. I've just been browsing their forum and it's way friendlier too, I would definately go with Sparkfun over Roundsolutions if you get the choice.

Edit 2: I've had all sorts of problems uploading Python scripts larger than about 7kb to the Telit module. In the end I updated my script to send files in chunks with enough delay for the module to catch up. I also had problems deleting large files until I removed the quotes around a file name. Much much more details on this forum post.

Edit 3: I've just been shown this great guide about Telit Python development, well worth reading.