Sida 2 av 3

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 09:39:03
av pinch
Har nu satt ihop en sketch och provkört på bordet, fungerar som det var tänkt :tumupp:
Eftersom ni är sådana snillen på det här och detta är första gången jag ens rör en Arduino så skulle jag tacksamt ta emot tips och råd
om ni ser något som är rent fel, eller kanske bara kan förbättras.

Kod: Markera allt



unsigned long up_time;
unsigned long down_time;
const int upin = 7;     // height sensor low input
const int upout =  13;  // compressor     
const int downin = 5;   // height sensor high input
const int downout = 9;  // relief valve 

int upState = 0;         // variable for reading height sensor status
int downState = 0;
void setup() {
  // initialize pin output:
  pinMode(upout, OUTPUT);
  pinMode(downout, OUTPUT);
  // initialize pin input:
  pinMode(upin, INPUT);
  pinMode(downin, INPUT);
  delay(10000); // startup delay
  digitalWrite(upout, HIGH);  // start compressor
  delay(5000);                // wait 5 sec
  digitalWrite(upout, LOW);   // stop compressor
}

void loop() {
 
  
  upState = digitalRead(upin);

  
  if (upState == LOW ) up_time = millis();
    
    if ((millis() - up_time) >= 15000)
    {
       // start compressor
    digitalWrite(upout, HIGH);
  }
  else {
    // stop compressor
    digitalWrite(upout, LOW);
  }
  {
  
  downState = digitalRead(downin);

  
  if (downState == LOW ) down_time = millis();
    
    if ((millis() - down_time) >= 15000)
    {
       // activate relief valve
    digitalWrite(downout, HIGH);
  }
  else {
    // deactivate relief valve
    digitalWrite(downout, LOW);
}
  }
}

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 09:52:16
av Jan Almqvist
Det kommer nästan att fungera skulle jag säga.

Ett (?) av problemen är konstruktionen 'if ((millis() - up_time) >= 15000)...'

Om villkoret som sätter up_time blir falskt strax före ( eller inom 15s ) innan millis() slår runt kommer 'if ((millis() - up_time) >= 15000)' att bli falskt varje gång som millis() slår runt.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 10:26:19
av Jan Almqvist
Jag provade med 16 bitar och kom fram till följande:

Ex:

start_time = 65000

millis() = 0

millis() - start_time = 536

Då blir väl 'if ((millis() - up_time) >= 15000)' inte uppfyllt?

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 10:39:46
av bearing
Ursäkta, jag tog bort mitt inlägg då jag blev osäker på vad du egentligen syftade på.
Men det du skriver är ju att det gått 536 millisekunder, och då ska ju kriteriet inte vara uppfyllt, så det är väl ingen bugg.

Det kommer ju bli en bugg ifall millis() snurrar runt ett varv, och det var detta som gjorde mig osäker, och som gjorde att jag tog bort inlägget. millis() slår runt var 49 dag, eller hur det nu var. Den buggen skulle man kunna få bort genom att göra så att up_time "följer efter" millis() på 30 sekunders avstånd, eller liknande. Men det finns nog någon tjusigare lösning.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 10:43:45
av pinch
Maximal tid mellan resets är ca 4 timmar, så det ska inte vara något problem med overflow.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 10:59:22
av Jan Almqvist
bearing skrev: Det kommer ju bli en bugg ifall millis() snurrar runt ett varv, och det var detta som gjorde mig osäker, och som gjorde att jag tog bort inlägget. millis() slår runt var 49 dag, eller hur det nu var. Den buggen skulle man kunna få bort genom att göra så att up_time "följer efter" millis() på 30 sekunders avstånd, eller liknande. Men det finns nog någon tjusigare lösning.
Visst, buggen märks bara en gång vart 49 dygn och bara om millis() slagit om strax innan värdet sparades.

I TS fall spelar det kanske ingen roll men den aktuella konstruktionen är inte tillförlitlig utan man bör göra på annat sätt tycker jag. Alla processer tål kanske inte att en utgång kan hoppa till c:a 8 ggr per år. Många av de system jag gör körs 24/7 och startas normalt aldrig om.

