Uppbyggnad av kod, Arduino

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46930
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Uppbyggnad av kod, Arduino

Inlägg av TomasL »

Tänk i sekvens, först så händer sak 1, sedan 2 osv.
kodar-holger
EF Sponsor
Inlägg: 970
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: Uppbyggnad av kod, Arduino

Inlägg av kodar-holger »

Inser att jag bröt mot forumetisk regel nummer 1a i mitt förra inlägg. Jag hade inte läst TS tidigare inlägg ordentligt.

I morgon (senare idag) skall jag åka en massa tåg. Då skall jag fundera på hur jag skulle lägga upp detta. Att göra en tillståndsmaskin som sköter upp och en annan ner är förmodligen inte mitt sätt att lösa det. Inte heller att ha en som gör allt. Ber att få återkomma sent i morgon om jag kommer på något smart.

Tillståndsmaskiner behöver för övrigt inte implementeras med switch även om det är väldigt vanligt och kan ge översiktlig kod. Ett annat sätt är med arrayer. D.v.s du gör en konstant 2-dimensionell array med tillstånd/händelse som index och nytt tillstånd som output. Och sen något som tar hand om vad som händer vid tillståndsbygen. Det som jag tycker är lättast att jobba med är s.k moore-maskiner där något händer när man går in i ett nytt tillstånd.

I en så här "långsam" process är array-hanteringen kanske mest bara krångligt. I ett system med hårda prestandakrav kan det ge fördelar som konstant uppslagstid medan en switch-sats tar olika lång tid beroende på hur case satserna är ordnade och hur kompilatorn lägger upp det. Garanterat överkurs på det.
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Uppbyggnad av kod, Arduino

Inlägg av SeniorLemuren »

ludde_018 skrev:Låter intressant :)
Men hur ska jag kunna läsa av 7 lägesgivare/strömbrytare på en port?
Sodjan gav ju ett enkelt exempel på hur man kan avläsa olika kombinationer av de olika ingångarnas status, men det du skriver ger ju intrycket av att du tror att en port är detsamma som en ingång (pinne) på µC. Så är det inte.

En port på den µC du använder består av åtta pinnar, t.ex A0, A1,...A7. Du kan alltså läsa av 8 ingångar på en port. Du får då ett binärt tal från den porten där du kan läsa vilka pinnar som är höga resp. låga.

Om du t.ex. läser det binära talet 11000001 från porten så betyder det att pinne 0,6,7 är höga och de andra är låga. Det ger decimala heltalet = 193. Du kan sedan jämföra detta tal med det tal som skall ge sant eller falskt.
Användarvisningsbild
Jan Almqvist
Inlägg: 1652
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: Uppbyggnad av kod, Arduino

Inlägg av Jan Almqvist »

Om man ska styra utgångar så blir det snart obegriplig kod om man använder if () och switch ().

Jag tycker att det är bättre att, så långt det möjligt, istället göra konstruktioner som ser ut ungefär så här:

Utgång = Logiskt_villkor;

Logiskt_villkor byggs upp med logiska operationer dvs and, or, not etc.

Utgången bör sättas på ett (1) enda ställe.
ludde_018
Inlägg: 50
Blev medlem: 27 juni 2011, 20:41:09

Re: Uppbyggnad av kod, Arduino

Inlägg av ludde_018 »

Det här blev ju riktigt trevligt! Vad mycket svar jag får :)

Både intressant och kul att läsa förslag plus att man får en hel del nytt att lära sig :)

Kodarholger, låter riktigt kul :) Ser fram emot och se ett förslag, och gärna vad som gör det bättre att använda än det jag beskrivit.

Senior Lemuren, helt sant! Jag trodde port och pinne var samma sak. Hade ingen koll alls att det funkade så. Där hade man kunnat krymt och effektiviserat koden en hel del. Frågan är, finns det nackdelar att som jag har gjort att läsa från flera pinnar på olika portar?

Jan almqvist, har inte riktigt hamnat i det tänket ännu. Men ska klura vidare på det med sektioner av funktioner. Funkar ditt förslag när man tex ska använda en funktion till olika åtgärder? Har tex en hydralpump som både öppnar/stänger bakluckan samt öppnar/stänger taket. Höger/vänstervarv på den plus kombination med styrventiler på hydralsidan avgör funktionen från pumpen..


