Saturday, April 22, 2017

Nusbio - UART Api

Overview

The Nusbio v1 USB device which offer
  • 8 gpios with I2C and SPI support 
  • for Windows programmable in any .NET language
is based in the FTDI chip FT232RL. Therefore it can also be used as a UART or serial communication.
This also known as an FTDI friend and can be use to upload code on an Arduino compatible that do not have a UART chip on board like the
  • Diavolino from Evil Mad Scientist
  • Trinket Pro from Adafruit
  • Arduino Pro Mini


Extension

We used to sell the following extension which allows to connect some devices using the following UART pins: TX, RX, CTS,  RTS, VCC and GND.


In case you want to use the Nusbio's 8 GPIOs as USART communication here is the mapping.
  • GPIO 0 - RI
  • GPIO 1 - DSR
  • GPIO 2 - DTR
  • GPIO 3 - DCD
  • GPIO 4 - CTS
  • GPIO 5 - TX
  • GPIO 6 - RX
  • GPIO 7 - RTS
Remember that
  • The pin 8 is VCC and pin 9 is GROUND. 
  • Most Nusbio can be configured to be 5 volt or 3.3 volt

Activation

How do I use the Nusbio as a UART interface ?

Simply plug the device in the Windows machine and do not run any Nusbio code. Once plugged a COMX port should be available on the PC.
Use the general Serial Port class offered with your programming language

Sunday, April 2, 2017

Nusbio GPIO API

Overview


Nubsio is a Windows plug and play USB interface to connect your PC to the external world and control electronic devices with any .NET languages.

Nusbio offers:
  • 8 digital Input/Output pins (or GPIO) with support of the SPI and I2C protocols
  • 8 analog to digital pins (ADC, with the Analog or Sensor extension) 
programmable in any .NET languages


GPIO API


PinMode 

By default the GPIO pins are initialized as output. To change the direction of an GPIO pin, use the following methods from the Nusbio class.
public void SetPinMode(NusbioGpio pin, PinMode mode);
public void SetPinMode(int pin, PinMode mode);

// Sample 

var serialNumber = Nusbio.Detect();
using (var nusbio = new Nusbio(serialNumber: serialNumber))
{
    nusbio.SetPinMode(NusbioGpio.Gpio0, PinMode.Output); // Enum type syntax
    nusbio.SetPinMode(1, PinMode.InputPullUp); // Integer syntax
}

 
The nusbio.GPIOS property allow to access the 8 GPIO pins using the following interface.

public interface GpioPublicApiBase
{
    PinMode Mode { get; }
    string Name { get; }
    PinState PinState { get; }
    bool State { get; set; }

    PinState DigitalRead();
    void DigitalWrite(PinState on);
    void DigitalWrite(bool high);
    void High();
    void Low();
}

// Sample

var serialNumber = Nusbio.Detect();
using (var nusbio = new Nusbio(serialNumber: serialNumber))
{
    nusbio.SetPinMode(NusbioGpio.Gpio0, PinMode.Output); // Enum type syntax
    nusbio.SetPinMode(1, PinMode.InputPullUp); // Integer syntax

    // Turn gpio pin 0 on
    nusbio.GPIOS[NusbioGpio.Gpio0].DigitalWrite(PinState.High);
    nusbio.GPIOS[NusbioGpio.Gpio0].DigitalWrite(true);

    // Read the state for gpio 1
    var state = nusbio[1].DigitalRead();
    state = nusbio[1].DigitalReadDebounced();
}

Code Sample

For more information on using the GPIO pins in output mode see the following samples:
For more information on using the GPIO pins in input mode see the following samples:


Sunday, March 19, 2017

Azure Web Site versus GoDaddy

Over the years GoDaddy has build a terrible reputation
But I have been with them for years and changing hosting create issues.

Anyway I was not very happy with the performance of the hosting plan:

"Economy Windows Hosting with Plesk"
It took about 10 seconds to access my web site, when it was shutdown. And it only remains in memory for about 5 minutes. I probably got a good deal for the first year for hosting and 1 domain name.

But this week it is renewal time and here are the prices
  • Economy Windows Hosting with Plesk $95.88
  • For the name MadeInTheUSB.net $16.99
That is close to $113 per year, for a domain name + hosting that perform really slowly.

