timer delay() nélkül

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
Válasz küldése
Avatar
broland
Tranzisztorgyógyász
Hozzászólások: 152
Csatlakozott: 2009. április 20. hétfő, 6:00

timer delay() nélkül

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

Sziasztok,

Agyvérzés kerülget, nem jövök rá, hogy hogy kellene megoldanom.

A feladat: adott ideig egy kimenet magas, majd alacsony, ha kell akkor még 1x-2x-ugyan ez, majd egy adott idő letelte után egy másik kimenet kell, hogy magas, majd alacsony szinten legyen. Delay()-el már megoldottam, de nem jó, mert a köztes kimenetek befolyásolják a másik kimenet kezdő időpontját. Valami olyasmire gondoltam, hogy megy folyamatosan a loop, vagy egy do{}while(); de nem sikerült. Nekem az lenne fontos, hogy a kezdés, és az expoDelay közötti időben bárhol tudjak egy-kettő adott ideig tartó magas kimenetet generálni. Nem tudom, hogy jól, értetően tudtam -e elmondani. Talán a mostani kód(részlet) segít egy picit. Nem kérek kész kódot, csak iránymutatást. A segítséget előre is köszönöm. Üdv.: Roland

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


expoDelay = round(sqrt(tmpMath1) * 1000) + drop1size - drop2delay - drop2size - drop3delay - drop3size + expoCorrection;

void loop() {

  server.handleClient();
  button.update();

  if ( button.pressed() ) {

    server.stop();
    delay(1000);
    digitalWrite(ledPin, LOW);
    Serial.println("Server stopped");

    //start dropping

    //drop1
    digitalWrite(valvePin, HIGH);
    delay(drop1size);
    digitalWrite(valvePin, LOW);

    //GAP for drop2
    if (drop2delay > 0) {
      delay(drop2delay);
    }

    //drop2
    if (drop2size > 0) {
      digitalWrite(valvePin, HIGH);
      delay(drop2size);
      digitalWrite(valvePin, LOW);
    }

    //GAP for drop3
    if (drop3delay > 0) {
      delay(drop3delay);
    }

    //drop3
    if (drop3size > 0) {
      digitalWrite(valvePin, HIGH);
      delay(drop3size);
      digitalWrite(valvePin, LOW);
    }

    delay(expoDelay);

    digitalWrite(expoPin, HIGH);
    delay(500);
    digitalWrite(expoPin, LOW);

    digitalWrite(ledPin, HIGH);
    server.begin();
    Serial.println("Server started");
  }

}
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: timer delay() nélkül

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

Delay helyett:

Lefut állandóan a kódod, és a gombok állapotát változóba rakod.
setup:
gomb1magas=0
gomb1magasmarad=10000 //10000 msecig legyen magas

loop:
If gomb_magas_legyen == OK
gomb1magas=1
gomb1magasstart=millis()

if gomb1magassstart+gomb1magasmarad<millis()
digitalwrite(gomb1,HiGH)
else
digitalwrite(gomb1,LOW)
loop vége



Egyéb tipp:
https://www.arduino.cc/en/Tutorial/Buil ... thoutDelay
http://www.tavir.hu - a gazda :)
Avatar
broland
Tranzisztorgyógyász
Hozzászólások: 152
Csatlakozott: 2009. április 20. hétfő, 6:00

Re: timer delay() nélkül

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

Szia Róbert, köszi a segítséget, a minta progit ismertem, de nekem átírva nem működik úgy ahogy szeretném:

változók:
elso nyitas 20ms
masodik nyitas kesleltetes 100ms
masodik nyitas 15ms
expo 250ms

loop 1x!
x kimenet magas elso nyitas értékéig, majd vissza alacsonyra
nem történik semmi masodik nyitas kesleltetes
x kimenet magas masodik nyitas értékéig, majd vissza alacsonyra
nem történik semmi
y kimenet magas expo idő múlva, magas 500ms, majd vissza alacsonyra.

rajzoltam egy oscillogrammot, mire gondolok (elég egye-bugya, de érthetőbb mint leírni) :)

köszönöm előre is a segítséget.