Och till Er som kan mer än mig, förslaget jag angivit.. Finns det funktionella nackdelar med det som äventyrar driftsäkerheten eller funktionen inte blir korrekt? Fick vid ett test motorn att pulsera istället för att gå jämnt som jag önskat.. Om det har med koden eller något annat att göra?

Vill tacka ännu en gång för alla olika lösningar, man märker att det finns massor av sätt att lösa ett problem på. Gäller att lära sig för och nackdelarna :)
Användarvisningsbild
Jan Almqvist
Inlägg: 1652
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: Uppbyggnad av kod, Arduino

Inlägg av Jan Almqvist »

Jo, det fungerar även när man ska en funktion till olika åtgärder.
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Uppbyggnad av kod, Arduino

Inlägg av SeniorLemuren »

ludde_018 skrev: Senior Lemuren, helt sant! Jag trodde port och pinne var samma sak. Hade ingen koll alls att det funkade så. Där hade man kunnat krymt och effektiviserat koden en hel del. Frågan är, finns det nackdelar att som jag har gjort att läsa från flera pinnar på olika portar?
Kan du använda en port till alla ingångar så är det ju lättare att ta hand om resultatet. Du får läsa på om AND, OR, XOR det är dessa du använder för att manipulera de binära värden du får in på porten. Det går givetvis att använda fler än en port, men har du inte mer än 8 givare och en ledig hel port så är det ju enklare.
slo
Inlägg: 103
Blev medlem: 7 januari 2009, 10:57:35
Ort: Åbo, Finland
Kontakt:

Re: Uppbyggnad av kod, Arduino

Inlägg av slo »

Jag skulle #define ingångarna enligt vilken bit i Porten de är anslutna till, läsa in hela porten till en variabel och köra switch på den.

Kod: Markera allt

#define TAK_UPPE 		(1<<0)
#define TAK_NERE 		(1<<1)
#define BAKLUCKA_UPPE 	(1<<2)
#define BAKLUCKA_NERE	(1<<3)
#define CABLUCKA_UTE 	(1<<4)
#define CABLUCKA_INNE	(1<<5)

switch(portData){
		case TAK_UPPE|BAKLUCKA_NERE|CABLUCKA_INNE:
			//unlockMotor();
			printf("Unlock motor\n");
			break;
		case TAK_UPPE|CABLUCKA_INNE:
			printf("Hydraul Motor|Ventil + Motor\n");
			break;
		case TAK_UPPE|BAKLUCKA_UPPE|CABLUCKA_INNE:
			printf("Cabluckemotor\n");
			break;
		default:
			printf("Default, disable everything\n");
			break;
	}	
Exempel som går att testa på PC, https://pastie.se/80f01399
ludde_018
Inlägg: 50
Blev medlem: 27 juni 2011, 20:41:09

Re: Uppbyggnad av kod, Arduino

Inlägg av ludde_018 »

Stort tack ännu en gång för all hjälp :)


Summerar man förslagen så känns det som om dom flesta av er här inne skulle samla ingångarna under samma port. Har ännu inte hunnit läsa på och göra då jag haft en hel del på jobbet.

Efter det så finns det lite olika varianter som jag ska ta mig tid att lära, känns som att det är ett bra projekt att träna grunderna i.

:)
ludde_018
Inlägg: 50
Blev medlem: 27 juni 2011, 20:41:09

Re: Uppbyggnad av kod, Arduino

Inlägg av ludde_018 »

Just det, skulle behöva flytta bilen snarast och då cabben står fast i olämpligt läge tänkte jag vara fräck nog att fråga om någon har lust att skumma igenom koden jag har idag. För att se vad som gör att det inte funkar.

Anledningen som sagt är att jag inte kommer hinna lära och skriva helt nytt innan jag bör flytta bilen hem till mig..

Tack och bock :)

Kod: Markera allt

