DAT290 / dokumentation / projektrapport / include / Methods.tex
Methods.tex
Raw
\chapter{Metod}
\label{sec:metod}
\section{Nätverksprotokoll}
\label{sec:nätverksprotokoll}
%översikt här
I nätverksprotokollet används CAN-ramar av standardlängd för all kommunikation mellan enheter.
Kommunikation mellan två enheter sker på följande vis:

\setlength{\parskip}{1pt plus 1em}
\begin{enumerate}
    \label{enum:oversiktOrdning}
    \item $P_0$ sänder en dataram till $P_1$
    \item $P_1$ tar emot ramen och returnerar en ACK-ram till $P_0$
    \item $P_0$ tar emot ACK-ramen
\end{enumerate}
\setlength{\parskip}{1em plus 1pt}

Om en ram går förlorad kommer STM-biblioteket sända ramen igen till dess att den når fram
till en periferienhet. För att garantera att det finns en anslutning mellan en 
periferienhet och centralenheten har nätverksprotokollet avbrottshanterade klocka
som aktiveras vid sändning av ramar. Om en ACK-ram inte tas emot innan tidsgränsen
återsänds ramen som gick förlorad. Bilden nedan (se figur~\ref{fig:droppedFrames}) visar hur
utbyten av ramar kan gå till.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{figure/auxiliary/droppedFrames}
    \caption{Kommunikationsexempel}
    \label{fig:droppedFrames}
\end{figure}


\subsection{Teknisk specifikation}
\label{sec:tekniskSpecifikation}
Nedan beskrivs en rams väsentliga struktur och innehåll. 
\subsubsection{Ramhuvud - ID-fältet}
\label{sec:idfält}
Ramhuvudet består av 11 bitar och har 4 fält (se tabell~\ref{tab:idHeader}) där varje 
fält består av olika antal bitar. Detta ID-fält är inkluderat i varje ram som sänds på
nätverket. 
\begin{description}
    \item[Larm] Signalerar om meddelandet är av larmtypen.
    \newline Består av $b_{10}$. 
    \newline 1 - Larm aktivt. 0 - Inget larm.
    \item[Till/från centralenhet] Visar om ramen är inkommande till eller utgående från centralenheten. 
    \newline Består av $b_9$. 
    \newline 1 - Ingående. 0 - Utgående.
    \item[Meddelandetyp] 4 bitar som representerar de olika meddelandetyperna (se teori kapitel~\ref{sec:meddelandetyper}). 
    \newline Består av $b_8-b_5$.
    \item[Periferienhetens ID] 5 bitar som representerar ID till periferienheten som kommuniceras med. 
    \newline Består av $b_4-b_0$.    
\end{description}


\begin{table}[H]
    \centering
    \begin{tabular}{||c||c||c|c|c|c||c|c|c|c|c||}
        \hline
        x & x & x & x & x & x & x & x & x & x & x \\
        \hline  
            $b_{10}$ & $b_9$ & $b_8$ & $b_7$ & $b_6$ &
            $b_5$ & $b_4$ & $b_3$ & $b_2$ & $b_1$ & $b_0$ \\
        \hline    
    \end{tabular}
    %doesn't center for some reason
    \caption{Nätverksprotokollets ID-fält}
    \label{tab:idHeader}
\end{table}

\subsubsection{Ramdata}
\label{sec:ramdata}
Varje CAN-ram har variabel datalängd mellan 0 och 8 byte där längden beror på meddelandetyp. Datan består
därmed av två olika fält: datalängdsfältet och datan.
\begin{description}
    \item[Datalängdsfältet] Definierar antalet byte som finns i datafältet.
    \newline Längd: 3 bitar
    \item[Datafältet] Innehåller ramens data. Längden är bestämd av datalängdsfältet.
    \newline Längd: 0--8 byte
\end{description} 
Lösenordet som varje ram har placerats i de två första byten i ramen vilket lämnar 6 byte åt meddelandeinformation.

\subsection{Lösenordshantering}
\label{sec:lösenordshantering}
Återuppspelningsattacker motverkas genom att lösenord används i varje ram. För att fortsatt
tillåta ramar gå förlorade och inte ockupera stora delar av arbetsminnet i MD407 behövs stor
omsorg läggas på lösenordshanteringen. Nätverksprotokollet genererar nya lösenord vid start 
av nytt ramutbyte, vilket kan ske antingen när en enhet sänder i väg en ny ram eller när en
enhet tar emot en ny ram som inte har meddelandetypen ACK. När ett nytt ramutbyte är påbörjat
genereras två lösenord, ett för den första och ett för den andra ramen i utbytet. För ett
framgångsrikt utbyte krävs det att de mottagna lösenorden och de genererade lösenorden 
stämmer överens för bägge ramar. 

