[Solved]Subroutine

Geachte,

Ik wil alles in een subroutine steken omdat alles onder void loop nogal veel is.
Dit is mijn voorbeeld code:

void setup(){}
void loop()
{   
blink();
}
void blink()
{
"code hier"
}

Het probleem is nu in de arduino software gaat dit allemaal wel maar ik programmeer in atmel studio 6.
Hier geeft hij de error: 'blink' was not declared in this scope.

Opgelost door in Arduino.h regel toe te voegen void blink(void);
Hierdoor herkent hij de regel

Ouwe truck: definieer je blink() vóór je hem aanroept. Zomaar een suggestie, ik ken atmel studio niet.

Het is geen goed idee om de aanpassing in Arduino.h te doen,

je kunt het veel beter in de source file zelf doen, of 2e optie een lokale .h maken

// PROTOTYPES OF FUNCTIONS
void blink();

// ARDUINO SKETCH STARTS HERE
void setup()
{
}

// INFINITE LOOP
void loop()
{   
  blink();
}

void blink()
{
  // "code hier"
}

of 2e optie een lokale .h maken

#include "blink.h" // bevat de blink code..

// ARDUINO SKETCH STARTS HERE
void setup()
{
}

// INFINITE LOOP
void loop()
{   
  blink();
}

Bedankt!

Ik heb dan nog een vraag.
Ik wil een output voor een bepaalde tijd hoog laten staan tenzij ik een puls krijg van een bepaalde input ( of constant) zodat deze uitgang laag word. De puls verkrijgen heb ik al maar weet totaal niet hoe eraan te beginnen.

Een timertje dus.
Ik heb ook de grootste moeite met die timertjes.
Ik had vorig jaar uit frustratie een tuintimertje gemaakt.
Die is echter nog nooit in de praktijk uitgetest.

Maar als ik m zo eens even over lees, is ie wel lekker simpel.

Misschien kan je er wat mee.

Bijgesloten.

tuintimer.ino (2 KB)

Citystars:
Ik wil een output voor een bepaalde tijd hoog laten staan tenzij ik een puls krijg van een bepaalde input ( of constant) zodat deze uitgang laag word.

Hoi.
Het kan niet vaak genoeg gezegd worden:
Deel je probleem op in kleinere, wel oplosbare problemen.
Zo behoud je het overzicht en wanneer je die kleinere problemen hebt opgelost, heb je je grote probleem ook opgelost.

