valtozok adatainak ciklusonkenti mentese

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

csabeszq!
Imádom, mikor játszod a felsőbbrendűt, fórumokon keresztül!

A téma már napok óta napirenden van.
De nem vetted a fáradságot, hogy segítsél!
Most, hogy én elmagyaráztam a tömbök kezelését!
És említést tettem, hogy a for cikluson belül deklarált változó láthatóságát növelheti az extern kulcs szóval.
Ráadásul linkeltem a könyvet, mivel ez a téma túl bonyolult ide!

Nem bírtad ki, hogy ne játszd meg a fejed 1 semmitmondó mondat erejéig!

Majd most fog jönni, hogy ezt mi az egyetemen nem így tanultuk?
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

Példa a könyv 41. oldalárol:

Kód: Egész kijelölése

#define MAXLINE 1000 /*A beolvasott sor maximális mérete*/
char line [MAXLINE]; /* A beolvasott sor*/
char save [MAXLINE]; /*A leghosszabb sor mentésére*/
int max; /*Az eddigi maximális hossz*/
/* Speciális változat*/
getline ()
{
int c, i;
extern char line [];
for (i = 0; i < MAXLINE 1
&& (c=getchar ()) != EOF
&& c !='\n'; ++i)
line (i] = c;
if (c == '\n') {
line [i] = c;
++i;
}
line [i] = '\0';
return (i);
}
/*Speciális változat*/
copy ()
{
int i;
extern char line [], save [];
i = 0;
while ((save [i] = line [i]) != '\0')
++i;
}
/*A leghosszabb sor kiválasztása; speciális változat*/
main ()
{
int len; /*A pillanatnyi sor hossza*/
extern int max;
extern char save [ ];
max = 0;
while ((len = getline ()) > 0)
if (len > max) {
max = len;
copy ();
}
-
Szóval lehet az extern-t használni!
Máshol is!
Tiborx8
DrótVégénSzéndarab
Hozzászólások: 35
Csatlakozott: 2016. november 28. hétfő, 19:40

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: Tiborx8 »

Sziasztok!

Épp most meséltem a feleségemnek hogy milyen tuti hogy komoy profik segitenek a kezdő kérdéseimben... Tényleg köszönöm mindannyiotóknak!
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

A linkelt könyv kb. 50 oldalon át tárgyalja csak a változok létrehozását, használatát, típusait és láthatóságát.
Még létezik olyan is, hogy típus konverzió.
A Cpp-ben meg már szinte mindent felüldefiniálhatsz, vagyis az ésszerűség keretein belül csinálhatsz bármit.

Nem vagyok profi, úgy kezdtem én is mint Te.
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: csabeszq »

Fontos, hogy a kezdők externnel kezdjenek, az asm volatile-t ki ne hagyjátok a rutinból. Szoktam én is extern-t használni, nem azért mert szeretem, hanem mert időnként nem lehet kihagyni. Mondjuk a tanköny első 2000 példáját azért extern nélkül is végig lehet csinálni.

A lényeg az, hogy amit a függvényen belül definiálsz, az elveszti az értékét, amit a függvényen kívül definiálsz, az megtartja.

Kezdjük egy példával: három dolgot mérsz futásonként - az időt, az ADC-t és D9-es digitális pin állapotát. Ezeket fogod elmenteni, kiírni és kiszámolni az analóg jelek átlagát.

Kód: Egész kijelölése

#define MERESEK_SZAMA 5

// egy mérés ezeket a mezőket fogja tartalmazni
struct meres
{
  uint32_t ido;          // ekkor mértél
  uint16_t analogJel;    // analóg jel
  bool     d9esLab;      // d9-es PIN
};

// itt fogod tombben a mereseidet eltarolni
struct meres meresekTombje[MERESEK_SZAMA];

void merj(int meres)
{
  meresekTombje[meres].ido = micros();             // ekkor mérted
  meresekTombje[meres].analogJel = analogRead(A0); // A0 pin-en analóg jel mérése
  meresekTombje[meres].d9esLab = digitalRead(9);   // ezt a pin-t olvasod
}

void setup() {
  Serial.begin(115200);
  Serial.println("Itt indul a mérés!");
}

void loop() {
  // ebben a ciklusban fogsz mérni
  for( uint8_t meres = 0; meres < MERESEK_SZAMA; meres++ )
  {
    merj(meres);
  }

  // amikor a ciklus végetér, a mérések tömbje minden fontosat tartalmazni fog
  // írjuk ki
  for( uint8_t meres = 0; meres < MERESEK_SZAMA; meres++ )
  {
    Serial.print("Mérés:");
    Serial.println(meres + 1); // a tömböt nullától indexeled, viszont 1-től számolsz
    Serial.print("Idő:");
    Serial.println(meresekTombje[meres].ido);
    Serial.print("Analóg jel:");
    Serial.println(meresekTombje[meres].analogJel);
    Serial.print("D9-es láb:");
    Serial.println(meresekTombje[meres].d9esLab);
    Serial.println();
  }

  // itt kiszámolod az analóg jelek átlagát
  uint16_t atlag = 0;
  for( uint8_t meres = 0; meres < MERESEK_SZAMA; meres++ )
  {
    atlag += meresekTombje[meres].analogJel;
  }
  atlag /= MERESEK_SZAMA; // itt az atlaghoz osztasz a mérések számával

  Serial.print("Analóg jelek átlaga:");
  Serial.println(atlag);
  Serial.println();
  
  delay(10000); // itt pihensz 10 másodpercet, majd újrakezded
}
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: csabeszq »

Kedves kapu48,

Lehet, hogy kicsit néha kukacoskodásnak tűnik amit csinálok viszont teljesen más környezetben dolgozom. Több millió soros kódokat fejlesztünk és ott más szabályok a mérvadóak. A legfontosabb a kód értelmezhetősége, minden más (teljesítmény, memóriafoglalás) ennek van alárendelve.

A legfontosabb, hogy hátradőlsz a székben és nézed, hogy az adott kód mit csinál. Egy projekten dolgoznak 10-en, a legtöbb kódot nem is ismered, mások munkáját kell folytatnod. Teljesen mindegy, hogy gyors-e a kód, mennyi memóriát fogyaszt, működik-e vagy sem, ha nem átlátható, akkor újraírod. Más szabályok vonatkoznak millió soros programokra, mert senki az ég világon nem akarja mindet átnézni, megérteni, hogy az egész mit csinál. Nem akarunk gondolkozni trükkös rutinokon, ha érthetetlen, akkor megy a levesbe. Kifejezetten irritál mindenkit ha érdemleges munka helyett azon kell filozofálni, hogy vajon a sor megírója mi a fenét szándékozott csinálni a rutinnal.

Ebbe a filozófiába az extern-nem illik bele, semennyire. Ha meghívsz egy függvényt A,B paraméterekkel, akkor az visszaad C-t. Az extern megvariálja a függvényt, ami visszaad C,D,E,F-et, ahogy éppen jólesik. Nézed a függvényt, látod a bemeneti paramétereid, viszont fogalmad sincs, hogy mit fog visszaadni. Nem elég nekem azt nézni, hogy a "printf"-nek mik a bemenő paraméterei, mert ugyanarra a bemenetre mást ad vissza. Nem elfogadható az egész bizonyos méret fölött.

Amikor a 70-es években Kernighan és Ritchie megcsinálta a C-t, még nem voltak millió soros kódok, mai szemmel egy Atmega328P is csúcskategória lett volna akkortájt. Az akkori eszközök közül nem minden állja meg ma a helyét.

Egy programozó számára a trükkös rutinok borzasztó irritációt okoznak és néha nem bírják ki, hogy ne szóljanak be valamit miattuk.
:)
Avatar
winnerbt
Elektronbűvölő
Hozzászólások: 907
Csatlakozott: 2007. március 25. vasárnap, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: winnerbt »

