VoCore, Micropython, more Blinking

Lately I measured the maximum frequency I could get out of the VoCore by toggling a GPIO as fast as possible using various approaches. Today I wrote a simple Kernel module which allows me to set/clear a GPIO through IOCTL. Also I created a FFI binding to IOCTL for micropython and the usual test program for toggling the pin. And, no surprise, this is the fastest I was able to get so far from user space and micropython: 9kHz (remember, pure Kernel implementation was 14kHz).

Thus, the ranking now is:

Code Freq
Shell, sysfs 1.2kHz
Micropython, sysfs 1.6kHz
Python 2.7, sysfs 0.7kHz
C, sysfs 3.2kHz
Micropython, IOCLT, kmod 9.2kHz
Pure kmod 14kHz

The full source code could be found in this gist.

VoCore Maximum Blink Frequency

Today I did some testing on the maximum blink frequency I could get out of the VoCore using the “sysfs“ GPIO interface. I used four different candidates:

  • A shell script
  • A Python 2.7 program, basically the one described here (gist)
  • A Micropython program, more or less the same as the above, but using native libc file IO trough FFI as described here (gist)
  • And finally a C program

To summarize up the code used here the relevant snippets:

Shell Test Code

while true                           
do                                   
  echo 1 > /sys/class/gpio/gpio12/value
  echo 0 > /sys/class/gpio/gpio12/value
done

Python/Micropython Test Code

pin = DigitalIO.get_output(GPIO12)

while True:
  pin.set()
  pin.clear()

Full source:

C Test Code

#include <sys/types.h<
#include <sys/stat.h<
#include <fcntl.h<

#define SYSFS_ENTRY     "/sys/class/gpio/gpio22/value"

static int f;

void gpio_init()
{
        f = open(SYSFS_ENTRY, O_WRONLY | O_SYNC);
}

void gpio_term()
{
        close(f);
}

void gpio_set(void)
{
        write(f, "1", 1);
}

void gpio_clear(void)
{
        write(f, "0", 1);
}

int main()
{
        gpio_init();

        for(;;)
        {
                gpio_set();
                gpio_clear();
        }

        gpio_term();

        return 0;
}

Results

The results measured through OpenBench Logic Sniffer:

Code Freq
Shell 1.2kHz
Micropython 1.6kHz
Python 2.7 0.7kHz
C 13kHz

Addition: I also tried the same from within a Kernel module. By doing so, I was able to get about 14kHz.

The clear winner is C (note, that it is essential for the performance to NOT open/close the FD each time, but keep it open), followed by Micropython and the shell script. At the end is Python with very poor performance (which I could not explain up to now).

VoCore, Micropython and the SYSFS

As I wrote a while ago I was not able to access the Kernels SYSFS through the build-in “open/read/write” methods from micropython. I thought this might be because of the old version of micropython which comes from the OpenWrt binary repository, but even rebuilding OpenWrt did’t change anything.

Then I realized, there is FFI (foreigen function interface) support build into micropython. This allowed me to wrap the libc’s open/read/write operations directly into micropython. And finally, when using the wrapped libc methods, I am able to blink a LED from micropython on the VoCore. The source for this looks like so:

Simple Snap-In Case for Hacklace2 v2.0

I refined the previous case a little to have less height and rounded corners. Looks much lighter now. The new design could be found on thingiverse as usual.

Hacklace2 Snap-In Case v2.0

Hacklace2 Snap-In Case v2.0

Hacklace2 Snap-In Case v2.0

Hacklace2 Snap-In Case v2.0

Hacklace2 Snap-In Case v2.0

Hacklace2 Snap-In Case v2.0

VoCore Arrived

Today my VoCore modules arrived from China (they are amazingly tiny). So time for a first LED blink right? Ok, I wanted to get things working quickly so I decided to go with the pre-installed OpenWrt and Python + sysfs. Unfortunately there is not Python on the device, and also the right package sources are missing. However, this could be easily fixed.

VoCore Top

VoCore Top

VoCore Size

VoCore Size

VoCore Bottom

VoCore Bottom

VoCore compared to ESP8266

VoCore compared to ESP8266

1) Add additional package source to /etc/opkg.conf

src/gz cheese_packages http://downloads.openwrt.org/snapshots/trunk/ramips/packages/packages

2) Update package index

opkg update

3) Install Python

Unfortunately the Python package has a unresolved dependency (to libcrypt). Thus, we need to fore the install:

opkg install --force-depends python

Now we are able to use this simple script (since the sysfs GPIO support is already enabled on the VoCore):

VoCore 1st Blink

VoCore 1st Blink


Note on Micropython

I was very happy to see that micropython is available as a package from the OpenWrt repository. So this was my first try. Unfortunately, mircropython was not able to read/write the sysfs pseudo-files, and thus I had to revert to “real” Python.

Simple Snap-In Case for Hacklace2

Just created a simple snap-in case for the Hacklace2. Two versions are provided: One which houses a Hacklace2 with soldered on headers, one which houses a Hacklace2 without headers. The OpenSCAD sources and printable STL files could be found on thingiverse.

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

Hacklace2 Case

EDIMAX Smart Plug SP-1101W – Simple Python API