[#]Output moet standaard hoog zijn.
[#]Tenzij er een bepaalde tijd is verlopen.
[#]Of tenzij er een inputwaarde geldig is.

Nu oplossen:
Je moet altijd bijhouden wat je aan het doen bent, en wat je al gedaan hebt.
Daarom werk je met variabelen.
Die variabele kun je gebruiken om een bewerking op te doen (je kan er bijvoorbeeld mee rekenen, of m ergens mee vergelijken).
Uiteindelijk gebruik je de waarde van de variabele om je uitgang te sturen.

  • Maak de variabele en geef die een waarde die correspondeert met HOOG.
    Maak een tweede variabele waarin de vorige toestand word opgeslagen, zodat je kunt bijhouden of er iets veranderd is.
  • Houd de tijd bij.
    Dat doe je zoals in het voorbeeld van "Blink without delay".
    Ook hiervoor gebruik je meerdere variabelen.
    Kijk of er voldoende tijd verstreken is om iets te doen.
    Hiervoor moet je ook weten wat de huidige toestand is.
    Doe wat er gedaan moet worden (dat kan dus ook "niets" zijn)
  • Kijk of de inputwaarde geldig is.
    Doe wat er gedaan moet worden (dat kan dus ook "niets" zijn)

Zoals je ziet kan er hier ook nog aan de efficiëntie gewerkt worden maar dat zit er bewust in...

if (years>7) { years = 0; decades++; }
wordt natuurlijk
if (years>9) { years = 0; decades++; }

En zo zitten er nog wat foutjes in.:slight_smile:

Blinkwithoutdelay, met alle respect, werkt niet nar mijn idee.
Want die loopt na een dag of 50 stuk.
Op de ..weet ik hoe het heet.. overflow ofzoiets.
Blinkwithoutdelay moet je weggooien.
Scheelt een paar weken vogelen.

Of eigenlijk is het dat je de max millies value erin moet sleutelen.
Het is een schande dat dat nog steeds niet in de "officiele" arduino software is ingesleuteld.

#define MAX_MILLIS_VALUE 34359738
etc.

Met alle respect.
Happy new year.

rikky:
Blinkwithoutdelay, met alle respect, werkt niet nar mijn idee.
Want die loopt na een dag of 50 stuk.
Op de ..weet ik hoe het heet.. overflow ofzoiets.
Blinkwithoutdelay moet je weggooien.
Scheelt een paar weken vogelen.

integendeel

Blink without delay loopt prima, maar enkel omdat er aftrekken gebruikt wordt heeft de overflow geen gevolgen.

Dit is makkelijk aan te tonen met een korte schets die de waarde van miellies laat overflowen en daar een andere van aftrekt.

void setup() 
{
  Serial.begin(115200);
  Serial.println("Start ");
  
  uint32_t x = 0xFFFFFFF0;
  uint32_t miellies = 0xFFFFFFF0;
  Serial.print(x);
  
  while (miellies - x < 50)
  {
    Serial.print(miellies);
    Serial.print(" - ");
    Serial.print(x);
    Serial.print(" = ");
    Serial.println(miellies - x);
    
    miellies++;
  }
}

void loop() 
{
}

natuurlijk is miellies een gesimuleerde millis();

Kortom Blink without delay is een prima techniek voor scheduling.

Het pattern is

void loop()
{
  if (millis() - previousTime >= threshold)   // soms ook  millis() - previousTime > threshold 
  {
     previousTime += threshold;                    // previousTime = millis();   kan ook, net iets ander gedrag, voor meeste sketches niet relevant.

     // doe de code die 1 keer per threshold milliseconden gedaan moet worden
  }
  
  // schedule andere zaken.
}

Wegens de tips het kunnen klaren.
Paar uurtjes men hoofd erop gebroken maar toch de oplossing gevonden ;)!

int relaisState = LOW;
long previousMillis = 0;
long interval = 20000;

void setup()
{
pinMode(contact, INPUT_PULLUP);
pinMode(relais, OUTPUT);
}

Void loop()
{
	deurcontact = digitalRead(contact);
	unsigned long currentMillis = millis();

	if(buttonPushCounter % 2 == 1)
	{
		relaisState = LOW;
		previousMillis = currentMillis;
	}

	if (deurcontact == HIGH && buttonPushCounter % 2 == 0)
	{
		if(currentMillis - previousMillis > interval) {
			
			if (relaisState == HIGH);
			{
				relaisState = LOW;
			}
		}
		else
		{
			relaisState = HIGH;
		}
	}

	digitalWrite(relais,relaisState);
}

Voor de mensen die nieuwsgierig zijn.
Kan zijn dat er dingen weggelaten zijn.
Dit stuk code eruit gehaalt.

Bedankt!

Oh, nou at ga ik dan eens bekijken binnenkort.
Bedankt in ieder geval voor de uitleg.

Nou, ik ben blijkbaar niet de enige die problemen heeft (gehad) met de timerfunctie van blinkwithout delay.
Als je een klein applicatietje maakt, dat in de praktijk 24 op 24 uur moet werken, jaar in jaar uit, voldoet ie niet, of je moet heel erg uitkijken, hoe je m schrijft.
En als je je arduinotje dan ergens achter hebt geplakt, en je moet er helemaal heen kruipen met je laptop, om het 1 en ander te veranderen, (bijvoorbeeld resetten voor de volgende 50 dagen), wordt je daar best wel sjacherijnig van.
millis loopt over na 50 dagen en begint weer terug op nul.
Dus pas op hoe je dat opvangt, en druk vooral niet op je knopje (of watever) tijdens dat ie overloopt.
Afhankelijk van je timer kan dat een seconde, uur of dag beslaan, dat je niet op je knopje mag drukken.

In het geval van Citystar neem ik aan dat ie zijn deur het hele jaar door bewaakt wil hebben.

Er is inmiddels nogalwat voor op het internet te vinden gelukkig.
onder vele anderen:
http://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html

Misschien een nieuw topic?
Of deze gewoon houden?

Nou, ik ben blijkbaar niet de enige die problemen heeft (gehad) met de timerfunctie van blinkwithout delay.
Als je een klein applicatietje maakt, dat in de praktijk 24 op 24 uur moet werken, jaar in jaar uit, voldoet ie niet, of je moet heel erg uitkijken, hoe je m schrijft.

Er zijn mischien wel duizenden mensen dieproblemen met blink without delay gehad hebben.
Het komt wekelijks voor op het forum, mischien wel vaker.

En ja, voor alle applicaties geldt dat je uit moet kijken hoe je hem schrijft. Het algoritme om hoe op de juiste manier met de overflow van de millis() en micros() klok om te gaan is al jaren bekend, maar het is minder intuitief dat aftrekken wel werkt waar optellen faalt.

Er is mij op dit moment één probleem bekend met millis(), en dat is NIET de overflow. millis() heeft de eigenschap dat hij een getal kan overslaan, oorzaak, de ophoging van de interne teller gebeurt tegelijk met een foutcorrectie. DIt is een bekend probleem waarvoor geen goede oplossing bestaat zover ik weet. [ Een goede oplossing heeft vrijwel dezelfde code grootte en snelheid als de huidige millis().]
De enige manier om hiermee om te gaan is altijd ongelijkheden (> en < en >= en <= ) te gebruiken als je met millis() of micros() en tellers in het algemeen werkt. Als je namelijk == gebruikt en hij springt net met 2 omhoog (of je bent gewoon een paar millis te laat) dan faalt de IF.

Dus pas op hoe je dat opvangt, en druk vooral niet op je knopje (of watever) tijdens dat ie overloopt.
Afhankelijk van je timer kan dat een seconde, uur of dag beslaan, dat je niet op je knopje mag drukken.

Kun je een voorbeeld sketch posten waarin dit misgaat? Ik ben heel benieuwd.

Van de link die jij geeft
If you are just interested in a repeating timer then see http://arduino.cc/en/Tutorial/BlinkWithoutDelay for a simple reliable repeating timer which does not count down. The code below works because even if currentMillis overflows back to a small number, currentMillis – previousMillis still gives the correct result.
void loop() {

  • unsigned long currentMillis = millis();*
  • if(currentMillis - previousMillis> interval) {*
  • // save the last time*
  • previousMillis = currentMillis;*
  • // do stuff here each interval (interval -- an unsigned long)*
  • ...*
  • }*

Er staat wel een fout op de pagina, hier wordt == gebruikt met millis(). - zie boven)
// the loop routine runs over and over again forever:
void loop() {
_ if (millis() == timeout) { // NOTE: the == only toggle led when millis() equals timeout_

  • // time to toggle the Led*
  • timeout += 1000;*
  • if (digitalRead(led)) {*
  • digitalWrite(led, LOW); // turn the LED off by making the voltage LOW*
  • } else {*
  • digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)*
  • }*
  • }*
    }
    This code works because when timeout + 1000 overflows, millis() will not equal it until millis() also overflows.
    Deze code werkt niet als millis() net met 2 verspringt over de waarde van timeout heen,
    Millis() zal ~50 dagen moeten ophogen voordat ie weer een kans heeft om gelijk aan timeout te zijn.

Een mijn insziens betere uitleg van hoe om te gaan met millis() - Gammon Forum : Electronics : Microprocessors : How to do multiple things at once ... like cook bacon and eggs -

Kun je een voorbeeld sketch posten waarin dit misgaat? Ik ben heel benieuwd.

Daar maar eens mee beginnen.
http://forum.arduino.cc/index.php?topic=168476.0
Dat was naar aanleiding van:
http://forum.arduino.cc/index.php?topic=141106.new;topicseen#new

Ik heb nu dus inmiddels wel geleerd dat ook digitalread() een interne delay heeft, en zo nog wel wat opdrachten, waardoor ik inmiddels begin te bevroeden, wat er allemaal nog zo meer fout kan gaan.
Ik ga het eens even allemaal bestuderen.

0 - 4294967295 = 1

Als ik het scetchje van robtillaart run, zien ik als x: 4294967280.
mijn : #define MAX_MILLIS_VALUE 34359738 ..... is dus al fout.
maar als ik 0-x doe krijg ik 16.

Als ik dit run:

void setup()
{
Serial.begin(115200);
Serial.println("Start ");
uint32_t x = 0xFFFFFFF0;
uint32_t miellies = 0xFFFFFFF0;
Serial.print("0 - ");
Serial.print(x);
Serial.print(" = ");
Serial.println(0 - x);
Serial.print("0 - 4294967295 = ");
Serial.println(0 - 4294967295);

Start
0 - 4294967280 = 16
0 - 4294967295 = 1

Ik denk dus gewoon te moeilijk.
Het is een soort van cirkeltje.

Maar je moet wel het goede getalletje pakken.

Maar scheinbaar kan het dus allemaal ook zonder rekening te houden met die overflow.
Ik zal het allemaal nog eens bekijken.
Het is niet makkelijk.

dat is unsigned rekenen.

Het is een soort van cirkeltje.

Inderdaad! n et zoals jijzelf doet met een 12 uurs klok.

voorbeeld duration = eindtijd - begintijd

  1. 4 uur - 2 uur = 2 uur.
  2. 4 uur - 10 uur = 6 uur

precies hetzelfde alleen loopt de millis klok van 0 tot 4294967295 ipv 0..11

PS ik heb je tuinsproeier gerefactored als voorbeeld hoe je met de millis werkt. (andere thread)
Als je er vragen over hebt, hoor ik het graag.