I already use Azure Storage for backup, so I decided to try the Azure free plan and well it is free, but there is no wait time to access the web site.
Try it.
There are limits though
  • The free plan is limited to 60 minutes of CPU/Day
  • The shared plan is 240 minutes of CPU/Day, cost $0.013/hour (Required for SSL and domain name)
I may get away with the free plan or will move to the shared plan, but that is definitely, better. 

Conclusion

Now I need to learn if I can find cheaper domain name and how to transfer my domain names.
Capitalism is not about monopoly, it is about competition.



Monday, January 23, 2017

Nusbio I2C

Overview

The Inter-Integrated Circuit (I²C, i2c) is a multi-master, multi-slave serial communication protocol invented by Philips Semiconductor (now NXP Semiconductors), primarily used in embedded systems.
A lot devices like an EEPROM, LCD, GPIO expander, LED drivers and more support the I2c protocol.

It is generally not available for Windows easily, though it is available on the Raspberry PI via Python and C.

That is why I created Nusbio.net in 2015 that offers in a simple way to talk I2C from Windows and .NET

 

A lot of devices designed by Adafruit use the I2C protocol and are compatibles with Nusbio and any .NET languages.

C# Class


This post explains the I2CEngine .NET class for the Nusbio device.

Wiring

Since Nusbio has 8 gpio pins, you can technically setup 4 independent I2C buses. But generally one is enough.
I use Gpio0 for SCL and Gpio1 for SDA as convention. Obviously you can connect multiple I2C devices to the bus.
Nusbio does not come with any pull up resistors so it is up you to take care of it.
Generally if you use an I2C breakout it is part of the breakout.

Software

For each I2C device on the bus you must create an object of the class I2CEngine. After that you call the WriteBuffer() method to initiate an I2C write operation and the method ReadBuffer for a I2C read operation.
The methods takes care of the I2C Control byte. You do not have to pass it as part of the buffer.
The methods return true if the operation succeeded. For the Readxxxx methods, if the operation succeeded you can then read the buffer which will be updated with the data.


public I2CEngine(Nusbio nusbio, NusbioGpio sdaOutPin, NusbioGpio sclPin, byte deviceId);
public bool ReadBuffer(int len, byte[] data);
public bool WriteBuffer(byte[] buffer);
public bool WriteBuffer(byte address8bit, byte[] buffer);


Samples


I2C EEPROM


Here is a basic sample reading the first 64 bytes of the I2C EEPROM 24LC256 which is a 32k bytes EEPROM with a page size of 64 byte.

byte EEPROM1_WR = 80; // 0xA0;
                                
var i2c = new I2CEngine(nusbio, NusbioGpio.Gpio1, NusbioGpio.Gpio0, EEPROM1_WR);
var addr = 0;
var buffer = new byte[64];
if (i2c.WriteBuffer(new byte[2] { (byte)(addr >> 8), (byte)(addr & 0xFF) }))
{
  var r = i2c.ReadBuffer(64, buffer);
}

We do offer specific classes to handle I2C and SPI EEPROM, see our folder EEPROM on github.


I2C MCP9808 Temperature Sensor

Here part of our class MCP9808 _Temperature Sensor.cs available on Github.
The method Begin will return true if the device is detected on the bus else false.

public bool Begin(byte deviceAddress = MCP9808_I2CADDR_DEFAULT)
{
    try
    {
        this._i2c.DeviceId = deviceAddress;
        if (read16(MCP9808_REG_MANUF_ID) != MCP9808_REG_MANUF_ID_ANSWER) return false;
        if (read16(MCP9808_REG_DEVICE_ID) != MCP9808_REG_DEVICE_ID_ANSWER) return false;
        return true;
    }
    catch (System.Exception ex)
    {
        System.Diagnostics.Trace.WriteLine(ex.ToString());
        return false;
    }
}

public double GetTemperature(TemperatureType type = TemperatureType.Celsius)
{
    uint16_t t = read16(MCP9808_REG_AMBIENT_TEMP);
    double temp = t & 0x0FFF;
    temp /= 16.0;
    if ((t & 0x1000) == 0x1000) temp -= 256;
    switch (type)
    {
        case TemperatureType.Celsius: return temp;
        case TemperatureType.Fahrenheit: return CelsiusToFahrenheit(temp);
        case TemperatureType.Kelvin: return temp*CELCIUS_TO_KELVIN;
        default:
            throw new ArgumentException();
    }
}

