neděle 7. července 2013

Lekce 5. Co je přerušení a jak funguje - infračervené čidlo pohybu

 Jak již název článku napovídá, v této lekci se budeme věnovat přerušení. A aby to bylo trošku zajímavější, tak namísto nudného tlačítka použijeme infračervené pohybové čidlo.
Pohybové čidlo je snadné zapojit. Má totiž jen dva kontakty od tlačítka Tamper (pokud otevřete kryt čidla tak se rozepne). Další dva kontakty jsou od spínacího relé čidla (pokud čidlo zaznamená pohyb tak je rozepne). No a nakonec jsou dva napájecí kontakty pro +12V.


 
Zapojení:
Do nepájivého pole si zapojíme adapter s +12V pro napájení čidla. Kontakty relé a tlačítka Tamper připojíme přes Pull-Up rezistory na vstupní porty D3 a D5. Dále si zapojíme dvě diody na porty D7 a D9.

Detail zapojení svorek pohybového čidla
Detail zapojení svorek čidla
Pohled na celé pohybové čidlo
Pohled na celé pohybové čidlo
 
Přerušení je příjemnou abstrakcí nad digitálními vstupy. Při změně jejich hodnoty je automaticky vygenerována událost na kterou můžeme reagovat.
Při deklaraci máme na výběr z několika způsobů detekování přerušení:

  • InterruptNone
  • InterruptEdgeLow
  • InterruptEdgeHigh
  • InterruptEdgeBoth
  • InterruptEdgeLevelHigh
  • InterruptEdgeLevelLow

Pokud použijete při deklaraci hodnotu InterruptNone tak při přidávání reakce na událost OnInterrupt obdržíte výjímku An unhandled exception of type 'System.ArgumentException' occurred in Microsoft.SPOT.Hardware.dll. Nejčastěji použijete asi hodnotu InterruptEdgeBoth, která vyvolá přerušení při změně stavu z LOG1 na LOG0 a zpět. Další dvojice InterruptEdgeLow a InterruptEdgeHigh reaguje pouze na náběžnou, nebo sestupnou hranu.
To jak funguje poslední dvojice se mi nepodařilo rozklíčovat. Při použití těchto hodnot se mi podařilo přerušení vyvolat pouze jedenkrát. Potom už na stisknutí tlačítka nereagovalo.

Reakci na přerušení připojíme stejně jako reakci na běžnou událost.
Tamper.OnInterrupt += new NativeEventHandler(Tamper_OnInterrupt);

Metoda reagující na přerušení má potom tři parametry.
data1 obsahuje číslo pinu na kterém došlo k přerušení. data2 obsahuje hodnotu 0 nebo 1 odpovídající úrovni vstupu. Poslední parametr time pak obsahuje čas vzniku přerušení.
static void Tamper_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            GreenLed.Write(data2 == 1);
        }

Video:

Zdrojový kód:
namespace Lekce05
{
    using System;
    using System.Threading;
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware.NetduinoPlus;

    public class Program
    {
        public static readonly OutputPort AlarmLed = new OutputPort(Pins.GPIO_PIN_D7, false);
        
        public static readonly OutputPort TemperLed = new OutputPort(Pins.GPIO_PIN_D9, false);

        public static readonly InterruptPort Temper = new InterruptPort(Pins.GPIO_PIN_D3, false, ResistorModes.Disabled, Port.InterruptMode.InterruptEdgeBoth);
        
        public static readonly InterruptPort Alarm = new InterruptPort(Pins.GPIO_PIN_D5, false, ResistorModes.Disabled, Port.InterruptMode.InterruptEdgeBoth);

        public static void Main()
        {
            Temper.OnInterrupt += new NativeEventHandler(Temper_OnInterrupt);

            Alarm.OnInterrupt += new NativeEventHandler(Alarm_OnInterrupt);

            Thread.Sleep(Timeout.Infinite);
        }

        static void Temper_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            TemperLed.Write(data2 == 1);
        }

        static void Alarm_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            AlarmLed.Write(data2 == 1);
        }
    }
}