Apró sülthal kérdésem lenne a Nagytudásúakhoz :
Például van egy kijelzőre dolgozó egyeneshúzó rutin, aminek van ugye X-Y (meg U-W) értéke. A rutin kezeli (kezelnie kell) a kijelzőn kívülre eső szakaszrészt is. No, nekem a rutinfában (X-Y=> vonalhúzó=>overlay-t/átlátszóságot kezelő=>pontberakó)keletkezik a lefutás után egy X-Y (végpont), amit nekem meg kell őriznem és teljesen más külső rutin is nézegetné, illetve a következő szakasz kezdőpontja lesz. Akkor az X-Y-om milyen változó legyen? (már hogy megmaradjon és elérhető legyen mindenkihez az értéke)
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: csabeszq »

Globális változó a legegyszerűbb.

Kód: Egész kijelölése

uint16_t  vx; // x végpont, globális változó
uint16_t  vy; // y végpont, globális változó

void moveTo(uint16_t x, uint16_t y) // ez ugrasztja a pontot egyenes húzása nélkül
{
  vx = x;
  vy = y;
}

void lineTo(uint16_t x, uint16_t y) // ez egyenest húz az új végpontig
{
  // itt húzol [vx,vy]-[x,y] között egyenest
  
  vx = x; // itt beállítod az új végpontot
  vy = y;
}