Om en ram med fel lösenord tas emot kommer en av två saker 
hända, antingen kommer lösenordet vara helt fel eller vara associerat med det föregående 
ramutbytet. I det första fallet ignoreras ramen i sin helhet, medan i det andra fallet
återsänds den ACK-ram som gått förlorad (se figur~\ref{fig:droppedFrames}).


\subsection{Automatisk initialisering}
\label{sec:automatiskInitialisering}
Periferienheter måste bli tilldelade ett ID för att kunna kommunicera med centralenheten. Eftersom
kommunikation genom nätverkslagret kräver att meddelandet har ett periferienhets-ID uppstår en paradox
- Hur ska en periferienhet tilldelas ett periferienhets-ID utan att ha ett periferienhets-ID? Protokollet
löser detta genom att tillåta vissa förbrytelser i ramutbyten vilka är: ramar måste ha ett periferienhets ID
och att alla icke ACK-ramar som tas emot ska sända tillbaka en ACK-ram.

Initialiseringsprocessen går till på följande vis:
\begin{enumerate}
    \label{enum:autoInit}
    \item $P_0$ sänder en ram till $P_1$ för att bli initialiserad.
    \item $P_1$ besvarar $P_0$ genom att tilldela ett periferienhets-ID.
    \item $P_0$ tar emot ramen och har därmed blivit initialiserad.
    \item $P_0$ sänder en ACK-ram till $P_1$ för att godkänna initialiseringen.
\end{enumerate}
Inuti ramen som sänds i steg 2 finns startvärdet för lösenordsgeneratorn vilket synkroniserar central- och
periferienheten och möjliggör att ordinära ramar kan sändas till och från periferienheten.

\subsection{Implementation}
\label{sec:nätverkImplementation}
För att en enhet ska kunna reagera på inkommande paket registreras meddelandehanterare genom anrop av
\texttt{CAN\_registerMessageHandler} där en meddelandetyp och funktionspekare krävs, för att associera 
en meddelandetyp med en funktion som hanterar det nyankomna meddelandet.

För att sända en ram anropas \texttt{CAN\_send} med önskad periferienhets-ID, meddelandetyp, data och
datalängd. I \texttt{CAN\_send} låses all kommunikation med specificerad periferienhet till dess att 
ramutbytet är avslutat. \texttt{CAN\_send} sköter lösenordshanteringen och generar ett nytt lösenordspar
för ramutbytet och placerar det första lösenordet i de två första byten av datadelen av ramen.

Lösenord lagras i nätverkslagret i en lista som associerar en periferienhets ID med ett 
lösenordspar. Listan behövs för att tillåta användning av samma nätverkslagermodul i samtliga 
enheter på nätverket och längden är därmed definierad som maximalantalet periferienheter. Varje gång
en ram tas emot undersöks den först om det är en ACK-ram, och om ramens lösenord är samma som det andra
lösenordet för periferienheten. Om det inte var en ACK-ram undersöker protokollet om ramens lösenord är
antingen:
\begin{enumerate}
    \item Samma som det lagrade på första positionen för periferienheten
    \item Samma som det lösenord som fås av att generera det första lösenordet i nästa lösenordspar
\end{enumerate}
Det första alternativet kontrollerar att det inte är ramen som togs emot i förra ramutbytet (d.v.s. att
en ramförlust har ägt rum). Det andra alternativet undersöker om den mottagna ramen har lösenordet som
tillhör nästa ramutbyte. Om alternativ 1 inträffar återsänds den korresponderande ACK-ramen. Om alternativ 
2 inträffar lagras det nya lösenordsparet i listan av lösenordspar och sänder en ACK-ram med det nya lösenordet.

Den automatiska Initialiseringsprocessen är implementerad genom att periferienheten sänder ett meddelande
av typen \texttt{REQUEST\_INIT} till periferienheten med ett slumpmässigt temporärt ID för att tillåta för
flera periferienheter att initialiseras samtidigt. I centralenheten är en funktion registrerad för meddelandetypen 
\texttt{REQUEST\_INIT} som genererar ett nytt periferienhets-ID, initialvärde till lösenordsgeneratorn och sänder
tillbaka ett meddelande av typen \texttt{AUXILIARY\_INIT} med det temporära ID:t som periferienheten genererade.
När periferienheten tar emot \texttt{AUXILIARY\_INIT} meddelandet lagrar nätverkslagret lösenordet och periferienhets-ID:t
och sänder tillbaka en ACK-ram till centralenheten för att bekräfta och godkänna initialiseringen.

