Wie weet wat leuks om te maken?

Je moet helemaal geen delay gebruiken, lees de tutorial "blink without delay" - http://arduino.cc/en/Tutorial/BlinkWithoutDelay -

voor iedere functie die je wilt schedulen maak je een dergelijke constructie.

Dankjewel! Inmiddels heb ik de tutorial gedaan.
Echter blinkt de led geen 1 seconden lang maar 1 milli sec ofzo (net genoeg om waar te nemen). Weet iemand waarom dit is? Er staat toch duidelijk 1000 in de code:

unsigned long iTimer = 0;
unsigned long iTimerCurrent = 0;
int ledState = LOW;

void randLed()
{
   iRandomNum = random(8, 11);
   iTimerCurrent = millis(); 
   
   if(iTimerCurrent-iTimer > 1000)
   {
     iTimer = iTimerCurrent;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(iRandomNum, ledState);
   }
}

void loop()
{
   pressButton(buttonRed, ledRed);
   pressButton(buttonGreen, ledGreen);
   pressButton(buttonBlue, ledBlue);
   
   randLed();
}

change this line iRandomNum = random(8, 11); to iRandomNum = 8;

You use one state for 3 different leds, that should be three states I guess.

Hoi Rob,

Ik ben erachter gekomen wanneer ik de functies:
pressButton(buttonRed, ledRed);
pressButton(buttonGreen, ledGreen);
pressButton(buttonBlue, ledBlue);

Uit de code verwijder hij wel de ledjes laat branden. En inderdaad je opmerking klopt over 3 leds ipv 1.

Ik snap nu ook waarom hij maar 1 milli sec brandt. Hij voert de pressButton functie uit en ziet dat de knop niet is ingedrukt en zet de LED dus op LOW.
Hoe kan ik dit omzeilen?

je moet pressbutton niet de led veranderen, maar een variabele zetten en onthouden dat je de knop ingedrukt hebt.
Later als je de led veranderd kijk je of de knop ingedrukt was.

voldoende?
Wat ik bijna altijd doe is op papier de gewenste werking simuleren, zelf ben ik dan de processor en vraag me af welke stappen ik moet doen en wanneer.

robtillaart:
Wat ik bijna altijd doe is op papier de gewenste werking simuleren

Dat doe ik ook altijd even op papier je algoritme uittekenen werkt een stuk makkelijker.

@ Rob: Thanks voor de tip, ga ik in het vervolg doen.
Echter zeg je wanneer ik de LED aan zet checken of de knop was ingedrukt, maar dat doe ik nu toch ook?

void pressButton(int button, int led)
{
   if(digitalRead(button) == HIGH)
   {
      digitalWrite(led, HIGH); 
   }
   else
   {
      digitalWrite(led, LOW);   
   }
}

Probleem is dat hij steeds in de ELSE terecht komt als de button niet is ingedrukt. En dat komt in conflict met de andere functie die de LED just random aan wil zetten.

Nee dat doe je niet.
Je controleert of de knop is ingedrukt, en zet dan de LED aan.
Dat is iets anders als wanneer je de LED aanzet, je controleert of de knop ook was ingedrukt.

Dan je probleem.
Je controleert nu of de knop is ingedrukt, en in dat geval ga je wat doen, maar dat lukt niet.
Anders moet ie wat anders doen, en hij gaat dat andere dan ook doen, zo heb je geconstateerd.
Draai het dan eens om (is net zo moeilijk).
Controleer of de knop NIET is ingedrukt en zet dan de LED uit, en anders zet je de LED aan.
Kijken of dan de LED altijd aan blijft.

Overigens, hoe heb je je buttons aangesloten ?
Ik adviseer je de button een verbinding naar GND te laten maken, en de pullup aan de ingang aan te zetten.
Dan krijg je geen ongedefinieerde ingangen (die dus alle denkbare waarden kunnen geven).
Alleen word het dan wel:

if digitalRead(button) == LOW 
 {
  digitalWrite(led, HIGH);
  }
else
  {
      digitalWrite(led, LOW);   
   }
}

In principe kun je zelfs de gewenste waarde achter de if weglaten maar ik weet niet of de IDE dat accepteert.
Dan zou je moeten krijgen:

if digitalRead(button)
 {
  digitalWrite(led, LOW);
  }
else
  {
      digitalWrite(led, HIGH);   
   }
}

De voorwaarde is dan die van je button.
Zo'n if voorwaarde heeft maar 2 mogelijkheden, waar (= 1 of HIGH) of niet waar (= 0 of LOW).
De heren met meer ervaring mogen aangeven of dit op deze manier kan en of dat ook wel netjes genoeg is.

Zoiets misschien.

