04.01.2013Projekt "Diagnostický přístroj"

Rozhodl jsem se postavit zařízení, které bude schopné komunikovat se všemi zařízeními, které vytvořím. Umožní mi programovat chip, který je již na desce nějakého zařízení, aniž bych musel odendavat chip z desky. Zároveň bude možné komunikovat s jinými zařízeními z důvodu diagnostiky.


Dokumentace sestavení a zkouška částí


Všimněte si umístění vyhlazovacího kondenzátoru uvnitř patice chipu. Ušetřil jsem tak místo a kondenzátor je umístěn velmi nenápadně. Na dalším obrázku je zase vidět žluté a bílé lanko vstupující pod patici. Jedná se o propojení programovacích pinů tak aby se ušetřilo místo kolem chipu. Zároveň je vidět umístění zákládních prvků projektu. programovací část Launchpadu, DSUB interface, patice pro MSP430. Vyvedení 5V, země, 3V a programovacích pinů (TEST,RST) na desku.

První zkouška displeje
Napojení displeje
Základní zapojení
Chaoticky vypadající zapojení všech součástí
Debouncing tlačítka na inkrementálním senzoru
Debouncing tlačítka


Zkouška částí diagnostického zařízení


Zkouška komunikace se zařízením

Při stisknutí červeného tlačítka dojde k odeslání příkazu "START", launchpad má za úkol při přijetí příkazu START odeslat ten samý příkaz zpět. Příkaz START je z Launchpadu také odeslán jednu vteřinu po startu. Po stisknutí červeného tlačítka tedy dojde k odeslání příkazu a v zápětí k přijetí toho samého příkazu a jeho zobrazení na displeji. Komunikace je patrná na dvou LED diodách, které komunikaci vizualizují.


První zkouška diagnostiky s funkčním menu

Diagnostický přístroj je připojený k jinému zařízení. v tomhle případě k testovacímu boardu přes testovací interface. Diagnostika je v této komunikaci pasivním členem a pouze umožňuje druhému zařízení "přístup" ke svému interface.

Červené tlačítko zažádá zařízení o informace o sobě. Zařízení pošle seznam příkazů které akceptuje (hlavní menu). Diagnostika toto menu zobrazí a umožní se v něm pohybovat a volit. Při volbě položky menu je zařízení zaslán příkaz s kódem zvolené položky a je na zařízení jak bude dále reagovat.


První menu je pouze testovací, obsažené v kódu diagnostiky. Po stisknutí červeného tlačítka se ale načte menu které definuje připojené zařízení a tedy není obsaženo v kódu diagnostiky. Všimněte si stavových LED nahoře vedle indikace napájení. Zelená pro přijímání dat, červená pro odesílání dat


Test všech vlastností diagnostického přístroje

Musel jsem změnit způsob práce s menu kvůli paměti MSP430 v diagnostice. Nyní je menu přijímáno po částech a pak teprve se skládá dohromady. Položky menu mohou nabývat několika různých typů, které určují chování diagnostiky. Popis najdete níže.

Nyní je přístroj schopen přijmout menu od připojeného zařízení, vybírat z menu, posílat připojenémy zařízení hodnotu zvolenou otáčivým voličem a umožnit připojenému zařízení využít LCD pro zobrazení libovolného textu


Funkce knihovny pro zařízení


