Saturday, April 22, 2017

Nusbio - UART Api

Overview

The Nusbio v1 USB device which offers
  • 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 used 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 as I read it should have been: 240 minutes of CPU/Day, cost $0.013/hour,  240/60*0.013*31 == $1.6 per month, Sound great but. (Required for SSL and domain name).
    But in reality you are charged for 24 hour per day, therefore 24*0.013*31 == $9.6 or $116 for the all year.
    See: App Service Pricing
  • So Azure Share Web Site is more expensive than godaddy 'Economy Windows Hosting with Plesk', Azure Share Web Site also perform much much much better.
I used the free plan and the shared plan, I am now back on the free plan.

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;
        }
      
    }
}