I puzzled the findings from my previous posts regarding the EDIMAX Smart plug (Basics, Scheduling) together and uploaded a simple Python API for the plug to my github. More details are available in the README of the project.

EDIMAX SP-W1101W

EDIMAX SP-W1101W

To give a quick impression of the API, here some examples (full code is here):

Set/Get plug state

# import plug API
from ediplug.smartplug import SmartPlug

# create plug object for plug with IP 172.16.100.75, login admin and password 1234
p = SmartPlug("172.16.100.75", ('admin', '1234'))

# change state of plug to ON
p.state = "ON"
print("Plug is now: ", p.state)

# change state of plug to OFF
p.state = "OFF"
print("Plug is now: ", p.state)

Set/Get scheduling

# import plug API
from ediplug.smartplug import SmartPlug

# create plug object for plug with IP 172.16.100.75, login admin and password 1234
p = SmartPlug("172.16.100.75", ('admin', '1234'))

# write schedule for one day to plug (Saturday, 11:15 - 11:45)
p.schedule = {'state': u'ON', 'sched': [[[11, 15], [11, 45]]], 'day': 6}

# query and print current schedule
print(p.schedule.__str__())

# write schedule for one week
p.schedule = [
        {'state': u'ON', 'sched': [[[1, 0], [1, 30]]], 'day': 0},
        {'state': u'ON', 'sched': [[[2, 0], [2, 30]]], 'day': 1},
        {'state': u'ON', 'sched': [[[3, 0], [3, 30]]], 'day': 2},
        {'state': u'ON', 'sched': [[[4, 0], [4, 30]]], 'day': 3},
        {'state': u'ON', 'sched': [[[5, 0], [5, 30]]], 'day': 4},
        {'state': u'ON', 'sched': [[[6, 0], [6, 30]]], 'day': 5},
        {'state': u'ON', 'sched': [[[7, 0], [7, 30]]], 'day': 6},
    ]

# query and print current schedule
print(p.schedule.__str__())

EDIMAX Smart Plug Switch SP-1101W – Scheduling

As an response to my article on operating the EDIMAX Smart Plug with Python today I got an E-Mail from Jorge, asking if I could give some details on how to program the schedule of the EDIMAX Smart Plug. So here are some basics on how this could be done through HTTP/XML (sorry, no Python code yet basic Python API supporting scheduling).

01_http_post.sh

This is the shell script I use to post the example XML requests and print the results from the plug.

02_getsched.xml

Sample XML to query the current scheduling set on the plug. E.g. the following call:

./http_post.sh getsched.xml

Would return a result as shown in 02_getsched_response.xml. For each day we have an entry like:

 <Device.System.Power.Schedule.X value="ON">...</Device.System.Power.Schedule.X>

X = 0 is Sunday, X = 1 is Monday, X = 6 is Saturday. The “value” attribute is “ON” if the schedule for this day is active or “OFF” if disabled. The data of the “Device.System.Power.Schedule.X” tag is 360 bytes long. Each hour is represented by 15 bytes, thus 360 bytes = 24h.

Each byte in the hour could represent 1, 2, 3 or 4 minutes on an ending interval:

0 = 0 min
8 = 1 min
C = 2 min
D = 3 min
F = 4 min

And on an beginning interval:

0 = 0 min
7 = 1 min
3 = 2 min
1 = 3 min
F = 4 min

The sum of all hour bytes is 60. Thus, a full hour of scheduling could be represented by:

FFFFFFFFFFFFFFF

Half an hour would be:

FFFFFFFC0000000

This is because F = 4 min., C = 2 min. and thus: 4 + 4 + 4 + 4 + 4 + 4 + 4 + 2 = 30 min.

04_sched_sun_0100-0130.xml

So for example set a schedule for Sunday from 01:00 till 01:30, we could send the XML as shown in “04_sched_sun_0100-0130.xml”.

Propeller Tool-Chain Installer (GCC, SPIN, BST, ..) Updated

I updated my installer-script for the Parallax Propeller tool-chain (GCC, SPIN, BST and others) to make it work (agin) on Ubuntu 14.04. Main issue was that the current “makeinfo” seems not to be happy with some of the “.texi” files from “binutils” used by the Propeller GCC. Thus, I added a patch to the script to solve this problem. Also the open-source-spin compiler needed a small patch since it now uses “stricmp” which is not POSIX and thus not known …

Finally I dropped support for the “loader” hack which allowed compilation of the “propgcc” on non Intel platforms. This is not any more such an issue since cross-compiling of “propgcc” is now supported (see “propgcc” README).

NOTE: if you are on a 64bit platform an you are going to install BST Tools, you need to make sure to install the required i386 libraries since BST binaries are 32bit only. On Ubuntu 14.04 the following should do the trick:

sudo apt-get install libgtk2.0-0:i386

Operate Real Light From ComputerCraft

Recently I got notice about ComputerCraft, a Minecraft mod which is all about computers and programming in Minecraft. Each computer block could be connected to redstone in-/outputs, and is programmable in Lua. Today I installed the mod and played a little with it. The result is: I am now able to use a redstone switch to turn on/off a real life light. As a back end I use my recent work on RCSwitch, running on the Pi (using the Python REST-Server to accept command), and making a HTTP-post request from ComputerCraft/Lua. Pretty simple, pretty impressive.