Att använda millis(), GetTickCount(), currentTimeMillis() eller vad det nu kan heta olika OS är ofta rätt metod men det bör göras lite annorlunda. Det finns enkla lösningar, jag brukar separera själva beräkningen av tid sedan förra varvet från timern.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 11:04:00
av mri
pinch: Det ser ut att fattas något i din kod, men jag ids inte komplettera eftersom det saknas uppgifter hur det är tänkt att fungera. Du säger att kompressorn skall starta efter 15 sekunder, men sen då? Vad skall hända sen när den startat?

Jan Almqvist: Du svarade korrekt på din egen fråga. Villkoret är inte uppfyllt (ännu) eftersom det bara gått 536 ms.

Vad gäller bugg när millis() slår runt till noll ber jag herrskapet kolla upp lite hur 2-komplement matte fungerar.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 11:07:28
av Jan Almqvist
@mri:

Buggen kan uppstå när millis() slår runt gång 2..n dvs vart 49 dygn.

Edit: Jag svarade på Bearings inlägg som han tog bort sedan.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 11:30:52
av mri
Jan Almqvist: Hur tänker du nu? Man kan givetvis inte mäta tid eller skapa en fördröjning som är *längre* än vad räknaren man använder kan räkna... Det måste man givetvis hålla reda på och gardera sig mot i koden! Programmet som TS presenterat såhär långt verkar inte beakta det.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 11:50:15
av SeniorLemuren
Verkar ha gått prestige i detta. Påminner mig lite om vad som händer när man släpper ihop 2 tuppar. :D

TS >>Maximal tid mellan resets är ca 4 timmar, så det ska inte vara något problem med overflow.<<

Så varför fortsätta hacka sådant som är helt oväsentligt för TS.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 12:00:50
av Jan Almqvist
@mri:

Problemet uppstår även vid fördröjningar på t.ex. 5000 eller 15000 ms och är lätt av påvisa.

Både start_time och millis() är heltal mellan 0 och 4294967295.

Den ena minus den andra (modulo 4294967296 ) ger ett resultat i samma område.

Ponera att start_time råkat bli 4294967296 - 5000.

Då kan inte '(millis() - up_time) >= 15000' bli uppyllt innan millis() returnerar ett värde > 10000 eller hur?

Den första gången som millis() slår runt gör det givetvis inget men 49, 98, 147 etc dagar senare händer samma sak...

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 12:08:20
av Jan Almqvist
SeniorLemuren skrev:Verkar ha gått prestige i detta. Påminner mig lite om vad som händer när man släpper ihop 2 tuppar. :D

TS >>Maximal tid mellan resets är ca 4 timmar, så det ska inte vara något problem med overflow.<<

Så varför fortsätta hacka sådant som är helt oväsentligt för TS.
- TS kanske ändrar sej och vill köra kompressorn längre tid?

- TS eller någon annan kanske använder samma lösning i en annan tillämpning och/eller med en tidbas som bara är 8 eller 16 bitar?

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 12:16:14
av bearing
Jan, problemet med att räknaren slår runt har ingenting med startvärdena att göra. Det finns inte någon bugg i if-satsen, och det var detta jag påvisade i mitt inlägg, som jag tog bort.

8-bit:

start = 200
millis = 215
millis - start = 15
I detta fall kommer buggen när millis passerar 200 andra gången, d.v.s 256 ms efter start.

start = 250
millis = 9
millis - start = 15
I detta fall kommer buggen när millis passerar 250 andra gången, d.v.s 256 ms efter start.

Du har alltså fel, det är ingen skillnad mellan om starten sker precis innan variabeln slår runt, eller annars.

Och som jag skrev ovan, man kan fixa så att programmet inte buggar var 256:e ms med ett par till rader kod.

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 12:22:21
av Jan Almqvist
@bearing

Jag hade uppenbarligen fel och buggen är alltså allvarligare än jag trodde...

Re: Arduino, programera fördröjning.

Postat: 19 augusti 2015, 12:29:07
av pinch
mri skrev:pinch: Det ser ut att fattas något i din kod, men jag ids inte komplettera eftersom det saknas uppgifter hur det är tänkt att fungera. Du säger att kompressorn skall starta efter 15 sekunder, men sen då? Vad skall hända sen när den startat?
När den har startat så går den så länge den får styrsignal.
Det hela är ett tidsfördröjt tillslag till relä, kunde ha köpt ett färdigt relä med justerbar fördröjning av tillslaget, men detta är roligare :)
Skrev redan i orginal inlägget att tanken var att det skulle fungera så.