Using teensy 3.0 / 3.1 and enc28j60 ethernet module with ethercad library

ENC28J60 SPI Clock at 4MHz

The teensy 3.0 and 3.1 boards, based on the MK20DX128 / MK20DX256 ARM Cortex-M4 micro-controller, part of the Kinetis K20 MCU family from Freescale, can be easily connected to the internet by using an inexpensive Microchip ENC28J60 module.

Having used the AVR based teensy 2.0 in the past, to accomplish similar functionality, I tried with the newer teensy 3.1, since I wanted to make use of it on a interesting project, which I’ll describe in another post. I had to make a few small changes to the ethercard library to be able to compile it, since the MK20DX256 is an ARM core. A copy of those changes is available on my personal repo teensy31 branch.

An important detail concerns a few pinout differences for the Serial Peripheral Interface (SPI), since now we are required to pass the CS pin 10 as argument when initializing the ethercard library:

// teensy 2.0 - enc28j60 connectivity
// teensy 3.1 - enc28j60 connectivity
// http://www.pjrc.com/teensy/pinout.html
// http://www.pjrc.com/teensy/td_libs_SPI.html
// 10 - CS
// 11 - SI
// 12 - SO
// 13 - SCK

const uint8_t csPin = 10;

void setup()
{
   if (ether.begin(sizeof(Ethernet::buffer), mymac, csPin) == 0)
   {
     Serial.println(F("Failed to access Ethernet controller"));
   }
}

If running the teensy at a speed other than 24MHz, say 48MHz , 72MHz or over-clocked at 96MHz, we also have to set the SPI clock speed, by choosing appropriate values for the SPI CTAR registers (SPI0_CTAR0, SPI0_CTAR1 for SPI0). For this we can make use of the spi4teensy3 library, or just take the piece of init code that accomplishes that. Right before we call the ether.begin() function we can set the speed as follows:

  // SPI.setClockDivider(SPI_CLOCK_DIV4);
  //
  // we want SPI clock to be set at 4MHz:
  // speed = 1 , ratio = 1/4
  // speed = 2 , ratio = 1/8
  // speed = 3 , ratio = 1/12
#if defined(__MK20DX128__) || defined(__MK20DX256__)
  #if F_BUS == 48000000
  spi4teensy3::init(3);
  #elif F_BUS == 24000000
  // spi4teensy3::init(2);
  #endif
#endif

   if (ether.begin(sizeof(Ethernet::buffer), mymac, csPin) == 0)
   {
     Serial.println(F("Failed to access Ethernet controller"));
   }

Note that bus frequency (F_BUS) is set to 24MHz when the MCU is running at 24MHz, but only at 48MHz even if the MCU main clock runs at a higher frequency (48MHz, 72MHz or 96MHz). For more details, check the reference manual in the Freescale link above.

ss4200 crash with newer kernel

