Skip to content

Using up to 24 interrupt pins on Arduino Mega.

This weekend I finally completed my several months long venture into the Atmega interrupt registry, in attempts to get more than just Arduino Megas’ 3 interrupt pins available for my project (which calls for at least 16 interrupt pins). Along with the interrupts I also tackled the Serial communication issue, in order to use the end result circuit some day as a game controller for a desktop game, but that is a topic for another blog post.

Previously I entertained the idea of using MCP23017 I/O expander for interrupt port expander, but I gave up on that avenue because:

  1. It seemed needlessly complicated to use interrupts via the IO expander
  2. I need those 7 available I/O expanders for other purposes, namely for running 16 leds each.

As usual, everything here is provided freely as is, with no warranties and in hopes it may be useful for someone.

PCINT-registries

Atmega 1280 – the IC running on Arduino Mega – provides a way to run a total of 24 interrupt pins by using PCINT0-PCINT23 -pins.

I used the interrupt pins for reading changes in 8 rotary encoders, which is why I set them up as  pairs.
Since I also needed only 16 pins, I only used PCINT0_vect and PCINT2_vect for my interrupts:

#ifndef ROTARY_ENCODER_H
#define ROTARY_ENCODER_H
struct RotaryEncoder
{
  int pin0;
  int pin1;
  volatile int rotationState;
  volatile int previousState;
};
#endif ROTARY_ENCODER_H

RotaryEncoder encoders[8];

//#define DEBUG

void pciSetup(byte pin)
{
  *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
  pinMode(pin, INPUT);
}

RotaryEncoder encoderSetup(int pin0, int pin1) {
  pciSetup(pin0);
  pciSetup(pin1);
  RotaryEncoder *encoder = (RotaryEncoder *) malloc(sizeof(RotaryEncoder));
  RotaryEncoder enc;
  enc.pin0=pin0;
  enc.pin1=pin1;
  enc.rotationState=0;
  enc.previousState=digitalRead(pin0);
  *encoder=enc;
  return *encoder;
}



void setup() {
  Serial.begin(9600);

  encoders[0] = encoderSetup(53,52);
  encoders[1] = encoderSetup(51,50);
  encoders[2] = encoderSetup(13,12);
  encoders[3] = encoderSetup(11,10);
  encoders[4] = encoderSetup(A8,A9);
  encoders[5] = encoderSetup(A10,A11);
  encoders[6] = encoderSetup(A12,A13);
  encoders[7] = encoderSetup(A14,A15);
}

That set the pins up as interrupt listeners, but it does not yet have anything that listens for the changes:

void interruptChange(RotaryEncoder *encoder) {
  int i0val = digitalRead((*encoder).pin0);
  int i1val = digitalRead((*encoder).pin1);
  if (i0val != i1val) {
    if (i0val != (*encoder).previousState) {
      (*encoder).rotationState=(*encoder).rotationState-1;
    } 
    else {
      (*encoder).rotationState=(*encoder).rotationState+1;
    }
  }
  else {
    (*encoder).previousState = i0val;
  }
#ifdef DEBUG
    Serial.println("Interrupted: ");
    Serial.println((*encoder).pin0);
    Serial.println((*encoder).pin1);
    Serial.println((*encoder).rotationState);
#endif
}

ISR(PCINT0_vect)
{
  interruptChange(&encoders[0]);
  interruptChange(&encoders[1]);
  interruptChange(&encoders[2]);
  interruptChange(&encoders[3]);
}

ISR(PCINT2_vect)
{
  interruptChange(&encoders[4]);
  interruptChange(&encoders[5]);
  interruptChange(&encoders[6]);
  interruptChange(&encoders[7]);
}

Note that this implementation means that any time any of the PCINT0_vect interrupt pins fires, the whole 8-pin vector will be observed for changes. As far as I can tell, this does not cause any problems, but no doubt there will be some. Please educate me if you know of something to beware here.