Knihovna dbg.h je pro jakákoliv zařízení, která chtejí mít možnost komunikovat s diagnostikou. Knihovna nabízí pouze pár funkcí pro komunikaci s diagnostikou.

  • dbg_send(string str) : odešle text příkazu. Každý příkaz musí začínat a končit #. Existuje pouze p8r příkazů, které diagnostika akceptuje viz. níže.
  • dbg_lcd(int x,int y,string str) : odešle příkaz k zobrazení textu na souřadnicích X a Y. Pomocí souřadnic lze diagnostiku přinutit k vymazání řádku, sloupce, nebo celého displeje. Pokud je souřadnice X menší než 0, platí, že se smaže celý řádek podle souřadnice Y a na souřadnici (X+1)*(-1) se zobrazí text. Souřadnice -1,0 tedy vymaže řádek 0 a na souřadnice 0,0 se vypíše text. Souřadnice -2,0 vymaže řádek 0 a na souřadnice 1,0 se vypíše text. Pro souřadnici Y platí totéž, při záporné souřadnici Y se smaže sloupec podle souřadnice X. Pokud je záporná souřadnice X i Y, smaže se celý displej a souřadnice se převedou na kladné stejným způsobem.
  • dbg_begin(int pin,int bit_pin,boolean side,int led_receiver,int led_sender) : Funkce pro inicializaci debug knihovny. Parametr pin vyžaduje definici pinu pro komunikaci, např. P1_0, parametr bit_pin vyžaduje definici komunikačního pinu pomocí bitové konstanty, např. "BIT0" a parametr side vyžaduje boolean hodnotu na jakém čísle se nachází komunikační pin. "false" znamená, že název pinu začíná "P1.", true znamená, že začíná "P2." číslo za slovem "BIT" pak znamená číslo v názvu pinu za tečkou. Platí tedy, že PX.Y = (X==1){false}else{true} a BITY. Poslední dva parametry jsou definice pinů pro LED diodu indikující příjmání dat a odesílání dat. Pokud je hodnota 0, nebude odesílání, nebo příjmání indikováno. Volání funkce může vypadat takto: dbg_begin(P2_2,BIT2,true,P1_6,P1_0);
  • dbg_listen() : funkce slouží k naslouchání na komunikačním pinu a v případě odposlechnutí validního příkazu volá funkci dbg_commandHandler(char* cmd). parametr "str" obsahuje příkaz bez počátečního a konečného #.


Validní příkazy a jiná pravidla


Příkazy které může zařízení posílat, nebo které může od diagnostiky přijímat mají určitá pravidla:

  • Každý příkaz, který je odesílán musí začínat a končit křížkem #
  • příkaz nesmí být delší než 35 znaků


Příkazy:

  • #START# : Příkaz zaslán diagnostikou. Jako odpověď je očekáváno menu (viz. níže)
  • #COMMANDS# : Příkaz odesílán zařízením. Příkaz uvozující menu. Diagnostika následně očekává části menu a příkaz ukončující menu.
  • #END# : Příkaz ukončující sekvenci menu (viz. níže)


Menu:

Příkaz položky menu má několik částí, první dvě povinné a další volitelné, podle typu menu. Položky menu se musí posílat mezi kódy #COMMANDS# a #END#. Tyto příkazy uvádějí skupinu položek menu, ne každou položku svlášť! Stavba je následující:
#_KOD_|_TEXT_|_TYP_|_PARAMETR1_|_PARAMETR2_#

  • _KOD_ : Kód menu. Tento kód zašle diagnostika ve chvíli kdy je menu zvoleno. Zařízení tak pozná jaké menu bylo zvoleno a může podle toho reagovat.
  • _TEXT_ : Tento text bude položku menu reprezentovat na displeji diagnostiky.
  • _TYP_ (volitelný): Typ menu určuje chování diagnostiky po zvolení menu. Vlastnosti typů je vysvětleno níže. Pokud není parametr s typem definován, použije se typ 0.
  • _PARAMETR1_ (volitelný): Parametr 1 se používá jen pro typ menu 1,2 a 3 a znamená spodní hranici volby čísla otočným voličem
  • _PARAMETR2_ (volitelný): Parametr 2 se používá jen pro typ menu 1,2 a 3 a znamená horní hranici volby čísla otočným voličem
  • _PARAMETR3_ (volitelný): Parametr 3 se používá jen pro typ menu 1,2 a 3 a znamená počáteční hodnotu při volbě čísla otočným voličem
  • _PARAMETR4_ (volitelný): Parametr 4 se používá jen pro typ menu 2 a 3. Po ukončení volby čísla je tento kód odeslán zařízení (stejným způsobem jako když se zvolí položka menu)