\section{Centralenheten}
\label{sec:centralenheten}
Centralenheten är en av de viktigaste enheterna i projektet. Det är nämligen centralenheten som styr och initierar de olika periferienheterna
som används. Via nätverkslagret (\ref{sec:nätverksprotokoll}) kan centralenheten skicka och ta emot meddelanden, vilket är nödvändigt för denna typ av system.
Centralenheten utgörs av ett MD407-kort som sedan kopplas ihop med diverse periferienheter via CAN-bussen.

\subsection{USART-kretsen}
\label{sec:usartkretsen}
% ref stm bibliotek?
För att larmets administratörer ska ha möjlighet att initiera periferienheter med önskad kalibrering och känslighet så kräver centralenheten någon typ av indata.
För detta ändamål används USART-kretsen. MD407-kortet innehåller åtta USART-kretsar, dock behövs endast en av dessa kretsar för att åstadkomma en in- och utmatningskommunikation
mellan centralenheten och en dator inkopplad till en av dess USB-portar.

Med hjälp av STM-biblioteket så kan USART-kretsen enkelt initieras för användning tillsammans med avbrottsrutiner. STM-biblioteket för USART-initiering tillåter bland annat inställning
av önskad överföringshastighet vilket minskar antalet rader kod avsevärt. Avbrottsrutiner används tillsammans med USART-kretsen av prestandaskäl och körs när en karaktär skrivs som indata till centralenheten.

Följande USART-relaterade händelser sker under programmets exekvering:
\begin {itemize}
\item USART-kretsen initieras med hjälp utav STM-biblioteket. Under initieringen blir även avbrottsvektorn för USART tilldelad en referens till den funktion som ska köras vid avbrott.
\item När avbrottsrutinen körs har alltså en karaktär skrivits till USART. Programmet sparar alla de inskrivna karaktärerna i en statusvariabel.
\item Om karaktären ''Enter'' skrivs till USART så vet programmet att indatan är komplett och kan sedan leta efter kommandon i statusvariabeln.
\item Det inskrivna kommandot valideras för att säkerställa korrekt användning. Ifall inga fel uppstår körs sedan detta kommando.
\item Slutligen frigörs alla temporära pekare relaterade till USART från minnet. 
\end{itemize}

\subsubsection{Tillgängliga kommandon}
\label{sec:commands}
Centralenheten ger tillgång till ett fåtal kommandon för initiering och allmän styrning utav periferienheter.
Dessa grundläggande kommandon utgörs av:

\begin{description}
\item [ping 'id'] Testar kommunikationen mellan önskad periferienhet.
\\
\item [door init 'aux -id' 'seed' 'rng-nummer' 'antal dörrar'] Initierar en dörrenhet enligt specificerade egenskaper.
\item [door activate 'dörr-id'] Aktiverar en dörrenhet med specificerat ID, skrivs 0xFF i stället för ID aktiveras alla dörrenheter inkopplade till centralenheten.
\item [door deactivate 'dörr-id'] Inaktiverar en dörrenhet med specificerat ID, skrivs 0xFF i stället för ID deaktiveras alla dörrenheter inkopplade till centralenheten.
\item [door config 'dörr-id' 'tid innan larm utlöses (ms)']	Konfigurerar en dörrenhet med ett givet tidsintervall. Genom att konfigurera en dörrenhet med ett tidsintervall så kan en administratör styra hur länge en dörr kan vara öppen innan larmet utlöses.
\item [door info] Skriv ut information om de olika dörrenheterna.
\\
\item [motion init 'aux-id' 'seed' 'rng-nummer' 'känslighet' 'kalibrering'] Initierar en larmenhet enligt specificerade egenskaper.
\item [motion activate 'rörelse/vibrations-id'] Aktiverar en larmenhet, skrivs 0xFF i stället för ID aktiveras alla larmenheter inkopplade till centralenheten.
\item [motion deactivate 'rörelse/vibrations-id'] Inaktiverar en larmenhet, skrivs 0xFF i stället för ID inaktiveras alla larmenheter inkopplade till centralenheten.
\item [motion config 'rörelse/vibrations-id' 'känslighet' 'kalibrering'] Konfigurerar en larmenhet enligt specificerade egenskaper.
\item [motion info] Skriv ut information om de olika larmenheterna.
\end{description}