I tested this with running a single rotary encoder wired to randomly selected port pair. What I did not realize until much later is that if I did not ground the other pins, they were essentially floating, and would randomly read as high or low. Since the whole PCINTx_vect fires all at once, the floating pins caused ghost readings and major headaches. Grounding those pins solved this issue.

I debounced the rotary encoder signal, but for some reason I found that my circuit (below) worked better than the schematic I started with (https://hifiduino.wordpress.com/2010/10/20/rotaryencoder-hw-sw-no-debounce/). At this point I’m willing to concede that I did the circuit months ago and have no recollection why the wiring is like this – as opposed to the diagram in the blog.
This way my final proof of concept setup for the encoders & multiple interrupt pins looks like this:

usb_serial_duplex_bb

The resistors are 10 kohm and capacitors are 10 uF.

Wiring MCP23017 port expander to Arduino Uno

Arduino had too few pins for my project, so I researched some options for more pins:

Charlieplexing looks fancy, but since I need to run at least 128 leds in my project, it would require such a massive amount of wiring (N x N-1 >= 128 means N = 12) that I rejected it outright. I don’t have the patience nor the time to debug a rats nest of wires for this or any project if it can be avoided.

Multiplexers seemed like a good idea, but essentially I’m getting the same performance problems as Charlieplexing with just less wires – The SN74154 gives 16 pins for 4 binary inputs, but they are exclusive, which means that Arduino code is responsible for rotating the signals for each LED so that every LED gets to be on within a period of 20ms (50hz was given somewhere as required frequency for human eye). I want to avoid duct tape code almost as much as I want to avoid excessive wiring.

Hooking up multiple Arduinos could be a viable solution, but then I would be wiring and writing code for master + multiple slaves, and I dislike sharing the control responsibility among multiple Arduinos.

Since I already researched the I2C for using multiple Arduino boards, finding the I/O expander chips was a jackpot. I could get a large amount of additional ports with just using the I2C pins on Arduino (on Uno: A4 for SDA, A5 for SCL). And while MCP23017 only gives you 16 ports, the 23017’s addressing pins enables using 8 of them on a single I2C bus. That means getting 128 additional pins by using just 2 analog pins on your Arduino. The code remains clean as well, as long as you can logically group the needed pins in groups of 8 – which happily matches my requirements.

The wiring

Fritzing diagram for the circuit containing Arduino and MCP23017

Fritzing diagram for the circuit

There are few things you need to watch out for when wiring the MCP23017 and I2C bus connections.

First of all: MCP23017 address and RESET pins must be externally biased, even if you disable the addressing. Externally biasing them means in this case setting them to +5V or GND. RESET pin should be set for HIGH since it resets on active LOW. I just used the 0x20 address for MCP23017, so I set all three address bits to LOW. If any of them were high, they would affect the least significant bits of the address, resulting in possible address range of 0x20 to 0x27 for this device.

Another one is the required pull-down resistors for the I2C connection. I used 4k7 ohm resistors connected to GND.

LEDs are connected to GND through 220 ohm resistors to limit the current below 25mA.

The Fritzing diagram as well as the custom MCP23017 Fritzing part are available at this projects Github repository (MIT license)

The code

// @author Jukka Dahlbom
// @created 30.12.2014

// Adapted from Wire Master Writer sample code 
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates running multiple leds in sequence on MCP23017
// I2C port expander.


#include <Wire.h>

int ADDRESS = 0x20; // Default address for MCP23017
int IODIRA = 0x00;
int GPIOA = 0x12; // IOCON.BANK bit resets to 0, so using that mode.

void setup()
{
  delay(1000);
  Serial.begin(9600);
  Wire.begin(); // join i2c bus (address optional for master)
  Wire.beginTransmission(ADDRESS);
  Wire.write(IODIRA);         // IODIRA register
  Wire.write(0x00);        // Set bank A to output
  Wire.endTransmission();    // stop transmitting
}

void loop()
{  
  setOutput(computeUpdatedState());
  delay(300);
}

int computeUpdatedState() {
  static int phase = 0;
  int pin6 = 0x00, pin7 = 0x00, pin8 = 0x00;
  if (phase > 0 && phase < 4) {
    pin6 = 0x20;
  }
  if (phase > 1 && phase < 5) {
    pin7 = 0x40;
  }
  if (phase > 2 && phase < 6) {
    pin8 = 0x80;
  }
  phase = ++phase % 6;
  return pin6 + pin7 + pin8;
}

void setOutput(int value) {
  Wire.beginTransmission(ADDRESS);
  Wire.write(GPIOA);        // select GPIOA register
  Wire.write(value);        // Set output bits in bank A
  Wire.endTransmission();   // stop transmitting
}

In short, computeUpdateState rotates through 6 phases, setting LED pins GPA6-GPA8 HIGH in order, and then setting them LOW in order.

Of course you could achieve this sort of 3 LED demonstration much simpler with using Arduino directly, but the point here is was to validate my understanding of writing to MCP23017.

Next step

There are two more assumptions I need to test, and hopefully find the motivation to post here about:

  • Using multiple I/O expanders on the same I2C bus, and seeing if having 100 LEDs on causes any issues.
  • Using MCP23017 to expand the number of interrupt pins for Arduino. (EDIT 2015-11-29: See https://jdahlbom.wordpress.com/2015/11/29/using-up-to-24-interrupt-pins-on-arduino-mega/)

Setting up Oracle developer day VM on OSX

I have long felt that OSX is an excellent combination of UNIX console environment and office computer able to run MS Office suite.

This means I use my MacBook for everything, including running local databases to allow offline development. Imagine my surprise when it turns out that Oracle databases are not available for OSX. While it makes sense business wise (you wouldn’t run OSX on servers), it is still unfortunate for all of us developers on OSX platform.

Internet tells me there used to be an OSX port for version 10, but that seems to have disappeared at some point. So the only thing that remains for me is to set up a virtual machine image running the database. More effective image could be had by setting up a fresh Linux VM and installing the database from scratch, but since my initial need is to just test my application on Oracle DB, I went for the OTN Developer Day VM image. This image has the database and a number of Oracle tools installed, so all I need to do is spin it up and log in to play with the database.

At least that is how I thought it would go. After a long time of poking around the VM I realize that the instructions are incomplete or plain wrong. The only way I managed to log in to the database is by doing

sqlplus sys@orcl AS sysdba

This gives me local administration rights on the database, which pretty much gives me everything I need from now on. Now I have a database running locally, with full rights to it.

Thanks to everyone else who has documented their trial and error efforts with the Developer Day VM, I would have given up on this approach long before figuring this out if you had not posted those now mostly obsolete results.

Fixing Mac & iPhone hotspot USB tethering

Ever since iOS 5.1 & iTunes 10.6 updates the USB tethering has been broken.

As I have had to waste few hours fixing the issue every time iTunes gets updated again – with the broken
implementation – it is a high time I posted the solution that works for me for future reference.

This post was written when I had iOS 6.1.3 on iPhone 4, iTunes 11.0.5 and OSX 10.6.8 on Macbook Pro.

Steps to fixing it:

0. Make sure you can run sudo. If not, ask for your helpful company administrator to do this for you.

1. Download http://www.mediafire.com/download/zo22n2u2eml78vc/AppleUSBEthernetHost (md5: a817e7413bd3df29594c187e64859045)

2. Take a moment to consider the wisdom of downloading unknown content from public internet and copying it to your /System directory with root privileges.
Even though you can verify that you are using the same file as I am, you have no guarantee that I am not malicious.
Actually I’m just sloppy, and having weighed the risks and benefits of using an unknown, unverifiable file, I’m going with whatever gets me back to working quickly. Last time I did this, there were no noticeable side effects.

3. Replace the kernel extension contents with what you just downloaded:
sudo cp ${DOWNLOADS}/AppleUSBEthernetHost /System/Library/Extensions/AppleUSBEthernetHost.kext/Contents/MacOS

4. Fix the permissions for the file:
sudo chmod 644 /System/Library/Extensions/AppleUSBEthernetHost.kext/Contents/MacOS

5. Reload the AppleUSBEthernetHost kernel extension (if this seems a bit too magical, just restart your computer):
cd /System/Library/Extensions
sudo kextunload AppleUSBEthernetHost.kext/
sudo kextload AppleUSBEthernetHost.kext/

Works for me!

References

DopeyDupes post on Apple forums
Kernel extension loading

Container managed authentication, part I: Simple JAAS authentication provider

This is the first of a series of posts on authentication for Jboss + Spring security. The series attempts to provide a good walkthrough on how to set up container managed authentication accessing JDBC datasource for authentication information, and controlling the actual user authentication process via Spring Security.

None of this is hard to do by itself, but gathering it all together from online manuals did take a decent amount of time for someone understanding the basics. In this post I will set up a trivial security constraint on a trivial site, just to get you warmed up on the concept of container managed security.

Container managed security refers to having your application server manage part or all of your web application security.

As an application server I am using JBoss 6.1 community edition – the specifics may vary but the priciples are same across implementations.

How to authenticate – the application server configuration

In JBoss you have multiple server configurations ready for use – I used the configuration named “default”. Adding a new security policy is done by editing JBOSS_HOME/server/default/conf/login-config.xml:

<?xml version='1.0'?>
<policy>
<!-- Other, existing policies are here.. -->

<!-- This is additional policy used in the tutorial -->
  <application-policy name="demo-user-login">
    <authentication>
      <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
        flag="required">
        <module-option name="usersProperties">hardcoded-users.properties</module-option>
        <module-option name="rolesProperties">hardcoded-roles.properties</module-option>
      </login-module>
    </authentication>
  </application-policy>
</policy>

Both the properties files reside in the JBOSS_HOME/server/default/conf as well.
The hardcoded-users.properties refers to a property file containing username=password pairs.

user=password
unauthenticatedIdentity=guest

The hardcoded-roles.properties refers to a property file containing username=Role1,Role2 listings.

user=TestRole,OtherRole
guest=Guest

Application configuration: jboss-web.xml and web.xml

To control which application policy to use for your application, you modify jboss-web.xml:

<jboss-web>
<security-domain>java:/jaas/demo-user-login</security-domain>
</jboss-web>

The security domain element takes a reference to a JNDI name of the security domain. The JNDI name is formed by prepending java:/jaas/ to the application-policy name entered earlier.

Finally, we need to configure when to authenticate. This is done in web.xml of your WAR:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Name of the web resource being secured</web-resource-name>
            <description>Example constraint</description>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>TestRole</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Authentication tutorial test</realm-name>
    </login-config>

    <security-role>
        <role-name>TestRole</role-name>
    </security-role>
</web-app>
security-constraint

Security constraint defines which resource paths are secured. The auth-constraint sub-element constrains the access for specific user roles.

login-config

Login config defines how the authentication credentials are given: Basic authentication will do fine here – it causes the browser to prompt for authentication information.

security-role

Security role element defines security roles available within the application. It need not match the auth-constraint roles, but for simplicity, let us use those directly.

Start up your web server, deploy your WAR package and try to access it – your browser should prompt you for username/password. Username user and password should give you access.

That concludes the trivial case – next up: authentication against a JDBC data source.

Sources:

JBoss 6.0 security guide: Login Modules

Copying the address book from N900 to iPhone4

For some reason it seems that there are lot more people copying the address book from iPhone to N900, but I guess I’ll be the odd one out here.

What I’m working with here is a N900, iPhone4 and a MacBook with OSX Snow Leopard, so your mileage may vary when using some other operating system for syncing with your iPhone.

First of all: Export your contacts from N900

  1. From Address Book application, select Export from top menu
  2. Select vCard 3.0 for file format.
  3. Select location where you want your exports.

And that’s it, all contacts are in that directory you chose, one vcf file for each contact.

Now, plug that N900 to your computer as Mass Storage Media, and copy the files.

On my mac:

  1. Open the Address Book application and select File > Import
  2. Import any vcf file to add the contact

Now, you may notice that it only added one. At least on my OSX Address Book application, I could only select single file at a time. Out of more than a hundred.

Quick google shows that vCard 3.0 supports saving several contacts in one file, and it’s just a matter of catenating the files together.

One way of doing this quickly is just creating the following shell script and running it:

#!/bin/bash

TARGET="combined.vcf"
rm $TARGET

FILES=`ls -1|grep -e "vcf$"`

SAVEDIFS=$IFS
IFS=`printf "\n\b"`

for FILE in ${FILES}; do
echo "Processing file ${FILE}"
cat ${FILE} >> ${TARGET}
printf "\n" >> ${TARGET}
done

IFS=${SAVEDIFS}

Now you can import that file (“combined.vcf”, if you didn’t change it) to your Address Book and it will contain all the contacts you exported.

To sync the contacts to your iPhone you will need to turn on Address Book syncing.

  1. plug your iPhone to a mac and open iTunes (because it’s logical to use a music player to manage your phone…)
  2. From iTunes, select the iPhone volume
  3. From the Info menu you’ll find a deselected option “Sync Address Book Contacts”. Select it.
  4. Click Apply
  5. Sync

Verify from your iPhones address book that everything went as it should have.

QAbstractItemModels in QML views

UPDATE (2013-10-04):

The article below was written for Qt 4.7 tech preview. Since Qt 5.0 things have changed quite a bit. I’ve updated the example code and pushed it to https://github.com/jdahlbom/QtQmlListModel . The article still serves as a useful example for the codebase but I’ve tried to remove any redundant code that I wrote in the original example.

The wonderful people at Trolltech published a tech preview release of Qt 4.7 and its Declarative module in March. Declarative UI, QML and Qt Quick are all synonyms for the new Qt way of prototyping and developing the UI faster, and with less hassle of recompiling.

While the initial documentation for QML will get you far enough to get you excited about it, there are a enough of missing key pieces to really slow you down once you start working on a proper application. My first prototype QML application required access to a model, which is helpfully documented in official QML documentation:

The model provides a set of data that is used to create the items for the view. For large or dynamic datasets the model is usually provided by a C++ model object. The C++ model object must be a QAbstractItemModel subclass or a simple list.

Which gives you the pointer towards QAbstractItemModel, but no help whatsoever towards actually getting it working within QML. After a few weeks of sporadic study and experimentation, I had it finally figured out. The following example is a simple demo about accessing a QAbstractListModel data from the QML script.QML ListView as produced by this demo application.

The model class inheriting from QAbstractListModel is the trickiest part. The header does not look special in any way – just another list model with two custom ItemDataRoles.

SimpleListModel.h:
class DataObject;
class SimpleListModel : public QAbstractListModel {
    Q_OBJECT
public:
    SimpleListModel(QObject *parent=0);
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;

private:
    Q_DISABLE_COPY(SimpleListModel);
    QList<DataObject*> m_items;
    static const int FirstNameRole;
    static const int LastNameRole;
};

The implementation of the SimpleListModel deserves a more thorough discussion:

SimpleListModel.cpp:
#include "DataObject.h"

// You can define custom data roles starting with Qt::UserRole
const int SimpleListModel::FirstNameRole = Qt::UserRole + 1;
const int SimpleListModel::LastNameRole = Qt::UserRole + 2;

SimpleListModel::SimpleListModel(QObject *parent) :
        QAbstractListModel(parent) {
    // Create dummy data for the list
    DataObject *first = new DataObject(QString("Arthur"), QString("Dent"));
    DataObject *second = new DataObject(QString("Ford"), QString("Prefect"));
    DataObject *third = new DataObject(QString("Zaphod"), QString("Beeblebrox"));
    m_items.append(first);
    m_items.append(second);
    m_items.append(third);

The QML script accesses model data via named roles. While C++ side works with ItemDataRole enums, QML needs to have separately named roles that map to these enums. I am assuming the QML view gets the available role names via QAbstractItemModel::roleNames().

  QHash roles = roleNames();
  roles.insert(FirstNameRole, QByteArray("firstName"));
  roles.insert(LastNameRole, QByteArray("lastName"));
  setRoleNames(roles);
}

int SimpleListModel::rowCount(const QModelIndex &) const {
return m_items.size();
}

The QAbstractItemModel data is accessed via data()-function. For grid or tree models, the QModelIndex might hold more interest to us, but for a simple list like ours we are only interested in the row index, and the requested role. The roles each map to different field of the DataObject:

QVariant SimpleListModel::data(const QModelIndex &index,
                                            int role) const {
    if (!index.isValid())
        return QVariant(); // Return Null variant if index is invalid
    if (index.row() > (m_items.size()-1) )
        return QVariant();

    DataObject *dobj = m_items.at(index.row());
    switch (role) {
    case Qt::DisplayRole: // The default display role now displays the first name as well
    case FirstNameRole:
        return QVariant::fromValue(dobj->first);
    case LastNameRole:
        return QVariant::fromValue(dobj->last);
    default:
        return QVariant();
    }
}

The object displayed in one list cell will use the data stored internally in a DataObject, although the SimpleListModel never reveals the underlying objects.

DataObject.h:
class DataObject {  // my custom container class
public:
  DataObject(const QString &firstName,
             const QString &lastName):
     first(firstName),
     last(lastName) {}
  QString first;
  QString last;
};

In order for the QML to access the model, it needs to be registered for it. I used the QDeclarativeView prototyping class to display the QML elements.

qmlwindow.cpp
#include <QDeclarativeView>
#include <QDeclarativeEngine>
#include <QDeclarativeContext>

#include "SimpleListModel.h"

// A simple main window widget pre-generated by qt creator
QmlWindow::QmlWindow(QWidget *parent)
    : QMainWindow(parent)
{
    model = new SimpleListModel(this);

    view = new QDeclarativeView(this);
    view->engine()->rootContext()->setContextProperty("myModel",
                                                      model);
    view->setSource(QUrl("myuiscript.qml"));
}

qmlwindow.h:
class QmlWindow : public QMainWindow
{
    Q_OBJECT

public:
    QmlWindow(QWidget *parent = 0);
    ~QmlWindow();
private:
    SimpleListModel *model;
    QDeclarativeView *view;
};

The last piece missing from this demo is the actual QML script to display the data:

myuiscript.qml:
import Qt 4.7

Rectangle {
    id: bgRect
    width: 200
    height: 200
    color: "black"
    Component {
        id: myDelegate
        Item {
            width: 200
            height: 40
            Rectangle {
                anchors.fill: parent
                anchors.margins: 2
                radius: 5
                color: "lightsteelblue"
                Row {
                    anchors.verticalCenter: parent.verticalCenter
                    Text {
                        text: model.lastName
                        color: "black"
                        font.bold: true
                    }
                    Text {
                        text: model.firstName
                        color: "black"
                    }
                }
            }
        }
    }
    ListView {
        id: myListView
        anchors.fill: parent
        delegate: myDelegate
        model: myModel
    }
}

The three points that are relevant to discussion at hand: ListView.model property defines the source of all data. We pass the name of the contextProperty we set for the SimpleListModel. ListView.delegate property determines the component used for displaying the data. Within the delegate component, you can access the data of that cell through “model” variable. The properties accessible to this model are determined by the role names of the QAbstractItemModel used.

That concludes the demo application. Just add a main method and the missing includes I stripped off, and you should be good to go.

[EDIT: Fixed the SimpleListModel to append to role names instead of overwriting them]

Design a site like this with WordPress.com
Get started