clock();
  
   if (seconds >= Time){
    toggleState = false; clock_reset();}
  

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    buttonState = reading;
  }
  lastButtonState = reading;
    
   if (buttonState == LOW)
       if (toggleReading == 0)
        {toggleReading = 1; 
        if (toggleState == 0) {toggleState = 1; clock_reset();}
        else {toggleState = 0;}
    }}
    
  if (buttonState == HIGH)
    {if (toggleReading == 1)  {toggleReading = 0;}
   }
    
 // set the LED using the state of the button:
  digitalWrite(ledPin, toggleState);

Deze was weggevallen, na clock(), sorrie

int reading =! digitalRead(buttonPin);

@MAS3:
"Je controleert of de knop is ingedrukt, en zet dan de LED aan.
Dat is iets anders als wanneer je de LED aanzet, je controleert of de knop ook was ingedrukt."

Kan je mij in een if / else voorbeeldje laten zien wat daar het verschil in is? Want voor mij komt het alsnog op hetzelfde neer.

Ik heb overigens de button met een pulldown 10k ohm naar de GND en de andere naar een digitalPin.
Ik ga nog even met de code aan de gang om te kijken hoe ik het oplos.

Het komt bijna op hetzelfde neer, dat klopt.
Maar je moet goed op de volgorde letten als je fouten gaat opzoeken.
Het verschil hier is dat jij kijkt of de knop IS ingedrukt, en dan meteen iets doet.

Dit is niet wat Rob bedoelde.
Wat Rob bedoelde is dat je nu nergens de status van de knop bijhoudt.
Dan zou je dus een extra variabele hebben waarin de stand van de knop word bijgehouden.
Aan de hand daarvan kun je op een later tijdstip zien of je ook iets moet veranderen aan de LED.
Bijkomend voordeel is dan ook dat je eventueel met dezelfde waarde ook nog iets anders kunt doen zonder dat je daarvoor de knop opnieuw inleest en wellicht een ander resultaat krijgt.

Rob heeft het dus over wat de knop WAS toen je er naar keek.

Zoals je ziet doet rikky een duit in het zakje om contactdender af te vangen, ook bekend als debouncing.
Ook hiervoor moet je bijhouden wat de stand van de knop was (lastButtonState) en (reading).

Ah ik snap hem. Ik heb het zowaar werkend gekregen:

  • De functie randLed stoort niet meer met de andere functie en hij knippert dus random een ledje met de gewenste tijd
  • De functie pressButton werkt MAAR er zit een bug in:

Als ik button van de rode led in druk gaat ineens de groene led aan
Als ik de button van de groene led in druk gaat de blauwe aan
Als ik de blauwe in druk gaat de rode aan

M.a.w. ze zijn allemaal een pin opgeschoven (ze staan op RGB volgorde en dus via de buttons op GBR), terwijl ik toch echt niets in het circuit veranderd heb.

Code (zie de wijziging waarbij ik de buttonstate onthoud):

int ledRed = 8;
int ledGreen = 9;
int ledBlue = 10;
int buttonRed = 5;
int buttonGreen = 6;
int buttonBlue = 7;
int aRandom[] = {};
int iRandomNum = 0;
unsigned long iTimer = 0;
unsigned long iTimerCurrent = 0;
int ledState = LOW;
int numUsed = 0;
int buttonState = LOW;
int randLedState = LOW;

void setup()
{
   pinMode(ledRed, OUTPUT);
   pinMode(ledGreen, OUTPUT);
   pinMode(ledBlue, OUTPUT);
   pinMode(buttonRed, INPUT);
   pinMode(buttonGreen, INPUT);
   pinMode(buttonBlue, INPUT);
}

void pressButton(int button, int led, int randLedState)
{
   if(buttonState == HIGH)
   {
      digitalWrite(led, HIGH); 
   }
   else if(randLedState == LOW)
   {
      digitalWrite(led, LOW);   
   }
   
   buttonState = digitalRead(button);
}

boolean randLed()
{
   if(numUsed == 0)
   {
     iRandomNum = random(8, 11);
   }
   iTimerCurrent = millis(); 
   
   if(iTimerCurrent-iTimer > 500)
   {
       iTimer = iTimerCurrent;
  
      // if the LED is off turn it on and vice-versa:
      if (ledState == LOW)
        ledState = HIGH;
      else
        ledState = LOW;
      
      numUsed ++;
  
      // set the LED with the ledState of the variable:
      digitalWrite(iRandomNum, ledState);
   }
   
   if(numUsed >= 2)
   {
      numUsed = 0; 
   }
   
   return ledState;
   
}

void loop()
{  
   randLedState = randLed();
   
     
     
     pressButton(buttonRed, ledRed, randLedState);
     pressButton(buttonGreen, ledGreen, randLedState);
     pressButton(buttonBlue, ledBlue, randLedState);
}

thabram:
Ik heb overigens de button met een pulldown 10k ohm naar de GND en de andere naar een digitalPin.

Dit is mij niet geheel duidelijk.
Heb je het hier over 2 buttons, of over de 2 pins van 1 button ?

