Notes About Working with Various Arduino & Netduino Microcontroller Boards

Sunday, December 30, 2012

Sparkfun DeadOn RTC DS3234 Breakout & Netduino Plus 2

On 12/27/2012, I published an example of using the DeadOn RTC with an Arduino Due.  I have also tried to get it to work with the Netduino Plus 2. The code below reads the date and time from the DS3234 clock chip via SPI and prints them to the debug console in Visual Studio. For some reason, the value for seconds is always returned as 0. I will keep looking into this issue. The code is an adaptation of the sample code for the Arduino, but it implements only the "read" function. I will work on the code for setting the time and date and publish it in the near future.

For documentation on using SPI with the Netduino, see  http://wiki.netduino.com/SPI.ashx and http://wiki.netduino.com/SPI-Configuration.ashx.

Connections:
DeadOn RTC  Netduino Plus 2
GND         GND
VCC         3V3
CLK         D13
MISO        D12
MOSI        D11
SS          D10

Code:
using System.Threading;

using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using Microsoft.SPOT;
using System;

namespace DeadOnRTC
{
    public class Program
    {
        public static void Main()
        {
            byte[] WriteBuffer = new byte[1];
            byte[] ReadData = new byte[7];
            uint[] TimeDate = new uint[7];

            SPI.Configuration Device1 = new SPI.Configuration(
                Pins.GPIO_PIN_D10, // SS-pin
                false,             // SS-pin active state - false = low
                0,                 // The setup time for the SS port
                0,                 // The hold time for the SS port
                true,              // The idle state of the clock
                true,              // The sampling clock edge
                2000,              // The SPI clock rate in KHz
                SPI_Devices.SPI1   // The SPI bus
            );
            SPI SPIBus = new SPI(Device1);
            // 0x8E is addr of config byte
            WriteBuffer[0] = 0x8E;
            SPIBus.Write(WriteBuffer);
            // 0x60 = b01100000
            // Disable Oscillator & Battery SQ wave @1hz, temp comp., no Alarms
            WriteBuffer[0] = 0x60;
            SPIBus.Write(WriteBuffer);
            while (true)
            {    
                WriteBuffer[0] = 0x01;
                SPIBus.WriteRead(WriteBuffer, ReadData);
                //Data order: second,minute,hour,null,day,month,year
                for (uint i = 0; i <= 6; i++)
                {
                    if (i == 3) 
                        i++; 
                    uint n = ReadData[i];
                    uint a = n & 0x0F;
                    if (i == 2)
                    {
                        uint b = ((n & 0x30) >> 4); //24 hour mode
                        if (b == 2)
                            b = 20;
                        else if (b == 1)
                            b = 10;
                        TimeDate[i] = a + b;
                    }
                    else if (i == 4)
                    {
                        uint b = ((n & 0x30) >> 4);
                        TimeDate[i] = a + b * 10;
                    }
                    else if (i == 5)
                    {
                        uint b = ((n & 0x10) >> 4);
                        TimeDate[i] = a + b * 10;
                    }
                    else if (i == 6)
                    {
                        uint b = ((n & 0xF0) >> 4);
                        TimeDate[i] = a + b * 10;
                    }
                    else
                    {
                        uint b = ((n & 0x70) >> 4);
                        TimeDate[i] = a + b * 10;
                    }
                }
                String time = padZero(TimeDate[2]) + ":" + padZero(TimeDate[1]) + ":" + padZero(TimeDate[0]);
                String date = padZero(TimeDate[5]) + "/" + padZero(TimeDate[4]) + "/" + padZero(TimeDate[6]);
                Debug.Print(date + " " + time);
                Thread.Sleep(1000);
            }
        }
        public static string padZero(uint num)
        {
            return num >= 10 ? num.ToString() : "0" + num.ToString();
        }
    }
}

Friday, December 28, 2012

IR Codes for CuteDigi Infrared Remote Control Kit for Arduino

The CuteDigi Infrared Remote Control Kit for Arduino includes a small (1.5" x 3.375"), light-weight IR remote  with 20 keys. The remote is marked "Car MP3," but I cannot tell who the manufcturer is. I am using this remote for a project that already includes an IR Receiver (TSOP85) breakout from Sparkfun, so I haven't yet tried the receiver that comes with the kit. 

The Sparkfun IR receiver (TSOP85) I am using does not work with an Arduino Due, but is fine with an Arduino Uno.

Using the IRremote library for Arduino, I have recorded the following codes for the keys on the IR remote:

Remote Key           IR Code (NEC)