Pokud tlačítko zapojíte mezi nulu a vstupní pin tak vhodná konfigurace portu vypadá něka takto:
public static readonly InterruptPort d = new InterruptPort(Pins.GPIO_PIN_D5, false, ResistorModes.PullUp, Port.InterruptMode.InterruptEdgeBoth);


PullUp rezistor zajistí filtrování kolísavého napětí pokud u tlačítka nezapojíte rezistor. Jinak se Vám bude přerušení generovat stále dokola podle toho kterou hodnotu se v rušení podaří detekovat.

V dalším díle se podíváme jak zjistit stav tlačítka
Zdrojové kódy ze všech lekcí jsou dostupné na https://csharpduino.codeplex.com/
Budu rád za každý komentář a konstruktivní kritiku.

pátek 5. července 2013

Lekce 4. Jak zjistit stav tlačítka?

V této lekci Vám ukážu, jak jednoduše zjistit stav tlačítka a reagovat jeho stisknutí. NetDuino Plus má na své desce jedno tlačítko, které můžeme pro tuto lekci využít. Ve výchozím nastavení toto tlačítko slouží jako Reset. Pokud ale v programu deklarujeme vstupní port pro pin s názvem Pins.ONBOARD_SW1, přestane tlačítko restartovat NetDuino a začne nám vracet jeho stav. Stav tlačítka zjistíme pomocí metody Read().


Inicializace vstupního portu:
Při inicializaci zadáme jako první parametr číslo pinu tlačítka, které je přímo na desce NetDuino Plus s názvem Pins.ONBOARD_SW1.
Jako další parametr je takzvaný GlitchFilter. K jeho vysvětlení se dostaneme v některé z dalších lekcí. Prozatím budeme používat hodnotu false. No a jako poslední je parametr ResistorMode. U tohoto parametru se trošku zastavím protože při jeho použití se můžete trošku zamotat jako já.
Tento parametr je totiž možné nastavovat hodnotami ze dvou namespace a to:
using Microsoft.SPOT.Hardware;
a nebo
using SecretLabs.NETMF.Hardware.NetduinoPlus;

Pokud totiž použijete výčtový typ z namespace Microsoftu, tak budete mít k dispozici enumerátor Port.ResistorMode který má tři možnosti:
  1. Disable
  2. PullUp
  3. PullDown
Naopak enumerátor ResistorModes.PullUp  z namespace NetduinoPlus má pouze dvě hodnoty.
  1. Disable
  2. PullUp
private static readonly InputPort Btn = new InputPort(Pins.ONBOARD_SW1, false, ResistorModes.Disabled);

Pokud se pokusíte deklarovat port v modu PullDown tak při spouštění programu dostanete výjimku System.ArgumentException.
Pull-Up - znamená, že vstupní pin je přes rezistor připojen na Log1 a stisknutím tlačítka se dostává do Log0. Protože je to naopak něž bychom očekávali (při stisku tlačítka je na vstupu LOG1) je toto nastavení invertující.
Pull-Down - je opačná varianta k Pull-Up. Vstupní pin je přes rezistor stažen na Log0 a stisknutím tlačítka se dostává do Log1. Toto nastavení je tedy neinvertující

MikroProcesor má nejspíše natvrdo zapojen odpor ke kladnému napětí a druhá varianta (PullDown) není tedy možná. Toto zapojení se používá k omezení šumu na vstupu kdy hodnota není ani v LOG1 ani v LOG0 a celý obvod se tak může chovat nepředvídatelně.

Podrobnější vysvětlení naleznete v tomto videu http://www.youtube.com/watch?v=BxA7qwmY9mg [EN]

Video:

Zdrojový kód:
namespace Lekce04
{
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware.NetduinoPlus;

    public class Program
    {
        private static readonly InputPort Btn = new InputPort(Pins.ONBOARD_SW1, false, ResistorModes.Disabled);

        private static readonly OutputPort Led = new OutputPort(Pins.ONBOARD_LED, false);

        public static void Main()
        {
            while (true)
            {
                Led.Write(Btn.Read());
            }
        }
    }
}
V dalším díle se podíváme jak fungují přerušení.
Zdrojové kódy ze všech lekcí jsou dostupné na https://csharpduino.codeplex.com/
Budu rád za každý komentář a konstruktivní kritiku.