Electronic Nirvana

Capacitive Touch with Windows IoT Core on Raspberry Pi 2 using MPR121

1/18/2016

0 Comments

 
After getting my Raspberry Pi 2 installed with Windows IoT core, I wanted to get a MPR121 Capacitive touch break out board working with it. While Adafruit had a library for Arduino, there wasn't one readily available for Windows IoT Core. So I wrote this MPR121 library in C# that can be used with the Raspberry Pi. In addition to the sample app available in the Github repo,  I also  created a Touch sensitive Christmas tree using this library.

About MPR121
​
MPR121 is a proximity and capacitive touch controller from NXP Semiconductors. Adafruit has this chip on a breakout board that can be interfaced with micro controllers. It has 12 pins that can be utilized as Capacitive touch sensing electrodes. A partial set of these pins can also be used as GPIO pins. This first version of the library is geared towards capacitive touch configuration only. 

Picture
MPR121 breakout from Adafruit
Note the pin configuration related to the ADDR pin. In case you have other I2C devices and their address conflicts with the default I2C address of MPR121 (0x5A), then address can be changed by connecting the ADDR pin to VSS, VDD, SDA or SCL line. The library i created gives the options to use any of the addresses while it defaults to 0x5A
Picture
Wiring

The hookup to Raspberry Pi is pretty straightforward. Apart from SCL/SDA and the Power/Ground hookups, only other hook up is the IRQ Pin to the GPIO Pin#5 on the Raspberry Pi 2. I am using an Adafruit Pi Cobbler but it can be hooked up directly to the PI. The Capacitive sensing pins are connected to some cardboard wrapped in aluminum foils.
Picture
Interfacing

MPR121 board can be interfaced using I2C. Once I2C connection is established, specific registers can be read to get the status of the pins.  The touch status for each pin is maintained as a bit. 1 to indicate touch and 0 to indicate no touch. By reading a byte at register 0x00, the touch status of the first 8 pins can be obtained. Five bits on the next register 0x01 indicate the status of the remaining 5 pins. Here is the register map:
Picture
All the register information can be found in this datasheet. Also of interest would be all the application notes.

IRQ Pin
Brute force method is to read this register in a loop every few milliseconds to check if they are touched or not. Fortunately MPR121 provides an elegant way of notifying the status. Its has an IRQ pin that can be connected to any GPIO digital input pin on the micro controllers. The MPR121 pulls this pin Low when there is a status change on any of the capacitive pins. So instead of looping to detect change, the micro controller can read the Register only when the IRQ status changes. This library uses the IRQ pin for detecting cap sense change.
Driver Walkthrough

The code for this driver can be found at this Github repository.

1. Its a simple Universal Windows App class library. Since it needs to work with GPIO and I2C, added the Windows IoT Extensions for the UWP.

