Goedemorgen.

op het moment ben ik bezig met een project waarbij een toon 60 keer per minuut herhaal moet worden dit constant.
maar later ook nog verandert moet kunnen worden op een relatief eenvoudige manier.

dit kan natuurlijk met een aantal delays & ee repeat functie kunnen worden gedaan. maar dit vereist telkens weer rekenwerk.
maar ik vroeg me af of hier een commando voor is, of iemand een simpele oplossing voor heeft.

ik zie graag de antwoorden binnenkomen!
alvast bedankt!

mvg
piet

een toevoging:
het geluid duurt 30 miliseconden, en moet dus 60 keer per minuut herhaald worden. het liefst automatich verdeeld.

dit om mijn code een stuk simpeler te houden dan dat hij nu is.

Post je code eens , dan is er makkelijker iets over te zeggen.

om mijn volledige code te posten is een beetje onzin.

het gaat enkel om dit stukje (dit heb ik dan wel een 30-40 keer in de code omdat dit geluid meerdere tonen bezit met meerdere voorwaade gekoppelt aan een anologe poort, en de bijbehoorende waarde. en de gekozen optie ).

nu staat er een delay dat het precies 1 maal per seconden komt.
maar ik wil een algeheel stukje waar ik straks kan invullen ("ik wil 60 x per seconden, of 80 keer per seconden etc")
en dat ik dat door kan lussen dmv een simpel commando, bijvoorbeeld door de klok voor een bepaald gedeelte aan te passen in mijn code (is dat mogelijk(?)

ik hoop dat u begrijpt wat ik bedoel

{
if (digitalRead(3) == HIGH)// testknop 1

tone(11,36,39); // eerste toon korotkoff 1 maal per seconden.
delay(951);

else
notone()
}

Delay eruit kieperen en werken met millis.
Zie Blink zonder delay.

precies.

delay's zijn niet goed om te programmeren. van in begin leren die dingen niet te gebruiken.

in je loop procedure maak je een aantal 'subprogrammas' die geladen moeten worden. bij elke loop kijk je hoeveel millis() je arduino heeft en ga je bv je subprogramma draaien als je 1000millis verder zit.

het vraagt een kleine aanpassing, maar is erna veeeeeeeeeel makkelijker. ik heb mijn hele autoprogramma zo met delay's uitgevoerd en het duurt heel lang voor bepaalde waardes aangepast worden op het display (omdat de arduino eenmaal in een bepaalde loop zit te wachten).
ben nu heel het programma aan het herzien.

https://learn.adafruit.com/multi-tasking-the-arduino-part-1/overview

ik zou die knop dan ook met een interupt laten werken. probleem is nu dus dat je programma in die delay van 951ms kan zitten, terwijl je de knop eens loslaat en weer indrukt. en dan gebeurt er niks.

voor je toon te maken, zou ik een klein subprogrammatje maken (function, procedure... whatever ze het noemen bij arduino).


unsigned long lastTime=0;

void makeTone(long currenttime){
    if ( (lastTime + 1000)< currentTime ){
       tone(11,36,39); // eerste toon korotkoff 1 maal per seconden.
       lastTime = currentTime;
    }
}

als je dit dan oproept uit een ander deel met
makeTone(millis() ); dan wordt het elke keer uitgevoerd als je 1000ms verder zit dan de vorige keer dat je het uitvoerde.
ik heb mijn programma zo eens aangepast met een 4tal leds (binair optellen) en elke seconde liet ik de leds verandereren van status.
ipv telkens een delay van 1sec uit te voeren, gebruikte ik het voorgaande. de arduino ging 54 000keer door mijn loop alvoorens die een ledstatus aanpaste. ik kon dus 54000 andere dingen uitvoeren alvoorens ik nog eens een ledje moest aanpassen


unsigned long lastTime=0;

void makeTone(long currenttime){
    if ( (lastTime + 1000)< currentTime ){
       tone(11,36,39); // eerste toon korotkoff 1 maal per seconden.
       lastTime = currentTime;
    }
}

Enkele opmerkingen hier.

De periode is 1001 ms. Gebruik <= ipv < of 999 ipv 1000.

De code veronderstelt dat makeTone() binnen de milliseconde aangeroepen wordt. Als dit niet het geval is dan kan lastTime beginnen verschuiven zodat sommige periodes langer worden.

Je kan best lastTime initialiseren met millis() i.p.v. nul. millis() is waarschijnlijk nul als de Arduino pas opgestart is, maar als je de timer op een later moment start dan is dit niet gegarandeerd en loopt het fout tijdens de eerste iteratie.

De code loopt fout als millis() de max. waarde nadert (na ongeveer 49 dagen): lastTime + 1000 kan dan overlopen waardoor ((lastTime + 1000) < currentTime) altijd waar is tot millis() uiteindelijk ook overloopt. Dus best dit gebruiken: (1000 < (currentTime - lastTime)). Merk op dat (A + cst < B) niet hetzelfde is als (cst < B - A).

die code heb ik rap uit mijn mouw geschut. ik weet ook niet hoe je het het beste schrijft.
ik heb dan ook de link toegevoegd waar je alles kan nalezen zodat het verstaanbaar wordt.

mijn arduino laptop ligt voor het moment op mijn werk, dus kon ook mijn source codes niet ff snel raadplegen

in mijn voorbeeld roep ik ook millis() op bij het aanroepen van de functie.
echter in mijn programma's gebruik in in de loop ergens
currentTime = millis().

lasttime moet niet geinitialiseerd worden met millis. als de arduino start, dan start die de bootloader, gaat alle variabelen inlezen (ook mijn lastTime), gaat dan pas de setup lopen, en daarna komt die in de loop.
millis() zal dan zowieso al meer zijn dan 0+1000.

De periode is 1001 ms. Gebruik <= ipv < of 999 ipv 1000.

TS kan met die 1000 dan ook spelen en ervoor zorgen dat het totaal van zijn instructies + die wachttijd op de correcte tijd uitkomt. bij TS was het origineel 951ms in zijn delay.
In mijn loop'en die ik gebruik, staat ook die 1000 niet hardcoded in, maar is het een variabele van mijn classes. ik definier bij het aanmaken van een object, hoeveel 'tijd' de cpu daarin zal steken (beetje multithreading).
een functie waar de update() elke 1000ms uitvoert zal minder prioritair zijn dan eentje die elke 100ms gestart wordt.

De code veronderstelt dat makeTone() binnen de milliseconde aangeroepen wordt. Als dit niet het geval is dan kan lastTime beginnen verschuiven zodat sommige periodes langer worden.

die versta ik niet. stel de arduino loopt in het programma en op 5123 start hij makeTone. hij ziet dat de tijd verstreken is, en zal 5123 ook in lasttime schrijven (ik roep hier nergens millis() nog eens op dus die tijd verloopt niet).
daarna gaat de arduino een paar 1000keer door de loop totdat er 1000ms verlopen zijn en op 6126 roept hij MakeTone op. de tijd is vertreken en hij zal 6126 in het geheugen zetten van lasttime.
en alweer telt die 1000ms verder. waarom zou die beginnen schuiven aangezien die telkens opnieuw 1000 zal bijtellen tov de oude tijd?

om die paar ms toch correcter te lopen zou je eventueel ook lastTime = lastTime + 1000; kunnen doen.

int SpeakerPin = 11;  // speakerpin (pwm pin)
int SpeakerState = LOW;
unsigned long previousMillis = 0; //onthoudt de tijd
long OnTime = 39;       // toon lengte
long OffTime = 1000;     // totale lengte toon

void setup() {
  // put your setup code here, to run once:
  pinMode(SpeakerPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long currentMillis = millis();   // kijkt naar tijd

  if((SpeakerState == HIGH && (currentMillis - previousMillis >= OnTime)))
  {
    SpeakerState = LOW; // zet speaker uit
    previousMillis - currentMillis; // onthoudt tijd
    digitalWrite(SpeakerPin, SpeakerState); // update status speaker
  }
  else if ((SpeakerState ==LOW && (currentMillis - previousMillis + OnTime >= OffTime)))
  {
    tone(11,224,39); // toon generator. pin/feqeuntie/duur. hierbij is duur ook bovin in gegeven maar de code werkt anders niet??
    previousMillis = currentMillis;
    digitalWrite(SpeakerPin, SpeakerState); // 
  }
}

okee ik heb het nu in de richting van dit.

Zeker het werkt zeer vloeiend. en ik kan ook simpelweg boven in mijn programmatje veranderen wat de tijd zal moeten zijn etc.

Nu vraag ik me af waarom de functie "tone" nog steeds de volgorde "pinnummer, freqeuntie, duur" moet zijn. terwijl de duur ook bovenin wordt aangegeven. en de arduino niks lijkt te doen met de gegeven tijd in de tone functie.

je mag onderaan gewoon zetten
tone (SpeakerPin, 224,OnTime)

en dan hoef je enkel bovenaan de variabelen te veranderen om de tijd te wijzigen

class Bmp60   // standart waaruit we verder werken.
{ 
    int SpeakerPin; // speaker pin nummer (wordt 11 (PWM))
    long OnTime;    //miliseconden AAN
    long OffTime;   //miliseconden UIT

    int SpeakerState;   // onthoudt de huidige status LED
    unsigned long previousMillis; // onthoudt de miliseconden

  public:
  Bmp60(int pin, long on, long off)
  {
        SpeakerPin = pin;
        pinMode(SpeakerPin, OUTPUT);

        OnTime = on;
        OffTime = off;

        SpeakerState = LOW;
        previousMillis = 0;     // de waardes bij clas bmp60
  }

  void Update() 
  {
  unsigned long currentMillis = millis();   // kijkt naar tijd

  if((SpeakerState == HIGH && (currentMillis - previousMillis >= OnTime)))
  {
    SpeakerState = LOW; // zet speaker uit
    previousMillis - currentMillis; // onthoudt tijd
    digitalWrite(SpeakerPin, SpeakerState); // update status speaker
  }
  else if ((SpeakerState ==LOW && (currentMillis - previousMillis + OnTime >= OffTime)))
  {
    tone(11,36,OnTime); // toon generator. pin/feqeuntie/duur. hierbij is duur ook bovin in gegeven maar de code werkt anders niet??
    previousMillis = currentMillis;
    digitalWrite(SpeakerPin, SpeakerState); // 
  }
}
};  // Gedebugdt

Bmp60 Speaker1(11, 30, 2000);
Bmp60 Speaker2(11, 30, 5000);      //  instelbare waarde voor speaker. (werkt atm op 11:42 op 7-3-2016 nog niet)

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
  Speaker1.Update();
  Speaker2.Update();
}

Heel mooi. heb ik die mooie webpagina van "fcapri" bekeken en dan kom ik na een aantal keer doorklikken op en heel mooi iets uitkomt met 1 class waarbij voor elke uitbreiding maar 2 regels te hoeven worden geschreven.

nu ben ik daar al geruim een 1,5-2 uur mee bezig. maar ik kom er weer niet uit.
bij "bmp60 Speaker 1" moet een andere toon komen dan bij "bmp60 Speaker 2"
maar ik kan dit niet goed inplementeren in de code.
(nee dit krijgt voorwaardes en zullen nooit tegelijk afspelen)

ziet iemand hier de oplossing waar ik gewoon overheen kijk?

tevens de OnTime werkt idd zoals verteld.
in de enkelvoudige versie.

bedank daarvoor.

uw toon, zit dat niet gewoon in de frequentie?
hier dus die 36
tone(11,36,OnTime);


class Bmp60   // standart waaruit we verder werken.
{ 
    int SpeakerPin; // speaker pin nummer (wordt 11 (PWM))
    long OnTime;    //miliseconden AAN
    long OffTime;   //miliseconden UIT
    int freq = 36;
    int SpeakerState;   // onthoudt de huidige status LED
    unsigned long previousMillis; // onthoudt de miliseconden
 
  public:
  Bmp60(int pin, long on, long off)
  {
        SpeakerPin = pin;
        pinMode(SpeakerPin, OUTPUT);
 
        OnTime = on;
        OffTime = off;
 
        SpeakerState = LOW;
        previousMillis = 0;     // de waardes bij clas bmp60
  }

  void setFreq(int frekwentie){
        freq = frekwentie;
  }
 
  void Update() 
  {
  unsigned long currentMillis = millis();   // kijkt naar tijd
 
  if((SpeakerState == HIGH && (currentMillis - previousMillis >= OnTime)))
  {
    SpeakerState = LOW; // zet speaker uit
    previousMillis - currentMillis; // onthoudt tijd
    digitalWrite(SpeakerPin, SpeakerState); // update status speaker
  }
  else if ((SpeakerState ==LOW && (currentMillis - previousMillis + OnTime >= OffTime)))
  {
    tone(11,freq,OnTime); // toon generator. pin/feqeuntie/duur. hierbij is duur ook bovin in gegeven maar de code werkt anders niet??
    previousMillis = currentMillis;
    digitalWrite(SpeakerPin, SpeakerState); // 
  }
}
};  // Gedebugdt
 
Bmp60 Speaker1(11, 30, 2000);
Bmp60 Speaker2(11, 30, 5000);      //  instelbare waarde voor speaker. (werkt atm op 11:42 op 7-3-2016 nog niet)
 
void setup() {
  // put your setup code here, to run once:
  Speaker1.setFreq(50);
  Speaker2.setFreq(100);

 
}
 
void loop() {
  // put your main code here, to run repeatedly:
  Speaker1.Update();
  Speaker2.Update();
}


ik heb gewoon een variabele toegevoegd freq = 36; als default. en dan nog een setFreq functie toegevoegd in uw class zodat je die kan aanpassen.

bij de setup heb ik ze dan beid eaangepast naar 50hz (speaker1) en 100hz (speaker2). vind het nog altijd hele lage frequenties

Freqeuntie is ook niet zo laag ;)

maar in de testen was dit een goed te herkennen iets vandaar.

Hartelijk bedankt!
weer zo stom iets dat ik zelf makkelijk had kunnen bedenken...
maar overheen keek.

mvg
piet

Ik zie nu in 2 postings de regel:

 previousMillis - currentMillis; // onthoudt tijd

voorbij komen.

Die regel doet zo volgens mij niks, die '-' moet een '=' zijn.

daar had u helemaal gelijk in!.

ik heb het meteen aangepast. dank daarvoor. :)

Onlangs gelezen op de ATmel website.

Een loop indien mogelijk laten lopen van max naar 0. Van 0 naar max dient er telkens een vergelijking te zijn tussen waarde en max. Omgekeerd stopt de loop sowieso als 0 bereikt wordt.