private UInt16 read16(uint8_t reg)
{
    UInt16 value = 0;

    if (this._i2c.WriteBuffer(new byte[1] { reg }))
    {
        var buffer = new byte[2];
        this._i2c.ReadBuffer(2, buffer);
        value = (System.UInt16)((buffer[0] << 8) + buffer[1]);
    }
    else throw new ArgumentException();    
}


We do offer specific classes to handle I2C and SPI EEPROM, see our folder EEPROM on github.


Advanced Methods

To improve transfer performance, the class I2CEngine expose the following methods which optimize the number of USB operations to execute the I2C operations (we combine an I2C Read + I2C Write operation in one USB transaction)

public bool Send16BitAddressAnd1Byte(int address16bit, byte b);
public bool Send16BitsAddressAndBuffer(int address16bit, int len, byte[] buffer);
public int  Send16BitsAddressAndRead1Byte(short address8bit);
public bool Send16BitsAddressAndReadBuffer(int address16bit, int len, byte[] data);

public bool Send1ByteCommand(byte command);
public bool Send2BytesCommand(byte command0, byte command1);
public bool Send3BytesCommand(byte command0, byte command1, byte command2);

public int Send1ByteRead1Byte(byte address8bits);
public _2BytesOrInt16Result Send1ByteRead2Bytes(byte cmd);        



Performance

Using the EEPROM 24LC256 which is an I2C 32k bytes with a max clock of 400 kHz, we can transfer the 32 k byte of data from the EEPROM to the PC at the rate of 15 k bytes per second in batch mode of 64 pages at a time.

Transferring one page a the time give a transfer rate of 8 k bytes per second.

Output or input batch mode is necessary to increase performance for all I2C devices.

Transfer speed may vary also depending on the speed of the computer.

 

Sunday, January 15, 2017

$0.5 2K EEPROM M93C86 for .NET, CSharp and Nusbio.net

I experimented with a cheap EEPROM the M93C86 2k byte of data for $0.5 programmed in C# with Nusbio.net (M93C86 datasheet).

The EEPROM used the SPI protocol but its API is not as straightforward as the Microchip EEPROMs.
After a day of work it seems that we can only write one byte at the time and for that we need to pass 4 bytes, of protocol. So write speed is very slow.
It does not seems that there is a concept of page per say, but since I want to re use a C# base class, I set up a page to 256 bytes, and the read performance in SPI out of the box is 10 K byte/S with Nusbio v1.
Since it is just an experiment I will not optimize the code to get 28 K byte/S like with the Microchip SPI EEPROM.
As a reminder Nusbio v 2 can transfer at the rate of 1 to 3 M byte/S in SPI and 100 K byte/S in I2C in
any .NET language. Nusbio v 2 is in prototype mode as 2017/01.


/*
   Copyright (C) 2015, 2016, 2017 MadeInTheUSB LLC
   Written by FT for MadeInTheUSB

   MIT License (MIT)
*/

using System;
using System.Collections.Generic;

namespace MadeInTheUSB.EEPROM
{
    /// 
    /// m93c86 is a 2k byte spi cheap eeprom
    /// http://www.mouser.com/ds/2/389/m93c46-w-955034.pdf
    ///     CS(PD-1k)[] [] VCC
    ///     SCK      [] [] Not used
    ///     MOSI     [] [] ORG Leave unconnected for 16kbit orf
    ///     MISO     [] [] GND
    /// 
    public class EEPROM_M93C86 : EEPROM_25AAXXX_BASE
    {

#if NUSBIO2
        public EEPROM_M93C86() : base(16)
        {
        }
#else
        public EEPROM_M93C86(Nusbio nusbio, 
            NusbioGpio clockPin, 
            NusbioGpio mosiPin, 
            NusbioGpio misoPin, 
            NusbioGpio selectPin,
            bool debug = false) : base(nusbio, clockPin, mosiPin, misoPin, selectPin, 16, 
                debug, 
                chipSelectActiveLow:false // << important
                )
        {
            var b = this.MaxByte;
            var p = this.MaxPage;
            this.SetWriteRegisterEnable();
            //this.SetWriteRegisterDisable();
        }
#endif

    
        public override bool Is3BytesAddress
        {
            get { return false; }
        }

        public override int PAGE_SIZE
        {
            get{ return 256; }
        }