Typy menu:

  • 0: Základní menu, po zvolení je kód menu odeslán připojenému zařízení
  • 1: Po zvolení je kód menu odeslán připojenému zařízení a otevře se rozhraní pro volbu čísla otáčivým voličem. OD a DO hodnoty jsou určeny v položce menu. Po zvolení vybraného čísla kliknutím se číslo odešle, ale je stále možné provádět další výběr. Do menu se je potřeba vrátit červeným tlačítkem.
  • 2: Po zvolení je kód menu odeslán připojenému zařízení a otevře se rozhraní pro volbu čísla otáčivým voličem. OD a DO hodnoty jsou určeny v položce menu. Po zvolení vybraného čísla kliknutím se čislo odešle a jste vráceni do hlavního menu
  • 3: Po zvolení je kód menu odeslán připojenému zařízení a otevře se rozhraní pro volbu čísla otáčivým voličem. OD a DO hodnoty jsou určeny v položce menu. Zvolené číslo je odesíláno při každé změně. Volba se ukončí kliknutím.
  • 4: Po zvolení je kód menu odeslán připojenému zařízení, diagnostika se přepne do debug módu, vymaže LCD a čeká na příkazy pro zobrazení dat na LCD. Mód se ukončí kliknutím otáčivým voličem



Knihovna dbg.h

// Version:1.1
//////////////

const boolean DBG_OUT=true;
const boolean DBG_IN=false;
const int DBG_MULTIPLIER=100;
const int DBG_ZERO=1*DBG_MULTIPLIER;
const int DBG_ONE=2*DBG_MULTIPLIER;
const int DBG_GO=3*DBG_MULTIPLIER;
const int DBG_SPACE=250;

int DBG_LED_RECEIVER;
int DBG_LED_SENDER;
int dbg_pulsePin;
boolean dbg_b[7];
int dbg_bPos=0;
char dbg_command[40];
char dbg_wch[5];
int dbg_commandPos=0;
char dbg_ch;
int dbg_pulse;
boolean dbg_dir=DBG_IN;
boolean dbg_reported=false;

int DBG_PIN_BIT;
boolean DBG_PIN_P;

void dbg_begin(int pin,int bit_pin,boolean side,int led_receiver,int led_sender)
{
  dbg_pulsePin=pin;
  DBG_PIN_BIT=bit_pin;
  DBG_PIN_P=side; // 1 - false,2 - true
  
  DBG_LED_RECEIVER=led_receiver;
  DBG_LED_SENDER=led_sender;
  
  if(DBG_PIN_P){P2DIR&=~DBG_PIN_BIT;}else{P1DIR&=~DBG_PIN_BIT;}
  P1DIR|=BIT6;
  P1DIR|=BIT0;
  P1OUT&=~BIT6;
  P1OUT&=~BIT0;
}

void dbg_pulseOut(int us)
{
    if(DBG_PIN_P){P2OUT|=DBG_PIN_BIT;}else{P1OUT|=DBG_PIN_BIT;}
    delayMicroseconds(us);
    if(DBG_PIN_P){P2OUT&=~DBG_PIN_BIT;}else{P1OUT&=~DBG_PIN_BIT;}
}

void dbg_char2bin(char c,boolean* barr)
{
  short int barrPos=0;
  for (short int i = 7; i >= 0; --i)
  {
    barr[barrPos++]=(c&(1<<i))?true:false;
  }
}

