středa 6. dubna 2016

Zkušenosti s PICAXE 28X1

8. 4. 2016

 Jako svůj druhý soukromý hobby projekt s mikrokontroléry PICAXE (po vcelku úspěšném modulu pro automatické ovádání stopek ve vysílači DX6i)  jsem zahájil vývoj řídicí a kontrolní jednotky pro Vojtíškovo elektrické autíčko.

Prvotním impulsem bylo zjištění, že pro instalaci blinkrů, světel, couvaček a brzdovek nevystačím s přepínači, zabudovanými do autíčka od výrobce. Jako nejjednodušší se mi zdá použít mikrokontrolér s několika relé. Na to by stačil PICAXE 08M2. Rozhodl jsem se ale toho využít a doplnit autíčko o další funkce jako je sledování palubního napětí a proudu pohonných motorů (s inteligentním ukazatelem stupně vybití akumulátoru) ev. i s výhledem na zavedení proporcionálního řízení otáček motorů (plynu) někdy v budoucnu. Vznikne tak jakýsi palubní počítač pro elektroautíčko.

Takže jsem zvolil kontrolér PICAXE 28X1, který mám v domácí zásobě z jiného nerealizovného projektu.

Měl by vyhovět jak počty vstupů/výstupů, tak i kapacitami pamětí. (Pokud jste se dosud nesetkali s mikrokontroléry Picaxe, tak vězte, že to množné číslo v předchozí větě je úmyslné a má dobrý důvod. :))

PICAXE 28X1 ovšem má, jak se ukázalo,  některé zvláštnosti a hlavně poměrně nepříjemné  nedostatky v podpoře ve vývojovém prostředí Picaxe Editor.

Jak je to s těmi paměťmi