Je moet voorkomen dat het onbekend is of die button nou wel of niet is ingedrukt, en in beide gevallen een min of meer geforceerde waarde genereren.

Vwb de verschoven LEDs, dat is vreemd.
Heb je ook al iemand anders naar je bedrading laten kijken ?
Vaak zit je zelf zo vast in je werkwijze dat je voor de hand liggende fouten niet opmerkt, terwijl een ander die vrijwel direct ziet.

Toen ik het topic zag dacht ik echt "moet een vrij simpel iets zijn om te maken"

Maar wordt toch nog heel projectje :slight_smile: Blijf um zeker volgen!

Ik heb 3 buttons elk met een 10k ohm naar de GND + aangesloten op een digitalPin en de andere kant van de button naar de +.
Ik heb ook 3 LEDs elk naar de GND en de plus met tussenkomst van een 180ohm naar een digitalPin.

Verder heb ik geen wijzigingen gemaakt met de bedrading. Het is ook een simpel circuit. Kan het door code komen dat ze opschuiven?

EDIT: Ik heb het gevonden, zat in de code:

void pressButton(int button, int led, int randLedState)
{
   //Op deze plek werkt het zoals het hoort
   buttonState = digitalRead(button);
   
   if(buttonState == HIGH)
   {
      digitalWrite(led, HIGH); 
   }
   else if(randLedState == LOW)
   {
      digitalWrite(led, LOW);   
   }

    //buttonState = digitalRead(button); <-- op deze plek veroorzaakt hij het probleem
}

Maar ik heb geen idee waarom, iemand?

MAS3:

thabram:
Ik heb overigens de button met een pulldown 10k ohm naar de GND en de andere naar een digitalPin.

Dit is mij niet geheel duidelijk.
Heb je het hier over 2 buttons, of over de 2 pins van 1 button ?

Je moet voorkomen dat het onbekend is of die button nou wel of niet is ingedrukt, en in beide gevallen een min of meer geforceerde waarde genereren.

Vwb de verschoven LEDs, dat is vreemd.
Heb je ook al iemand anders naar je bedrading laten kijken ?
Vaak zit je zelf zo vast in je werkwijze dat je voor de hand liggende fouten niet opmerkt, terwijl een ander die vrijwel direct ziet.

OK, nu snap ik de bedrading.

thabram:
Ik heb het gevonden, zat in de code:

    //buttonState = digitalRead(button); <-- op deze plek veroorzaakt hij het probleem

}




Maar ik heb geen idee waarom, iemand?

Heb je het ook opgelost dan, omdat je zegt zat in de code ?

Enige dat mij opvalt is dat ik de variabele (button) maar op 2 plaatsen terug zie, als je 'm initieert, en als je m gebruikt om te lezen.
Vergis ik me daar in ?

Het is inderdaad opgelost. De button read moest boven de IF / ELSE statement komen. Ik definieer de buttonstate helemaal bovenaan het script (op LOW).
Maar ik snap even niet waarom hij de leds doorschuift als de button read onder de IF / ELSE staat.

Ik ben inmiddels begonnen met de code voor het simon-says spelletje. Aller eerste wat ik maak is een functie die adhv parameters 1 of meerdere leds laat knipperen voor een bepaalde tijd.
Die heb ik namelijk meerdere keren nodig.

Wat ik in gedacht heb is het volgende:

Startgame functie:
Deze start het spel op. Eerst laat hij een paar ledjes knipperen etc.

PlayGame functie:
Het spel gaat beginnen, er wordt een random ledje aangezet, daarna is de gebruiker aan de beurt.

Fail functie:
Heb je het fout? Dan gaan de ledjes knipperen en begint het spel overnieuw.

Proceed functie:
Antwoord is goed. Laat ledjes knipperen (op een andere manier dan fail) en ga verder met spelen.

CheckInput functie:
Deze controleert de user input tegen de gegenereerde input en roept fail of proceed aan.

Dat is hoe ik het voor nu wil bouwen. Iemand tips?

Wat ik later wil toevoegen is:

  • LCD om bv score te laten zien.
  • Speaker om geluidjes te spelen
  • Programmeren voor meerdere spelers

Uiteindelijk wil ik alles echt in elkaar knutselen via een printplaat + PCB etc. (wat ik nog nooit gedaan heb en dus 0 ervaring mee heb).
Maar ik wil het gewoon onder de knie krijgen dus lijkt me een goede oefening.

Simon is een goed project, je top down analyse zit in de juiste richting. Hieronder hoe ik het zou opdelen in de vorm van pseudo-code.
Zonder de variabelen (OK eentje) en uitgewerkte functies.

setup()
{
  initializeGame();
}

void loop()
{
  simonsTurn();
  playersTurn();

  if (compareSimonPlayer() == true)
  {
     happyLeds();
     highScore();
     level++;
  }
  else
  {
    sadLeds();
    level--;
  }
}