Hantering av funktioner i Arduino IDE

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Icecap
Inlägg: 26147
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Hantering av funktioner i Arduino IDE

Inlägg av Icecap »

Albireo: du borde lära dig hur man skriver program först och främst.
Du har fått svaren ett antal gångar men jag ska göra det enklare för dig:

Kod: Markera allt

void defChar() {
  /* -----( Save åäöÅÄÖ on the LED-display )----- */
  byte AwithRing[8] = {  //å
    B00100,
    B01010,
    B01110,
    B00001,
    B01111,
    B10001,
    B01111,
  };
 
  byte AwithDots[8] = {  //ä
    B01010,
    B00000,
    B01110,
    B00001,
    B01111,
    B10001,
    B01111,
  };
   
  byte OwithDots[8] = {  //ö
    B01010,
    B00000,
    B01110,
    B10001,
    B10001,
    B10001,
    B01110,
  };
 
  byte BigAwithRing[8] = {  //Å
    0b00100,
    0b01010,
    0b01110,
    0b10001,
    0b11111,
    0b10001,
    0b10001,
    0b00000
  };
 
  byte BigAwithDots[8] = {  //Ä
    0b01010,
    0b00000,
    0b01110,
    0b10001,
    0b11111,
    0b10001,
    0b10001,
    0b00000
  };
 
  byte BigOwithDots[8] = {  //Ö
    0b01010,
    0b01110,
    0b10001,
    0b10001,
    0b10001,
    0b10001,
    0b01110,
    0b00000
  };

  lcd.createChar(1, AwithRing);     //å
  lcd.createChar(2, AwithDots);     //ä
  lcd.createChar(3, OwithDots);     //ö
  lcd.createChar(4, BigAwithRing);  //Å
  lcd.createChar(5, BigAwithDots);  //Ä
  lcd.createChar(6, BigOwithDots);  //Ö
  lcd.backlight();      // turn on backlight.
När du kör initieringskoden lägger du till:
defChar();

Du tar såklart bort de andra lcd.createChar() i resten av källkoden.

Vid att deklarera karaktärdatan INUTI en rutin FINNS DE BARA I DEN RUTIN!
Alltså MÅSTE du använda dom därifrån också.

Såklart finns de i resten av programmet då de ju skrivs in i programminnet - men lokala variabler/konstanter är inte globala.
Du kan alltså inte deklarera dom inuti en funktion och komma åt dom när programmet INTE är i den rutin.

Och det är "korrekt" att skapa en rutin för detta och sedan anropa den.

Man kan såklart deklarera de data globalt och komma åt dom globalt men rent faktisk är det ett dåligt sätt om det inte är data som är grundläggande för programmet och som använd av snart sagt alla rutiner.
Albireo
Inlägg: 73
Blev medlem: 30 november 2019, 00:29:39

Re: Hantering av funktioner i Arduino IDE

Inlägg av Albireo »

Tack för Ert tålamod. Ska försöka svara så gott jag kan.

I början av tråden finns en kod för Arduino UNO, som testar text via serieport och till en I2C LED-display som fungerar. (dock saknas "del2" - att kunna använda / hantera de tecken som sparats i LCD-displayen.)
Men i denna tråd är min önskan att kunna flytta kod till funktioner. - (just nu verkar det svårt)
Att slippa alla definitioner för t.ex. åäö mm. i början av programmet. (100? 200? rader... som inte tillför så mycket information.) är mitt mål med denna tråd.

Subrutiner finns inte i Arduino? eller... (flyttar bara kod - vilket min önskan är)

Först försökte jag att returnera flera variabler från en funktion (ex. AwithRing, AwithDots osv.)
För att sedan använda dessa variabler när LCD-displayen ska programmeras. lcd.createChar(1, AwithRing);
Men det är tydligen omöjligt - (bara en variabel kan returneras från en funktion)

Fick tipset att programmeringen av LCD-displayen (ex. lcd.createChar(1, AwithRing);) skulle flyttas in i funktionen - Inget problem, men för att kunna utföra den programmeringen behöver variabeln / objektet lcd (vad det nu är) som finns utanför funktionen passas in i funktionen på något sätt.
(Har testat anropet .: defChar(lcd); och funktionen .: void defChar(lcd) { ... - men fungerar inte.)

Om jag förstår saken rätt är 1, i instruktionen lcd.createChar(1, AwithRing); någon form av adress i LCD-displayen (inte en variabel). När tecknet har sparats, kan adressen anropas från vilken plats som helst i programmet. (utan att behöva returneras från funktionen)
Om inte "1" är en "adress" - kvarstår problemet.

I bland får jag känslan att funktionstypen måste deklareras för funktioner - på något sätt (enligt Functions)
- ex. char defChar(lcd) men det fungerar inte.
Kanske inte ens är möjligt att "passa" lcd till funktionen defChar();?
Jag har haft defChar(); utanför void setup() men kanske måste placeras innanför? (men då uppstår väl problem att returnera lcd från funktionen setup?)

Eller något jag missar?
I programmet jag refererar till sätts värdet .: lcd utanför funktionen .: void setup() men här uppstår inget problem. (kanske funktionen setup och loop har andra kriterier?)

Har jag laddat ned rätt bibliotek? - ingen aning!
____________________________

Med displayen jag köpte, följde inget "papper" med.
Om det som står på säljarens annons stämmer - ingen aning - men displayen är .: LCD, I2C, blå, 2x16tkn och det står 1602A på displayen.
Utdrag från annonsen .:
LCD 1602 Modul inkl. I2C Treiber 16x2
Bildschirm Blau + IIC/I2C PCF8574T Kompatibel Arduino PIC AVR STM32

Spezifikation (LCD):

Chip: HD44780 kompatibler Controller
Versorgungsspannung: DC 5 V
Zeilen: 2
Zeichen pro Zeile: 16
Hintergrundbeleuchtung: Blau
Größe Display: 6,4 cm * 1,4 cm
Größe: 8 cm * 3,6 cm * 1,2 cm

Spezifikation (I2C Interface Modul):

Versorgungsspannung: DC 2,5 V bis 6 V
Interface: I2C
I2C Adresse 0x20 - 0x27, 0x3F (Einstellbar)
Einstellbarer Kontrast (Potentiometer)
Castor
Inlägg: 1989
Blev medlem: 24 mars 2012, 13:03:49

Re: Hantering av funktioner i Arduino IDE

Inlägg av Castor »

Där står ju tydligt att styrchippet är HD44780, sök på det och se efter hur de tecken du vill addera (åäö) skall flyttas med hjälp av ditt program till den del av chippet som är avsedd för detta. Sedan tar du reda på hur du ska skriva ut den information som finns på de platserna i chippet, om jag kommer ihåg rätt skriver man ett tecken som ligger utanför ASCII-tabellen för att visa något av de tecken man lagt upp i den skrivbara arean.
Det är inte alltid så att man kan kopiera vad någon annan gjort, ibland måste man läsa och förstå själv. Om man inte förstår kan man fråga och få hjälp, men då måste man nog ta sig tid att förstå grunderna för hur displayen fungerar och dessutom ha en grundläggande förståelse för hur ett program hanterar de ingående delarna och hur dessa måste samarbeta.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Hantering av funktioner i Arduino IDE

Inlägg av sodjan »

Controllern kan ju vara HD44780 kompatibel men ha en I2C interface.
Men det borde döljas i drivrutinen/interfacet...
Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: Hantering av funktioner i Arduino IDE

Inlägg av Shimonu »

Jag skulle rekommendera att du hittar några grundläggande kurser eller övningar för C eller C++. Du behöver förstå grunderna innan du börjar ta dig allt för mycket vatten över huvudet.
Albireo
Inlägg: 73
Blev medlem: 30 november 2019, 00:29:39

Re: Hantering av funktioner i Arduino IDE

Inlägg av Albireo »

Vet inte om den display jag fått, är den som beskrivs i specifikationen - kan vara så (men behöver inte vara det - kan inte kontrollera) En sak som inte framgår, är vilken teckentabell som ingår i LCD-displayen (europeisk / asiatisk eller...) Har egentligen inget problem att få displayen att fungera. (problemen ligger på annan nivå)

Vid en studie av c-programmering kommer jag då att veta vad funktionen .: lcd.createChar(1, AwithRing); utför?
Förstå instruktionen LiquidCrystal_I2C lcd(0x27, 16, 2); - Om .:
- "lcd" är en variabel eller ett objekt?
- "1" är en variabel eller adress?
(Jag tror inte det - men kan ha fel)

Det lilla jag känner till om programmering i "C", så behövs inte funktionerna void setup() och void loop() (vilket jag har förstått är ett krav i Arduino)

Förstår dock inte varför följande fungerar (ett utdrag ur koden)

Kod: Markera allt

byte AwithRing[8] = {  //å
  B00100,
  B01010,
  B01110,
  B00001,
  B01111,
  B10001,
  B01111,
};

LiquidCrystal_I2C lcd(0x27, 16, 2)

void setup() {
   lcd.createChar(1, AwithRing);     //å
}
men varför detta inte fungerar (ett utdrag ur koden)

Kod: Markera allt

LiquidCrystal_I2C lcd(0x27, 16, 2)

void setup() {
}

void defChar() {
  byte AwithRing[8] = {  //å
  B00100,
  B01010,
  B01110,
  B00001,
  B01111,
  B10001,
  B01111,
  };

  lcd.createChar(1, AwithRing);     //å
}

Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: Hantering av funktioner i Arduino IDE

Inlägg av Shimonu »

I det andra fallet anropar du inget i setup.
Användarvisningsbild
Klas-Kenny
Inlägg: 11338
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Hantering av funktioner i Arduino IDE

Inlägg av Klas-Kenny »

Skillnaden är den att just funktionen setup() anropas automatiskt vid programstart.
Och efter den, anropas loop() upprepat.

Detta gäller *enbart* de två funktionerna!
Inga andra funktioner körs automatiskt. Allt annat måste anropas ifrån någonstans, då setup() eller loop(), eller ifrån någon annan funktion som anropas därifrån.
Albireo
Inlägg: 73
Blev medlem: 30 november 2019, 00:29:39

Re: Hantering av funktioner i Arduino IDE

Inlägg av Albireo »

Ursäkta, missade instruktionen defChar(); i utdraget från min kod.

Men funderar fortfarande över funktionen .: void setup(); {
Har förstått att funktionen endast körs en gång, men det gör väl alla instruktioner som finns innan?
ex.

Kod: Markera allt

...
LiquidCrystal_I2C lcd(0x27, 16, 2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
  lcd.init();       // initialize the lcd
...
Både LiquidCrystal_I2C lcd(0x27, 16, 2); och lcd.init(); kommer väl att bara att utföras en gång?

Dock finns det en skillnad (som jag inte förstår)
Jag tror att instruktionen LiquidCrystal_I2C lcd(0x27, 16, 2); skapar något (variabel / objekt eller...) som heter lcd.
Detta "något" kan användas på lite olika sätt som lcd.init(); , lcd.backuplight(); osv.
lcd verkar inte behöva passas in i funktioner - utan kan ändå anropas i en funktion...
Hur blev det en global variabel? (eller vad det är)

Men flyttas instruktionen lcd.init(); utanför funktionen .: void setup(); på detta sätt .:

Kod: Markera allt

LiquidCrystal_I2C lcd0x27, 16, 2);
lcd.init();

void setup() {
...
Uppstår följande problem .:
SerialDisplay_16x2_-_1:23:1: error: 'lcd' does not name a type
lcd.init(); // initialize the lcd
^~~
Så det måste ändå finnas en skillnad - eller? (vilken?)

Med denna upptäckt flyttade jag in anropet defChar(); in i funktionen void setup();
och plötsligt försvann alla problem som jag tidigare kämpat med.
ex.
SerialDisplay_16x2_-_1:23:10: error: expected constructor, destructor, or type conversion before ';' token
defChar(); // Save åäöÅÄÖ on the LED-display

Multiple libraries were found for "Wire.h"
Multiple libraries were found for "LiquidCrystal_I2C.h" ^
expected constructor, destructor, or type conversion before ';' token
Sammanfattning .:
Vissa saker bör/ska/kan passas till/från funktioner, andra inte.
Är det så att konstanter / objekt aldrig behöver passas till funktioner (endast variabler)?
Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: Hantering av funktioner i Arduino IDE

Inlägg av Shimonu »

Ena är en variabeldeklaration och -definition. Det resulterar i anrop till en konstruktor men det är inte detsamma som ett funktionsanrop.

Som sagt, du behöver studera grunderna. Ingen kommer orka vara lärare för att lära ut allt om programmering.
kodar-holger
EF Sponsor
Inlägg: 920
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: Hantering av funktioner i Arduino IDE

Inlägg av kodar-holger »

Albireo skrev: Har förstått att funktionen endast körs en gång, men det gör väl alla instruktioner som finns innan?
Nej. Jag tror det grundläggande du missat är att till skillnad från Basic så startar inte exekveringen från första raden. I just C och C++ (som används i Arduino) så är det första som körs en funktion som heter main. I Arduino ligger den inte i ditt program utan inne i den kod som tillhandahålls och som du aldrig ser. Den ser i princip ut så här:

Kod: Markera allt

int main(void)
{
	setup();
	while (1) {
		loop();
	}
}
D.v.s
Ingen annan kod än den som anropas som "subrutiner" eller funktioner som det heter här kommer att köras. Allt är funktioner.

När programmet startas görs det i main. I arduino anropar den alltså först funktionen setup som skall finnas i ditt program. Den kan vara tom, men måste finnas. Sen anropas funktionen loop i ditt program gång på gång tills tidens ände.

Skall någon annan kod köras måste den anropas från setup eller main. Ingen annan kod du skriver kommer någonsin att köras. (Inte riktigt sant, men det här utrymmet är för litet för att förklara)

Sen är den andra stora skillnaden mot basic att man undviker i det längsta att göra globala variabler. Så variabler som deklareras inne i en funktion finns inte utanför. Dom är inte bara osynliga utan dom finns verkligen inte. Så om du deklarerar en variabel och sätter ett värde på den ena gången du anropar funktionen finns det värdet inte kvar nästa gång. Så vill du ha värden med dig från en funktion till en annan måste dessa skickas med som argument eller hanteras som globala variabler. Dessa deklareras "utanför" funktionerna. Till exempel före. Det är till och med så att om en funktion anropar sig själv finns inte variabler från den anropande funktionen med inuti den rekursivt anropade. Men nu blev det svårt. Använd inte rekursion förrän du har minst 5års erfarenhet, och när du har 10 kommer du inte vilja använda det igen.

I exempelvis pascal skiljer man på procedurer och funktioner. Det gör inte C/C++. Allt är funktioner. Däremot finns funktioner som inte lämnar returvärde. Det är därför det står void före setup i följande. Det är deklarationen som säger att den inte lämnar något returvärde.

Kod: Markera allt

void setup(){
}
Alternativet är att säga att något har ett returvärde, till exempel ett heltal.

Kod: Markera allt

int min_funktion(){
  return 42;
}
Allt det här får du lära dig om du letar på en grundkurs i programmering för arduino.

Lycka till.
Skriv svar