\subsection{Knappsatsen}
\label{sec:knappsats}
En knappsats kopplad till centralenheten används för avlarmning. Detta för att man enkelt ska ha möjlighet att stänga av larmet utan att behöva koppla upp en persondator till centralenheten för avlarmning via USART. En avbrottsrutin är programmerad för att läsa av knappsatsen. Genom att kontinuerligt läsa av knapptryckningar från knappsatsen kan en status-variabel hålla koll på den inskrivna sekvensen. På så sätt vet centralenheten när rätt sekvens är inskriven och det är dags att larma av.

\subsection{Hantering av periferienheter}
\label{sec:hanteringAvPerif}
Flera dörr- och larmenheter kan kopplas till centralenheten via CAN-bussen och dessa periferienheter behöver kommunicera med centralenheten av olika skäl.
Nätverksprotokollet (\ref{sec:nätverksprotokoll}) hanterar all logik som behövs för att skicka och ta emot data mellan olika periferienheter, däremot behöver viss logik implementeras på
centralenheten för en korrekt initiering av enheterna. Det är centralenheten som tilldelar en periferienhet dess id och utan denna viktiga funktion skulle ingen kommunikation mellan centralenheten och en enskild periferienhet vara möjlig.
Periferienheterna (larm- och dörrenhet) kommer att skicka meddelanden till centralenheten när ett larm behöver utlösas. Därför är även centralenheten programmerad att utlösa ett larm om ett larmmeddelande tas emot.

Se avsnittet om tillgängliga kommandon (\ref{sec:commands}) för manuell konfiguration av periferienheter via USART.


\section{Periferienheter}
\label{sec:periferienheter}
En periferienhet består av en MD407 och en typ av sensor eller krets. Det är periferienheternas jobb att komplementera centralenheten med
extra funktionalitet.
\subsection{Dörrlarm}
\label{sec:dörrlarm}
Varje dörrlarm körs på ett eget MD407 kort som är kopplat till centralenheten (\ref{sec:centralenheten})
 med hjälp av nätverkslagret (\ref{sec:nätverksprotokoll}). Systemet har stöd för så många dörrenheter som det
 finns ID:n tillgängliga (\ref{sec:idfält}). Varje dörrenhet har sedan stöd för upp till 15 dörrar, vilket betyder att antalet dörrar
 som stöds inte kommer vara en flaskhals i systemets storlek. Varje dörr på varje dörrenhet tilldelas även
 ett eget ID vilket betyder att de kan adresseras separat. Vilket i sin tur medför att alla dörrar kan larmas på och av 
 separat och man kan veta vart ett eventuellt larm har gått.

De enskilda dörrlarmen ansluts till MD407:s GPIO D-port till bitarna $b_0$-$b_{14}$. Vilken bit larmet är ansluten till motsvarar dörrens ID.
 Pinnarna som dörrlarmen är konfigurerade som pull-up-motstånd (\ref{sec:pullup}). Varje dörr består av en koppling mellan dörrenheten och jord,
 när kontakten bryts läggs det en logisk etta på pinnen.
  På grund av detta är dörrenheten i princip en sladd kopplad till
 jord och när kontakten bryts läggs en logisk etta på pinnen. 

Varje dörr har en motsvarande grön lysdiod på samma bit fast på MD407-kortets GPIO E-port. Dessa lysdioder lyser då dörren är olarmad för att indikera
det förutnämnde. Bit $b_{15}$ är reserverad för larmlysdioden som tänds när en dörr som är larmad öppnas.
Denna lysdiod släcks om dörren stängs innan den konfigurerbara fördröjningen tagit slut, annars så måste ett avlarmningsmeddelande från centralenheten mottas
 för att lysdioden ska släckas.

När en dörrenhet öppnas och den inte längre är kopplad till jord startas en klocka (\ref{sec:timer}) med fördröjningen som
konfigurerats av centralenheten och den röda larmlysdioden tänds. Om dörren stängs innan timern tagit slut släcks lampan och inget
mer händer. Om dörren däremot är fortsatt öppen när timern tagit slut så skickas en larm ram till centralenheten och larmet går.

Dörrenheten har två saker som kan konfigureras. Dessa två variabler ändras när enheten mottager ett konfigurationsmeddelande från centralenheten.
Det som kan konfigureras är dels hur länge en dörr kan vara öppen innan ett larmmeddelande skickas till centralenheten och hur många dörrar som
är inkopplade. Dessa två variabler sätts även vid initialiseringen.