int RemoteActiv = 13;
int RemoteOpen = 12;    
int RemoteClose = 11;
int RemoteA =  10;
int RemoteB =  9;
int Bryt1 =  31;
int Bryt2 =  32;
int Bryt3 =  3;
int Bryt4 =  4;
int Bryt5 =  35;
int Bryt6 =  36;
int Bryt7 =  37;
int ledPin =  53;
int hydralG= 38;   ///1
int hydralR = 39;  ///2
int cabluckaU = 40;  ///3
int cabluckaI = 41;   ///4
int LockL = 43;    ///5
int LockO = 42;     ///6
int Solinod_fram_AKTIV = 45;
int Solinod_Bak_AKTIV = 45;

void setup() {
  pinMode(RemoteActiv, OUTPUT);
  pinMode(RemoteOpen, INPUT);
  pinMode(RemoteClose, INPUT);
  pinMode(RemoteA, INPUT);
  pinMode(RemoteB, INPUT);
  pinMode(Bryt1, INPUT);
  pinMode(Bryt2, INPUT);
  pinMode(3,INPUT_PULLUP);
  pinMode(4,INPUT_PULLUP);  
  pinMode(Bryt5, INPUT);
  pinMode(Bryt6, INPUT);
  pinMode(Bryt7, INPUT);
  pinMode(RemoteOpen, INPUT);
  pinMode(RemoteOpen, INPUT);
  pinMode(RemoteOpen, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(hydralG, OUTPUT);
  pinMode(hydralR, OUTPUT);
  pinMode(cabluckaU, OUTPUT);
  pinMode(cabluckaI, OUTPUT);
  pinMode(LockL, OUTPUT);
  pinMode(LockO, OUTPUT);
  pinMode(Solinod_fram_AKTIV, OUTPUT);
  pinMode(Solinod_Bak_AKTIV, OUTPUT);
  
  Serial.begin(9600);
  Serial.print("STARTAT");
  digitalWrite(RemoteActiv, HIGH); // Aktiverar +5 volt till fjärr mottagare 
  }

void loop() {
  
 int RemoteOpenState = digitalRead(RemoteOpen);
 int RemoteCloseState = digitalRead(RemoteClose);
 int RemoteAState = digitalRead(RemoteA);
 int RemoteBState = digitalRead(RemoteB);
 int Cab_Lucka_Ute = digitalRead(3);                 //Brytare märkt 3, ingång 3
 int Cab_Lucka_Inne = digitalRead(Bryt2);            //Brytare märkt 32, ingång 32
 int Baklucka_Uppe = digitalRead(4);                 // Brytare märkt 4, ingång 4 
 int Baklucka_Lockt = digitalRead(Bryt5);            //Brytare märkt 35, ingång 35
 int Tak_Uppe = digitalRead(Bryt6);                  //36
 int Tak_Nere = digitalRead(Bryt7);                  //37

  
////------------------------------------------------------------------------------------------------------------------------------------------------------------
///// START CABBA NER
////------------------------------------------------------------------------------------------------------------------------------------------------------------


  
   if  (RemoteOpenState == HIGH)
   
   {
    if (Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == LOW && Baklucka_Lockt == HIGH && Tak_Uppe == HIGH && Tak_Nere == LOW)
   {
     digitalWrite(LockO, HIGH); 
     delay(10); 
     Serial.println("1");
    }
else
    {
  digitalWrite(LockO, LOW);
    }
    //// Ovan, bilens tak är på och sekvensen börjar när fjärren används. Enbart upplåsningsmotorerna går tills dess att "Baklucka_Lockt" Är LOW.
    //// efter det så aktiveras nedan öppning av bagagelucka
    
    
    if (Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == LOW && Baklucka_Lockt == LOW && Tak_Uppe == HIGH && Tak_Nere == LOW)
    {
      digitalWrite(LockO, HIGH);
      digitalWrite(hydralG, HIGH);
      digitalWrite(Solinod_Bak_AKTIV, HIGH);
      delay(10);
      Serial.println("2");
      }
      else
      {
      digitalWrite(LockO, LOW);
      digitalWrite(hydralG, LOW);
      digitalWrite(Solinod_Bak_AKTIV, LOW);
      
      }
      /// Ovan, bilens baklucka öppnas genom att aktivera hyralG samt Solinod BAK. För säkerhetsskull går låsO aktiv.
      /// Detta görs fram tills bakluckan ställer sig fullt öppet läge som nedan..
      
      if (Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == HIGH && Tak_Nere == LOW)
      {
      digitalWrite(cabluckaU, HIGH);
      delay(10);
      Serial.println("4");
      }
      else
      {
        digitalWrite(cabluckaU, LOW);
      }
       //// Ovan, cabluckan börjar fällas ut när backluckan är fullt öppen (BLÅ/VIT) kabel    
      
       if (Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == LOW && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == HIGH && Tak_Nere == LOW)
      {
      digitalWrite(cabluckaU, HIGH);
      delay(10);
      Serial.println("5");
      }
      else
      {
        digitalWrite(cabluckaU, LOW); 
        }
        /// Ovan gör att cabluckan fortsätter att öppna fast kontakt med "Cablucka inne" bryts..
        
        if (Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == HIGH && Tak_Nere == LOW)
        {
          digitalWrite(hydralR, HIGH);
          digitalWrite(Solinod_fram_AKTIV, HIGH);
          delay(10);
          Serial.println("6");
          
          }
          else
          {
          digitalWrite(hydralR, LOW);
          digitalWrite(Solinod_fram_AKTIV, LOW);
          }
          ////Ovan, cabluckan har nu nått sitt ändläge  börjar sänka ner taket..
           if (Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == LOW)
        {
          digitalWrite(hydralR, HIGH);
          digitalWrite(Solinod_fram_AKTIV, HIGH);
          delay(10);
          Serial.println("7");
          
          }
          else
          {
          digitalWrite(hydralR, LOW);
          digitalWrite(Solinod_fram_AKTIV, LOW);
          }
          /// Ovan fortsätter sänka taket trots brytare tak_uppe blir låg. Fortsätter tills det har aktiverat brytaren för tak nere, nedan:
          if (Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == HIGH)
          {
            digitalWrite(Solinod_Bak_AKTIV, HIGH);
            digitalWrite(hydralR, HIGH);
            digitalWrite(LockL, HIGH);
            delay(10);
            Serial.println("8");
            }
            else
            {
            digitalWrite(Solinod_Bak_AKTIV, LOW);
            digitalWrite(hydralR, LOW);
            digitalWrite(LockL, LOW);
            }
            ///Ovan börjar sänka backluckan igen..
            if (Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == LOW && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == HIGH)
          {
            digitalWrite(Solinod_Bak_AKTIV, HIGH);
            digitalWrite(hydralR, HIGH);
            digitalWrite(LockL, HIGH);
            delay(10);
            Serial.println("9");
            }
            else
            {
            digitalWrite(Solinod_Bak_AKTIV, LOW);
            digitalWrite(hydralR, LOW);
            digitalWrite(LockL, LOW);
            }
            
            if (Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == LOW && Baklucka_Lockt == HIGH && Tak_Uppe == LOW && Tak_Nere == HIGH)
            {
  
             digitalWrite(hydralR, LOW);
             Serial.println("10");
             digitalWrite(LockL, LOW);
             digitalWrite(Solinod_Bak_AKTIV, LOW);
             Serial.println("10");

             }        
 
  
///////////////////////////////////////////////////Stänga taket//////////////////////////////////////////////////////////////////
  if(RemoteCloseState == HIGH)
  
  
  
  
    {
    if(Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == LOW && Baklucka_Lockt == HIGH && Tak_Uppe == LOW && Tak_Nere == HIGH)
    {
     digitalWrite(LockO, HIGH); 
     delay(10); 
     Serial.println("11");
    }
    else
    {
    digitalWrite(LockO, LOW);
    }
  
  /// Ovan, börjar med taket nedfällt, LockO körs tills Baklucka_Lockt blir låg, då startar uppfällningen av bakluckan..
  if(Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == LOW && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == HIGH)
    {
      digitalWrite(LockO, HIGH);
      digitalWrite(hydralG, HIGH);
      digitalWrite(Solinod_Bak_AKTIV, HIGH);
      delay(10);
      Serial.println("12");
      }
      else
      {
      digitalWrite(LockO, LOW);
      digitalWrite(hydralG, LOW);
      digitalWrite(Solinod_Bak_AKTIV, LOW);
      }
      
   /// Ovan, Uppfällning av baklucka börjar...
      if(Cab_Lucka_Ute == HIGH && Cab_Lucka_Inne == LOW && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == HIGH)
      {
      digitalWrite(cabluckaI, HIGH);
      delay(10);
      Serial.println("13");
      }
      else
      {
       digitalWrite(cabluckaI, LOW);
      }
        
    /// Ovan, Bakluckan når sitt ändläge vilket börjar fälla in cabluckan.. 
        if(Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == LOW && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == HIGH)
      {
      digitalWrite(cabluckaI, HIGH);
      delay(10);
      Serial.println("14");
      }
      else
      {
        digitalWrite(cabluckaI, LOW);
        
      }
        
     /// Ovan, fortsätter fälla cabluckan fast cab_lucka_ute blir LOW
       
        
        if(Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == HIGH)
        {
        
        
          digitalWrite(hydralG, HIGH);
          digitalWrite(Solinod_fram_AKTIV, HIGH);
          delay(10);
          Serial.println("15");
          
          }
          else
          {
          digitalWrite(hydralG, LOW);
          digitalWrite(Solinod_fram_AKTIV, LOW);
          }
          
      /// Ovan, när cabluckan nått ändläge börjar taket fällas ut..
           if(Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == LOW && Tak_Nere == LOW)
           {
        
        
          digitalWrite(hydralG, HIGH);
          digitalWrite(Solinod_fram_AKTIV, HIGH);
          delay(10);
          Serial.println("17");
          
          }
          else
          {
          digitalWrite(hydralG, LOW);
          digitalWrite(Solinod_fram_AKTIV, LOW);
          }
      /// OVAN FORTSÄTTER FÄLLER UPP TAKET
          
          
          if(Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == HIGH && Baklucka_Lockt == LOW && Tak_Uppe == HIGH && Tak_Nere == LOW)
          
            {
            digitalWrite(Solinod_Bak_AKTIV, HIGH);
            digitalWrite(hydralR, HIGH);
            digitalWrite(LockL, HIGH);
            delay(10);
            Serial.println("18");
            }
            else
            {
            digitalWrite(Solinod_Bak_AKTIV, LOW);
            digitalWrite(hydralR, LOW);
            digitalWrite(LockL, LOW);
            }
            
        /// Ovan, taket är helt uppfällt och bakluckan börjar sänkas..
             if(Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == LOW && Baklucka_Lockt == LOW && Tak_Uppe == HIGH && Tak_Nere == LOW)
          
            {
            digitalWrite(Solinod_Bak_AKTIV, HIGH);
            digitalWrite(hydralR, HIGH);
            digitalWrite(LockL, HIGH);
            delay(10);
            Serial.println("19");
            }
            else
            {
            digitalWrite(Solinod_Bak_AKTIV, LOW);
            digitalWrite(hydralR, LOW);
            digitalWrite(LockL, LOW);
            }
            
         /// Fortsätter sänka bakluckan då Baklucka_upp blir LOW
            if(Cab_Lucka_Ute == LOW && Cab_Lucka_Inne == HIGH && Baklucka_Uppe == LOW && Baklucka_Lockt == HIGH && Tak_Uppe == HIGH && Tak_Nere == LOW)
            {
            digitalWrite(Solinod_Bak_AKTIV, LOW);
            digitalWrite(hydralR, LOW);
            digitalWrite(LockL, LOW);
            }
            
            

  
 
 

}
}
}
Användarvisningsbild
Bosen
Inlägg: 1753
Blev medlem: 18 juli 2005, 10:56:31
Ort: Karl Gustav, Varberg
Kontakt:

Re: Uppbyggnad av kod, Arduino

Inlägg av Bosen »

Hej ludde_018,

Roligt projekt. Jag ser att du har fått en massa bra svar. Jag skulle också försökt läsa hela porten och göra en switch case på den.
slo skrev:Jag skulle #define ingångarna enligt vilken bit i Porten de är anslutna till, läsa in hela porten till en variabel och köra switch på den.

Kod: Markera allt

#define TAK_UPPE 		(1<<0)
#define TAK_NERE 		(1<<1)
#define BAKLUCKA_UPPE 	(1<<2)
#define BAKLUCKA_NERE	(1<<3)
#define CABLUCKA_UTE 	(1<<4)
#define CABLUCKA_INNE	(1<<5)

switch(portData){
		case TAK_UPPE|BAKLUCKA_NERE|CABLUCKA_INNE:
			//unlockMotor();
			printf("Unlock motor\n");
			break;
		case TAK_UPPE|CABLUCKA_INNE:
			printf("Hydraul Motor|Ventil + Motor\n");
			break;
		case TAK_UPPE|BAKLUCKA_UPPE|CABLUCKA_INNE:
			printf("Cabluckemotor\n");
			break;
		default:
			printf("Default, disable everything\n");
			break;
	}	
Denna idé är väldigt bra, och otroligt enkel att hålla koll på i koden. I min kod till min automatlådestyrning läser jag en port för att hålla koll på mina range-switchar i växellådan och det fungerar väldigt bra, men jag skall ta och implementera en #define på ingångarna som slo föreslår, mest för att lätt hålla koll på koden.
Info om hur du läser en port hittar du här: http://www.arduino.cc/en/Reference/PortManipulation.

Jag kan ju inte låta bli att bli nyfiken på vad det är för bil.... är det en Lincoln månne? ;)
Användarvisningsbild
SeniorLemuren
Inlägg: 8407
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Uppbyggnad av kod, Arduino