        protected override bool SetWriteRegisterEnable()
        {
            var r = this.SpiTransfer( new List(){ 0x98 /*0b10011000*/, 00 } );
            return r.Succeeded;
        }

        protected override bool SetWriteRegisterDisable()
        {
            var r = this.SpiTransfer(new List() { 0x80 /*0b10000000*/, 00 });
            return r.Succeeded;
        }
        /// 
        /// http://www.mouser.com/ds/2/389/m93c46-w-955034.pdf
        /// based on the data sheet in ORG: 8 byte (low)
        /// writing one byte require 22 Clock Cycle
        /// 1 start bit, 2 bit-opCode, 11-Addr == 2 Clock cycle
        /// We send 24 bits the first 2 bits are 00
        /// I do not think that this EEPROM support write in bulk mode
        /// It does support Read in bulk
        /// 
        /// 
        /// 
        /// 
        public virtual bool WritePage(int addr, byte[] buffer)
        {
            int dt1, dt2, ans;

            for (var num = 0; num < buffer.Length; num++)
            {
                //dt1 = 0b00101000 | ((adrs & 0b0000011100000000) >> 8) ;
                //dt2 = (adrs & 0b0000000011111111) ;
                dt1           = 0x28 | ((addr & 0x700) >> 8);
                dt2           = (addr & 0xFF);
                var spiBuffer = new List() { (byte)dt1, (byte)dt2, buffer[num] };
                var writeR    = this.SpiTransfer(spiBuffer);
                var readR     = this.SpiTransfer(new List() { 0 });
                ans           = readR.Buffer[0];
                addr += 1;
            }
            return true;
        }

        public override EEPROM_BUFFER ReadPage(int addr, int len = -1)
        {
            if (len == -1)
                len = PAGE_SIZE;

            var eb = new EEPROM_BUFFER();
            int dt1, dt2;

            //dt1 = 0b00110000 | ((adrs & 0b0000011100000000) >> 8) ;
            //dt2 = (adrs & 0b0000000011111111) ;
            dt1 = 0x30 | ((addr & 0x700) >> 8);
            dt2 = (addr & 0xFF);

            var spiBufferWrite = new List() { (byte)dt1, (byte)dt2 };
            var spiBufferRead = GetEepromApiDataBuffer(len);
            var buffer = new List();
            buffer.AddRange(spiBufferWrite);
            buffer.AddRange(spiBufferRead);

            var r = this.SpiTransfer(buffer);

            if (r.Succeeded)
            {
                eb.Succeeded = true;
                eb.Buffer = r.Buffer.GetRange(spiBufferWrite.Count, r.Buffer.Count - spiBufferWrite.Count).ToArray();
            }
            return eb;
        }
      
    }
}

Saturday, December 31, 2016

External Keypad For Windows controlled by .NET code


Overview

This keypad below is very cheap, so i bought 2 just to try them with Nusbio.net. Though it is a very simple device, it is not easy to explain how this work and moreover the theory behind the source code.
It is a little bit tricky and requires to understand sourcing and sinking current.
If you do not get it right away it is normal.
But you should be able to understand the basic idea just by reading the source code and my comments below.
With an Arduino you will find tutorial and library already made, but for .NET and Nusbio I had to write my own class (that is part of the open source samples that come with the Nusbio device).


First

There are plenty of tutorial on the internet about it, here is one I like the most to read first Arduino with Keypad Tutorial

Here is my take on it for software developers.

We have a grid of 4 rows and 3 colums. Each rows and columns connect to each other when one of the 12 buttons is pressed. We are going use 4+3 == 7 GPIO pins and monitor the connection between rows and the columns.

From a software point of view we have to constantly polled the state of the 12 buttons.

Initialization


The 4 GPIO pins connected to the 4 rows are open in input pull up mode, simply said this mean that the state of the pin is Readable (Input) and default state value is HIGH (AKA 1 or 5 Volts) and could be come a LOW (AKA 0 or 0 Volt) if there is a path to ground.
The 3 GPIO pins connected to the 3 columns are open in output mode, (the state can be set to HIGH or LOW programmatically) and set first to HIGH (1).
In this state nothing will happen, no current flow even if one button is pressed because current only flow from HIGH to LOW.

For one specific column if one button is pressed a connection is made between the column and the row and the state of the row will change from HIGH to LOW.