PLAY/PAUSE  40BF00FF
CH-         40BF807F
CH+         40BF40BF
EQ          40BF20DF
-/VOL-      40BFA05F
+/VOL+      40BF609F
0           40BF10EF
PREV        40BF906F
NEXT        40BF50AF
1           40BF30CF
2           40BFB04F
3           40BF708F
4           40BF08F7
5           40BF8877
6           40BF48B7
7           40BF28D7
8           40BFA857
9           40BF6897
PICK SONG   40BF18E7
CH SET      40BF58A7

Thursday, December 27, 2012

Notes on Using the CuteDigi NFC Shield with an Arduino Uno

The CuteDigi NFC (near field communication) shield works with the Arduino Uno R3. I have tried it unsuccessfully with the Arduino Leonardo and the Arduino Due.

The NFC shield works with Mifare One tags (ISO14443 Type-A) and cards (13.56 MHZ).

The CuteDigi NFC shield product page includes a link to the LinkSprite wiki page for the product. The product's wiki page includes some sample code and mentions the PN532 library but does not include a link or information about how to find it. There are a number of variants of this library, but not all of them will work. I have found that the PN532 SPI library from Seeedstudio works with a couple small modifications:

In both PN532.h and PN532.cpp, change #include <WProgram.h> to #include <Arduino.h>. (This is also mentioned on the product wiki page.) 

Test the shield using the examples that come with the PN532 SPI library.


Sparkfun DeadOn RTC DS3234 Breakout & Arduino Due

The DeadOn real-time clock on a breakout board from Sparkfun connects to the Arduino using SPI (rather than I2C like the Chronodot).  If you look at the documentation for the SPI library on the Arduino site, it talks in the "Connections" section about using the ICSP pins. On the Arduino Due, though, you need to use the SPI header (with the SPI label).

Here is the layout of the SPI header:

SPI
(1)  MISO      (2)  +Vcc
(3)  SCK/CLK   (4)  MOSI
(5)  RESET/RST (6)  GND

Using the correct header for the SPI connections, the sample Arduino code for the DeadOn RTC works just fine. If you connect to the ICSP pins the way the Arduino SPI documentation might lead you to believe, the sample sketch runs but the date and time are nonsense (and the time does not increase as the sketch runs). Of course, this is not a surprise, since you've connected to the wrong pins.

When using SPI, be sure to use the VCC and GND power connections on the SPI header, not the "regular" 3V3 and GND pins.

The Sparkfun DeadOn RTC and breakout definitely is an easier fit on a breadboard than the Chronodot from Adafruit. 

Tuesday, December 18, 2012

MLX90614 Infrared Sensor & the Netduino Plus 2

The MLX90614 is a non-contact infrared temperature sensor. This example uses I2C for communication between the sensor and the Netduino (Plus 2). The following code reads the temperature every second and prints it out to the debugging console in degrees Fahrenheit. The code is derived from the Arduino example at Bildr and code posted in the Netduino community forum.  

Connections:
(With the small brass nib on the MLX90614 pointing to the right)
MLX90614  -->  Netduino Plus 2
Top Left       SDA  (4K7 pullup resistor)
Top Right      SCL  (4K7 pullup resistor)
Bot. Left      3V3  (0.1mf capacitor between
Bot. Right     GND    3V3 & GND)
Code:
using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Reflection;
using System.Threading;

namespace MLX90614
{
    public class Program
    {
        public static void Main()
        {
            byte i2cAddr = 0x5A;
            I2CDevice mlx90614 = new I2CDevice(new I2CDevice.Configuration(i2cAddr, 100));
            while (true)
            {
                byte[] cmd = { 0x07 };
                byte[] tempData = { 0, 0 }; //LowByte, HighByte
                I2CDevice.I2CTransaction[] reading = new I2CDevice.I2CTransaction[] {
                    CreateWriteTransaction(cmd, 0x07, 1),
                    CreateReadTransaction(tempData, 0x07, 1)
                };
                int bytesRead = mlx90614.Execute(reading, 100);
                Double tempFactor = 0.02; // 0.02 deg./LSB (MLX90614 resolution)
                Double temp = ((tempData[1] & 0x007F) << 8) + tempData[0];
                temp = (temp * tempFactor) - 0.01;
                Double celcius = temp - 273.15;
                Double fahrenheit = (celcius * 1.8) + 32;
                Debug.Print(fahrenheit.ToString());
                Thread.Sleep(1000);
            }
        }