Inlägg av SeniorLemuren »

Ja. Det där funkar ju bra. Men om det inträffar att 2 eller fler villkor skall vara uppfyllda från samma port, samtidigt för att man skall gå till en viss åtgärd i visst skede, då kan man även använda AND, OR eller XOR stället, beroende på vad man vill titta på för invärden.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Uppbyggnad av kod, Arduino

Inlägg av Swech »

Ett bättre sätt att bygga upp denna typ av program är att försöka separera hårdvaran
från mjukvaran så långt som det är möjligt.
Att försöka gruppera ingångar till en och samma port betyder att man inte insett detta.

Du gör en subrutin som tar dina hårdvaruingångar från olika pinnar / portar och slår ihop
allt till en ny, egen mjukvaruvariabel. Denna variabel bygger du upp så att
givare x är på bit 0, givare y på bit 1 ... osv....
Dina övriga rutiner arbetar då endast mot mjukvaruvariabeln.

Subrutinen som skapar mjukvaruvariabeln är ensam om att veta hur hårdvaran ser ut
så om du flyttar givare x till en annan pinne / port så behöver du bara ändra på 1 ställe i programmet
Övrig logik behöver inte ändras.

Samma sak med utgångar, i ditt fall motorer. Styr dessa via en mjukvaruvariabel och ha en
enda rutin som omvandlar mjukvaruvariabeln till rena hårdvarukommando.

