Archiv rubriky: Raspberry PI

Časovače MSP430

Spíše sporadicky než pravidelně pracuji na finální podobě časomíry, jejíž srdcem bude TI MSP430G2553. V posledních dnech jsem pracoval na přerušeních od vstupů (startovací tlačítko, koncové spínače) a od časovače.

První dílčí úspěch je napájení. Nevěděl jsem, zda stabilizátor LE33 bude dodávat dostatečný proud. Problém byl jediný, v dokumentaci byly přehozené piny Vin a Vout.

Další problém se objevil na vstupech, které způsobovaly přerušení zcela náhodně. Toto více méně vyřešilo připojení kondenzátorů 100 nF mezi pin a zem.

Větší úskalí nastalo při programování. Přístup s přerušeními se diametrálně liší od toho, na co jsem byl  zvyklý a vyžaduje si naprosto jiné smýšlení o problému. Nakonec jsem vypotil kód, který při sepnutí startovacího tlačítka spustí oba časovače a koncový spínač zase jeden z časovačů vypne. Mělo by tak dojít k docela přesnému měření času.

Problém první: jak se ovládá druhý časovač. Původně jsem měl za to, že je v MCU časovač A i časovač B. To byl omyl, v zařízení jsou dva časovače, ale jsou to A0 a A1. Časovač A0 jsem ovládal příkazy, které se běžně dají najít, ale jak na časovač A1?

  TA0CCTL0 = CCIE;					// CCR0 interrupt enabled
  TA0CCR0 = 2048-1;					// 2048 -> 1 sec for ACLK/8
  TA0CTL = TASSEL_1 + ID_3 + MC_0;			// ACLK, /8, stopped
  TA1CCTL0 = CCIE;					// CCR0 interrupt enabled
  TA1CCR0 = 2048-1;                                     // A1 CCR0 level
  TA1CTL = TASSEL_1 + ID_3 + MC_0;			// ACLK, /8, stopped
  TA0R = 0;                                             // clear counter
  TA1R = 0;                                             // clear counter

Za těmito řádkami stojí spousta hledání, pokusů a omylů 🙂 Máme tedy nastavené časovače, tak je spustíme

  TA1CTL |= (MC_1 + TACLR);    //timer A1 starts counting
  TA0CTL |= (MC_1 + TACLR);    //timer A0 starts counting

a zase vypneme

  TA0CTL &= ~MC_1;                         //stop timer A0
  TA1CTL &= ~MC_1;                              //stop timer A1

Pokud časovač dosáhne hladiny CCR0 spustí přerušení. Pro tyto časovače mají vektory přerušení poněkud matoucí názvy

  #pragma vector=TIMER0_A0_VECTOR
  #pragma vector=TIMER1_A0_VECTOR

Zbytek ISR se nijak neliší od běžně dostupných návodů.

Další problém bylo zmenšení ISR pro stisknutá tlačítka na minimum. Pokud pošlete procesor spát a budete naslouchat přerušením. Po provedení ISR jde zase spát. My však potřebujeme aby vykonal ještě nějaké instrukce. Základní myšlenka je taková: pokud se nám spustí několik přerušení najednou, vykonávají se podle předem dané priority, pokud se vykonává ISR k jednomu přerušení, nemůže se spustit ISR jiného a proto potřebujeme v kritických chvílích, jako je měření času, udržet ISR na co nejmenší délce, třeba jen nastavit vlajku a podle ní vykonat zbytek instrukcí jinde, tam, kde se může program přerušit a procesor obsloužit nově příchozí přerušení. Jak na to? Na konci

main()

většinou máme něco jako

_BIS_SR(LPM3_bits + GIE);       // Enter LowPowerMode 3 w/ interrupt

. To jsem obalil nejdříve cyklem

while(1)

, ve kterém je strom

if

, který vykonává zbývající práci po přerušeních, na základě nastavené vlajky.

_BIS_SR(LPM3_bits + GIE);       // Enter LowPowerMode 3 w/ interrupt

přesunu do jeho

else