        static I2CDevice.I2CWriteTransaction CreateWriteTransaction(byte[] buffer, uint addr, byte addrSz)
        {
            I2CDevice.I2CWriteTransaction writeTransaction = I2CDevice.CreateWriteTransaction(buffer);
            Type writeTransactionType = typeof(I2CDevice.I2CWriteTransaction);

            FieldInfo fieldInfo = writeTransactionType.GetField("Custom_InternalAddress", 
                BindingFlags.NonPublic | BindingFlags.Instance);
            fieldInfo.SetValue(writeTransaction, addr);

            fieldInfo = writeTransactionType.GetField("Custom_InternalAddressSize", 
                BindingFlags.NonPublic | BindingFlags.Instance);
            fieldInfo.SetValue(writeTransaction, addrSz);

            return writeTransaction;
        }

        static I2CDevice.I2CReadTransaction CreateReadTransaction(byte[] buffer, uint addr, byte addrSz)
        {
            I2CDevice.I2CReadTransaction readTransaction = I2CDevice.CreateReadTransaction(buffer);
            Type readTransactionType = typeof(I2CDevice.I2CReadTransaction);

            FieldInfo fieldInfo = readTransactionType.GetField("Custom_InternalAddress", 
                BindingFlags.NonPublic | BindingFlags.Instance);
            fieldInfo.SetValue(readTransaction, addr);

            fieldInfo = readTransactionType.GetField("Custom_InternalAddressSize", 
                BindingFlags.NonPublic | BindingFlags.Instance);
            fieldInfo.SetValue(readTransaction, addrSz);

            return readTransaction;
        }
    }
}

Saturday, December 8, 2012

Using a TMP102 Temperature Sensor with a Netduino Plus 2


The following example takes a reading and prints out the temperature in degrees Celsius and Fahrenheit. 

Connections:
TMP102  -->  Netduino Plus 2
GND           GND
SCL           SCL
SDA           SDA
V+            3V3
ADD0          GND  

C# Code:

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace TMP102
{
    public class Program
    {
        public static void Main()
        {
            // 
            byte TMP102Addr = 0x48;
            I2CDevice tmp102 = new I2CDevice(new I2CDevice.Configuration(TMP102Addr, 100));
            byte[] tempData = { 0, 0 };
            I2CDevice.I2CTransaction[] reading = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateReadTransaction(tempData)
            };
            int bytesRead = tmp102.Execute(reading, 100);
            int readVal = ((tempData[0] << 8) | tempData[1]) >> 4;
            double c = readVal * 0.0625;
            double f = c * 1.8 + 32;
            Debug.Print(c.ToString() + " C / " + f.ToString() +" F");            
        }
    }
}

Sparkfun Color LCD - Breakout Board (Nokia LCD-11062 ) Notes

See the Sparkfun p\roduct page at https://www.sparkfun.com/products/11062.

There is an Arduino library provided by TCWorld at https://github.com/TCWORLD/gLCD-Library.

In the setup() method of the test pattern and basic function examples, use the line for the Phillips_0 driver

  graphic.begin(0,0,0,PHILLIPS_0);

I have also found that I need to increase the contrast by uncommenting and editing the line changing the contrast:

 graphic.Contrast(-0x3F); 

Connections:
LCD Board  -->  Arduino Uno
VBATT           5V
3.3V            3.3V
GND             GND
RESET           Digital 8
DIO             Digital 11
SCK             Digital 13
CS              Digital 9

Connecting VBATT to 5V works better than 3.3V, otherwise the backlight tends to vary in brightness or flicker. 

The display and library (ver. 3.2) also work with the Arduino Leonardo and Arduino Due. 

Friday, December 7, 2012

Sending Data from a Netduino Plus 2 to an Arduino Leonardo Using I2C

The example Arduino sketches for the Wire library include examples of communication between two Arduinos using I2C. I wanted to try the same thing between a Netduino (Plus 2) and an Arduino (Leonardo).

Based on a posting the Netduino forums, it seems that the Netduino can only act as a master, not a slave. The Arduino can function as either a master or a slave.  In the example below, the Netduino Plus 2 serves as the I2C master sending data to the Arduino Leonardo acting as slave.

The I2C address for the slave is 0x04, though values up to 127 are allowed as addresses. No address is needed for the master. 

The code for the Arduino Leonard is the slave_receiver program found in the sample sketches for the Wire library included with the Arduino IDE.

This example requires the updated firmware for the Netduino Plus 2 to fix problems with I2C. This is a fairly easy update and only requires a few minutes.

Connect the 5V, GND, SCL, and SDA  pins of the Netduino to the Leonardo. Pull-up resistors are needed on the SCL and SDA lines. (In my original post, I said that pull-up resistors were not needed, but that was incorrect - see the comments.)