\subsection{Rörelselarm}
\label{subsec:rörelselarm}

Rörelselarmet styrs av en MD407 som är kopplad till centralenheten via CAN-bussen.
Den har två olika typer av sensorer inkopplade, en vibrationssensor och en ultraljudsbaserad avståndssensor.

\subsubsection{Vibrationssensor}
\label{sec:vibrationssensor}
Den första sensorn är en vibrationssensor av modellen SW-19010P och den kan användas både digitalt och analogt.
När den används digitalt avger sensorn en signal när vibrationen överstiger en viss nivå som justeras via en potentiometer som sitter på sensorn.
När den används analogt avläses spänningen från sensorn för att avgöra vibrationsnivån som sedan jämförs med ett tröskelvärde i mjukvara.
En låg spänning innebär en hög vibrationsnivå.
Denna metod används för att enkelt kunna justera tröskelvärdet via mjukvara.
Avläsningarna sker med 1 kHz frekvens för att inte missa korta stötar.

För att genomföra avläsningen starts en upprepande klocka mellan TIM2--TIM7 som skickar en signal till en analog-till-digital-omvandlaren (ADC) med 1 kHz frekvens.
ADC:n avläser den analoga signalen och omvandlar den till ett 12-bitars digitalt tal.
Detta tal lagras direkt i primärminnet utan att gå via processorn med tekniken Direct Memory Access (DMA).
När talet har lagrats sker ett avbrott där avläsningen jämförs med tröskelvärdet och om avläsningen är under tröskelvärdet avlöses ett larm.

\subsubsection{Ultraljudsbaserad avståndsmätare}
\label{sec:ultraljudssensor}
Den andra sensorn är en avståndsmätare av modellen HC-SR04 består av två ultraljudsgivare där den ena används
som sändare och den andra som mottagare. Sändaren skickar ut en serie av ultraljudspulser som studsar mot omgivningen
avståndsmätaren befinner sig i och tas upp av mottagaren. Tidsfördröjning mellan sändning och mottagning används för
att beräkna distansen som pulsen färdats.

HC-SR04 har 4 pinnar var olika funktioner beskrivs nedan:
\begin {description}
\item [VCC] Spänningskälla, ansluts till en 5 V spänningskälla.
\item [Trigger] Indata till enheten, ansluts till MD407:s GPIO A på bit $b_{0}$.
\item [Echo] Utdata från enheten, ansluts till ICU pinnen.
\item [Ground] Jordpinnen, ansluts till GND.
\end{description}

Sensorn mäter avstånd genom att skicka en 10$\mu$s puls till triggerpinnen, vilket får sändaren att skicka ut
8 pulser vid 40KHz vilka sedan spelas in och visas på Echo pinnen. För att mäta hur långt pulserna färdats måste
tiden mellan sändning och mottagning mätas, vilket görs med hjälp av en TIM-klocka i ICU-läge. ICU-läget tillåter
en klocka avfyra en avbrottshanterare när en styrsignal blir hög eller låg. När man sänder första pulsen startas
klockan och när pulsen registreras i mottagaren stoppas klockan. Mellanskillnaden är den uppmäta tiden, vilket
används för att beräkna distansen $\mathrm{{Restid}\ast{Ljudhastighet(340m/s)/{2}}}$, $\mathrm{{Restid} = {T_{2}}-{T_{1}}}$.
\begin{comment}
Sensoren mäter avstånd genom att skicka en kort 10us puls till Trigger stiftet,
sen skickar den ut åtta pulser ultraljud vid 40KHz på echo stift. den digital pulsen som skickadas ut är pulsbredd och intervallet i proportion.
Intervallet räknas genom \( \mathrm{{Restid}\ast{Ljudhastighet(340m/s)/{2}}}\).
För att räknas totala pulsbredden \( \mathrm{{T} = {T_{2}}-{T_{1}}}\) användas Input Capture mode (ICU) av timermoduler för att fånga tiden,
när ekopulsen går HÖG och LÅG. Programeras ICU för att fånga Timer2 -värdet in i CCR1-registret, som är T1, 
sen capture- händelse avfyrar en avbrottsignal som aktiveras för att vända Capture kanten tills fallande kanten. 
När echo sktift går låg, fångas Timer- värdet som är T2, då räknas totala pulsbredden. Sen användas denna informationen för att enklet beräkna avståndet.
\end{comment}