, takže se provede tolik cyklů while(), kolik máme nastavených vlajek, jsou-li všechny vlajky vyčištěny, jde procesor spát a čeká se na další přerušení.

To ale nestačí, protože normálně po vykonání ISR jde procesor zase spát. V tom mu dočasně zabráníme tím, že na konec ISR, které potřebují ještě vykonat něco mimo, a tedy nastaví příslušnou vlajku, umístíme ještě řádek

__bic_SR_register_on_exit(LPM3_bits + GIE); // Don't Enter LowPowerMode 3 immidiately

Tak se vrátíme do cyklu while() v main(). V té době už můžeme obsluhovat další přerušení.

A to je vše podstatné, ideu ze které jsem čerpal najdete na obrázku v souboru www.ti.com/lit/an/slaa294a/slaa294a.pdf

Texas Instruments Launchpad

Až z dalekého Texasu, nebo spíše naopak z Číny, ke mě dorazila malá destička zvaná Launchpad. Poprvé jsem viděl Launchpad v loni na podzim ve článku na serveru Živě.cz, to je ale, jak nyní vidím, Stellaris Launchpad, který má blíže k Raspberry PI. Můj Launchpad je programátor a debuger, vloží se do něj 14/20 nožičkový MCU, nahraje se program, díky připraveným vývodům je možné jej hned otestovat, nakonec MCU vzít a připájet jej do DPS, kde bude plnit úkoly, na které je Raspberry PI zbytečně velké. Navíc by měly bohatě stačit dvě tužkové baterie. Zatím jsem vyzkoušel jen připojení k Ubuntu, které funguje. V budoucnu plánuji nahradit Raspberry PI v časomíře pro požární sport jedním z MCU řady MSP430G2xxx, protože i RPI je zbytečný přepych. A samozřejmě různé ty domácí práce, měření teploty, kontroly, myslím, že se toho najde dost.Launchpad a RPI
Proč jsem si vlastně vybral Launchpad? Hlavně kvůli ceně. Jsem kvidla, moc eltech. vzdělání nemám a z MCU mám strach 🙂 Raději holduji software.

  • Launchpad se připojuje rovnou do USB.
  • Nestojí ani tisíc ani pět set, ale jen 160 Kč na farnell.com (v českých obchodech tak 360 Kč) a stával ještě méně.
  • Dostanu v balení dva kusy MCU a zdá se, že deska samotná je skoro za pakatel.
  • Chtěl jsem pouzdro DIL, kvůli snadnému pájení, připojení do breadbordu atp.
  • Narozdíl od PIC a Atmel dostávám 16-bit počítač (bude to výhoda?) za stejnou cenu.
  • Vybraný MCU má AD převodník a sériové komunikační protokoly, které potřebuji.
  • Pravděpodobně nebude problém s programování v Linuxu.

Ale, rodina MCU MSP430 je mnohem širší nejvyšší řada stojí od jednoho do tří set korun a mají třeba integrovaný LCD, USB a další řadiče, ale teď už trochu vařím z vody, protože jsem vše neprozkoumal. Pointa měla být takové, že je možnost se stejnými postupy naučenými na základní řadě postoupit k lepšímu vybavení, byť si připlatíme za dražší programátory. Je třeba nějak začít a nevidím nic lepšího, než koupit tak levný hotový programátor a jen cvakat kód programu a jednoduše testovat funkčnost s vědomostmi získanými pomocí Raspberry PI.
Takže po drobném martyriu se softwarem jsem našel pěkný článek vysvětlující základy. Já musel přidělat symlink pro 64-bitovou knihovnu a pak už se otevřelo malé okénko editoru Energia, zkusil jsem příklad s blikáním diod a hned je mi jasno, jak to celé funguje, no to je paráda, do večera bych klidně zvládl zprovoznit display. Pokud se neobjeví něco zásadně velkého, budu jen tento článek jako úvodník k MSP430 rozšiřovat.

GPIO přerušení

