<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Simon Dobson (Posts about software)</title><link>https://simondobson.org/</link><description></description><atom:link href="https://simondobson.org/categories/software.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:simoninireland@gmail.com"&gt;Simon Dobson&lt;/a&gt; </copyright><lastBuildDate>Fri, 07 Aug 2026 09:08:10 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>New release of epydemic</title><link>https://simondobson.org/2024/11/29/new-release-of-epydemic/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;div id="outline-container-org0c1efed" class="outline-2"&gt;
&lt;h2 id="org0c1efed"&gt;New release of epydemic&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org0c1efed"&gt;
&lt;p&gt;
It's been a while – about 15 months since v.1.13.1 – but today I
finally released v.1.14.1 of &lt;code&gt;epydemic&lt;/code&gt;, a library for epidemic (and)
other simulation over complex networks.
&lt;/p&gt;

&lt;p&gt;
This release include several bug-fixes and two major changes.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb28d1d3" class="outline-3"&gt;
&lt;h3 id="orgb28d1d3"&gt;Better Newman-Ziff percolation&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgb28d1d3"&gt;
&lt;p&gt;
The Newman-Ziff algorithm for bond and site percolation is widely
used. The version that's been in &lt;code&gt;epydemic&lt;/code&gt; for a while emphasise
speed over everything. However, in the course of some work by one
of my MSc students on how grids of different dimensions respond to
random failure, we discovered that we needed to be able to do some
more flexible operations. In particular, we wanted to sample things
other than just the size of the largest connected component, and
wanted to be able to dig into to exactly how the network was
deforming.
&lt;/p&gt;

&lt;p&gt;
The problem was that this information wasn't readily available. It
&lt;i&gt;was&lt;/i&gt; encoded within the algorithm's data structure, but it wasn't
being reflected as an evolving network that was easy to get at. So
we upgraded the algorithm to build a working copy of the network as
it was constructed, so that it could be interrogated by
normal &lt;code&gt;networkx&lt;/code&gt; operations within the sampling process. This adds
some time penalty, but it's acceptable slowdown for the extra
capability.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org88cc177" class="outline-3"&gt;
&lt;h3 id="org88cc177"&gt;Multiple process instances&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-org88cc177"&gt;
&lt;p&gt;
&lt;code&gt;epydemic&lt;/code&gt; defines different epidemic processes (and indeed
non-disease processes like pulse-coupled oscillators). Until now
these have been usable alone in a simulation, but not together: one
couldn't run &lt;i&gt;two&lt;/i&gt; diseases in the &lt;i&gt;same&lt;/i&gt; simulation over the &lt;i&gt;same&lt;/i&gt;
population simultaneously. Doing so is obviously very desirable,
especially if you want to explore co-infecting diseases.
&lt;/p&gt;

&lt;p&gt;
Co-infection is a difficult problem. As a first step we've added
multiple process instances which can have their own parameters and
results – or can share parameters if required. This involves
assigning distinct names to each instance, and then optionally
using them to decorate parameter/result names.
&lt;/p&gt;

&lt;p&gt;
This is fiddly if done manually, so we also added some methods on
the &lt;code&gt;Process&lt;/code&gt; class to get and set parameters and results using any
instance name on the calling process. For example:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;   &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

   &lt;span class="c1"&gt;# network&lt;/span&gt;
   &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;
   &lt;span class="n"&gt;kmean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
   &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ERNetwork&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
   &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ERNetwork&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KMEAN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kmean&lt;/span&gt;

   &lt;span class="c1"&gt;# first infection&lt;/span&gt;
   &lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Disease1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P_INFECT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P_INFECTED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
                         &lt;span class="p"&gt;})&lt;/span&gt;

   &lt;span class="c1"&gt;# second infection&lt;/span&gt;
   &lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Disease2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P_INFECT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P_INFECTED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
                         &lt;span class="p"&gt;})&lt;/span&gt;

   &lt;span class="c1"&gt;# common removal rate&lt;/span&gt;
   &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SIR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;P_REMOVE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;

   &lt;span class="c1"&gt;# run the processes together&lt;/span&gt;
   &lt;span class="n"&gt;ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProcessSequence&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
   &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StochasticDynamics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ERNetwork&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
   &lt;span class="n"&gt;rc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fatal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The &lt;code&gt;setParameters&lt;/code&gt; call sets the parameters decorated with the name