Üdv Roland
scopekesz.jpg
Nincs meg a kellő jogosultságod a hozzászóláshoz csatolt állományok megtekintéséhez.
vargham
Chipgyilok
Hozzászólások: 308
Csatlakozott: 2014. január 8. szerda, 8:32

Re: timer delay() nélkül

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

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

uint16_t gStateDelaysMs[] = {20U, 100U, 15U, 250U, 500U}; // Idők millisecundumban
constexpr uint8_t gcStateCount = 5U; // A folyamat fázisainak száma
uint8_t gCurrentState = 0U; // Az aktuális fázis
bool gRunning = false; // Éppen fut-e a folyamat
unsigned long gTimestamp; // Legutóbbi művelet időbélyege

void setup() {
  // 
}

void loop {
  if (button.pressed() && !gRunning) { // Gombnyomásra elkezdődik a folyamat
    gTimestamp = millis(); // Start pillanatának eltárolása
    digitalWrite(ledPin, LOW); // LED bekapcsolása
    digitalWrite(valvePin, HIGH); // Szelep nyitása 0. fázis elején
    gRunning = true; // Futás flag beállítása
  }
  if (gRunning && millis() - gTimestamp > gStateDelaysMs[gCurrentState]) { // Ha fut a folyamat és letelt az aktuális idő
    gTimestamp = millis(); // Művelet időbélyegének eltárolása
    switch gCurrentState {
      case 0U: // A 0. fázis végén zárni kell a szelepet
        digitalWrite(valvePin, LOW);
        break;
      case 1U: // Az 1. fázis végén nyitni kell a szelepet
        digitalWrite(valvePin, HIGH);
        break;
      case 2U: // A 2. fázis végén zárni kell a szelepet
        digitalWrite(valvePin, LOW);
        break;
      case 3U: // A 3. fázis végén be kell kapcsolni valamit
        digitalWrite(expoPin, HIGH);
        break;
      case 4U: // A 4. fázis végén ki kell kapcsolni valamit
        digitalWrite(expoPin, LOW);
        break;
      default:
        break;
    }
    gCurrentState = ++gCurrentState < gcStateCount ? gCurrentState : 0U; // Aktuális fázis nővelése, ha eléri a maximumot, akkor visszaállítása nullára
    if (gCurrentState == 0U) { // Ha visszaállt nullára, akkor végetért a folyamat.
      gRunning = false; // Futás flag törlése
      digitalWrite(ledPin, HIGH); // LED kikapcsolása
    }
  }
}
Avatar
broland
Tranzisztorgyógyász
Hozzászólások: 152
Csatlakozott: 2009. április 20. hétfő, 6:00

Re: timer delay() nélkül

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

Szia vargham,

Nagyon szépen köszönöm a kódot, még nem néztem scoppal, de serial.print-ekkel tökéletesen működik.
Nem tudom miért vannak benne "U" jelzések, én azt kivettem belőle :) ( lehet, hogy nem kellett volna?! )

Nagyon köszi még egyszer.

Üdv Roland
vargham
Chipgyilok
Hozzászólások: 308
Csatlakozott: 2014. január 8. szerda, 8:32

Re: timer delay() nélkül

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

Örülök, ha jól működik. Érted is a múködését? Mert akkor bővíteni is könnyű. Ha nem világos, kérdezz nyugodtan!
A konstansokat illik postfixszel jelölni, hogy kerüljük az implicit típuskonverziót, de a program írójához is szól. Rögtön látszik, mi a szám ábrázolási tartománya. Érdemes megszokni a használatát. U = unsigned, L = long, F = float, D = double, stb.
Avatar
broland
Tranzisztorgyógyász
Hozzászólások: 152
Csatlakozott: 2009. április 20. hétfő, 6:00

Re: timer delay() nélkül

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

Szia vargham,

Picit leszakadt az állam, amikor láttam a forrást, de megértettem. Csak azaz "U" volt kérdéses, eddig.

az értékadás pl.:

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

gStateDelaysMs[0]=47;
működött. ezt vissza is tudtam olvasni.

Úgyhogy próbálkozom, holnap scopra teszem, és ha nem baj, akkor keressük egymást.