void line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
  moveTo(x0, y0); // mozgatod a pontot a kezdő pozícióra
  lineTo(x1, y1); // vonalat húzol x1,y1-ig
}

Avatar
winnerbt
Elektronbűvölő
Hozzászólások: 907
Csatlakozott: 2007. március 25. vasárnap, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: winnerbt »

Szóval rutinon belül átmásolom, aztán visszamásolom X-Y-ba a belül keletkezett értékeket. Mert ugye az kavar meg, hogy az X-Y változókat "mindenki" használja össze-vissza (tehát pl. vonalhúzásnál X-Y a kezdőérték, de a benne meghívott kipöttyöző rutin is a pixelhez az X-Y-t használja (akár máshonnan hívva azt, ha pl. a körrajzoló hívja meg), mert a vonalhúzóban X-Y tart a végpontokhoz, tehát pont az az értékük a folyamat során, ahova pötty kell, viszont a következő szakaszhoz kell nekem, hol hagyta abba a vonalhúzó, tehát aktuálisnak kell lennie.
"amit a függvényen belül definiálsz, az elveszti az értékét, amit a függvényen kívül definiálsz, az megtartja." Tehát ezek szerint másolgatni kell, dupla annyi memóriahasználat.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

Írtam 1 nagyon egyszerű példát extern-re. (Nekünk, nem profiknak!)
Mindent az alap mappába pakolsz!
Most legyen: valtozok

Kód: Egész kijelölése

// valtozok.ino

#include "Defines.h"

// Mikor először használod:
uint16_t vegpontX;
uint16_t vegpontY;
uint16_t vegpontU;
uint16_t vegpontW;

uint16_t i = 0;


void setup() {
  Serial.begin(9600);
  // put your setup code here, to run once:
  vegpontX = 11; 
  vegpontY = 22;
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println(i); 
  Serial.print("vegpontX = ");
  Serial.println(vegpontX);  
  Serial.print("vegpontY = ");
  Serial.println(vegpontY);
  delay(1000); 
  vonal(10, 20);
  Serial.println(i++); 
  Serial.print("vegpontX = ");
  Serial.println(vegpontX);  
  Serial.print("vegpontY = ");
  Serial.println(vegpontY); 
  delay(1000);
}

Kód: Egész kijelölése

/**
 * Defines.h 
 * Ahol latni akarod, oda: #include "Defines.h"
 *
 */
#ifndef DEFINES_H
#define DEFINES_H

#include "Arduino.h"
/* Put your global defines for all libraries here used in your project */
// Változók
// Hogy lathato legyen it is kel: extern 
extern uint16_t vegpontX;
extern uint16_t vegpontY;
extern uint16_t vegpontU;
extern uint16_t vegpontW;

// Fügvények
void Lcd();
void vonal(uint16_t lineX, uint16_t lineY);


#endif

Kód: Egész kijelölése

// Defines.cpp


#include "Defines.h"


void Lcd(){
  //...
}

// össze ado pelda:
void vonal(uint16_t lineX, uint16_t lineY)
{
	uint16_t X, Y;  // ezt csak itt latod
	 vegpontX += lineX;   // Ezek az értékek megmaradnak kilépés után is!
	 vegpontY += lineY;   // Ezek az értékek megmaradnak kilépés után is!
  //...

}

Így is működik!
(Aztán lehet ezt bonyolultabban is! Azt majd csabeszku!)

Az eredmény:

Kód: Egész kijelölése

0
vegpontX = 11
vegpontY = 22
0
vegpontX = 21
vegpontY = 42
1
vegpontX = 21
vegpontY = 42
1
vegpontX = 31
vegpontY = 62
2
vegpontX = 31
vegpontY = 62
2
...
És lehetőleg ne használj 1 karakteres változó neveket!
Esetleg csak függvényen belül!
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

csabeszq!
Csak 1 megjegyzés!

Nagyon kevés Arduinohoz található .lib van úgy dokumentálva, hogy használható legyen!
Ami az arduino reference linken van az is csak éppen több a 0-ánál.
Ezért sajnos beléjük kel menni és megérteni!

Ilyen példák után, mit vársz a mezei felhasználótól?
Nem tanultuk 4-5 évig az egyetemen, és nem is követelnek tőlünk ipari minőséget!


Nálatok gondolom így legtöbbet el sem fogadnák?
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: csabeszq »

Kapu48, teljességgel ugyanazt csináltad, amit én. Csak csináltál egy header fájlt is hozzá és belepakoltad az extern-nel a definíciókat. Arduino-n bizonyos bizonyos szint alatt nincsenek header fájlok. Mindenesetre legalább az tisztázódott, hogy ugyanarról beszélünk.

Úgy néz ki, hogy teljesen félreértettük egymást, de most legalább ez is kiderült.

A kód, ahol elszálltam:

Kód: Egész kijelölése

// extern ként megőrzi a tartalmát
extern float average = 0;
for(int x = 0; x<4; x++){
   average += tombx[x];
}
average /= 4;
Ez nekem így jött le:

Kód: Egész kijelölése

float valamiFuggveny()
{
  // extern ként megőrzi a tartalmát
  extern float average = 0;
  for(int x = 0; x<4; x++){
     average += tombx[x];
  }
  average /= 4;
  return average;
}
Ennek a szakirodalomban neve is van: spagetti kód. Amikor mindenki a programban keresztül kasul mindenbe belepiszkál. A program meg úgy néz ki, mint a spagetti. Minden rutin minden változót piszkál, mindenhova belerondít egy kicsit.

Nem volt tiszta az egész, átlagszámoláshoz miért akarod megőrizni a tartalmat, meg miért nem static-kal őrzöd meg, ha ennyire szeretnéd. Bocs, kicsit talán pongyola volt az eredeti megfogalmazás, ezért teljesen félreértettem amit mondani szerettél volna. Azért beismerhetjük, hogy a másodiknál példánál jogosan száll el az agyam.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

Amitől elszállt az agyad, azokat a kérdező írta. Én csak kicsit bele szúrtam, hogy mit lehet tenni ilyenkor.

Én vagy a legtöbben úgy csináljuk, ha kapunk a kezünkbe valami új HW-t amit életre kellene kelteni.
1. Keresünk a neten használható dokumentációt hozzá.
2. Mivel lusta vagyok oldalnyi definíciókat írni, ezért keresek valami alkalmazást, amiben már a munka javát elvégezték.
3. Ugyan az erdőben lehet találni sok hasznos dolgot, de nem teljesen arra való, amit én szeretnék.
4. Ezért rakom össze az egész lib-et 1 könyvtárba. Így átlátom az egész kódot, és szerkeszthetem 1 helyen.
(Utálom, hogy az arduino elrejti előlem ezek tartalmát!)
5. És most jön, ami neked fájhat! Én bizony belenyúlok az állományokba. Kidobom, ami nem kel, és kiegészítem hasznos dolgokkal.
...
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: kapu48 »

Mivel szerintem a fórumon a GLCD-k legnagyobb szakértője winnerbt!

És az ilyen grafikus rutinokat külön állományokban szokták megírni.
Ezért jó, ha egyes változók láthatóságát megoszthatja az állományok között.

És üdvözlöm, hogy kimerészkedet a Bascom világából, zavarosabb vizekre!
Avatar
winnerbt
Elektronbűvölő
Hozzászólások: 907
Csatlakozott: 2007. március 25. vasárnap, 6:00

Re: valtozok adatainak ciklusonkenti mentese

Hozzászólás Szerző: winnerbt »

Várom, hogy bekattanjon a logikája az egésznek :) ASM és Bascom között találni kell valami középutat. Ugyebár azért vakargatom a fejem, mert a kis memória miatt (mert 50Ft-ért képes szájbalőni magát a megrendelők egy típusa) sokszor használok több belépési pontot egy rutinba (most pl. 8190byte a program és bele szerettek volna tetetni új funkciót a Tiny85-be) és nem akar beugrani, hogy ilyenkor hogyan (minek) is kellene a változókat deffiniálni. Honnan fogja tudni a rendszer, mit merre tekeregjen, ha bele szeretnék ugrani a közepébe? Szóval van még mit agyalnom. Egy kicsit még értetlenkedek meg buta kérdéseket fogok feltenni.
Válasz küldése