Picaxe 28X1 dává uživateli přístup k několika druhům paměti, které se liší způsobem adresování a přístupu (v podstatě pro každý druh paměti má vlastní adresový prostor, jiné příkazy a jiný princip přístupu), volatilitou (zda udrží obsah při odpojení napájení), možností modifikace obsahu (zápisu) a velikostí.
  1. Paměť programu (interpretovaný program, table, readtable)
  2. RAM (uživatelsky přístupná "hlavní" pracovní paměť). Má neomezený počet cyklů čtení/zápis, při odpojení napájení či resetu se obsah ztrácí.
    • Pojmenované registry ("proměnné") b0-b27, w0-w13 (let, částečně: peek, poke)
    • Zbytek RAM - nepojmenované  (peek, poke)
  3. EEPROM (eeprom, write, read). Má omezený (i když vysoký - obvykle se udává 100000) počet cyklů čtení/zápis. Při vypnutí napájení zachová obsah.
  4. Externí paměť EEPROM (readi2c, writei2c
  5. ScratchPad (ptr, get, put)
  6. SFR - System Function Registers (peeksfr, pokesfr)

Paměť programu


PICAXE 28X1 disponuje 4096B paměti programu. Jedná se o paměť typu EEPROM, naplněnou speciálním běhovým kódem, vzniklým ze zdrojového programu v Basicu při programování mikrokontroléru. Obsah této paměti je interpretován za běhu programu. Do této paměti program, běžící na PICAXE, nemůže zapisovat.

V části této paměti lze direktivou table připravit data pro naplnění oblasti o max velikosti 256B, pro následné čtení za běhu programu pomocí příkazu readtable.

RAM


Uživatelsky přístupnou RAM lze u 28X1 rozdělit na pojmenované registry, využitelné ve většině příkazů Basicu ve formě  proměnné a na zbývající část, přístupnou jen příkazy peek a poke.

 

Pojmenované registry


Nejpoužívanější část paměti RAM jsou pojmenované proměnné (registry) :
  • 16 bitové w0-w12
  • 8 bitové b0-b27
  • 1 bitové bit0-bit31
Pojmenované proměnné různých typů se překrývají v paměti na stejných fyzických místech:
  • w0 sdílí paměť s b0 a b1 (b1 je MSB) a bit0-bit15 (bit15 je MSb)
    • w1  sdílí paměť s b2 a b3 (b3 je MSB) a bit16-bit31 (bit31 je MSb)
      • w2  sdílí paměť s b4 a b5 (b5 je MSB)
                  ...
        • w12 sdílí paměť s b26 a b27 (b27 je MSB)
          Pamětníkům to jistě vzdáleně připomene Common a Equivalence ve Fortranu :).

          Příklad:    w0 = $1234
                                      w0
              +-----------------------------------------------+
              |                     1234                      |
              +-----------------------------------------------+    

                         b1                       b0
              +-----------------------+-----------------------+
              |          12           |           34          |
              +-----------------------+-----------------------+      

          bit  15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
              +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
              | 0| 0| 0| 1| 0| 0| 1| 0| 0| 0| 1| 1| 0| 1| 0| 0|
              +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

           

          Nepojmenovaná RAM


          Uživatelsky přístupná paměť má velikost  108B:
          • 14B proměnné, 
          • 94B = 2 x 47B volné úseky

          Příkazy peek, poke umožňují jednotný přístup k celé RAM. Některé typy Picaxe umožňují navíc i nepřímý přístup přes adresu v proměnné bptr (28X1 to neumí, mladší bráška 28X2 již ano). Při vypnutí napájení se ztrácí obsah, po restartu je vynulován.

          Jako všechny starší PICAXE (typy bez přípony v označení a řady M, X a X1) má i 28X1 paměť rozdělenu do několika souvislých úseků, obsluhovaných příkazy peek, poke
          • Adresy 32 ($20) až 47 ($2F) překrývají obecně použitelné pojmenované registry (b0-b27) - pozor, nejsou zdaleka všechny!
            Přes peek/poke jsou přístupné proměnné, odpovídající sudým 16b registrům: w0, w2, w4, w6 , w8, w10, w12
            • b0<-32   (w0)
            • b1<-35
            • b4<-36   (w2)
            • b5<-37
            • b8<-38   (w4)
            • b9<-39
            • b12<-40 (w6)
            • b13<-41
            • b16<-42 (w8)
            • b17<-43
            • b20<-44 (w10)
            • b21<-45
            • b24<-46 (w12)
            • b25<-47
          • Adresy $50$7E obecně využitelné nepojmenované registry – paměťová místa $70-$7F mohou sdílet fyzické umístění s $F0-$FF
          • Adresy $C0$EF, využitelné u PICAXE-28X1, 40X1

          EEPROM


          Lze naplnit při programování čipu (direktivy eeprom, data), za běhu programu pak číst (příkaz read) a zapisovat (write). Pamatuje si obsah trvale i při vypnutí napájení.
           
          PICAXE 28X1 nabízí 128B velkou oblast paměti EEPROM.

          Externí EEPROM


          Přídavná paměť ve formě samostatného integrovaného obvodu. Někdy i kombinovaná do jednoho pouzdra s jinými funkcemi (hodiny reálného času, teploměr).

          Připojená a obsluhovaná přes I2C sběrnici (hi2csetup, hi2cin, hi2cout).

          Zatím jsem externí EEPROM nepotřeboval použít.
           

          Scratchpad


          128 B velká paměť pro uživatelská data, přístupná přes proměnné ptr, @ptr, @ptrinc, @ptrdec, nebo příkazy get a put.

          Může být využívána pro výměnu dat mezi kontroléry Picaxe:
          • může být plněna na pozadí přes high-speed serial
          • pokud mikrokontrolér funguje jako I2C slave může být zapisována a čtena jiným Picaxe pomocí I2C rozhraní

          SFR


          System Function Registers (peeksfr, pokesfr) - hodně chaoticky dokumentovaná paměť systémových proměnných s nepředvídatelnými důsledky zápisu. V PICAXE je přístupná  jen 1. stránka 0-$100. Podrobnosti lze nalézt v dokumebtaci k typu PIC, ze kterého daný PICAXE vznikl, tedy v případě PICAXE 28X1 je to PIC16F886.

          Tímto způsobem může zkušený vývojář využít některé vlastnosti či části mikrokontroleru, se kterými nepracuje PICAXE FW, ev. použití modifikovat.  Potíž je v tom, že v dokumentaci k PICAXE nelze prakticky vůbec dohledat které části PIC a k jakému účelu FW používá. I vývojáři firmy Revolution Education, která PICAXE vyvíjí a dodává, se odmítají na podpůrném fóru v diskusích s uživateli k této problematice vyjadřovat.

          Prográmek pro testování práce s pamětí


          Program cvičně zapisuje do různých druhů pamětí v PICAXE. Scratchpad je zaplněn daty ze struktury Table (data uložená ve formě pole byte v paměti programu). Tím jsem si ověřoval použitelnost této konstrukce. Ostatní paměti pak dostanou jako obsah svoji adresu v rámci daného typu paměti.

          ;
          ; Test pameti (test PICAXE 28X1)
          ;
          ; Copyright (c) 2016 Zdenek Trojanek
          ;
          ; ---------------------------------------------------------------
          ;    Filename:       TestPicaxe28X1.bas  
          ;    Date:           12.3.2016  
          ;    File Version:   1.0  
          ;    Written by:     Zdenek Trojanek
          ;    Last Revision:  12.3.2016
          ;    Target PICAXE:  28X1  
          ; ---------------------------------------------------------------
          ;
          ;                                              28X1
          ; 
          ;                                          .----..----.
          ;                               (RESET) 1 -| RST  B.7 |- 28 (Output 7)
          ;                (ULPWU / ADC0 / In a0) 2 -| A.0  B.6 |- 27 (Output 6)
          ;                        (ADC1 / In a1) 3 -| A.1  B.5 |- 26 (Output 5)
          ;                        (ADC2 / In a2) 4 -| A.2  B.4 |- 25 (Output 4 / hpwm D)
          ;                        (ADC3 / In a3) 5 -| A.3  B.3 |- 24 (Output 3)
          ;                           (Serial In) 6 -| SI   B.2 |- 23 (Output 2 / hpwm B)
          ;                          (Serial Out) 7 -| SO   B.1 |- 22 (Output 1 / hpwm C)
          ;                                       8 -| 0V   B.0 |- 21 (Output 0)
          ;                          (Resonator)  9 -| XT    +V |- 20
          ;                          (Resonator) 10 -| XT    0V |- 19
          ;         (timer clk / Out c0 / In c0) 11 -| C.0  C.7 |- 18 (In 7 / Out c7 / hserin / kb data)
          ;             (pwm 1 / Out c1 / In c1) 12 -| C.1  C.6 |- 17 (In 6 / Out c6 / hserout / kb clk)
          ;     (hpwm A/ pwm 2 / Out c2 / In c2) 13 -| C.2  C.5 |- 16 (In 5 / Out c5 / spi sdo)
          ; (spi sck / i2c scl / Out c3 / In c3) 14 -| C.3  C.4 |- 15 (In 4 / Out c4 / i2c sda / spi sdi)
          ;                                          `----------'      
          ;                                            28-Pin
          ;
          ; Program overuje funkcnost internich pameti pro data mikrokontroleru PICAXE 28X1:
          ;
          ;  Table:              256B
          ;  ScratchPad memory:  128B
          ;  RAM:                256B (přístupné 108B - 14B proměnné, 96B = 2 x 47B volné úseky)
          ;  EEPROM:             256B
          ;
          
          #Picaxe 28X1 
          
          ;
          ; Test Table
          ;
          table (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32)
          table (33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63)
          table 65, ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_")
          table (128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144)
          table ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_")
          table (208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224)
          table ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcd.")
          
          start:
          
          ;
          ; Test ScratchPad pameti
          ;
          for w0=0 to 127
            ;
            ; Test zapisem dat, nactenych z table
            ;
            readtable b0,b2
            put b0,b2
          next
          
          ;
          ; Test RAM
          ;
          ; Do kazde bunky pameti se zapise jeji adresa
          ;
          ; POZOR: Nejde ladit pod Picxe editorem V6 (hlasi neplatnou adresu pri poke),
          ;        musi se pouzit v5,
          ;
          ; Prostor pracovnich registru. 
          ; Chova se to nejak divne, viz nasl. soupis:
          ;
          ; b0 <-32
          ; b1 <-35
          ; b4 <-36
          ; b5 <-37
          ; b8 <-38
          ; b9 <-39
          ; b12<-40
          ; b13<-41
          ; b16<-42
          ; b17<-43
          ; b20<-44
          ; b21<-45
          ; b24<-46
          ; b25<-47
          ;
          for b0=32 to 47
            poke b0,b0
          next
          
          ;
          ; 1. usek RAM (47byte)
          ;
          for b0=80 to 127
            poke b0,b0
          next
          
          ;
          ; 2. usek RAM (47byte)  
          ;
          for b0=192 to 239
            poke b0,b0
          next
          
          ;
          ; Test EEPROM
          ;
          ; Do kazde bunky pameti se zapise jeji adresa
          ;
          for b0=0 to 255
            write b0,b0
          next
          
          end
          

          Co nefunguje v PICAXE Program Editoru?


          Picaxe Programming Editor je poměrně dobře navržené a realizované prostředí pro vývoj aplikací s PICAXE. Bohužel, pestrá nabídka mikrokontrolérů a jejich někdy značně odlišné chování, způsobují vývojářům problémy. Poměrně často tak uživatel narazí na problémy s překladem programů a jeho interpretací po nahrání na čipu (to je naštěstí méně časté), nebo na časté problémy se zpracováním programu v simulátoru, který je součástí PE.

          Stává se, že překladač odmítne přeložit konstrukci, která je podle dokumentace správná. Pak nezbývá než problém nějak obejít, většinou to jde.

          Více problémů bývá v simulátoru. Někdy se jedná o odmítání některé operace provést, nebo jsou prováděny odchylně od skutečného chování mikrokontroléru a tedy chybně. Vývojáři z Revolution Education se snaží problémy řešit, takže je dobré občas aktualizovat na novou verzi PE.

          V souvislosti s PICAXE 28X1 jsem narazil na poměrně zásadní problém: simulátor odmítá povolit čtení a zápis z RAM pomocí příkazů peek a poke. Takže používání RAM pomocí těchto příkazů nejde v simulátoru ladit.

          Naštěstí jsem našel způsob, jak věc obejít: použít starší verzi PE (v5) namísto aktuální v6. V PE 5.5.6 vše funguje dobře a lze ladit. Bohužel, PE5 a PE6 mají některé rozdíly v syntaxi Basic, takže je nutné program upravit, aby šel na PE5 zpracovávat. Je to škoda, protože jinak je PE6 pohodlnější a srozumitelnější.

          Záporná čísla


          Ačkoli se v dokumentaci uvádí, že PICAXE nepodporuje práci s čísly se znaménkem, není to tak úplně pravda. Podpora je ovšem jen minimální, přesně taková, aby umožnila vytvoření vlastních algoritmů pro zpracování záporných čísel. Zřejmě to souvisí s původním účelem PICAXE - výukou základů počítačů na základních a středních školách.

          Podpora spočívá v tom, že Basic umožňuje zápis záporných konstant a změnu znaménka čísla v proměnné. Výsledek odečtení většího čísla od menšího je kódován v 2. doplňku (doplňkový kód). Sčítání a odečítání pracuje s takto kódovanými čísly správně, pokud nedojde k přetečení. To je vše.

          Ostatní věci si musí zařídit programátor. Takže například porovnávání čísel se znaménky a jejich násobení a dělení je třeba ošetřit programově.

          Připojování LCD


          LCD se dají k Picaxe připojovat mnoha způsoby:
          • Paralelní rozhraní s 8b daty
          • Paralelní rozhraní s 4b daty
          • Sériové rozhraní UART ("RS232")
          • Sériové rozhraní I2C
          • Sériové rozhraní SPI
          Nejlákavější se zdá na první pohled sériové připojení: RS232 nebo I2C. Problém je, že LCD s rozhraním RS232 stojí cca 500Kč a špatně se shání.

          Mnohem levnější a dostupnější jsou různé varianty displejů s rozhraním I2C. Bohužel, ty levné s obvodem 8574 jsou s PICAXE (hlavně pro začátečníka) svépomocí většinou prakticky nerozchoditelné. Nejen, že mají často všelijaké obskurní znakové sady, ale hlavně se použité obvody rozhraní musí inicializovat a  vědět jak jsou přiřazeny bity v rozhraní displeje k bitům v datech I2C.

          Zatímco pro Arduino jsou k dispozici knihovny, které to umí zařídit, na PICAXE jsme odkázání na programování na úrovni základních funkcí použitých řadičů. Dokumentace k LCD s I2C rozhraním v podstatě neexistuje. Jediná šance je analyzovat knihovnu Arduina a pokusit se implementovat příslušné inicializační sekvence a mapování pinů.

          Naštěstí je pro některé rozšířené typy těchto I2C LCD displejů možné sehnat na fóru Picaxe vzorové programy, které displej obsluhují.  Používání je  ale dosti složité a nelze využívat pohodlí funkce writei2c, protože data se displejům s obvyklým obvodem rozhraní 8574 musí posílat po částech (půlkách byte). Je to docela otravné a pomalé, zvláště ve srovnání s LCD s rozhraním UART.

          Existují i displeje LCD a OLED, které fungují přes I2C přímo a bez problémů. Bohužel, podle popisu na e-shopech to většinou nejde odhadnout. Snad podle toho, že neobsahují IO 8574, využívají místo něho nějaký mikrokontrolér.

          Daleko jednodušší (a v konečném důsledku levnější) se mi zdá použití jednoho z paralelních způsobů připojení. Obvykle je ale (vzhledem k počtu nutných výstupů) nutné použít variantu se 4bitovými daty, což rovněž komplikuje práci podobně jako připojení I2C. Připojování těchto typů LCD (zejména s řadiči kompatibilními s HD44780) je ale velmi dobře popsané v řadě publikací a článků na internetu.

          Vcelku se nabízí možnost použití Picaxe (obvykle 20X2 - umí I2C slave režim) jako obvodu rozhraní. Pak lze poměrně jednoduše naprogramovat komunikaci jak přes I2C, tak i UART, ev SPI.

          1 komentář:

          1. Dobrý den,
            Prosím o radu, nemohu naprogramovat LCD displej 1602 s přídavkem i2C převodník pro LCD displej 1602 s I2C expanderem PCF8574). Zapojený s procesorem picaxe 28X2 a v jazyce Basic.
            Můžete prosím pomoc. Děkuji
            Tomášek.

            OdpovědětVymazat