<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4910051342384298494</id><updated>2011-07-30T09:47:46.191-07:00</updated><category term='gdb macros'/><category term='python ctypes'/><category term='yaffs'/><category term='testing'/><category term='realtime gnuplot plotting'/><category term='Setting up Debian chroot under Ubuntu'/><title type='text'>Embedded Janitor</title><subtitle type='html'>Cleaning up embedded systems</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-2075161219791600087</id><published>2010-05-06T16:58:00.000-07:00</published><updated>2010-05-10T19:40:51.954-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gdb macros'/><title type='text'>gdb macros</title><content type='html'>gdb provides an amazingly versatile debugging platform supporting mechanisms to debug local and remote software.&lt;br /&gt;&lt;br /&gt;One of gdb's less known features is its rich macro language.  Although I had used it before working at Apple, that's where I was really exposed to how gdb can be used to the max.&lt;br /&gt;&lt;br /&gt;OSX can be debugged from a remote machine via gdb remote. Navigating around the guts of a running OS is challenging. You need to locate the task structures etc that you are debugging by finding them in lists of running tasks. Doing this manually takes time and is error prone. So to make this easy, Apple provides a &lt;a href="http://www.opensource.apple.com/source/xnu/xnu-792.13.8/kgmacros?txt"&gt;file of gdb macros&lt;/a&gt; that will do this for you.&lt;br /&gt;&lt;br /&gt;While these macros won't work on your embedded system, they do provide examples for how you can construct complex macros containing ifs, while loops etc.&lt;br /&gt;&lt;br /&gt;To give you a taster, here's a very simple example using a linked list of structures.&lt;br /&gt;&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;#include &lt;stdio.h&gt;&lt;/stdio.h&gt;&lt;/span&gt;&lt;stdlib.h&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;#include &lt;stdlib.h&gt;&lt;/stdlib.h&gt;&lt;/span&gt;&lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;struct enu{&lt;br /&gt;  float x;&lt;br /&gt;  float y;&lt;br /&gt;  float z;&lt;br /&gt;  struct enu *next;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct enu *addpoint(float x, float y, float z, struct enu *next)&lt;br /&gt;{&lt;br /&gt;  struct enu * np; &lt;br /&gt;  np = malloc(sizeof(struct enu));&lt;br /&gt;  if(np){&lt;br /&gt;      np-&gt;x = x;&lt;br /&gt;      np-&gt;y = y;&lt;br /&gt;      np-&gt;z = z;&lt;br /&gt;      np-&gt;next = next;&lt;br /&gt;  }&lt;br /&gt;  return np;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;main()&lt;br /&gt;{&lt;br /&gt;  struct enu *list = NULL;&lt;br /&gt;  struct enu *i;&lt;br /&gt;&lt;br /&gt;  list = addpoint(1,2,3,list);&lt;br /&gt;  list = addpoint(1,2,4,list);&lt;br /&gt;  list = addpoint(1,2,5,list);&lt;br /&gt;  list = addpoint(1,2,6,list);&lt;br /&gt;&lt;br /&gt;  for(i = list; i; i=i-&gt;next)&lt;br /&gt;      printf("%f %f %f\n",i-&gt;x,i-&gt;y,i-&gt;z); &lt;br /&gt;}&lt;/stdio.h&gt;&lt;/stdlib.h&gt;&lt;/span&gt;&lt;/blockquote&gt;Here are a few macros&lt;br /&gt;&lt;br /&gt;&lt;blockquote  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;define dump_entry&lt;br /&gt;  set $l=(struct enu *)($arg0)&lt;br /&gt;  printf "Entry is %f %f %f\n", $l-&gt;x, $l-&gt;y, $l-&gt;z&lt;br /&gt;end&lt;br /&gt;document dump_entry&lt;br /&gt;Print out a list entry&lt;br /&gt;Usage: dump_entry pointer&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;define dump_list&lt;br /&gt;  set $list = $arg0&lt;br /&gt;  if(!$list)&lt;br /&gt;      printf "List is empty\n"&lt;br /&gt;  else&lt;br /&gt;      while($list)&lt;br /&gt;          dump_entry $list&lt;br /&gt;          set $list=$list-&gt;next&lt;br /&gt;      end&lt;br /&gt;      printf "End of list\n"&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;document dump_list&lt;br /&gt;Print out a whole list&lt;br /&gt;Usage: dump_list pointer&lt;br /&gt;end&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;And here is a session using them:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;gdb-demo$ gdb gdb-demo&lt;http: org="" licenses="" html=""&gt;&lt;br /&gt;&lt;http: org="" software="" gdb="" bugs=""&gt;...&lt;br /&gt;Reading symbols from /home/charles/gdb-demo/gdb-demo...done.&lt;br /&gt;(gdb) source demo.gdb  &lt;---- loading up the macros&lt;br /&gt;(gdb) list main&lt;br /&gt;23        }&lt;br /&gt;24        return np;&lt;br /&gt;25    }&lt;br /&gt;26&lt;br /&gt;27    main()&lt;br /&gt;28    {&lt;br /&gt;29        struct enu *list = NULL;&lt;br /&gt;30        struct enu *i;&lt;br /&gt;31   &lt;br /&gt;32        list = addpoint(1,2,3,list);&lt;br /&gt;(gdb) break 32 Breakpoint 1 at 0x8048468: file gdb-demo.c, line 32.&lt;br /&gt;(gdb) run Starting program: /home/charles/gdb-demo/gdb-demo&lt;br /&gt;Breakpoint 1, main () at gdb-demo.c:32&lt;br /&gt;32        list = addpoint(1,2,3,list);&lt;br /&gt;(gdb) dump_list list&lt;br /&gt; List is empty&lt;br /&gt;(gdb) n&lt;br /&gt;33        list = addpoint(1,2,4,list);&lt;br /&gt;(gdb) n&lt;br /&gt;34        list = addpoint(1,2,5,list);&lt;br /&gt;(gdb) n&lt;br /&gt;35        list = addpoint(1,2,6,list);&lt;br /&gt;(gdb) dump_list list&lt;br /&gt;Entry is 1.000000 2.000000 5.000000&lt;br /&gt;Entry is 1.000000 2.000000 4.000000&lt;br /&gt;Entry is 1.000000 2.000000 3.000000&lt;br /&gt;End of list&lt;br /&gt;(gdb) &lt;/http:&gt;&lt;/http:&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;In embedded systems, macros are really handy as a way to explore the state of RTOS tasks, semaphores etc as well as peripherals etc.  Careful though... reading some peripheral registers can change their state.&lt;br /&gt;&lt;br /&gt;Building infrastructure like this takes some time but pays off in the long run.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-2075161219791600087?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/2075161219791600087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=2075161219791600087' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/2075161219791600087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/2075161219791600087'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2010/05/gdb-macros.html' title='gdb macros'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-7735964871691213189</id><published>2010-04-25T21:01:00.000-07:00</published><updated>2010-04-25T21:54:34.272-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='realtime gnuplot plotting'/><title type='text'>Simple realtime plotting</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_l0SZr-Pvve4/S9UcZ7ImaiI/AAAAAAAAABs/MQAwkohjJks/s1600/yafs-bg.gc.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 264px;" src="http://1.bp.blogspot.com/_l0SZr-Pvve4/S9UcZ7ImaiI/AAAAAAAAABs/MQAwkohjJks/s400/yafs-bg.gc.jpg" alt="" id="BLOGGER_PHOTO_ID_5464304954580036130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A picture is worth a thousand words, they say. Well that's certainly the case when you're trying to view the impact of some code changes over a period of time.&lt;br /&gt;&lt;br /&gt;One thing I needed to do when writing the new background garbage collection feature for the &lt;a href="http://www.yaffs.net/"&gt;yaffs&lt;/a&gt; file system was to see how the background garbage collection heuristics were working. In particular I needed to trace how the erased space compares to the free space (the garbage collector changes dirty free space into erased free space).... and I wanted a graphic trace in real time.&lt;br /&gt;&lt;br /&gt;This really helped to monitor and debug some interesting problems where the background garbage collector should have stopped working but did not.&lt;br /&gt;&lt;br /&gt;There are quite a few ways to do this for static logs (gnuplot, spreadsheets, etc) and there are also quite a few logging database tools (rrdtool etc) but those just all seemed too much effort to set up or docs to read. Why use a chainsaw to cut butter?&lt;br /&gt;&lt;br /&gt;I was able to crank out something simple using bash and gnuplot. The bash script has three parallel processes: data gathering and driving gnuplot and gnuplot itself.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;&lt;/tt&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;tt&gt;#!/bin/sh&lt;/tt&gt;&lt;/span&gt;&lt;tt&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# Script that gathers data erased vs free data from /proc/yaffs_stats and simultaneously \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# plots it using gnuplot.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#Gather settings&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;log_file=data&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;gather_delay=1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# Plot settings&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;trunc_file=trunc_data&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;plot_samples=1000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;plot_delay=2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# Gathering task&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;gather_data() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;i=0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;rm -f $log_file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while true; do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;str=$(cat /proc/yaffs_debug)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo "$i, $str" &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo "$i, $str"  &gt;&gt; $log_file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;let i=$i+1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sleep $gather_delay&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;done&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# Plotting task&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# Periodically creates a truncated version of the log file and&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;# outputs commands into gnuplot, thus driving gnuplot&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;drive_gnuplot(){&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sleep 5&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;tail -$plot_samples $log_file &gt; $trunc_file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;plot_str=" plot '$trunc_file' using 1:3 with linespoints title 'free', '' using 1:4 with linespoints title 'erased'"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo "set title 'yaffs free space and erased space'"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo $plot_str&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while true; do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sleep $plot_delay&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;tail -$plot_samples $log_file &gt; $trunc_file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo replot&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;done&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo "Start gathering task in background"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;gather_data &amp;amp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;echo "Run plotting task"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;drive_gnuplot | gnuplot&lt;/span&gt;&lt;/tt&gt;&lt;/span&gt;&lt;tt&gt;&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The data gatherer periodically reads from a Linux kernel procfs entry and dumps a new data record onto the end of a log file.&lt;br /&gt;&lt;br /&gt;The gnu-plot driver process uses tail to truncate the last n lines of the log into a truncated log file, then sends commands to gnuplot to either start a plot (for the first time around) or replot (on subsequent iterations). The nifty bit here is the pipe. Since the process is piping into gnuplot, output from this process is treated as if a user typed the command in gnuplot.&lt;br /&gt;&lt;br /&gt;The above script gets run in a terminal and we get a nice gnuplot picture that automatically updates every few seconds.&lt;br /&gt;&lt;br /&gt;The same basic idea is readily modified for all sorts of applications. For example if your embedded system spits out stats periodically on a serial port that info can get logged and run through a similar plotting task.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-7735964871691213189?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/7735964871691213189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=7735964871691213189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/7735964871691213189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/7735964871691213189'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2010/04/simple-realtime-plotting.html' title='Simple realtime plotting'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_l0SZr-Pvve4/S9UcZ7ImaiI/AAAAAAAAABs/MQAwkohjJks/s72-c/yafs-bg.gc.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-4149010849926336954</id><published>2009-11-05T18:33:00.000-08:00</published><updated>2010-05-02T17:52:49.458-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='yaffs'/><category scheme='http://www.blogger.com/atom/ns#' term='python ctypes'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Using python + ctypes + gdb for testing yaffs</title><content type='html'>I'm doing a short lightning talk at KiwiPycon this week end. You can't put much info into a lightning talk so this blog posting provides some further info.&lt;br /&gt;&lt;br /&gt;You can get the yaffs code with python ctypes stuff &lt;a href="http://www.yaffs.net/node/346"&gt;here&lt;/a&gt; . Grab the tarball. Inside that go to yaffs2/direct/python.&lt;br /&gt;&lt;br /&gt;All up, yaffs is over 20k lines of C and is used all sorts of applications, particularly cell phones. yaffs is under [almost] daily modification and needs a reasonable test environment. Regression testing is handy to prevent things taking a step backward, but a more dynamic test framework is needed when testing new features/mods. I call this "walk testing".&lt;br /&gt;&lt;br /&gt;I used to do walk testing using C test routines + gdb but am switching over much of that to python + ctypes + gdb.&lt;br /&gt;&lt;br /&gt;The problem with doing this in C is that the slightest change to the "walk" needs a whole coding/compile/restart cycle.&lt;br /&gt;&lt;br /&gt;In-kernel walk testing using bash gives a dynamic environment but no gdb. An error can crash the kernel which forces a reboot.&lt;br /&gt;&lt;br /&gt;Using python, rather than C, as the test harness environment provides both a programming environment + a command line. This provides a far superior "walk testing" enviroment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Why not SWIG?&lt;/span&gt;&lt;br /&gt;I tried SWIG first, but soon gave up because it just seemed far more cumbersome.... and I really didn't want to have to learn the SWIG command syntax. Further, SWIG requires compilation against the correct python headers which makes building a pain if you use different python versions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ctypes&lt;/span&gt;&lt;br /&gt;ctypes provides a way to wrap C code, in this case the YAFFS direct library, so that it can be accessed from python. The actual ctypes wrapping is in the yaffsfs.py module and examples.py shows some calling.&lt;br /&gt;&lt;br /&gt;Ctypes wrapping is pretty simple for the most part but a few things are tricky, like handling pointers to structures. The yaffsfs cases do a few interesting things so this can be a useful example, particularly with handling the stat and directory entry structures:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;pre&gt;&lt;span class="PY_KEYWORD"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;def yaffs_ls(dname):&lt;br /&gt;if dname[-1] != "/": dname = dname + "/"&lt;br /&gt;dc = yaffs_opendir(dname)&lt;br /&gt;if dc != 0 :&lt;br /&gt;    sep = yaffs_readdir(dc)&lt;br /&gt;    while bool(sep):&lt;br /&gt;        se = sep.contents&lt;br /&gt;        fullname = dname + se.d_name&lt;br /&gt;        #print fullname, " ", se.d_ino," ",ord(se.d_type)&lt;br /&gt;        st = yaffs_stat_struct()&lt;br /&gt;        result = yaffs_stat(fullname,byref(st))&lt;br /&gt;        perms = st.st_mode &amp;amp; 0777&lt;br /&gt;        isFile = True if st.st_mode &amp;amp; 0x8000 else False&lt;br /&gt;        isDir  = True if st.st_mode &amp;amp; 0x4000 else False&lt;br /&gt;&lt;br /&gt;        if isFile :&lt;br /&gt;            print "File ",se.d_ino, hex(perms), st.st_size, fullname&lt;br /&gt;        if isDir :&lt;br /&gt;            print "Dir  ",se.d_ino, hex(perms), fullname&lt;br /&gt;            yaffs_ls(fullname)&lt;br /&gt;        &lt;br /&gt;        sep = yaffs_readdir(dc)&lt;br /&gt;    yaffs_closedir(dc)&lt;br /&gt;    return 0&lt;br /&gt;else:&lt;br /&gt;    print "Could not open directory"&lt;br /&gt;    return -1&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;/blockquote&gt;What is appealing about using python is that it provides a programming environment as well as a command shell to immediately execute code. This makes it really handy for testing a library.  I like to do this with gdb when "walk testing" individual fixes and features.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Using gdb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Firstly you'll need a debug version of python with symbols if you don't already have that.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;sudo apt-get install python-dbg&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;You use two terminal windows: one for python and the other for gdb You could use one window, but this is neater and easier.&lt;br /&gt;&lt;br /&gt;In the python window start python and load up the modules:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;yaffs2/direct/python$ python&lt;br /&gt;Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)&lt;br /&gt;[GCC 4.3.3] on linux2&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; from yaffsfs import *&lt;br /&gt;&gt;&gt;&gt; from examples import *&lt;br /&gt;yaffs: Mounting /yaffs2&lt;br /&gt;...&lt;br /&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Now in the gdb window you need to find out the python process id, start gdb and attach to the python process. Attaching to a process halts that process. You will have to tell gdb to continue. But we're first going to set a breakpoint on yaffs_open().&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;yaffs2/direct/python$ ps -ef | grep python&lt;br /&gt;charles   3791  3597  0 Nov03 ?        00:00:00 python /usr/share/system-config-printer/applet.py&lt;br /&gt;charles   4070 18972  0 15:21 pts/4    00:00:00 python&lt;br /&gt;charles   4100  4071  0 15:22 pts/9    00:00:00 grep python&lt;br /&gt;&lt;br /&gt;yaffs2/direct/python$ gdb /usr/bin/python&lt;br /&gt;GNU gdb 6.8-debian&lt;br /&gt;Copyright (C) 2008 Free Software Foundation, Inc.&lt;br /&gt;License GPLv3+: GNU GPL version 3 or later &lt;/span&gt;&lt;http: org="" licenses="" html=""&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;This is free software: you are free to change and redistribute it.&lt;br /&gt;There is NO WARRANTY, to the extent permitted by law.  Type "show copying"&lt;br /&gt;and "show warranty" for details.&lt;br /&gt;This GDB was configured as "i486-linux-gnu"...&lt;br /&gt;(gdb) attach 4070&lt;br /&gt;Attaching to program: /usr/bin/python, process 4070&lt;br /&gt;Reading symbols from /lib/tls/i686/cmov/libpthread.so.0...done.&lt;br /&gt;[Thread debugging using libthread_db enabled]&lt;br /&gt;[New Thread 0xb7e226c0 (LWP 4070)]&lt;br /&gt;Loaded symbols for /lib/tls/i686/cmov/libpthread.so.0&lt;br /&gt;Reading symbols from /lib/tls/i686/cmov/libdl.so.2...done.&lt;br /&gt;Loaded symbols for /lib/tls/i686/cmov/libdl.so.2&lt;br /&gt;Reading symbols from /lib/tls/i686/cmov/libutil.so.1...done.&lt;br /&gt;Loaded symbols for /lib/tls/i686/cmov/libutil.so.1&lt;br /&gt;Reading symbols from /lib/libz.so.1...done.&lt;br /&gt;Loaded symbols for /lib/libz.so.1&lt;br /&gt;Reading symbols from /lib/tls/i686/cmov/libm.so.6...done.&lt;br /&gt;Loaded symbols for /lib/tls/i686/cmov/libm.so.6&lt;br /&gt;Reading symbols from /lib/tls/i686/cmov/libc.so.6...done.&lt;br /&gt;Loaded symbols for /lib/tls/i686/cmov/libc.so.6&lt;br /&gt;Reading symbols from /lib/ld-linux.so.2...done.&lt;br /&gt;Loaded symbols for /lib/ld-linux.so.2&lt;br /&gt;Reading symbols from /usr/lib/python2.6/lib-dynload/readline.so...Reading symbols from /usr/lib/debug/usr/lib/python2.6/lib-dynload/readline.so...done.&lt;br /&gt;done.&lt;br /&gt;Loaded symbols for /usr/lib/python2.6/lib-dynload/readline.so&lt;br /&gt;Reading symbols from /lib/libreadline.so.5...done.&lt;br /&gt;Loaded symbols for /lib/libreadline.so.5&lt;br /&gt;Reading symbols from /lib/libncursesw.so.5...done.&lt;br /&gt;Loaded symbols for /lib/libncursesw.so.5&lt;br /&gt;Reading symbols from /lib/libncurses.so.5...done.&lt;br /&gt;Loaded symbols for /lib/libncurses.so.5&lt;br /&gt;Reading symbols from /usr/lib/python2.6/lib-dynload/_ctypes.so...Reading symbols from /usr/lib/debug/usr/lib/python2.6/lib-dynload/_ctypes.so...done.&lt;br /&gt;done.&lt;br /&gt;Loaded symbols for /usr/lib/python2.6/lib-dynload/_ctypes.so&lt;br /&gt;Reading symbols from /opt/y/dev/yaffs2/direct/python/libyaffsfs.so...done.&lt;br /&gt;Loaded symbols for ./libyaffsfs.so&lt;br /&gt;0xb7ff9430 in __kernel_vsyscall ()&lt;br /&gt;(gdb) b yaffs_open&lt;br /&gt;Breakpoint 1 at 0xb745779e: file yaffsfs.c, line 402.&lt;br /&gt;(gdb) c&lt;br /&gt;Continuing.&lt;/span&gt;&lt;br /&gt;&lt;/http:&gt;&lt;/blockquote&gt;&lt;br /&gt;The python session is now running as per normal, but as soon as you call yaffs_open, the breakpoint will trigger and you're back in the debugger&lt;br /&gt;&lt;br /&gt;python session&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&gt;&gt;&gt; yaffs_open("/yaffs2/xx",66,0666)&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;gdb session&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;[Switching to Thread 0xb7e226c0 (LWP 4070)]&lt;br /&gt;&lt;br /&gt;Breakpoint 1, yaffs_open (path=0x95ac714 "/yaffs2/xx", oflag=66, mode=438) at yaffsfs.c:402&lt;br /&gt;402        yaffs_Object *obj = NULL;&lt;br /&gt;(gdb) &lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Using python + ctypes + gdb give me a much simpler and faster way to do this sort of testing than the approach I was using before.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-4149010849926336954?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/4149010849926336954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=4149010849926336954' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/4149010849926336954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/4149010849926336954'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/11/using-python-ctypes-gdb-for-testing.html' title='Using python + ctypes + gdb for testing yaffs'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-5748521217222412036</id><published>2009-06-07T19:15:00.002-07:00</published><updated>2009-06-07T19:37:42.970-07:00</updated><title type='text'>Setting up Debian chroot under Ubuntu</title><content type='html'>Wanting to build for  the &lt;a href="http://www.balloonboard.org/"&gt;balloon board&lt;/a&gt; using &lt;a href="http://www.emdebian.org/"&gt;emdebian&lt;/a&gt;, I started out with the Debian instructions. However this caused my Ubuntu-based system to pick up a whole lot of changes from Debian which broke my system.&lt;br /&gt;&lt;br /&gt;So on some advise from Wookey I tried chroot.&lt;br /&gt;&lt;br /&gt;I ended up using a variant of the instructions from &lt;a href="http://viral.media.mit.edu/wiki/tiki-index.php?page=Debian+chroot+environment"&gt;here&lt;/a&gt; and &lt;a href="https://wiki.ubuntu.com/DebootstrapChroot"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Some important differences...&lt;br /&gt;&lt;br /&gt;Started with:&lt;br /&gt;&lt;pre&gt; sudo debootstrap --arch i386 lenny /debian http://ftp.uk.debian.org/debian/&lt;br /&gt;&lt;span style="display: block;" id="formatbar_Buttons"&gt;&lt;span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;img src="img/blank.gif" alt="Link" class="gl_link" border="0" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;That bootstraps the basic chroot debian environment in a directory called /debian&lt;br /&gt;&lt;br /&gt;From there you can follow the instructions from &lt;a href="http://viral.media.mit.edu/wiki/tiki-index.php?page=Debian+chroot+environment"&gt;here&lt;/a&gt;, but:&lt;br /&gt;* Skip over the first buch of stuff about cdebootstrap.&lt;br /&gt;* using /debian instead of /path/to/chroot&lt;br /&gt;&lt;span style="display: block;" id="formatbar_Buttons"&gt;&lt;span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;img src="img/blank.gif" alt="Link" class="gl_link" border="0" /&gt;&lt;span style="font-family: Georgia,serif;"&gt;* Don't copy in the /etc/apt/sources from the host distro.&lt;br /&gt;&lt;br /&gt;Ubuntu does not use /etc/inittab so to set vt8 up as a debian terminal go to /etc/event.d and&lt;br /&gt;create tty8 with the following:&lt;br /&gt;&lt;br /&gt;# tty8 - debian chroot tty&lt;br /&gt;#&lt;br /&gt;# This service maintains a getty on tty8 from the point the system is&lt;br /&gt;# started until it is shut down again.&lt;br /&gt;&lt;br /&gt;start on runlevel 2&lt;br /&gt;start on runlevel 3&lt;br /&gt;&lt;br /&gt;stop on runlevel 0&lt;br /&gt;stop on runlevel 1&lt;br /&gt;stop on runlevel 4&lt;br /&gt;stop on runlevel 5&lt;br /&gt;stop on runlevel 6&lt;br /&gt;&lt;br /&gt;respawn&lt;br /&gt;exec /usr/sbin/chroot /debian /sbin/getty 38400 tty8&lt;br /&gt;&lt;br /&gt;Then execute&lt;br /&gt;  sudo initctl start tty8&lt;br /&gt;&lt;br /&gt;If you &lt;ctl&gt;&lt;alt&gt;F8 you should now have a debian terminal that will login with no root.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-5748521217222412036?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/5748521217222412036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=5748521217222412036' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/5748521217222412036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/5748521217222412036'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/06/setting-up-debian-chroot-under-ubuntu.html' title='Setting up Debian chroot under Ubuntu'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-874310896631502619</id><published>2009-06-07T19:15:00.001-07:00</published><updated>2009-06-07T19:15:50.031-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Setting up Debian chroot under Ubuntu'/><title type='text'></title><content type='html'>&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-874310896631502619?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/874310896631502619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=874310896631502619' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/874310896631502619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/874310896631502619'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/06/blog-post.html' title=''/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-8919449962439091363</id><published>2009-04-30T17:11:00.000-07:00</published><updated>2009-04-30T17:13:48.375-07:00</updated><title type='text'>Code on github</title><content type='html'>git is a really interesting way to do source control and github.com provides a free git server.&lt;br /&gt;&lt;br /&gt;I've moved my AVR code to github to make it more accessable. Find it &lt;a href="http://github.com/cdhmanning"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-8919449962439091363?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/8919449962439091363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=8919449962439091363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/8919449962439091363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/8919449962439091363'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/04/code-on-github.html' title='Code on github'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-1269879005984798608</id><published>2009-04-26T19:05:00.001-07:00</published><updated>2009-04-26T19:14:44.413-07:00</updated><title type='text'>Phototransistor speed</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_l0SZr-Pvve4/SfUTGPbu2vI/AAAAAAAAAAU/Ix4gOXCc5IE/s1600-h/pt1.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 251px;" src="http://2.bp.blogspot.com/_l0SZr-Pvve4/SfUTGPbu2vI/AAAAAAAAAAU/Ix4gOXCc5IE/s320/pt1.jpg" alt="" id="BLOGGER_PHOTO_ID_5329186732005841650" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I tried a phototransistor instead of an LDR. Look at the speed difference! The scale here is different (far faster sampling) which means that the phototransistor is at least 50x the speed of the LDR.&lt;br /&gt;&lt;br /&gt;I'm designing a multi-channel colour sensor which will have 4 colour sensors controlled by a single AVR ATMEGA48.&lt;br /&gt;* Each sensor has 3 LEDs red, green, blue.&lt;br /&gt;* Each of these LEDs is turned on in turn, the ADC is then sampled approx 4 times and some filtering is done on the returned signal. The signal is then corrected for differences in phototransistor sensitivity etc by applying a simple gamma correction to give reasonably matched RGB values.&lt;br /&gt;&lt;br /&gt;Using phototransistors should make this all fast enough to operate 4 channels at 100Hz or so.&lt;br /&gt;&lt;br /&gt;100Hz sampling should be fast enough for an NXT robot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-1269879005984798608?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/1269879005984798608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=1269879005984798608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/1269879005984798608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/1269879005984798608'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/04/phototransistor-speed.html' title='Phototransistor speed'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_l0SZr-Pvve4/SfUTGPbu2vI/AAAAAAAAAAU/Ix4gOXCc5IE/s72-c/pt1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-3088539491176502158</id><published>2009-04-22T19:22:00.000-07:00</published><updated>2009-04-22T19:50:17.784-07:00</updated><title type='text'>LDR Speed</title><content type='html'>&lt;div style="text-align: left;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_l0SZr-Pvve4/Se_VIFk0RdI/AAAAAAAAAAM/8itzQJofyJM/s1600-h/ldr.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 251px;" src="http://2.bp.blogspot.com/_l0SZr-Pvve4/Se_VIFk0RdI/AAAAAAAAAAM/8itzQJofyJM/s320/ldr.jpg" alt="" id="BLOGGER_PHOTO_ID_5327711219114853842" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Light dependent resistors are cheap and relatively wide-band light sensors, but they are a bit slow relative to photodiodes and phototransistors.&lt;br /&gt;&lt;br /&gt;I used an AVR-based board to measure this, as follows:&lt;br /&gt;&lt;br /&gt;* Put an LDR and 6.8k resistor in series between 5V and ground as a voltage divider.&lt;br /&gt;&lt;br /&gt;* Attach the AVR's ADC pin to the connection between the resistor and LDR.&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_l0SZr-Pvve4/Se_VIFk0RdI/AAAAAAAAAAM/8itzQJofyJM/s1600-h/ldr.jpg"&gt;&lt;span style="font-weight: bold;"&gt;* Set another pin up to toggle an LED every 50msec.&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_l0SZr-Pvve4/Se_VIFk0RdI/AAAAAAAAAAM/8itzQJofyJM/s1600-h/ldr.jpg"&gt;&lt;span style="font-weight: bold;"&gt;* AVR samples ADConce each millisecond and spits out the value as a string on the RS232 port.&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;* PC logs serial port into file&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_l0SZr-Pvve4/Se_VIFk0RdI/AAAAAAAAAAM/8itzQJofyJM/s1600-h/ldr.jpg"&gt;&lt;span style="font-weight: bold;"&gt;*Use gnuplot to plot results.&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;As you can see, after approx 15msec the ADC value has settled quite well.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I don't quite know why the formatting got hosed.... but so be it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-3088539491176502158?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/3088539491176502158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=3088539491176502158' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/3088539491176502158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/3088539491176502158'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/04/ldr-speed.html' title='LDR Speed'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_l0SZr-Pvve4/Se_VIFk0RdI/AAAAAAAAAAM/8itzQJofyJM/s72-c/ldr.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4910051342384298494.post-6073947012593594042</id><published>2009-04-13T13:27:00.000-07:00</published><updated>2009-04-30T17:14:58.487-07:00</updated><title type='text'>Make your own Lego NXT sensors</title><content type='html'>Just finished putting together a presentation for the &lt;a href="http://www.kiwibots.org/"&gt;Christchurch Robotics Group&lt;/a&gt; on making custom sensors for the Lego NXT.&lt;br /&gt;&lt;br /&gt;Making resistive/switch sensors is very simple, but one of the sensors is an AVR-based I2C sensor which puts all the flexibility of a microcontroller in the sensor. More info on that to be posted later.&lt;br /&gt;&lt;br /&gt;Presentation pdf and code for the micro&lt;a href="http://users.actrix.co.nz/manningc/lego-nxt/"&gt; here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Update: Code is now on &lt;a href="http://github.com/cdhmanning"&gt;github&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4910051342384298494-6073947012593594042?l=embeddedjanitor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedjanitor.blogspot.com/feeds/6073947012593594042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4910051342384298494&amp;postID=6073947012593594042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/6073947012593594042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4910051342384298494/posts/default/6073947012593594042'/><link rel='alternate' type='text/html' href='http://embeddedjanitor.blogspot.com/2009/04/make-your-own-lego-nxt-sensors.html' title='Make your own Lego NXT sensors'/><author><name>Charles Manning</name><uri>http://www.blogger.com/profile/18291726651708249991</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://2.bp.blogspot.com/_l0SZr-Pvve4/S9UQE0ITbaI/AAAAAAAAABE/LkG84a4n5co/S220/cropped-rock.jpg'/></author><thr:total>0</thr:total></entry></feed>