Swech
Nerre
Inlägg: 27188
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Uppbyggnad av kod, Arduino

Inlägg av Nerre »

För att förtydliga SeniorLemurens inlägg.

Med AND så kan man "maska bort" ointressanta bitar (eller nollställa utpekade bitar)
Med OR så kan man ettställa utpekade bitar
Med XOR så kan man växla utpekade bitar.

Det förutsätter dock att man har koll på binära tal.

Vi kan ta exempel med 3 bitar.

110 AND 010 blir 010 (3 AND 2 blir 2)
111 AND 010 blir 010 (7 and 2 blir 2)
100 AND 010 blir 000 (4 and 2 blir 0)
001 AND 010 blir 000 (1 and 2 blir 0)

vi "tittar" alltså bara på mittenbiten där, genom att jämföra resultatet med 2 (010) eller 0 så kan vi se om den biten är hög eller låg.

Vill vi nollställa mittenbiten så gör vi AND med 101 istället (OBS! 101 är samma sak som NOT 010)

110 AND 101 blir 100 (6 and 5 blir 4)
111 AND 101 blir 101 (7 and 5 blir 5)

Vill vi ettställa mittenbiten gör vi OR med 010

100 OR 010 blir 110 (4 OR 2 blir 6)
000 OR 010 blir 010 (0 OR 2 blir 2)
001 OR 010 blir 011 (1 OR 2 blir 3)