of the process, if it has one. There are other operations for
extracting the parameters, and for interacting with experimental
results without getting into the details of decoration.
&lt;/p&gt;

&lt;p&gt;
See &lt;a href="https://pypi.org/project/epydemic/"&gt;the project documentation&lt;/a&gt; for more details, as well as an
updated tutorial and a cookbook recipe for co-infection (which is
based around the code above). The &lt;a href="https://github.com/simoninireland/epydemic"&gt;Github repo&lt;/a&gt; is also available. To
upgrade, just run:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;   &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;upgrade&lt;/span&gt; &lt;span class="n"&gt;epydemic&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
or delete and re-build any virtual environments.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>epydemic</category><category>network science</category><category>software</category><guid>https://simondobson.org/2024/11/29/new-release-of-epydemic/</guid><pubDate>Fri, 29 Nov 2024 16:35:46 GMT</pubDate></item><item><title>epydemic hits 100,000 downloads</title><link>https://simondobson.org/2024/05/08/epydemic-100000/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;div id="outline-container-org9f8632c" class="outline-2"&gt;
&lt;h2 id="org9f8632c"&gt;epydemic hits 100,000 downloads&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org9f8632c"&gt;
&lt;p&gt;
Downloads of &lt;code&gt;epydemic&lt;/code&gt;, my &lt;a href="/development/projects/epydemic/"&gt;library&lt;/a&gt; for epidemic (and other) process
simulation on networks (and hopefully other combinatorial structures
soon…) recently passed 100,000.
&lt;/p&gt;

&lt;p&gt;
That number comes from the project's &lt;a href="https://www.pepy.tech/projects/epydemic"&gt;PePy page&lt;/a&gt;, which tracks
downloads from the main &lt;a href="https://pypi.org/project/epydemic/"&gt;PyPi page&lt;/a&gt; as used by &lt;code&gt;pip&lt;/code&gt;. I can't say
whether or not that number is accurate. Quite honestly it's at least
98,000 more than I ever expected, but 100,000 feels like something
of a milestone to be pleased about.
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;epydemic&lt;/code&gt; came about because of a lack of standard tooling for doing
epidemic simulation. This involves a lot of stochastic simulation,
which is quite tricky code to write and to make efficient. Testing
the system actually involved us thinking more deeply about the
effectiveness of unit testing for stochastic code, which then led to
a &lt;a href="/softcopy/stochastic-testing-21.pdf"&gt;presentation at UK Systems in 2021&lt;/a&gt; explaining the problems we'd
had.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>epydemic</category><category>software</category><guid>https://simondobson.org/2024/05/08/epydemic-100000/</guid><pubDate>Wed, 08 May 2024 15:21:29 GMT</pubDate></item><item><title>New version of epyc released</title><link>https://simondobson.org/2021/09/06/new-version-of-epyc-released/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;div&gt;&lt;p&gt;I released a new version of my &lt;code&gt;epyc&lt;/code&gt; experimental management
library.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://simondobson.org/2021/09/06/new-version-of-epyc-released/"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>development</category><category>epyc</category><category>experimental design</category><category>python</category><category>software</category><guid>https://simondobson.org/2021/09/06/new-version-of-epyc-released/</guid><pubDate>Mon, 06 Sep 2021 12:50:48 GMT</pubDate></item><item><title>First SleepySketch release</title><link>https://simondobson.org/2014/01/07/sleepysketch-release/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;p&gt;Happy 2014! We're particularly happy to be making the first release of the SleepySketch library for writing low-power Arduino sketches.

&lt;!--more--&gt;

SleepySketch changes the way you write Arduino sketches by letting the library, rather than the main body of the sketch, decide when to run code. The sketch stays asleep as much as possible, with the Arduino placed into a low-power state to preserve battery.