Here is the sample C# code for the Netduino, which sends a repeating cycle of bytes from 0 - 255.  Open the Arduino's serial console to see the values received from the Netduino Plus 2. 

using System.Threading;
using Microsoft.SPOT.Hardware;

namespace I2C
{
    public class Program
    {
        public static void Main()
        {
            I2CDevice slave = null;
            
            byte addr = 0x04;
            byte data = 0x00; 
            slave = new I2CDevice(new I2CDevice.Configuration(addr, 100));
            while (true)
            {
                byte[] i2cData = { data++ };
                I2CDevice.I2CTransaction[] sendData = new I2CDevice.I2CTransaction[] {
                    I2CDevice.CreateWriteTransaction(i2cData)
                };
                int bytesRead = slave.Execute(sendData, 100);
                Thread.Sleep(500);
            }
        }
    }
}

Tuesday, December 4, 2012

Using a HMC6352 Compass with a Netduino Plus 2

I posted an example of how to use an HMC6352 (Sparkfun breakout) with a Netduino Plus (v. 1.0). Here is an updated and improved version of that example for the Netduino Plus 2.  


Connections:
SDA to SDA (no pull-up resistor)
SCL to SCL (no pull-up resistor) 
VCC to 5V
GND to GND

This code requires the updated firmware for the Netduino Plus 2 to fix problems with I2C. This is a fairly easy update and only requires a few minutes.

Code:
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace Compass2
{
    public class Program
    {
        public static void Main()
        {
            byte HMC6352Addr = 0x42 >> 1;
            byte HMC6352ReadCmd = 0x41; //"A"
            I2CDevice compass = new I2CDevice(new I2CDevice.Configuration(HMC6352Addr, 100));
            byte[] compassCmd = { HMC6352ReadCmd };
            byte[] compassData = { 0, 0 };
            I2CDevice.I2CTransaction[] reading = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(compassCmd),
                I2CDevice.CreateReadTransaction(compassData)
            };
            int bytesRead = compass.Execute(reading, 100);
            float headingSum = (compassData[0] << 8) + compassData[1];
            float heading = headingSum / 10;
            Debug.Print(heading.ToString());
        }
    }
}



Sunday, December 2, 2012

Reading Time & Date from a Chronodot with a Netduino Plus 2

A few months back, I posted some C# code for a Netduino Plus (v. 1) that read the time and date from a Chronodot v. 2.1. It worked, but it wasn't the best and relied on a couple additional classes. I have written a new version for use with the Netduino Plus 2.

This code requires the updated firmware for the Netduino Plus 2 to fix problems with I2C. This is a fairly easy update and only requires a few minutes.

Connections:
SDA to SDA (with pull-up resistor)
SCL to SCL (with pull-up resistor) 
VCC to 3V3
GND to GND

Code:
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace chronodot
{
    public class Program
    {
        public static void Main()
        {
            // Chronodot's I2C address is 0x68
            // 100 is clock speed
            I2CDevice chronodot = new I2CDevice(new I2CDevice.Configuration(0x68, 100));
            byte[] timeCmd = { 0 };
            byte[] timeData = { 0, 0, 0 };
            I2CDevice.I2CTransaction[] time = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(timeCmd),
                I2CDevice.CreateReadTransaction(timeData)
            };
            int bytesRead = chronodot.Execute(time, 100);

            byte[] dateCmd = { 3 };
            byte[] dateData = { 0, 0, 0, 0 };
            I2CDevice.I2CTransaction[] date = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(dateCmd),
                I2CDevice.CreateReadTransaction(dateData)
            };
            bytesRead = chronodot.Execute(date, 100);
            int hour = bcdToDec(timeData[2]) & 0x3F;
            int min = bcdToDec(timeData[1]);
            int sec = bcdToDec(timeData[0]) & 0x7F;
            int month = bcdToDec(dateData[2]);
            int day = bcdToDec(dateData[1]);
            int year = bcdToDec(dateData[3]);
            string timeDate = padZero(hour);
            timeDate += ":";
            timeDate += padZero(min);
            timeDate += ":";
            timeDate += padZero(sec);
            timeDate += " ";
            timeDate += padZero(month);
            timeDate += "/";
            timeDate += padZero(day);
            timeDate += "/";
            timeDate += year.ToString();
            Debug.Print(timeDate);
            chronodot.Dispose();
        }

        public static byte bcdToDec(byte val)
        {
            return (byte)((val / 16 * 10) + (val % 16));
        }

        public static string padZero(int num)
        {
            return num >= 10 ? num.ToString() : "0" + num.ToString();
        }

    }
}