Trying to upgrade a ss4200 system to the latest linux kernel (3.11.0) was giving me this:

 [   17.350579] BUG: unable to handle kernel NULL pointer dereference at 00000000000000e0
 [   17.352014] IP: [<ffffffff8135dedd>] kobject_get+0xd/0x50
 [   17.352014] PGD 1f181067 PUD 1f182067 PMD 0 
 [   17.352014] Oops: 0002 [#1] SMP 
 [   17.352014] Modules linked in: nf_conntrack_ftp(F) serio_raw(F) nf_conntrack(F) iptable_filter(F) leds_ss4200(+) ip_tables(F) x_tables(F) lpc_ich mac_hid raid10(F)  raid456(F) async_raid6_recov(F) async_memcpy(F) async_pq(F) async_xor(F) async_tx(F) xor(F) raid6_pq(F) raid0(F) multipath(F) linear(F) raid1(F) e1000e(F) ptp(F) ahc i(F) libahci(F) sata_sil24 pps_core(F)
 [   17.352014] CPU: 0 PID: 300 Comm: systemd-udevd Tainted: GF            3.11.0-13-generic #20-Ubuntu
 [   17.352014] Hardware name: Intel SS4200-E/SS4200-E, BIOS V090L   12/19/2007
 [   17.352014] task: ffff880018971770 ti: ffff88001c4ee000 task.ti: ffff88001c4ee000
 [   17.352014] RIP: 0010:[<ffffffff8135dedd>]  [<ffffffff8135dedd>] kobject_get+0xd/0x50
 [   17.352014] RSP: 0018:ffff88001c4efbc0  EFLAGS: 00010202
 [   17.352014] RAX: 00000000000000a8 RBX: ffff88001c7ce810 RCX: 0000000000000000
 [   17.352014] RDX: 0000000000000001 RSI: ffffffff81abe58e RDI: 00000000000000a8
 [   17.352014] RBP: ffff88001c4efc20 R08: 0000000000000000 R09: 000000000000ffff
 [   17.352014] R10: ffffea000071a800 R11: 0000000000000000 R12: 0000000000000000
 [   17.352014] R13: 0000000000000000 R14: ffff88001c7ce800 R15: ffffffffa0112130
 [   17.352014] FS:  00007f57c0ed9880(0000) GS:ffff88001fc00000(0000) knlGS:0000000000000000
 [   17.352014] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
 [   17.352014] CR2: 00000000000000e0 CR3: 000000001f180000 CR4: 00000000000007f0
 [   17.352014] Stack:
 [   17.352014]  ffffffff81471c68 ffffffff8108edd7 ffff88001c7ce800 ffff88001c7ce800
 [   17.352014]  0000000000000000 ffff88001c7ce810 00000000edea726f ffff88001c7ce800
 [   17.352014]  0000000000000000 ffff88001c7ce810 0000000000000000 ffffffffa0112130
 [   17.352014] Call Trace:
 [   17.352014]  [<ffffffff81471c68>] ? device_add+0xe8/0x7a0
 [   17.352014]  [<ffffffff8108edd7>] ? complete_all+0x47/0x50
 [   17.352014]  [<ffffffff81472530>] device_create_groups_vargs+0xe0/0x110
 [   17.352014]  [<ffffffff814725c1>] device_create+0x41/0x50
 [   17.352014]  [<ffffffff8135f43b>] ? kobject_uevent+0xb/0x10
 [   17.352014]  [<ffffffff81475c5b>] ? driver_register+0x10b/0x150
 [   17.352014]  [<ffffffff815af962>] led_classdev_register+0x32/0x150
 [   17.352014]  [<ffffffffa0010129>] nas_gpio_init+0x10c/0xfe3 [leds_ss4200]
 [   17.352014]  [<ffffffffa001001d>] ? ss4200_led_dmi_callback+0x1d/0x1d [leds_ss4200]
 [   17.352014]  [<ffffffff810020fa>] do_one_initcall+0xfa/0x1b0
 [   17.352014]  [<ffffffff810548d3>] ? set_memory_nx+0x43/0x50
 [   17.352014]  [<ffffffff810cbd72>] load_module+0x12b2/0x1b80
 [   17.352014]  [<ffffffff810c7c40>] ? store_uevent+0x40/0x40
 [   17.352014]  [<ffffffff810cc6e2>] SyS_init_module+0xa2/0xf0
 [   17.352014]  [<ffffffff816f529d>] system_call_fastpath+0x1a/0x1f
 [   17.352014] Code: 81 48 c7 c7 f0 7c cf 81 31 c0 e8 df d4 01 00 eb ca 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 85 ff 48 89 f8 74 12 ba 01 00 00 00 <3e> 0f c1 57 38  83 c2 01 83 fa 01 7e 01 c3 80 3d ec b4 98 00 00 
 [   17.352014] RIP  [<ffffffff8135dedd>] kobject_get+0xd/0x50
 [   17.352014]  RSP <ffff88001c4efbc0>
 [   17.352014] CR2: 00000000000000e0
 [   17.643696] ---[ end trace 83a9ab314c41f120 ]---

The quick and easy solution was to start with an earlier bootable kernel, blacklist the leds_ss4200 module and reboot:
echo “blacklist leds_ss4200″ > /etc/modprobe.d/blacklist-leds.conf
A quick search leads me to Bug 950160 RedHat.

9 DOF IMU (ITG3205+ADXL345+HMC5883L) + Beaglebone Black

For this experiment I’m using a BeagleBone Black (BBB) running Ubuntu 13.04 from a micro SD card. Alternatively for the latter there’s also a ARM Linux image that can run directly from the eMMC. The Inertial Measurement Unit (IMU) has 3 sensors sharing the I²C bus:

  • InvenSense ITG3205 3-axis gyroscope
  • Honeywell HMC5883L 3-axis compass
  • Analog Devices ADXL345 3 axis accelerometer

The IMU requires 3.3V which is ideal, since the I/O ports of the BBB are NOT 5V tolerant. We only need 4 wires to connect the BBB to the IMU through the Expansion Header P9 (see Table 12 of the BeagleBone Black System Reference Manual, Rev A5.6):

  • PIN 1 for GND
  • PIN 3 for DC 3.3V
  • PIN 19 for SCL (Serial Clock)
  • PIN 20 for SDA (Serial Data)

Installing the required packages:

sudo apt-get install i2c-tools

Listing the I²C buses:

ubuntu@bb1:~$ i2cdetect -l
i2c-0	unknown   	OMAP I2C adapter                	N/A
i2c-1	unknown   	OMAP I2C adapter                	N/A

Detecting the I²C devices:

ubuntu@bb1:~$ sudo i2cdetect -r 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- 53 UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
ubuntu@bb1:~$ sudo i2cdump 1 0x1e
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1, address 0x1e, mode byte
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 10 20 03 00 32 00 61 00 7c 03 48 34 33 00 00 3c    ? ?.2.a.|?H43..<
10: 00 00 00 00 00 00 00 00 00 00 00 02 06 0b e8 10    ...........?????
20: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00    ........?.......
30: 00 00 00 14 81 74 75 00 a0 00 07 00 00 00 00 00    ...??tu.?.?.....
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 10 20 03 00 32 00 61 00 7c 03 48 34 33 00 00 3c    ? ?.2.a.|?H43..<
90: 00 00 00 00 00 00 00 00 00 00 00 02 06 0b e8 10    ...........?????
a0: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00    ........?.......
b0: 00 00 00 14 81 74 75 00 a0 00 07 00 00 00 00 00    ...??tu.?.?.....
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: e5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a    ?..............J
10: 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
20: 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00    ............?...
30: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
40: e5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a    ?..............J
50: 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
60: 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00    ............?...
70: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
80: e5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a    ?..............J
90: 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
a0: 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00    ............?...
b0: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
c0: e5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4a    ?..............J
d0: 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
e0: 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00    ............?...
f0: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 68 fe 00 1d 00 00 05 00 00 1b 00 00 00 00 00 00    h?.?..?..?......
10: 00 00 00 00 00 00 00 00 00 00 01 c4 d0 00 d5 00    ..........???.?.
20: 6d ff e0 00 00 00 00 00 00 00 00 00 00 00 00 00    m.?.............
30: 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00    ........?.......
40: 68 fe 00 1d 00 00 05 00 00 1b 00 00 00 00 00 00    h?.?..?..?......
50: 00 00 00 00 00 00 00 00 00 00 01 c4 f0 00 d9 00    ..........???.?.
60: 46 ff f0 00 00 00 00 00 00 00 00 00 00 00 00 00    F.?.............
70: 00 00 00 00 00 00 00 00 00 ff 00 00 e7 00 00 00    ............?...
80: 68 fe 00 1d 00 00 05 00 00 1b 00 00 00 00 00 00    h?.?..?..?......
90: 00 00 00 00 00 00 00 00 00 00 01 c4 d0 00 cf 00    ..........???.?.
a0: 74 ff de 00 00 00 00 00 00 00 00 00 00 00 00 00    t.?.............
b0: 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00    ........?.......
c0: 68 fe 00 1d 00 00 05 00 00 1b 00 00 00 00 00 00    h?.?..?..?......
d0: 00 00 00 00 00 00 00 00 00 00 01 c5 00 00 dd 00    ..........??..?.
e0: 6f ff e6 00 00 00 00 00 00 00 00 00 00 00 00 00    o.?.............
f0: 00 00 00 00 00 00 00 00 00 00 00 00 e7 00 00 00    ............?...

The mapping between the I²C address above and the devices was found by looking into the corresponding datasheets.

References:

Raspberry Pi Relay Board

Raspberry Pi based Relay Board Recipe

Hardware:

  • Raspberry Pi Model B version 1 (256MB RAM)
  • SD Card
  • Relay Board with opto-couplers rated for 110V/220V
  • Adjustable D.C. Switched Mode Voltage Regulator
  • A.C. Transformer rated at 12V 1A
  • Assorted metal strips cut from used juice can to affix transformer to board
  • tiny Wi-Fi USB card
  • Printed Circuit Boards (PCB) for mounting
  • breadboard and connector for GPIOs
  • Assorted Power Socket outlets connected to each relay
  • Socket Inlet for input power
  • RCA connectors for audio output
  • Solder, screws, mix of wires and patience

Software:

  • Debian GNU/Linux
  • Python code to control relays.
  • Python code to setup wake up alarm.
  • Python code to play Big Ben chime and bell toll every now and then.

gerbmerge 1.8 ubuntu 13.04 (raring)

Installing gerbmerge on a recent linux distribution gives the following error:

Traceback (most recent call last):
  File "setup.py", line 41, in <module>
    DestDir = os.path.join(DestLib, 'gerbmerge')
  File "/usr/lib/python2.7/posixpath.py", line 77, in join
    elif path == '' or path.endswith('/'):
AttributeError: 'NoneType' object has no attribute 'endswith'

Here’s a simple patch that solves the above error:

diff -Naur gerbmerge-1.8-old/setup.py gerbmerge-1.8-new/setup.py
--- gerbmerge-1.8-old/setup.py	2011-06-08 18:06:53.000000000 -0400
+++ gerbmerge-1.8-new/setup.py	2013-07-21 15:57:50.492420178 -0400
@@ -2,6 +2,7 @@
 import sys
 import glob
 import os
+import site
 
 from distutils.core import setup, Extension
 import distutils.sysconfig
@@ -37,7 +38,7 @@
   BinFiles = ['misc/gerbmerge.bat']
   BinDir = '.'
 else:
-  DestLib = distutils.sysconfig.get_config_var('LIBPYTHON')
+  DestLib = site.getsitepackages()[0]
   DestDir = os.path.join(DestLib, 'gerbmerge')
   BinFiles = ['misc/gerbmerge']
   BinDir = distutils.sysconfig.get_config_var('BINDIR')  
@@ -46,8 +47,8 @@
   fid = file('misc/gerbmerge', 'wt')
   fid.write( \
   r"""#!/bin/sh
-python %s/site-packages/gerbmerge/gerbmerge.py $*
-  """ % DestLib)
+python %s/gerbmerge.py $*
+  """ % DestDir)
   fid.close()
 
 dist=setup (name = "gerbmerge",

To apply do the following:

sudo apt-get install python-simpleparse
tar xf gerbmerge-1.8.tar.gz
cd gerbmerge-1.8
patch -p1 < ~/gerbmerge-1.8-ubuntu-13.04.patch
sudo python ./setup.py install

where ~/gerbmerge-1.8-ubuntu-13.04.patch is the location of the above patch.

network connected temperature and humidity sensor

Temperature
humidity

Having obtained a few ethernet modules based on the Microchip ENC28J60 Ethernet Controller and DHT21 temperature/humidity sensors, I put my time to work on a simple project to connect these to a teensy 2.0.

This way I can remotely monitor temperature and humidity through a web browser and plot it over time using the mrtg tool, as seen the images above, which are updated in realtime. To handle the network connection I used the EtherCard driver and configured it as a simple webserver that queries the sensor whenever it receives a page request.

The interface to the sensor is done through a slightly modified DHT22 library, to account for some issues with the bit-banging timing, which I tuned using an oscilloscope, I had to change the bit value detection threshold from 11 to 12.

For power I used a nokia phone charger that provides about 5V, which is sufficient for the temperature sensor, and using a linear regulator LM317 reduce that to the 3.3V required by the ethernet module. The remaining was to put everything into a small box, connect the power and the ethernet cable as seen in the pictures below.

The firmware source code and the configuration for mrtg with accompanying python query script can be found at the git repo for this project.

Rigol DS1052E (50MHz) -> DS1102E (100MHz) software upgrade

Sometime ago I got a Rigol DS1052E oscilloscope, it’s a 2 channel 50MHz analog bandwidth 1GSa/s digital scope with USB connection to the PC and easily upgradeable to 100MHz analog bandwidth by a simple firmware change. In my case, since the device had the 00.03.01 firmware version, I followed a slightly different procedure:

  • copy the firmware file to a clean vfat formatted usb flashdrive and check the md5sum ( 01d2d46d6c565c492b6f49725404f18b )
  • insert the flashdrive it into the scope, wait for it to be detected, and start the upgrade (takes a few minutes, do not power off the scope)
  • restart the scope (power off; power on)
  • recalibrate

There was some screen flickering, which went away after the recalibration procedure.

SMD Storage

I’ve been looking for quite a while for a convenient storage solution for Surface Mount Device (SMD) parts. The usual electronics drawers are too big and prone to mixing parts when jolted around. I ended up getting a few configurable storage boxes: 25mm x 31mm x 21.5mm and 75mm x 31mm x 21.5mm. I started with resistors and needless to say it took quite some time to put them into the small boxes. Using an automatic pick-and-place machine is probably out of the question now.