OR ser ut som en addering här men det är bara för att det är bit som var noll som vi OR:ar med, 110 OR 010 blir bara 110 (6 OR 2 blir 6)

Med XOR växlar vi en bit

001 XOR 001 blir 000 (1 XOR 1 blir 0)
001 XOR 010 blir 011 (1 XOR 2 blir 3)
001 XOR 100 blir 101 (1 XOR 4 blir 5)

Nu kan vi då använde det så här:

Vi definierar en konstant till vår port, ex. vi bestämmer att door=0x010 och att 1 där betyder stängd dörr.

Ingångarna kallar vi inputs, det är nu tre bitar i exemplet.

För att kolla om dörren är öppen gör vi

if((inputs & door)>0) { /*The door is open */

vi kan också göra

if((inputs & door) = door) { /*The door is closed */

Om vi sen har outputs och konstanten lock=0x100 så kan vi aktivera låset (aktivt hög) med

outputs = outputs | lock;

eller mer lättläst

outputs |= lock;


(Med reservation för att min C är väldigt ringrostig.)
extradrajven
Inlägg: 18
Blev medlem: 1 juni 2013, 18:07:48

Re: Uppbyggnad av kod, Arduino

Inlägg av extradrajven »

ludde_018 skrev:Just det, skulle behöva flytta bilen snarast och då cabben står fast i olämpligt läge tänkte jag vara fräck nog att fråga om någon har lust att skumma igenom koden jag har idag. För att se vad som gör att det inte funkar.

Anledningen som sagt är att jag inte kommer hinna lära och skriva helt nytt innan jag bör flytta bilen hem till mig..

Tack och bock :)

Kod: Markera allt

...
Hej.

Programmet du skrivit är inte en tillståndsmaskin eftersom inget tillstånd hålls. Det är snarare en rent kombinatorisk transformation av ingångarnas värden till utgångarnas värden. En tillståndsmaskin lagrar definitionsmässigt någonting (tillståndet). I det här fallet är det ju i princip bilen som är minnet. :)