Chodil jsem na přednášky a cvičení z „Céčka“ a tak vím, že existuje nějaké přerušení. Pro kontrolu vstupu se dá v základu použít přístup: spustím nekonečnou smyčku a co chvíli se budu dívat, zda se něco neděje, jenže to nelze dělat kontinuálně, proces si musí na chvíli oddychnout a nechat prostor dalším, v tu chvíli však nesleduje vstup a ten se může během krátké chvíle změnit, aniž by to program zpozoroval. Elegantnější cesta je nechat operační systém, aby sledoval tzv. přerušení. a ve chvíli, kdy k němu dojde o události spravil náš proces, který na to zatím čeká. Protože chystám provizorní časomíru, kterou bych i přesto chtěl mít co nejpřesnější, za pomoci RPi a vím, že běžné Linuxové jádro není real-time, vzpomněl jsem si na přerušení, které bych rád porovnal s externím zařízení v podobě čítače pulsů (viz astromik.org a jeho časomíra). Hledal jsem a nakonec našel.
Sice nejde o přerušení v pravém slova smyslu, ale zastane stejnou službu.
Vybereme si pin, já zvolil GPIO 15 (tj. P1-10) a dáme jej k dispozici programům jako vstup:

echo 15 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio15/direction

Zde jsem nalezl postup. Stahujte, upravujte a kompilujte, tam odkazovaný, soubor. Spusťte a sledujte veselá přerušení vždy, když se změní stav vstupního pinu. Podle jiného programu v pythonu, je časová prodleva mezi dalším přerušením do dt=0,002 s (včetně vypisování na obrazovku), což je dostatečné pro měření do řádu setin sekundy, ale pravděpodobně si to nezadá s měřením s rozlišením na 32×10-3 s, zajištěné externím čítačem.

Teploměr

Rád bych doplnil implementaci teploměru, o kterém si přečtěte povedený návod na stránce astromik.org pod položkou „15) Teploměr DS18B20“.

Pozor: GPIO4 je nyní špatně, teploměr funguje na GPIO18, alespoň u mě, pro ověření použijte dmesg | grep w1

Vytvořil jsem dva skripty, jeden pro záznam teploty a jeden pro vizualizaci dat. První je klasický bash skript čtoucí v cyklu data z teploměru, dokud se kontrolní součet neshoduje. Občas se totiž vyskytují v měření velké chyby, které se takto minimalizují. Skript zapisuje do souboru temps.log datum do prvního sloupce, čas do druhého sloupce a teplotu do třetího. Při zpracování je třeba teplotu vydělit tisícem. Skript lze volat cronem, já zvolil desetiminutový interval, vše je na libovůli. Nezapomeňte však použít ID vašeho teploměru, řetězec znaků mezi devices/ a /w1_slave je pro každé zařízení jedinečný.

#!/bin/bash

if [ -e /sys/bus/w1/devices/28-000001b44be4/w1_slave ]; then 

 txt=`cat /sys/bus/w1/devices/28-000001b44be4/w1_slave`

 while  [ "$(echo $txt | grep 'NO')" != "" ]; do
  txt=`cat /sys/bus/w1/devices/28-000001b44be4/w1_slave`
 done
 temp=`echo $txt | grep t= | cut -d '=' -f3`
 echo `date +%F%t%T%t`$temp >> ~pi/temps.log
fi

Druhý je skript pro gnuplot, který musíte předem nainstalovat. Části jsem sehnal na různých místech v nápovědách a jiných článcích, protože je to poprvé, kdy s gnuplot pracuji přímo:

#!/usr/bin/gnuplot

set terminal png size 1280,960
set output 'temperature.png'
set title "Inside temperature"
set xlabel "Time"
set ylabel "Temperature [C]"

set style line 11 lt 1 lw 0.5 lc rgb "#AAAAAA"
set style line 12 lt 0 lw 0.1 lc rgb "#DDDDDD"
set mxtics 2
set mytics 4
set grid xtics ytics, ls 11
set grid mxtics mytics, ls 12

set xdata time
set xtics rotate by -12
set timefmt "%Y-%m-%d %H:%M:%S"
set format x "%d.%m. %H h"
plot "temps.log" using 1:($3)/1000 title "Temperature" with lines

Mám tak hotovou první část své budoucí meteostanice.

FET přepínač/switch