In a function called constantly we going one at time 
  1. Change the state of one the column GPIO pin to LOW (so now we know the column)
  2. Then we are going to read the state of the 4 GPIO pins rows one after the other,
    if the state is HIGH the button matching the current column and row is not pressed,
    but if the state is LOW, then this mean there is a connection because the button is pressed and the current flowing from HIGH to LOW changing the state of the row GPIO pins (which is readable, because it was open as input)

Source Code

Initialization

private List _gpioRow;
private List _gpioCol;
private Nusbio           _nusbio;
private List<List<char>> _keys;

private void Init()
{
    for (var r = 0; r < this._gpioRow.Count; r++)
    {
        this._nusbio.SetPinMode(this._gpioRow[r], PinMode.Input);
    }
    for (var c = 0; c < this._gpioCol.Count; c++)
    {
        this._nusbio.SetPinMode(this._gpioCol[c], PinMode.Output);
        _nusbio.GPIOS[this._gpioCol[c]].High();
    }
}

Check() function


public KeypadPressedInfo Check()
{
    KeypadPressedInfo rr = null;
    var found            = false;
    for (var c = 0; c < this._gpioCol.Count; c++)
    {
        _nusbio.GPIOS[this._gpioCol[c]].Low();
        for (var r = 0; r < this._gpioRow.Count; r++)
        {
            var pressed = _nusbio.GPIOS[this._gpioRow[r]].DigitalRead() == PinState.Low;
            if (pressed)
            {
                rr = new KeypadPressedInfo {
                    Row = r, Col = c, Key = this._keys[r][c]
                };
                break;
            }
        }
        _nusbio.GPIOS[this._gpioCol[c]].High();
        if (rr!=null)
            break;
    }
    return rr;
}

See on github the C# project. and the Keypad.cs class.

About the Wiring

One electricity rule that you may know is that if the + touch the - directly, you create a short circuit and it is not good. In between the + and - you must have a load, something that consume current. Therefore in between the 3 GPIO pins column and the 3 wires of the keypad I inserted 3 10 K Ohm resistor.






Saturday, November 5, 2016

How to make an LED fade in, fade out with 1 Nusbio GPIO

Overview

With one GPIO (General Purpose Input Output) from an Arduino, Raspberry PI or Nusbio you can easily turn one LED on or off.
But making the LED fade in and fade out is a little bit more complicated. With a micro-controller like an Arduino you can use a GPIO with PWM (Pulse with modulation) and call the method analogWrite(pin, value). The value defines what is called the duty cycle, in simple term this will be the intensity of the LED.



But with a Raspberry PI linked to Linux or Nusbio linked to Windows, there is no PWM (PWM is a hardware function, not available on PC and not managed by the OS).

So for this post I used an good old analog solution:

  • 1 transistor 2N3904
  • 1 100mF capacitor
  • 1 220k Ohm resistor
  • 1 1k Ohm resistor
Wired as follow:

This circuit looks simple, but it is not easy to understand how it works, though it does work as shown in the video.
And I will not try to explain it today.
If you are like me a software developer interested in learning analog electronic, it is a good example to start with because there are so many concepts involved to understand before you can picture how the all thing works:
  • LED voltage drop
  • Capacitor
  • Transistor
  • Sourcing and sinking current
 The first step is to try it on a bread board.

Use a red LED because the LED voltage drop makes a different, a blue LED would require different resistors.

Programming

The programming on the other side is simple, turn the LED on and wait for the LED to fade in,
then the LED off and wait for the LED to fade out.
The speed of the fade in fade out is controlled by the size of the capacitor and the resistance in between the GPIO and the base of the transistor (in my case a 220K Ohm).


var serialNumber = Nusbio.Detect();
if (serialNumber == null) // Detect the first Nusbio available
{
    Console.WriteLine("Nusbio not detected");
    return;
}
Console.Clear();
using (var nusbio = new Nusbio(serialNumber: serialNumber))
{
    ConsoleEx.WriteMenu(0, 1, "Q)uit");
    while (true)
    {
        Console.Write("On ");
        nusbio.GPIOS[0].High();
        Thread.Sleep(1000 * 3);
        Console.Write("Off ");
        nusbio.GPIOS[0].Low();
        Thread.Sleep(1000 * 3);
        if (Console.KeyAvailable && Console.ReadKey().Key == ConsoleKey.Q)
            break;
    }
}