Köszönöm szépen még egyszer.

Üdv.: Roland
FoxiMaxi
Újonc
Újonc
Hozzászólások: 10
Csatlakozott: 2018. március 19. hétfő, 20:07

Re: timer delay() nélkül

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

Sziasztok!
Ebbe a témába írok, mert ez is időzítés.
Belefutottam egy olyan problémába, hogy a millis() függvény 1ms-ot jitterel. A kérdésem az lenne, hogy ez valós probléma, avagy csak én bénázom el a tesztelését?
Ezzel a nyulfaroknyi programmal tesztelem és nem jutok vele előrébb.


const unsigned int Timebase = 5; //5ms idoalap
const byte conLedOn = B00000001;
const byte conLedOff = B11111110;
unsigned long Actualmillis;
unsigned long Newmillis;

void setup()
{//PORT init
DDRD = B11111110; //iranyok
DDRC = B00111111;
DDRB = B00000111;
PORTD = B00000001; //indulo adat
PORTC = B00000000;
PORTB = 00000000;
Newmillis = millis()+ Timebase ;
}
void loop()
{
Actualmillis = millis();
if (Actualmillis >= Newmillis)
{
PORTB |= conLedOn;
Newmillis += Timebase; //idoalap ujra indit
PORTB &= conLedOff;
}
}
Avatar
pipi
SzínkódFestő
Hozzászólások: 80
Csatlakozott: 2008. július 6. vasárnap, 6:00

Re: timer delay() nélkül

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

Hali!
Láttál már olyan szoftvert ami 0 idő alatt lefut? Mert én nem....
A programod is "fogyasztja" az időt, meg a loop végén az Arduinó rendszer is csinálgat még ezt-azt...
Ha ettől "pontosabb" kell használd a hw timert megszakítással.
FoxiMaxi
Újonc
Újonc
Hozzászólások: 10
Csatlakozott: 2018. március 19. hétfő, 20:07

Re: timer delay() nélkül

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

Szia!
A jelenség felettébb érdekes. Mert alapból az 5ms-t időzít, de 8-9 periódusonként csak 4ms-t. Mintha valahol valami kerekítési hiba lenne. Az meg felettébb furcsa, hogy a feltétel vizsgálatnál az "=" nem működik, csak a ">=". Illetve ebből el is hagyható az "=". Miközben a program magja néhány mikroszekundum. Nem is annyira az abszolút pontosság a lényeg, hanem az egyformaság. Valószínű a hw Timer lesz a megoldás...csak azért mégse elegáns ha időnként elveszik 1ms a millis() függvényben.
atilla
Biztosítékgyilkos
Hozzászólások: 65
Csatlakozott: 2016. május 10. kedd, 18:35

Re: timer delay() nélkül

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

A millis() a timer0 megszakításai alapján fut. A timer, ha jól emlékszem 997 hertzen fut. Ez nem 1000. Ezt szoftveresen kompenzálja, ebből a jitter. A forráskódjában láthatod, olvashatod. Tehát a timer másodpercenként cirka 997 megszakítást generál, a hiányzó 3-at a szoftver adja hozzá. Itt jön a jitter.
Ha ez pontatlan, akkor csináljál egy hasonló megoldást a timer1-el, ami 16 bites és be tudod lőni, hogy másodpercenként kereken 1000 megszakítást generáljon.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: timer delay() nélkül

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

millis() helyett a micros()? Pontosabb....

micros() 4usec pontosságú... (8usec @8MHz / 4usec@16MHz)

De: 70sec a túlcsordulás!
http://www.tavir.hu - a gazda :)
FoxiMaxi
Újonc
Újonc
Hozzászólások: 10
Csatlakozott: 2018. március 19. hétfő, 20:07

Re: timer delay() nélkül

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

Nos...valóban...a Timer direkt kezeléssel áll a jel mint Katiban a gyerek. Azért furcsa...hiszen a millis() is így működik, működne.
Azért köszönöm! :)
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: timer delay() nélkül

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

A milis() a 8bites timer0-t használja...
A wiring.c rendszermagban van benne...
http://www.tavir.hu - a gazda :)
Válasz küldése