void dbg_sendChar(char c)
{
  boolean barr[7];
  dbg_char2bin(c,barr);
  dbg_pulseOut(DBG_GO);
  delayMicroseconds(DBG_SPACE);
  for (short int i=0; i<8; i+=1)
  {
    if(barr[i])
    {
      dbg_pulseOut(DBG_ONE);
    }
    else
    {
      dbg_pulseOut(DBG_ZERO);
    }
    delayMicroseconds(DBG_SPACE);
  }
  dbg_pulseOut(DBG_GO);
  delayMicroseconds(DBG_SPACE);
}

void dbg_sendString(char* str)
{
  char ch;
  short int i=0;
  ch=str[i++];
  while(ch!=0)
  {
    dbg_sendChar(ch);
    ch=str[i++];
  }
}

void dbg_send(char* str)
{
  //P1OUT|=BIT0;
  digitalWrite(DBG_LED_SENDER,HIGH);
  
  dbg_dir=DBG_OUT;
  if(DBG_PIN_P){P2DIR|=DBG_PIN_BIT;}else{P1DIR|=DBG_PIN_BIT;}
  dbg_sendString(str);
  if(DBG_PIN_P){P2DIR&=~DBG_PIN_BIT;}else{P1DIR&=~DBG_PIN_BIT;}
  dbg_dir=DBG_IN;
  
  //P1OUT&=~BIT0;
  digitalWrite(DBG_LED_SENDER,LOW);
}

void dbg_lcd(int x,int y,char* str)
{
  //P1OUT|=BIT0;
  digitalWrite(DBG_LED_SENDER,HIGH);
  
  dbg_dir=DBG_OUT;
  if(DBG_PIN_P){P2DIR|=DBG_PIN_BIT;}else{P1DIR|=DBG_PIN_BIT;}
  dbg_sendString("#LCD##");
  itoa(x,dbg_wch,10);
  dbg_sendString(dbg_wch);
  dbg_sendString("|");
  itoa(y,dbg_wch,10);
  dbg_sendString(dbg_wch);
  dbg_sendString("|");
  dbg_sendString(str);
  dbg_sendString("#");
  if(DBG_PIN_P){P2DIR&=~DBG_PIN_BIT;}else{P1DIR&=~DBG_PIN_BIT;}
  dbg_dir=DBG_IN;
  
  //P1OUT&=~BIT0;
  digitalWrite(DBG_LED_SENDER,LOW);
}

char dbg_binary2char(boolean b[8])
{
  byte c=0;
  for(short int i = 0; i < 8; i++)
  {
    if(b[i]==true)
    {
      c|=(1<<(7-i));
    }
  }
  return c;
}

void dbg_listen()
{
  if(dbg_dir==DBG_IN)
  { 
    dbg_pulse=pulseIn(dbg_pulsePin,HIGH);
    if(dbg_pulse>0)
    {
      dbg_reported=false;
      //P1OUT|=BIT6;
      digitalWrite(DBG_LED_RECEIVER,HIGH);
      
      dbg_pulse=round(dbg_pulse/100.0);
      if(dbg_pulse==3 && dbg_bPos!=0)
      {
        dbg_bPos=0;
        dbg_ch=dbg_binary2char(dbg_b);
        if(dbg_ch!='#')
        {
          dbg_command[dbg_commandPos++]=dbg_ch;
          dbg_command[dbg_commandPos]=0;
        }
        else
        {
          if(dbg_commandPos>0)
          {
            P1OUT&=~BIT6;
            dbg_reported=true;
            dbg_commandHandler(dbg_command);
            dbg_commandPos=0;
            dbg_command[0]=0;
          }
        }
      }
      else
      {
        if(dbg_bPos>7){dbg_bPos=0;}
        if(dbg_pulse==1)
        {
          dbg_b[dbg_bPos++]=false;
        }
        if(dbg_pulse==2)
        {
          dbg_b[dbg_bPos++]=true;
        }
      }
      if(!dbg_reported)
      {
        //P1OUT&=~BIT6;
        digitalWrite(DBG_LED_SENDER,LOW);
      }
    }
  }
}


comments powered by Disqus