Ač nejsem elektrotechnicky vzdělán a mám mlhavou představu o funkci součástek (mlhavější, než bych si představoval), povedlo se mi vytvořit elektronické relé. Totiž můj problém je na světě snad jedinečný. Měřím sepnutí koncových spínačů na vzdálenost 100 m. Na to už je potřeba nějaký zdroj, takže vezmu autobaterii (jedná se vždy o dočasnou instalaci). Jenže jemná elektronika připojená k PC by to nejspíš nezvládla napřímo a tak vezmu 12 V relé a spínám s ním. Zde je rozkol mezi mým a běžným užitím relé. Nižším napětím se obvykle ovládá vyšší, u mě naopak. A pak máte Raspberry Pi, ke kterému potřebuji vyvést ke GPIO kolíku 3,3 V v případě, že je uzavřen 12 V vnější obvod, navíc to potřebuji co nejrychleji, to mi mechanické relé nezajistí. Protože jsem k Raspberry pořídil n-kanálový FET BS107 jako měnič mezi hladinami 5 V a 3,3 V pro připojení příslušenství. Doufal jsem, že půjde udělat i přepínač, který si představuji. Dlouho jsem hledal a nic nenašel, až jsem se jal dělat pokusy a nakonec na to přišel. Řekl jsem si, že tranzistor otevírá napětí na GATE, přivedl jsem tam tedy 12 V od spínače, k SOURCE jsem připojil společnou zem (GND) přes odpor, měl jsem tady zrovna několik kousků 330k navíc, jistě by to chtělo propočítat. Nu a k DRAIN jsem připojil zatím 5 V, v rámci vývoje. Nyní po stisku tlačítka spínače na 12 V větvi, jsem multimetrem naměřil na nožičce SOURCE kýžené nižší z obou napětí. Po uvolnění tlačítka tam však zůstávalo, vzal jsem tedy ještě jeden 330k rezistor a píchnul jej mezi GATE a GND s tím, že náboj či co tam zůstává vybije do země. Stalo se, a přepínač funguje. Zbývá jen zjistit, zda by nestačil nějký levnější a běžný tranzistor, zda je FET opravdu nutný, stejně jako velikosti rezistorů připojených do země.

LED je úmístěna špatně, oprava dole. / LED is wrong placed, explanation is at the end of article.
fet_switch

EDIT: Vyzkoušel jsem mnohem levnější BS170, hlavní rozdíl je v maximálním napětí 200 V oproti 60 V, to však v mém případě vůbec nevadí. Na GME dostanete datasheet od Philips, ale na první pohled byly obrácené nožičky Source a Drain, Při zapojení podle Datasheetu mi to neběhalo, na údajné Source nožičce bylo pořád napětí. Vsadil jsem pouzdro stejně jako předchozí BS107 a funguje, tak jak já očekávám, kde je tedy chyba?

EDIT 10.3.2013: Po sestavení zkušební desky se ukázalo, že pin nastaveny v RPi jako vstupní je obdařen velkou impedancí a dioda se, dle mého prvotního nápadu, nerozsvítí. Stačí jednoduše přehodit LED na větev jdoucí ze SOURCE do země a je po problémech. I přesto, že se LED nerozsvítí, obvod fungoval dle předpokladů, dioda tam ani být nemusí, je určen obsluze pro kontrolu sepnutí koncového snímače.mosfet_switch

Ultrazvukový měřič vzdálenosti

Koupil jsem jej z DX.com, má označení HC-SR04, hledal jsem návod jak modul zprovoznit a našel odkaz na stránku http://www.raspberrypi-spy.co.uk/2012/12/ultrasonic-distance-measurement-using-python-part-1/. S malou obměnou vše funguje. Místo děliče napětí jsem zařadil N-kanál FET BS107, dle návodu na připojení I/O expanderu portů. Ten oddělí napěťové hladiny 3,3 V pro RPi a 5 V pro modul. Jako pull-up resistor jsem použil včera omylem koupený 330 kOhm, ale funguje to i s 10 k potenciometrem protaženým přes krajní svorky. To je vše, program ze stránky raspberry-spy funguje bez potíží.