Industriella Styrsystem Övningskompendium 27 mars 2012 REGLERTEKNIK AUTOMATIC CONTROL LINKÖPING Reglerteknik, Institutionen för systemteknik, Linköpings universitet, 581 83 Linköping www.control.isy.liu.se
Detta kompendium har utvecklats under flera år av olika lärare i reglerteknik vid Linköpings universitet.
Del I Uppgifter 1
Kapitel 1 PLC-programmering II Följande uppgifter är av lite mer krävande karaktär än i förra kapitlet och målsättningen är att tillämpa stegkodsprogrammering på mer komplicerade problem. När kommer ni istället för att få en lista på operationer som ska utföras, få ett problem som ska lösas med hjälp av stegkodsprogrammering. Ta för vana att skriva upp en tabell med vilka register som ni använder och vilka skalfaktorer som de innehåller. Definerar flaggor och register när ni tycker att de saknas. 1.1 Överfyllnadsskydd (fort.) Under laboration 1 införde ni ett överfyllnadsskydd till det skelett som visas i figur??. Detta skydd slog om regulatorn till manuellt läge med styrsignal 0 om nivån i någon av tankarna översteg ungefär 90% av maximal nivå. För att komma ur detta läge måste man sedan manuellt återställa regulatorn tillbaka till automatiskt läge. Detta kan vara ett problem i situationer när processer är oövervakade. Vi vill därför införa någon automatik som återställer regulatorn till automatiskt läge om något villkor är uppfyllt. Komplettera därför den struktur som ni använde under laboration 1 som överfyllnadsskydd med följande: a) om nivån i båda tankar är mindre än 60%, så återställs drift i automatiskt läge. (tänk på att detta inte ska ske om vi är i manuellt läge från början, utan bara när ett överfyllnadslarm verkligen har löst ut). b) om överfyllnadslarmet har löst ut och automatisk drift har återsällts enligt villkoret i föregående uppgift, 5 gånger så ska ingen mer automatisk återställning ske. c) inför begränsningen att dessa 5 gånger måste inträffa inom 2 minuter för att ingen mer automatisk återställning ska ske. Programmet körs i 100 Hz och därmed ska time base vara 0.01 sekunder. 3
4 KAPITEL 1. PLC-PROGRAMMERING II d) slutligen, ersätt de fasta gränserna för skyddet samt återställningen med variabler. Inför två register där man kan ange vilken nivå (i procent av maximal fyllnadsnivå) då de två händelserna ska utföras. Tips: Skalning, registernamn och stegkodsprogrammet till laboration 1, hittar ni i föregående kapitel i tabell?? samt figur??. För c) använd en timer för att återställa räknaren för antal återställningar. 1.2 Automatisk lastning Ett sätt att utföra en operation med visst intervall är att använda en timer. Tänk dig att du har en process där en vagn ska fyllas med järnmalm ur ett lager. En flagga N11:17/0 indikerar att en ny tom vagn inväntar järnmalm. Använd en timer för att ettsätta variabeln N11:17/4 (som styr att bandet som fyller vagnen med järnmalm körs) under exakt 10 sekunder eller tills dess att N14:1/2 (vagnens överfyllnadsskydd) är ettsatt. PLC-programmet körs i 70 Hertz. Skriv ned både psuedokoden samt ett RSLogixschema som löser detta problem. 1.3 Att undvika förgreningar Antag att vi har ett program med tester och förgreningar till ett djup av 3 enligt: N7:0/1 ADD N9:10 N9:11 N9:12 S:5/0 N9:10/15 MOV 32767 N9:12 N9:10/15 MOV -32768 N9:12 S:5/0 U Om man vill ha ett test i koden som kräver att flera villkor är uppfyllda samtidigt kan man seriekoppla testen. Till exempel kommer programmet
1.4. FYLLNADSBEGRÄNSNING 5 N7:0/1 S:5/0 N9:10/15 MOV 32767 N9:12 endast utföra MOV-instruktionen om N7:0/1 är hög, S:5/0 är hög, och N9:10/15 är låg. Antag för övnings skull att förgreningar inte är tillåtna alls. Rita om programmet utan förgreningar! 1.4 Fyllnadsbegränsning Vi har ett system med två likadana tankar. Bordet de står på är feldimensionerat och klarar inte av tyngden om båda tankarna är fyllda, utan riskerar att gå sönder om den totala fyllnadsgraden är större än tyngd motsvarande 1, 4 ggr en fylld tank. Därför vill man larma då de två tankarna tillsammans är fyllda till mer än motsvarande 1, 2 ggr en fylld tank. Nivån för tank 1 lagras i register I:3.0 och nivågivaren ger data i intervallet 0 800. Nivån för tank 2 lagras i register I:3.1 och nivågivaren ger data i intervallet 0 12 000. Ett larm körs då register N10:0 sätts till 1. Det finns även tomma register, N9:0-N9:2. Skriv ett RSLogix-program som larmar då den totala vattenmängden är för stor. (Du behöver inte nollställa larmet.) Tips: Börja med skalning av variabler (här kan t.ex. % vara en lämplig enhet att arbeta i). Skriv sedan upp pseudokod för vad du vill göra och översätt till sist denna till RSLogix-kod. 1.5 Regelbaserad styrning av vattenkokare Vi har en speciell vattenkokare, som kan koka vatten till 70, 80 eller 100 grader. Denna nivå kan man välja med hjälp av en brytare som finns på vattenkokaren. Vi vill nu använda oss av regelbaserad reglering, där man ställer ut en utsignal beroende på regler som beror på insignalen. Lös nu följande uppgifter: a) vad är in- respektive utsignal i detta fall. b) vad är lämpliga regler för styrningen av vårt system? Kom ihåg att vi vill hålla temperaturen kring varje nivå men vi kan tillåta temperaturen att avvika några grader. c) skriv nu ett stegkkodsprogram som ska göra följande: i) ettställer värmaren för alla tre fall när vattnet är för kallt (använd intervallen från b). Börja med att skriva pseudokod om det hjälper dig.
6 KAPITEL 1. PLC-PROGRAMMERING II ii) När man programmerar brukar man vilja återanvända så mycket kod som möjligt. Kan du skriva om programmet på endast en rad? iii) Utöka din stegkodning så att en lampan indikerat om vatten är kallt eller varmt för att man inte ska bränna sig. Lampan ska vara blå när vatten är kallare än 40 grader. När vattnet är varmare ska lampan bli röd. Skriv denna utökning på samma rad som ni hade i föregående uppgift. Vattenkokaren har en temperaturgivare som nås genom registret I:1.0 och är kalibrerad så att 0 betyder 0 grader och 32767 betyder 100 grader. Värmaren nås genom registret O:1.0 och är endast en binär variabel där 0 betyder att värmaren är avstängd och 1 betyder att värmaren är på maximal effekt. Registren O:1.1 och O:1.2 styr den röda respektive blåa lampan på samma sätt som med värmaren. 1.6 Bilsortering Vi har en bilsorterare som kan detektera om bilen är blå, röd eller gul med hjälp av en sensor. För alla tre fall vill vi transportera bilen till ett och samma magasin. Vi vill också räkna hur många blåa, röda och gula bilar som har passerat sensorn. När vi har antingen tre blåa, röda eller gula bilar, vill vi införa ett alarm så att någon transporterar bilar vidare. Dock vill vi inte att larmet ska låta kontinuerligt utan pipa till vart tredje sekund. Personen som kommer för att transportera bilar ska kunna återställa alarmen. Skriv pseudokod och stegkodningen. Du behöver bara fyra rader för att lösa problemet!
Kapitel 2 Överspill 2.1 Addition med binära tal Genomför följande additioner i binära tal. Blir resultatet det förväntade? a) 10 + 12 b) ( 10) + 12 c) 10 + ( 12) d) ( 10) + ( 12) 2.2 Multiplikation med överspill Vi vill nu multiplicera följande tal, vad blir resultatet om har obegränsat med bitar? Vad blir det om vi har tillgång till 6 bitar? Om överspill inträffar antar vi att svaret avrundas till det närmaste tal som kan representeras. a) 5 ( 6) b) 7 7 c) Vad måste vi göra för att få plats med alla bitarna i uppgift b)? 2.3 Skalad addition med överspill Vi vill addera två tal a och b, talet a är lagrat som 5 med en skalfaktor på 1, och talet b är lagrat som 7 med en skalfaktor på 2. För att kunna addera talen måste de ha samma skalfaktor. Det finns (minst) två sätt att göra detta. När kan de olika sätten vara bra att använda? Motivera svaret. 7
8 KAPITEL 2. ÖVERSPILL 2.4 Överspill i P-regulator Vi har nu bestämt oss för att göra en P-regulator, och vill utföra multiplikationen K e. e har skalfaktorn 1 och K har skalfaktorn 16. Vi vill att resultatet ska ha skalfaktorn 1. Vi har inte möjlighet att utföra multiplikationen först och sedan skala ned resultatet, utan måste skala ner antingen e eller K (eller båda två). Vilken eller vilka variabler skulle du skala ner och varför? 2.5 Skalad multiplikation med överspill I Vi vill nu återigen multiplicera a och b. Denna gång är a representerat som 4 och b representerat som 6 där båda har skalfaktor 2. Vi vill att resultatet ska ha skalfaktor 1. Vi har endast tillgång till 6 bitar. Om överspill inträffar, avrunda till närmaste tal som går att representera. Genomför multiplikationen genom att a) Först genomföra multiplikationen a b och sedan skala resultatet så att skalfaktorn är 1. b) Först skala b så att b har skalfaktorn 1 2, och sedan genomföra multiplikationen. Vad blir resultetet? c) Vilken av ordningarna är att föredra? Varför då? 2.6 Skalad multiplikation med överspill II Samma uppgift som i uppgift 2.5, men nu är a = 4 och b = 14. Både a och b har skalfaktor 2. Vi vill att resultatet ska ha skalfaktor 1. Vi har endast tillgång till 6 bitar. Om överspill inträffar, avrunda till närmaste tal som går att representera. Genomför multiplikationen genom att a) Först genomföra multiplikationen a b och sedan skala resultatet så att skalfaktorn är 1. b) Först skala b så att b har skalfaktorn 1 2, och sedan genomföra multiplikationen. Vad blir resultetet? c) Vilken av ordningarna är att föredra? Varför då? 2.7 Överspillshantering i stegkod Efter att ha gjort uppgifterna 2.5 och 2.6, tänk ut ett bra sätt att genomföra multiplikationen a b. Rita gärna ett stegdiagram (ladder diagram) eller skriv pseudokod för hur du tänkt.
2.8. ÖVERSPILL I PID-REGULATORN 9 2.8 Överspill i PID-regulatorn I PID regulatorn har vi tre olika bidrag till styrsignalen: bidragen från den proportionella, integrerande och deriverande återkopplingenn. Alla tre bidrag måste adderas för att vi ska kunna ställa ut en styrsignal till pumpen. Kommer ihåg att additionsblocken kan bara addera två olika värden. Vi måste därför addera två bidrag i en första steg och det tredje bidraget i ett andra steg. a) Ställ upp en pseudokod för detta samt ett stegkodsprogram. b) Låt bidraget från P-delen vara 24000, från I-delen vara 12000 och från D- delen vara 16000. Alla bidrag har skalfaktor 1. Försök nu addera dessa tal i alla möjliga ordningar. Vilka olika svar får vi? Glöm inte att PLC:n har begränsnad precision och maximala värde i PLC:n är 32767! c) Vi kan lösa problemet med överspill för detta fall genom att välja en lämplig ordning vid additionen. Men när talen i de olika delarna förändras, så kan vi råka ut för problem med överspill igen. Hur kan man använda skalning för att lösa detta problem? Lösningen ska inte bli perfekt för det här problemet men ska lösa alla problemen så bra som mögligt.
10 KAPITEL 2. ÖVERSPILL
Del II Lösningar/Svar 11
Kapitel 1 PLC-programmering II 1.1 1.2 1.3 1.4 Vi vill först skala om de två nivåerna med skalfaktorerna 8 resp. 120 för att få båda nivåerna i %. Därefter adderas de (okej eftersom de båda är i %) och den totala volymen beräknas. Om denna är för hög sätts larmregistret. Pseudokod: (:= betyder tilldelas) N9:0 := I:3.0 / 8 [skala om nivå tank 1 till \%] N9:1 := I:3.1 / 120 [skala om nivå tank 2 till \%] N9:2 := N9:0 + N9:1 [total vattenmängd i tankarna i \%] if N9:2 >= 120 [om nivån är för hög] N10:0 := 1 [sätt larmregistret] end if 13
14 KAPITEL 1. PLC-PROGRAMMERING II Figur 1.1: Lösningsförslag till uppgift 1.5 1.5 1.6
Kapitel 2 Överspill 2.1 a) 010110 (22) b) 000010 (2) c) 111110 (-2) d) 101010 (-22) 2.2 a) I båda fallen blir svaret 30 (100010) b) Har vi obegränsat med bitar blir svaret 49, (110001). Har vi endast tillgång till 6 bitar blir svaret 31 (011111). Observera att talet 110001 är lika med 15 eftersom den första biten är en teckenbit. c) Vi måste skala ner någon eller båda av talen. 2.3 Vi måste skala bitarna så de har samma skalfaktor. Vi kan antingen skala upp a eller skala ner b. Att skala ner b leder till minskad precision, men svaret tar upp färre bitar. Att skala upp a leder till bättre precision men riskerar att orsaka överspill. 15
16 KAPITEL 2. ÖVERSPILL 2.4 Förmodligen är det så att skalfaktorn med för K är vald med omsorg för att få mesta möjliga upplösning i K. Isåfall är det bäst att skala ner e eftersom de sista bitarna är de mest brusiga, och informationen som förloras isåfall inte är viktig. 2.5 2.6 2.7 a) Då blir svaret 6. b) Då blir svaret 4. c) Det är bäst att först utföra multiplikationen och sedan skala resultatet eftersom man då inte förlorar någon information. a) I multiplikationen inträffar överspill, och svaret blir därför 7. b) Nu inträffar inget överspill, och restultatet blir 12, vilket inte är det rätta värdet (vilket skulle vara 14), men det är bättre än att först utföra multiplikationen och sedan skala resultatet. c) I detta fallet är det bästa att först skala svaret eftersom om överspill inträffar så förloras mer information. Ett bra sätt att göra det på är att först försöka genomföra multiplikationen a b och undersöka om överspill inträffar. Om överspill inte inträffar skalar man ner resultatet och sparar undan det. I annat fall, dvs om överspill har inträffat skalar man först ner en eller båda variablerna och utför därefter multiplikationen. 2.8
Del III Bilagor 17
Bilaga A Grunderna i stegkodsprogrammering Följande bilaga innehåller grunderna i stegkodsprogrammering i den form som används under kursen. Vi kommer att kort diskutera olika datatyper, villkor, operationer och strukturer som främst används i programvaran RSLogix. En del av det diskuterade materialet är även tillämpligt i andra programmeringsspråk. Vi skiljer på operationer och villkor när vi programmerar. Vanliga villkor kan exempelvis vara IF-satser och matematiska villkor (såsom olikhet, likhet, osv.). Operationer kan vara multiplikation, addition eller manipulation av enskilda bitar. Vi gör även skillnad på register- och bitvisa operationer/villkor. Den första typen förändrar/kontrollerar talet som lagras i hela registret och den andra typen förändrar/kontrollerar bara värdet av en bit 1. Slutligen kan vi placera operationer och villkor i strukturer är att göra mer avancerade program. Vi kommer nu i tur och ordning redogöra för dessa begrepp i mer detalj och även ge exempel på hur de kan användas. A.1 Datatyper och variabler Datatyper kallas de olika typer av data som man kan spara i variabler och liknande. I de flesta programmeringsspråk idag är dessa av typen double vilket är stora flyttal (decimaltal). Inom PLC-programmering är det dock mer vanligt med typen integers (heltal) av en relativt begränsad storlek. Vanligt är att varje integer (i vårt fall) kan innehålla maximalt 16 bitar (varav en teckenbit). En annan typ av data är flaggor eller booleanska variabler, dessa kan antingen vara 0 (falskt) eller 1 (sant). Varje integer kan således innehåller 16 flaggor. 1 Kom ihåg att ett register Nx:y innehåller 16 bitar. Vi når hela registret om vi använder den tidigare hänvisningen och vi kan nå bit z genom att använda oss av adressen: Nx:y/z där z = 0, 1,..., 15 och 15 betecknar registrets teckenbit. 19
20 BILAGA A. GRUNDERNA I STEGKODSPROGRAMMERING Variabler av heltalstyp lagras som ett register under en datafil. En datafil benämner man som Nx där x är något heltal. Ett exempel på detta är det första registret i datafilen N9 som betecknas N9:0. Om vi istället vill använda registret för att lagra flaggor kan vi använda följande beteckning Nx:y/z där y är något register och z är en bit i registret. I N9:0 kan vi därför lagra flaggor med namnen N9:0/0 upp till N9:0/15 (som också är teckenbiten). Egentligen lagras heltalen i varje register som ett binärt tal. Detta innebär att ett 16-bitars heltal egentligen är 16 platser som vardera kan innehålla 0 eller 1. Vi kan därför se ett heltal som 16 lådor där varje låda också kan vara en flagga. Vi kan undersöka innehållet i en låda genom att använda /-operatorn. Om vi använder oss av operationer som påverkar hela registret kommer vi antagligen att påverka alla bitar/lådor som finns på den adressen. Därför kommer vi göra skillnad på register- och bitvisa operationer. Det är även viktigt att endast använda ett register till enbart flaggor (där varje bit/låda representerar en enskild sak) eller för att presentera ett heltal (där alla bitar/lådor används för att representera en sak). A.2 Villkor Vi fortsätter med några speciella villkor som finns att tillämpa i stegkodsprogrammering. Några exempel på dessa villkor finns i tabell A.1 nedan. Det finns två Tabell A.1: Vanliga villkor i stegkodsprogrammering Typ Kod Symbol Förklaring x:x/x Bitvis XIC x:x/x Testa för hög bit XIO Testa för låg bit Registervis EQU Testa = GEQ Testa GRT Testa > LEQ Testa LES Testa < Special TON Timer för nedklockning RES RES Nollställ timer enkla vanliga bitvisa villkor, nämligen testa för hög bit (ettsatt eller sann) och för låg bit (nollsatt eller falsk). Vi får passera genom dessa villkor om registret som villkoret pekar på faktiskt är ettsatt respektive nollsatt. Denna typ av villkor har alltså ett argument, det register som man vill undersöka om det är ettställt eller nollställt. För att använda oss av dessa jämförelser behöver vi bara använda
A.2. VILLKOR 21 respektive grind ur tabell A.1 och byta ut argumentet x:x/x till rätt bitadress. Vi förändrar dessa bitar genom de två operation som diskuteras i det kommande avsnittet om operationer. Stegkodningsspråket som vi kommer att nyttja på kursen innehåller även matematiska villkor. Dessa är exempelvis att testa för likhet och olikhet. I tabellen ser ni några exempel på dessa uttryck som har två argument. Vanligtvis fungerar dessa block att om villkoret A B är uppfyllt får vi passera. kan exempelvis vara likhet (=) eller större än eller lika med ( ). I dessa block skriver vi således in argument på två rader där den första raden är källregister A och den andra är källregister B. Vi har därför två argument i denna typ av villkor. Vi avslutar diskussionen om dessa enklare villkoren med två exempel som visas nedan. I det första exemplet är villkoret att 5000 N9:1 och om detta är uppfyllt får vi passera villkoret. Lägg här märke till att vi kan använda oss av både register och tal i vår jämförelse. 5000 här kan bytas ut till vilket heltal som helst eller ett register, som vi snart kommer att se. I det andra exemplet är villkoret att talen som lagras i register N9:0 och N9:1 ska vara lika. Om talen är lika får vi passera villkoret och då utförs det som står på höger sida av samma rad. Även här är det tillåtet att byta ut ett av registren till ett heltal. Genom att använda förgreningar och placera dessa villkor i rad kan vi vidare skapa de flesta logiska satser. Detta kommer vi att diskutera i ett senare avsnitt. A.2.1 Timers En sista typ av villkor är specialvillkor som bland annat innefattar timer och räknare. Timers byggs upp av ett block som ettsätter en bit när en visst uppräkning är slutförd. Som användare kan man ställa in hur ofta man ska räkna upp räknaren, alltså sätta i = i + 1, och vilket som är målvärdet i end. När man sedan når målvärdet med räknaren, alltså då i = i end ettsätter man biten DN annars (när i i end ) så är istället biten EN ettsatt. Ett timerblock ser i praktiken ut som följer:
22 BILAGA A. GRUNDERNA I STEGKODSPROGRAMMERING TON Timer Time Base Preset Accum Tn:0 t i end i start Tn:0/EN Tn:0/DN där Tn:0 är blockets namn, jämför PID-blocket i laboration 1. Time base indikerar hur lång tid som det ska ta innan man räknar upp variabeln Accum, alltså sätter i = i + 1. Time base beskriver denna tid i sekunder, så om man skriver 0.01 i denna variabel räknar man upp i hundra gånger per sekund, eller i 100 Hz. Preset är målvärdet som man önskar och Accum är det nuvarande värdet på i. Bitarna Tn:0/EN samt Tn:0/DN är ettsatta när vi har inte har nått respektive när vi har nått vårt målvärde. Vi avslutar detta med ett exempel där vi har döpt vår timer till T4:0: TON Timer T4:0 Time Base 0.01 Preset 1000 Accum 0 T4:0/EN T4:0/DN T4:0/DN (stuff) Blah... T4:0/DN T4:0 RES här har vi även lagt till ett villkor som kontrollerar om T4:0/DN är ettsatt. När detta villkor är uppfyllt kommer det som står i rutan stuff att utföras samt så kommer timern att nollställas av RES vilket betyder att Accum nollsätts, alltså i sätts till noll och uppräkningen påbörjas igen. I detta exempel har vi time base 0.01 sekunder (vi kommer alltid att använda denna time base, eftersom att vår PLC arbetar i 100 Hz) och preset är 1000, det kommer således att ta 0, 01 1000 = 10 sekunder innan vi ettsätter T4:0/DN. Därmed kommer vi att göra det som står i stuff -rutan vart tioende sekund. Lägg även märke till att vi kan använda oss av flaggan T4:0/EN för att utföra något annat när vi inte har nått målvärdet. Exempelvis kan detta vara en påfyllnadsprocess där påfyllnad sker sålänge som T4:0/DN är ettsatt och när T4:0/EN ettsätts som byts vagnen som ska fyllas på ut.
A.3. OPERATIONER 23 A.3 Operationer Operationer används för att förändra data som lagras i olika register. Detta kan vara att sätta registret till ett visst värde eller till något matematiskt uttryck som är funktion av andra register. I tabell A.2 presenterar vi några vanliga operationer Tabell A.2: Vanliga operationer stegkodsprogrammering Typ Kod Symbol Förklaring x:x/x Bitvis OTU U x:x/x Nollställa bit OTL L Ettställa bit Registervis MOV Kopiera ADD Addition SUB Subtraktion MUL Multiplikation DIV Division för både bitar och register. Bitvisa operationer har bara ett argument, nämligen den bit som man vill sätta till noll eller till ett. Vill vi således nollsätta biten som vi hittar på adressen S:5/0 (överspillsindikatorn) byter vi ut x:x/x operationen ovan och får följande: Registervisa operationer har två eller tre argument beroende på vilken typ vi använder oss av. Matematiska operationer har ofta tre argument och följer konventionen att A B = C där är exempelvis addition eller multiplikation. Sådana typ av block har alltså tre rader med register, två som kallas källregister (A och B) samt ett målregister C. Ett exempel på detta är: där A =N9:10, B =N9:11 och C =N9:12. På samma sätt kan vi även skapa block för multiplikation, division och subtraktion. MOV-blocket har endast två argument: källa och mål. Det flyttar således det som finns i källregistret till målregistret. Lägg märke till att vi även här kan byta ut ett av registren till något heltal om vi så vill. Detta kommer vi se exempel på i nästa avsnitt där vi behandlar strukturer i stegkodsprogrammering.
24 BILAGA A. GRUNDERNA I STEGKODSPROGRAMMERING A.4 Strukturer Man kan slutligen placera operationer och villkor i strukturer för att skapa avancerade program. Den grundläggande strukuren i stegkodsprogrammering består av olika steg. Varje steg är placerad i en rung eller rad. Ett program exekveras sekvensiellt uppifrån och ned i detta språk. Detta innebär att raderna utförs en och en i den ordning som de står i programmet. Varje rad delas in i en villkors- och operationsdel. Villkor placeras till vänster på raden och operationer till höger. Det är tillåtet att placera flera villkor efter varandra (seriekoppling) men endast en operation tillåts på vardera rad. Ett exempel på en enkel rad med flera villkor är som följer: N7:0/1 S:5/0 N9:10/15 MOV 32767 N9:12 där vi flyttar talet 32767 till registret N9:12 om följande tre villkor är uppfyllda samtidigt: (i) biten N7:0/1 är ettsatt, (ii) biten S:5/0 (överspillsindikatorn) är ettsatt, samt (iii) biten N9:10/15 (teckenbiten) är nollsatt (positivt tal). I detta exempel kontrollerar vi alltså bland annat om vi har ett överspill (vi försöker lagra ett större tal än som får plats i registret) samt om talet är positivt. När detta är uppfyllt skriver vi det största positiva talet vi kan till registret N9:12. Det föregående exemplet var av en struktur med villkor i serie som motsvarar ett logiskt och. Alltså att alla villkor samtidigt måste vara uppfyllda för att något ska hända. En annan vanlig konstruktion är logiskt eller där det räcker med att ett villkor är uppfyllt. Denna typ av struktur motsvarar en parallellkoppling, där man lägger en förgrening så att villkoren ligger över varandra. Ett exempel på detta är: där operationen (som är utelämnad ur figuren) utförs om minst ett av villkoren är uppfyllt, alltså om N9:0 är större än N9:1 eller om N9:2 är större än N9:1. Vi kan även kombinera denna struktur med ett villkor som är kopplat i serie:
A.4. STRUKTURER 25 nu kräver vi även att N9:5/4 är ettsatt för att vi ska multiplicera N9:1 och N9:2 och lagra resultatet i N9:3. På detta sätt kan vi skapa stora komplicerade villkor där vi kombinerar jämförelser med logiskt och samt eller. Tidigare nämnde vi begränsningen med att endast en operation får utföras per rad. Detta är ofta begränsande och skulle leda till att vi måste skapa många rader med samma villkor men olika operationer. Vanligtvis vill vi ha så få rader som möjligt där vi försöker att återanvända (modularisera) så mycket av vår kod som möjligt. Detta brukar man betrakta som god programmeringssed. För att undvika begränsningen kan vi lägga ett antal operationer parallellt med hjälp av en förgrening. Detta leder till strukturer som liknar de som vi introducerade för logiskt eller. Som vanligt beskrivs detta enklast med två exempel. I det första exemplet lägger vi ihop två tal från registren N9:10 och N9:11 samt sparar resultatet i N9:12. Samtidigt så nollsätter vi biten S5:/0 som indikerar överspill (den ettsätts då vi försöker lagra ett större tal än möjligt i ett register). ADD N9:10 N9:11 N9:12 S:5/0 U Det andra exemplet är en multiplikation och omskalning av svaret. Vi kommer först att utföra divisionen och sedan multiplikationen. Kom ihåg att vi läser programmet uppifrån och ned. Först skalar (dividerar) vi om registret N10:13 med 128 och sparar resultatet i N10:14. Sedan utför vi multiplikationen mellan talen i registren N10:14 och N10:2 och lagrar detta i registret N10:14.
26 BILAGA A. GRUNDERNA I STEGKODSPROGRAMMERING DIV N10:13 128 N10:14 MUL N10:14 N10:2 N10:14 Här ser vi ett exempel på att vi återanvänder ett register. Först läser vi ett tal från ett register genomför någon matematisk operation och slutligen skriver det till samma register. Detta är en tillåten operation och det enda vi behöver tänka på är i vilken ordning saker utförs: läsa register, utföra beräkning, skriva till register. Vi ser också att det är det skalade talet som vi utför multiplikationen med, vi kan därför göra matematiska operationer i sekvens genom att bygga parallella strukturer. Slutligen borde vi även nämna att man kan skapa nestlade strukturer som är mer avancerade än de som vi har gjort här. I sådana strukturer kan man ha parallella rader (fortfarande som tillhör samma huvudrad) där men både utför operationer och villkor. Detta kommer dock att vara utanför denna kurs och är därmed inte intressanta för våra syften. A.5 Praktisk programmering Vi avslutar detta dokument men en kort diskussion om hur man praktiskt går tillväga för att programmera ett program. Vi passar även på att nämna några saker som kan vara bra att komma ihåg och hur man skriver ett snyggt program. Som med de flesta saker blir man enbart duktig på programmering om man övar på att att skriva program. Programmering är till lika stor del en praktisk kunskap som en teoretisk. I princip har vi beskrivit all teori som krävs i detta kapitel för att skapa relativt komplicerade program. Det som inte har diskuterats är implementering, felsökning och andra praktiska aspekter. Dessa lär man sig bäst när man sitter vid datorn och provar själv. Ett bra sätt att strukturera sin programmering är att utgå från problemet och bryta ned det i delproblem. Sedan löser man varje delproblem för sig för att sedan plocka samman allt till en lösning av det ursprungliga problemet. För att underlätta detta är det bäst att börja med att skriva en pseudokod där man med enbart ord skriver ned vad som ska hända. Här identifierar man även de olika delar som programmet och problemet består av. Sedan försöker man hitta lösningar till vardera delproblem. Detta innebär att svara på frågor som vart man hittar den informationen man behöver, vilka villkor
A.5. PRAKTISK PROGRAMMERING 27 och vilka operationer som är nödvändiga. Tillslut bygger man upp en struktur som löser det problem man är ute efter. När man sedan har tänkt genom detta försöker man hitta grupper av villkor och operationer som återkommer. Detta kallas att modularisera sin kod och då försöker man återanvända så mycket av den som möjligt. Ska man exempelvis utföra samma beräkning på ett antal rader kanske man istället kan kombinera villkoren i en parallell struktur så att man kan slå ihop flera rungs till en. Detta kan även innebära att man skapar subrutiner där man genomför delberäkningar. Slutligen ska man alltid kommentera sin kod, både för sin egen del och för andras. Ute i industrin arbetar man ofta flera stycken med samma program och då behöver man beskriva vad man har gjort. Ni kanske även måste gå tillbaka i kod som ni skrev för flera år sedan. Att man då har kommenterat kort vad varje grupp av rader gör, kan spara mycket tid och möda. Tillsammans med detta tillhör även att döpa variabler till vettiga saker, detta hjälper både i felsökning och i dokumentation.