Swech har skrivit det bästa inlägget hittils i den här tråden: abstrahera bort hårdvaran från kodlogiken.

Exempel.

Kod: Markera allt

struct car_input {
 int RemoteOpenState;
 int RemoteCloseState;
 int RemoteAState;
 int RemoteBState;
 int Cab_Lucka_Ute;
 int Cab_Lucka_Inne;
 int Baklucka_Uppe;
 int Baklucka_Lockt;
 int Tak_Uppe;
 int Tak_Nere;
};

struct car_output {
  int hydralG;
  int hydralR;
  int cabluckaU;
  int cabluckaI;
  int LockL;
  int LockO;
  int Solinod_fram_AKTIV;
  int Solinod_Bak_AKTIV;
};

void getinputs(struct car_input *in)
{
/* I den här funktionen fyller du i alla fälten i variabeln "in". Se till att varje fält har antingen värdet 0 eller 1. */
  in->RemoteOpenState = digitalRead(BLA, BLABLABLA);
  in->RemoteCloseState = digitalRead(BLA, BLABLABLA);
  etc...
}

void setoutputs(struct car_output *out)
{
  /* Alla fält i structen out har antingen värdet 0 eller 1. */
  digitalWrite(PORTID, out->hydralG);
  etc...  
}

int main(void)
{
  struct car_input input;
  struct car_output output;

  while(1) {
    getinputs(&input);
    transform(&input, &output);
    setoutputs(&output);
    delay(10);
  }
}

void transform(struct car_input *in, struct car_output *out)
{
/* Den här funktionen uppdaterar variabeln out, givet innehållet i variabeln in.
Om möjligt, försök att beskriva transformationen i tabellform och inte en
massa if-satser (jobbigt att underhålla). */

/*
Troligtvis kan man identifiera ett dussin tillstånd hos bilen eller delar av den.
*/
enum {
  TAK_UPPE,
  TAKE_RÖRSIG,
  TAK_NERE
};

enum {
  LUCKA_ÖPPEN,
  LUCKA_STÄNGD
};

  int takstate;
  int luckstate;

  if (in->a & in->c) {
    takstate = TAK_UPPE;
  } else if (in->d) {
    takstate = TAK_RÖRSIG;
  } else {
    takstate = TAK_NERE;
  }

/* Och samma för luckstate. Sedan kan man använda takstate och luckstate för att bestämma utgångarna (out).
Observera att detta förfarande innebär ännu en abstraktionsnivå. Dvs vi jobbar inte med givarnas värde längre. */

/* Givet takstate och luckstate sätter vi nu fälten i out-structen. */
}
Med stor reservation för att jag inte alls förstår hur man manövrerar en cab. :-)
Skriv svar