2. The library contains two constructors. The default one and the overloaded constructor to change the I2C address and the IRQ pin.
3. The I2C connection is established by calling the OpenConnection method. This method accepts a Windows IoT core device descriptor id sting of the I2C master on the Raspberry PI. Once connection is established, a soft reset command is issued. After setting up the capacitive sense threshholds as defined in the Application note, i hook up the Interrupt pin.
4. One of the great advantages of the Windows IoT core is the native event framework. It makes it quite easy to design the software to respond to events on the connected GPIO pins. So the GPIO pin is simply initialized and hooked up to the ValueChanged event. Whenever IRQ pin value changes, the GPIO pin 5 will raise the event and execute the attached event handler. Note that the event execution happens in a different thread than the UI thread.
5. Before we look at the ValueChanged event handler, a word on the PinId enum flag that i am using to identify the pins. If you notice the touch status register information above, one bit is used to indicate each pins status. So having them represented with flags Enum makes it natural to translate the data read from the registers. The Flags enum also has an HasFlags method that makes it quite easy to check which pins are touched/released.
6. When the value changed event handler is invoked, the MPR121 pulls the IRQ pin low. So i track for the FallingEdge on the GPIO pin. Also MPR121 expects the status registers to be read immediately. The status register will hold the data for that moment. If two pins are touched at the same time, the register will have the bits for both pins turned on. So by simply reading the two bytes from address 0x00 and casting it in to PinId enum, I get the list of pins that are currently touched. Additionally i want to expose both the touched and released events. So i compare it with the previous touched event and do necessary checks to obtain newly touched pins and newly released pins. 
In order for the consumer hook up to simple Touched and Released events, i have included two events in the MPR121 class and invoke those two events with the appropriate event arguments.In addition i also update a Pins list the represents the continuous state of all the pins on the MPR121. 
Sample Usage
The library is available in NuGet as well as Windows.IoT.Core.HWInterfaces.MPR121 . So it can be installed to your Universal Windows app targeting Raspberry Pi from Nuget using:
Install-Package Windows.IoT.Core.HWInterfaces.MPR121
Once Installed,  initialize the mpr121 , open connection and hook up the events. Here is simple UI the tracks the pins pressed and the associated code. The complete sample is available at the Github repository.
Picture
Future Considerations
The code might not be very tight. There is lot of room for refactoring. In addition,  when time permits i hope to update this library to expose the GPIO configuration and the proximity sensing configuration. But all in all i ended up learning quite a few things when putting this together.
0 Comments

Windows IoT Core and the Raspberry Pi 2

12/30/2015

0 Comments

 
Had a load of fun getting my Raspberry PI 2 set up with Windows IoT core and the whole development environment that's needed for it.

1. Windows 10 and Visual Studio:

Can't develop for Windows IoT core without Windows 10.  So had to set up Windows 10 on Mid 2011 Mac. The problem was my Mac already had Debian Linux running on a separate partition. I used the wonderful rEFInd boot manager from Rod Smith earlier to do the partitioning and it came in handy to add the third partition for windows 10. Had some quirky troubles with the Apple Wireless mouse and keyboard but i have a wired keyboard/mouse connected to the Mac just in case. [So now my mac has two keyboards and two mouse.. :)  One day i need to get around to fixing the problem permanently.]

After getting Windows 10 on the Mac installing VS 2015  was a breeze.

2. Windows IoT Core on Raspberry Pi:

Followed the official instructions to create a SD card with Windows IoT core, transferred the SD card to Raspberry PI 2 and booted it up. Everything good so far. Then disaster struck when i tried to set up the WiFi connection.

My Logitech wired keyboard was not recognized properly by Windows IoT Core. Well, it recognized the keyboard but for some reason was skipping keys, treating single key press as long key press and all sorts of weird things. Tried using a powered USB hub but Iot Core doesn't recognize devices connected to the powered USB hub. 

Loaded Raspbian in another SD Card and verified that there is no problem with the USB port or my Keyboard. Raspbian worked like charm with my keyboard and mouse.

I didn't want to get another keyboard. My WiFi router is far away from my workspace and there is no wired connection. I need a wired connection near my workspace. So what to do?

Time for another long postponed project. Update my old Linksys router with DD-WRT and turn it in to a repeater. The folks at DD-WRT are wizards. Just had to follow the New Wiki installation instructions at DD-WRT for my model of Linksys router (WRT54G2) and the Repeater Bridge set up instructions.    

After this i was able to connect my Pi to my "new" repeater with a LAN cable and my IoT Dashboard running on Windows 10 was able to see the Pi. Now i can manage the PI over the network and don't need the keyboard connected to the PI. (Well.. I would need it if i have to run something that need keyboard input on the PI..Well.. that's for another day. Just have to design applications that don't need keyboard input for now..)

3. Testing..
So wrote up a quick Windows UWA application, loaded it on the PI and i was good to go. 

So far its mixed feelings. Realize that the Windows IoT core device support is not mature. But i like the idea about being able to hack the Pi with code written in C# and Visual Studio. 

​Will explore more..



0 Comments

WiFiLamp with FastLED and Windows Remote Arduino

12/28/2015