This is a first release of SleepySketch, for comments. It provides a sketch framework, a basic sleep manager, and an example "blinkenlights" demonstration to show how the system fits together. Future releases will provide more flexible sleep management and support for component-level power management for common components like Xbee radios.

You can download SleepySketch v. 0.1 from &lt;a href="https://simondobson.org/download/sleepysketch/"&gt;here&lt;/a&gt;.

 &lt;/p&gt;</description><category>arduino</category><category>making</category><category>power management</category><category>sleepysketch</category><category>software</category><guid>https://simondobson.org/2014/01/07/sleepysketch-release/</guid><pubDate>Tue, 07 Jan 2014 12:36:14 GMT</pubDate></item><item><title>Some improvements to SleepySketch</title><link>https://simondobson.org/2013/07/26/improvements/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;p&gt;It's funny how even early experiences change the way you think about a design. Two minor changes to SleepySketch have been suggested by early testing.&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;The first issue is obvious: milliseconds are a really inconvenient way to think about timing, especially when you're planning on staying asleep for long periods. A single method in SleepySketch to convert from more programmer-friendly days/hours/minutes/seconds times makes a lot of difference.&lt;/p&gt;
&lt;p&gt;The second issue concerns scheduling -- or rather regular
scheduling. Most sampling and communication tasks occur on predictable
schedules, say every five hours. In an &lt;a href="https://simondobson.org/2013/06/01/actor-systems/" target="_blank"&gt;actor
framework&lt;/a&gt;, that means the actor instance (or another one) has to
be re-scheduled after the first has run. We can do this within the
definition of the actor, for example using the &lt;code&gt;post()&lt;/code&gt;
action:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PeriodicActor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Actor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;behaviour&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PeriodicActor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheduleIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expandTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(This also demonstrates the &lt;code&gt;expandTime()&lt;/code&gt; function to re-schedule after 0 days and 5 hours, incidentally.) Simple, but bad design: we can't re-use &lt;code&gt;PeriodicActor&lt;/code&gt; on a different schedule. If we add a variable to keep track of the repeating period, we'd be mixing up "real" behaviour with scheduling; more importantly, we'd have to do that for &lt;em&gt;every&lt;/em&gt; actor that wants to run repeatedly.&lt;/p&gt;
&lt;p&gt;A better way is to use an actor combinator that takes an actor and a period and creates an actor that runs first re-schedules the actor to run after the given period, and then runs the underlying actor. (We do it this way so that the period isn't affected by the time the actor actually takes to run.)&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Actor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RepeatingActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SomeActor&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expandTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheduleIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expandTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;RepeatingActor&lt;/code&gt; runs the behaviour of
&lt;code&gt;SomeActor&lt;/code&gt; every 5 hours, and we initially schedule it to
run in 5 hours. We can actually encapsulate all of this by adding a
method to &lt;code&gt;SleepySketch&lt;/code&gt; itself:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheduleEvery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SomeActor&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expandTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;to perform the wrapping and initial scheduling automatically.&lt;/p&gt;
&lt;p&gt;Simple sleepy sketches can now be created at set-up, by scheduling
repeating actors, and we can define the various actors and re-use them
in different scheduling situations without complicating their own
code.&lt;/p&gt;</description><category>actors</category><category>framework</category><category>making</category><category>power management</category><category>project:ditch</category><category>sleepysketch</category><category>software</category><guid>https://simondobson.org/2013/07/26/improvements/</guid><pubDate>Fri, 26 Jul 2013 15:20:38 GMT</pubDate></item><item><title>Sleepy sketches</title><link>https://simondobson.org/2013/07/25/sleepy-sketches/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;p&gt;Keeping the microcontroller asleep as much as possible is a key goal for a sensor system, so it makes sense to organise the entire software process around that.&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;The standard Arduino software model is, well, standard: programs ("sketches") are structured in terms of a &lt;code&gt;setup()&lt;/code&gt; function that runs once when the system restarts and a &lt;code&gt;loop()&lt;/code&gt; function that is run repeatedly. This suggests that the system spends its time running, which possibly isn't all that desirable: a sensor system typically tries to &lt;a href="https://simondobson.org/2013/07/25/sleepy-sketches/2013/07/23/arduino-watchdog"&gt;stay in a low-power mode&lt;/a&gt; as much as possible. The easiest way to do this is to provide a programming framework that handles the sleeping, and where the active bits of the program are scheduled automatically.&lt;/p&gt;
&lt;p&gt;There are at least two ways to do this. The simplest is a library that lets &lt;code&gt;loop()&lt;/code&gt; sleep, either directly or indirectly. This is good for simple programs and not so good for more complicated ones, as it means that &lt;code&gt;loop()&lt;/code&gt; encapsulates all the program's logic in a single block. A more modern and compositional approach is to let program fragments request when they want to run somehow, and have a scheduler handle the sleeping, waking up, and execution of those fragments. That lets (for example) one fragment decide at run-time to schedule another&lt;/p&gt;
&lt;p&gt;If we adopt this approach,we have to worry about the fact that one fragment might lock-out another. A desktop system might use threads; this is more problematic for a microcontroller, but an alternative is to force all fragments to only execute for a finite amount of time, so that the scheduler always gets control back. This might lead to a fragment not running when it asked (if other fragments were still running), but if we assume that the system spends most of its time asleep anyway, there will be plenty of catch-up time. Doing this results in an &lt;a href="https://simondobson.org/2013/06/01/actor-systems/"&gt;actor system&lt;/a&gt; where the fragments are actors that are scheduled from an actor queue.&lt;/p&gt;
&lt;p&gt;Turning this into code, we get the &lt;code&gt;SleepySketch&lt;/code&gt; library: a library for building Arduino sketches that spend most of their time sleeping.&lt;/p&gt;
&lt;p&gt;&lt;img alt="SleepySketch design" src="https://simondobson.org/images/citizen-sensing/sleepysketch.png"&gt;&lt;/p&gt;
&lt;p&gt;There are a few wrinkles that need to be taken care of for running on a resource-constrained system. Firstly, the number of actors available is fixed at start-up (defaulting to 10), so that we can balance RAM usage.(With only 2k to play with, we need to be careful). Secondly, we use a class to manage the sleeping functionality in different ways: a &lt;code&gt;BusySleeper&lt;/code&gt; that uses the normal &lt;code&gt;delay()&lt;/code&gt; function (a busy loop) with no power-saving functions, a &lt;code&gt;HeavySleeper&lt;/code&gt; that uses the watchdog timer to shut the system down as far as possible, and possibly some other intermediate strategies. Actors are provided by sub-classing the &lt;code&gt;Actor&lt;/code&gt; class and providing a behaviour. We also allow pre- and post-behaviour actions to define families of actors, for example sensor observers. We separate the code for an actor from its scheduling.&lt;/p&gt;
&lt;p&gt;The standard library uses singleton classes quite a lot, so for example the &lt;code&gt;Serial&lt;/code&gt; object represents the USB connection from an Arduino to its host computer and is the target for all methods. We use the same approach and define a singleton, &lt;code&gt;Sleepy&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The program structure then loops something like this. If we assume
that we've defined an actor class &lt;code&gt;PingActor&lt;/code&gt;, then we can
do the following:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HeavySleeper&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheduleIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PingActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ping!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Sleepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;setup()&lt;/code&gt; code initialises the serial port and the sleepy sketch using a &lt;code&gt;HeavySleeper&lt;/code&gt;, and then schedules an actor to run in 10000ms. The loop() code runs the actors while there are actors remaining to schedule. If the &lt;code&gt;PingActor&lt;/code&gt; instance just prints its message, then there will be no further actors to execute and the program will end; alternatively the actor could schedule further actors to be run later, and the sketch will pick them up. The sketch will remain asleep for as long as possible (probably for over 9s between start-up and the first ping), allowing for some fairly significant power saving.&lt;/p&gt;
&lt;p&gt;This is a first design, now just about working. It's still not as easy
as it could be, however, and needs some testing to make sure that the
power savings do actually materialise.&lt;/p&gt;</description><category>actors</category><category>framework</category><category>making</category><category>power management</category><category>project:ditch</category><category>sleepysketch</category><category>software</category><guid>https://simondobson.org/2013/07/25/sleepy-sketches/</guid><pubDate>Thu, 25 Jul 2013 12:00:01 GMT</pubDate></item><item><title>The xbee-arduino library</title><link>https://simondobson.org/2013/07/03/xbee-arduino/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;p&gt;A library for using XBee radios with Arduinos.&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;The XBee radio operates in &lt;a href="https://simondobson.org/2013/07/01/xbee/" target="_blank"&gt;two modes&lt;/a&gt;: transparent or text-based, and API or binary-based. The latter (API mode) is generally considered more suitable for computer-to-computer interactions, as it's faster and simpler for computers to manipulate. However, using an XBee in this mode requires additional software.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://code.google.com/p/xbee-arduino/" target="_blank"&gt;xbee-arduino library&lt;/a&gt; provides Arduino functions to access the API mode functionality of the various XBee radio modules. The library is quite low-level, but does provide access to all the necessary functions like issuing AT commands to control the modem and sensing and receiving packets of data to other radios in the mesh network.&lt;/p&gt;
&lt;p&gt;To use the library you download the latest version from the web page and unpack it into the &lt;tt&gt;libraries/&lt;/tt&gt; directory of your Arduino IDE. You also need to make sure that the radios you use have the &lt;a href="https://simondobson.org/2013/07/02/xctu/" target="_blank"&gt;API function set installed using X-CTU&lt;/a&gt;, as the library only makes sense for radios in API mode. You also have to set the "AP" parameter to 2 when writing the firmware.&lt;/p&gt;</description><category>arduino</category><category>making</category><category>project:ditch</category><category>software</category><category>xbee</category><guid>https://simondobson.org/2013/07/03/xbee-arduino/</guid><pubDate>Wed, 03 Jul 2013 07:30:22 GMT</pubDate></item><item><title>XBee firmware management with X-CTU</title><link>https://simondobson.org/2013/07/02/xctu/</link><dc:creator>Simon Dobson</dc:creator><description>&lt;p&gt;Managing Digi's XBee radio modules requires using their X-CTU package to upload the correct firmware. In this post we explain how.&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;This post is slightly depressing: not because it's on an unhappy topic, but because the effort and software needed to manage XBee radios is so complex to set up. In many ways this is just a function of the good design of the XBee: it's so minimal in terms of footprint and power consumption at run-time that it offloads a lot of work to external tools (and the user) at system build-time. But it's still a lot of work to get such a small piece of kit running.&lt;/p&gt;
&lt;p&gt;X-CTU is intended to upload firmware to XBee radio modules. This is needed to change the firmware between router and co-ordinator of the Zigbee &lt;a href="https://simondobson.org/2013/07/02/mesh-network/" target="_blank"&gt;mesh network&lt;/a&gt;, and between the different protocol variants that the XBee radios can support.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Xbee on USB" src="https://simondobson.org/images/citizen-sensing/2013-06-29-13.35.45.jpg"&gt;&lt;/p&gt;
&lt;p&gt;One limitation of X-CTU is that it only works on Windows: if you're running Linux, X-CTU will run under &lt;a href="http://www.winehq.org/" target="_blank"&gt;Wine&lt;/a&gt;. You can download the latest X-CTU from &lt;a href="http://www.digi.com/support/kbase/kbaseresultdetl?id=2125" target="_blank"&gt;Digi's X-CTU page&lt;/a&gt;; alternatively, there's a version installed on the &lt;a href="https://simondobson.org/download/virtual-machine/" target="_blank"&gt;Citizen Sensing VM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To use X-CTU you need to connect your XBee module to your computer. The easiest way to do this is using an XBee USB breakout board, which provides an XBee socket and a USB socket. Insert the radio into the board, plug in a USB cable, and plug the other end into a USB socket. The light on the breakout board will then come on (see photograph above).&lt;/p&gt;
&lt;p&gt;&lt;img alt="X-CTU in operation" src="https://simondobson.org/images/citizen-sensing/xctu-connect.png"&gt;&lt;/p&gt;
&lt;p&gt;You next need to start up X-CTU and tell it where the XBee is. It hangs off a Windows COM port, and X-CTU will typically find it automatically. You should then be able to press the "Test/Query" button, and X-CTU will interrogate the XBee and display a small window showing some information about it, as shown in the screenshot on the right: the details don't matter, but this shows that the XBee is talking to the computer properly.&lt;/p&gt;
&lt;p&gt;&lt;img alt="X-CTU router firmware" src="https://simondobson.org/images/citizen-sensing/xctu-firmware-router.png"&gt;&lt;/p&gt;
&lt;p&gt;Assuming everything is now working correctly, the next step is to decide what firmware to download to the radio. Click on the "Modem configuration" tab, and then click the "Read" button: this reads the firmware that's on the XBee at the moment, and puts the details into the window. Typically this results in a display like that shown on the left. The important things to notice are the two drop-down boxes labelled "Function Set" and "Version". The function set is the description of the firmware, in which case indicating that the XBee is running Zigbee router firmware that responds to AT commands (more on this below).&lt;/p&gt;
&lt;p&gt;&lt;img alt="X-CTU co-ordinator firmware" src="https://simondobson.org/images/citizen-sensing/xctu-firmware-coordinator.png"&gt;&lt;/p&gt;
&lt;p&gt;To download a new firmware, we then select the function set and version we want to use. Suppose we want to make this XBee into the mesh co-ordinator. We change the function set to "Zigbee Coordinator AT" (keeping with Zigbee and the AT command set) in  "Function set" the drop-down, then select the most recent version of this function set from the "Version" drop-down. (Versions are identified by hex numbers: the most recent in the screenshot right is "20A7", that being the highest hex number. Unfortunately X-CTU orders the numbers alphabetically, not in hex-numeric order.) Pressing "Write" will update the radio's firmware, and the radio is then ready for use as a co-ordinator.&lt;/p&gt;
&lt;p&gt;If you look through the list of function sets, there will be quite a few options, including protocols other than Zigbee. These probably aren't worth too much exploration, but you'll also notice that there are Zigbee AT and API function sets corresponding to the &lt;a href="https://simondobson.org/2013/07/01/xbee/" target="_blank"&gt;two modes (transparent and API)&lt;/a&gt; that the XBee can support. Be sure to select the correct one for your application.&lt;/p&gt;
&lt;p&gt;That's it: the radio is now ready for use.
&lt;/p&gt;&lt;h3&gt;Advanced use: setting optional parameters&lt;/h3&gt;
There's one more thing that X-CTU can be used for: it can set parameters to the firmware function set, and this is sometimes important when using the radios.
&lt;p&gt;&lt;img alt="X-CTU parameter setting" src="https://simondobson.org/images/citizen-sensing/xctu-parameter-setting.png"&gt;&lt;/p&gt;
&lt;p&gt;When you've read the firmware from a radio, the main part of the X-CTU window contains a hierarchy of folders and cryptic values, for example "(4) PL - Power level". These are parameters that can be changed to modify the detailed behaviour of the radio. Some can also be set using AT commands. The example we used sets the radio's power level to 4. If you click on this, it will show a drop-down box giving other options. You might, for some applications, choose to reduce the radio power to 1 ("low") to save batteries. If you choose this and then write the firmware to the radio, the module will use this power setting.&lt;/p&gt;
&lt;p&gt;In the example shown on the left, we're changing the AP parameter ("API enable") to 2, which is needed for the &lt;a href="https://simondobson.org/2013/07/03/xbee-arduino" target="_blank"&gt;xbee-arduino library&lt;/a&gt; to work properly. If we now write the firmware (with the Zigbee co-ordinator API function set selected as shown), the radio will be ready for use.&lt;/p&gt;</description><category>arduino</category><category>firmware</category><category>making</category><category>project:ditch</category><category>software</category><category>wireless</category><category>x-ctu</category><category>xbee</category><guid>https://simondobson.org/2013/07/02/xctu/</guid><pubDate>Tue, 02 Jul 2013 08:00:34 GMT</pubDate></item></channel></rss>