0 Comments

 
In an earlier post I enabled an Arduino Yun to be controlled by Windows Remote Arduino over WiFi. This project is a further extension of it in exploring what is possible with Windows Remote Arduino. This time i connected a LED strip (TM1803 based three wire LED strip from Radioshack) to my Yun and controlled its color through an Universal Windows App that uses Windows Remote Arduino. Here is the lamp in action. 
(I realize that there is a lag in the video between the phone overlay and the lamp. Something wrong with my video encoder. Couldn't figure it out. Job for another day..)
 Key Components

Aside from Yun and Windows Remote Arduino, the key components are:
1. LED Strip : Most of the LED strips have dedicated IC chips on them to control a fixed set of LEDs and communicate the data downstream to next IC chip on the strip.  I used a Radioshack LED strip that uses TM1803. This is a small 1 meter strip with 10 chips controlling 30 LEDs.
2. Power Source: Most of the LED's strips would need a separate power source. Mine required a 12v power supply. Since the Yun is only a 5V device, the power source and Yun had to have a common ground. Even thought there are ways to use the same 12v power supply to drive both the LED and Yun, i chose to run them with separate power source and common ground.
3. FastLed Library:
This is an excellent Arduino library developed and maintained by Daniel Garcia and Mark Kriegsman. There is no other library that supports such a vast array of LED strips as this.

Wiring

Simple wiring steps:
1. 12V power adapter +V to RGB Led Strp +Vcc
2. 12v Power Adapter GND to Arduino Yun Gnd pin.
3. RGB Led Strip GND to Arduino Yun Gnd pin
4.RGB Led String Data Pin to Arduino Digital 3 ( ~ pwm)

Arduino can be powered with a battery or wall wart independent of the LED strip power. Here is my wired up Yun before installing it in the lamp.
Picture
Software

The LED strips will be controlled by an Arduino Sketch using the FastLED library. The sketch will receive the color information from the Windows Universal App over WiFi through the Windows Remote Arduino's Firmata interface.

Modified Firmata

​Instead of using the StandardFirmataYun as mentioned in the earlier project, i am using a stripped down version of the firmata sketch as i am interested only in handling the string message call back. The call back will accept a string with the format of "R,G,B" and parse it to provide the color information to the FastLed library.
Univeral Windows App

1. Create a new Universal Windows App in Visual studio
2. Prepare the UI. XAML can be found in GitHub repository.
3. The universal app establishes a Network Serial connection to the Yun's Linux Serial port. (Note: This works only if the Yun was prepared as per the instructions in the earlier project.). There is a slight variation in the initialization of the Windows Remote Arduino in this code as the "sendString" function is available only on the UwpFirmata class. So an instance of UwpFirmata should be initialized first and passed to the constructor of RemoteDevice. Then a network serial connection should be prepared and passed as parameter to firmata.begin.. Then the network serial begin() should be called to open up connection to Arduino. The WRA initialization code is listed below: ​
4. The app displays an UI element with a color gradient. The app uses the WriteableBitmapEx NuGet package to add some extension methods that makes it easier to pick the color at the screen location where the user touches. Initialize the writeableBitmap so that it can be reused. Code:

5. On Click/Touch event, picks the color at the touched point and sends it to Arduino Yun by using the firmata.sendString method. Making a "flush()" call after every send to ensure that the string is processed cleanly. I had issues without calling flush().
All source code is available at the following Github url.
0 Comments

    Author

    Mohan

    In search of the imperturbable stillness of mind after the fires of desire, aversion, and delusion have been finally extinguished.

    Archives

    January 2016
    December 2015
    January 2014

    Categories

    All
    Arduino
    Arduino Yun
    Capacitive Touch
    Energia
    LED
    MPR121
    Noob Mistakes
    Raspberry Pi
    Tiva
    TM4C123G
    TM4C123GXL
    Univeral Windows App
    Windows IoT
    Windows Remote Arduino

    RSS Feed

Powered by Create your own unique website with customizable templates.