Voorbeeldprogramma

Uit TrompBot
Naar navigatie springen Naar zoeken springen

Beginnen | Hardware | Software | Voorbeeldprogramma | Inkscape & lasersnijden | Errors & Tips | Kekbot | [TrompBot Website] | Trompbots | Percussie & ritme | Fioretti programma


De Microcontroller wordt in de taal C++ geprogrammeerd. Deze taal heeft een aantal regels die je in de gaten moet houden om een goed programma te maken. Die regels zijn net zoiets als de spelling en gramatica van de Nederlandse of Engelse taal. Ze regelen hoe de taal moet gebruiken. Als je een programma maakt wat niet volgens de regels is, zal de computer het niet begrijpen en een foutmelding geven. Je moet dan je programma veranderen. Lees de regels dus eerst goed, en houd je er aan! Hieronder staan een paar programma's om te beginnen.


Een aantal voorbeeldprogramma's staan hier:

De basis

Dit is een leeg programma. Het doet niets, maar is wel een correct programma (zonder spelfouten).

 //leeg.ino: Een leeg programma, dit doet niets
 void setup()
 {
   // Hier komen de opdrachten die 1 keer gedaan moeten worden bij het aanzetten
 }
 
 void loop()
 {
   // Hier komen de opdrachten die elke keer gedaan moeten worden
 }

tip: Als er op een regel twee forward slashes staan (dat ziet er zo uit: //) dan wordt alles daarna tot het einde van de regel niet gelezen door de computer. Dat is makkelijk want zo kan je commentaar in je programma zetten zodat je zelf nog weet wat je had bedoeld.

Led aan en uit

Een programma wat een lampje laat knipperen is de basis voor iedere programmeur. Het laat zien dat alles werkt:

 // knipper.ino: knipper de groene led, aan en uit, met 1 seconde ertussen.
 
 // Voer deze instructie 1x uit bij het aanzetten
 void setup() 
 {               
   pinMode(14, OUTPUT);     // Schakel aansluiting (pin) nummer 14 als uitgang. Deze aansluiting is verbonden met de LED
 }
 
 // Blijf deze functie herhalen, zoalang de microcontroller aan staat
 void loop() 
 {
   digitalWrite(14, HIGH);   // zet pin 14 uitgang HOOG (aan)
   delay(1000);              // Wacht 1 seconden (1000 milliseconden)
   digitalWrite(14, LOW);    // zet pin 14 uitgang LAAG (aan)
   delay(1000);              // Wacht 1 seconden (1000 milliseconden)
 }

Dan nog een: Dit is een variatie op het eerste programma, maar maakt een wat langer patroon

 // knipper2.ino: Maak een knipper patroon
 // Voer deze instructie 1x uit bij het aanzetten
 void setup() 
 {                
   pinMode(14, OUTPUT);     // Schakel aansluiting (pin) nummer 14 als uitgang. Deze aansluiting is verbonden met de LED
 }
 
 // Blijf deze functie herhalen, zoalang er spanning op de microcontroller staat
 void loop() 
 {
   digitalWrite(14, HIGH); 
   delay(100);   
  
   digitalWrite(14, LOW); 
   delay(100);  
  
   digitalWrite(14, HIGH);
   delay(200);
  
   digitalWrite(14, LOW);
   delay(200);          
 
   digitalWrite(14, HIGH);
   delay(200);
   
   digitalWrite(14, LOW);
   delay(1000);          
 }

Schakelaar inlezen

Als je de linker schakelaar S2 indrukt, dan gaat het rode lampje uit.

 // schakelaar.ino - lees een schakelaar in, en schake led aan en uit
 
 void setup()
 {
   pinMode(5, INPUT_PULLUP); // drukknop, als input
   pinMode(2, OUTPUT);   // LED als output
 }
 
 void loop()
 {
   if ( digitalRead(5) == HIGH ) // als de schakelaar HOOG is (niet ingedrukt)
   {
     digitalWrite(2, HIGH);      //  zet dan de uitgang HOOG (lamp aan)
   }  
   else                          // anders
   {   
     digitalWrite(2, LOW);       //  zet de uitgang LAAG (lamp uit)
   }
 }

Wachten op de schakelaar (met while loop)

// wacht.ino - lees een schakelaar in en wacht tot je er op drukt
 
void setup()
{
  pinMode(5, INPUT_PULLUP); // drukknop, als input
  pinMode(2, OUTPUT);       // Rode LED als output
  pinMode(14, OUTPUT);      // Groene LED als output
  digitalWrite(2, HIGH);    // zet de uitgang HOOG (lamp aan)  

  while ( digitalRead(5) == HIGH ) // zolang de schakelaar HOOG is (niet ingedrukt)
  {
    ; // doe niets (en doe de while loop nog een keer)
  }

  digitalWrite(2, LOW);       //  zet de rode led uitgang LAAG (lamp uit)  
}

// Knipper de groene led in de loop
void loop()
{
  digitalWrite(14, HIGH);   
  delay(1000);
  digitalWrite(14, LOW);  
  delay(1000);
}


Een servo besturen

Sluit de servo aan op de uitgang 13 van de Launchpad. Als je het programma start gaat de servo bewegen tussen twee posities (90 graden uit elkaar) met een wachttijd van 1 seconde tussen de bewegingen. Meer informatie over de Servo functies vind je op de Servo pagina.

 // beweeg.ino: Beweeg een servo tussen twee posities
 #include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken, anders kan hij die niet vinden

 Servo motorA;  // definieer een servo met de naam motorA 
 
 void setup() 
 {                
   motorA.attach(13); // vebind servo met aansluitpen 13
 }
 
 void loop() 
 {
   motorA.write(30);          // beweeg naar 30 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(120);         // beweeg naar 120 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
 }

Twee servos besturen

 // beweeg.ino: Beweeg een servo tussen twee posities
 #include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken, anders kan hij die niet vinden

 Servo motorA;  // definieer een servo met de naam motorA 
 Servo motorB;  // definieer een servo met de naam motorB 
 
 void setup() 
 {                
   motorA.attach(13); // vebind servo met aansluitpen 13
   motorB.attach(10); // vebind servo met aansluitpen 10

 }
 
 void loop() 
 {
   motorA.write(30);          // beweeg naar 30 graden stand
   motorB.write (30);         // beweeg naar 30 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(120);         // beweeg naar 120 graden stand
   motorB.write(120);         // beweeg naar 120 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
 }


Servo posities testen

Om te kijken waar de servo posities precies zijn kun je het volgende programma gebruiken (de maximale posities zijn 0 en 180)
Er zitten al twee motoren in dus je kunt het programma voor de tweede motor aanpassen (of de stekkers even omdraaien)

 // test.ino: Beweeg de servo naar alle posities
 #include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken, anders kan hij die niet vinden
 
 Servo motorA;  // definieer een servo met de naam motorA 
 Servo motorB;  // definieer een servo met de naam motorB 
 
 void setup() 
 {                
   motorA.attach(13); // vebind servo met aansluitpen 13
   motorB.attach(10); // vebind servo met aansluitpen 10
 
 }
 
 void loop() 
 {
   motorA.write(0);           // beweeg naar 0 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(30);          // beweeg naar 30 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(60);          // beweeg naar 60 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(90);          // beweeg naar 90 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(120);         // beweeg naar 120 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(150);         // beweeg naar 150 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
   motorA.write(180);         // beweeg naar 180 graden stand
   delay(1000);               // Wacht 1 seconden (1000 milliseconden)
    }



De servo besturen met de schakelaar

Start servo beweging met schakelaar

Sluit de servo aan op aansluitpen 13 en op 10 van de Launchpad. Druk op de linker schakelaar, de servos gaan nu bewegen.

// beweeg.ino: Beweeg servo na drukken op de knop
#include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken, anders kan hij die niet vinden
 
Servo motorA;  // definieer een servo met de naam motorA 
Servo motorB;  // definieer een servo met de naam motorB 
 
void setup() 
{          
  pinMode(5, INPUT_PULLUP); // drukknop, als input
  motorA.attach(13); // vebind servo met aansluitpen 13
  motorB.attach(10); // vebind servo met aansluitpen 10
 
  while ( digitalRead(5) == HIGH ) // zolang de schakelaar HOOG is (niet ingedrukt)
  {
    ; // doe niets (en doe de while loop nog een keer)
  } 
}

// Beweeg motor A en B op en neer 
void loop() 
{
  motorA.write(30);          // beweeg A naar 30 graden stand
  delay(100);                // Wacht 0,1 seconden (100 milliseconden)
  motorB.write (30);         // beweeg B naar 30 graden stand
  delay(1000);               // Wacht 1 seconden (1000 milliseconden)
  motorA.write(120);         // beweeg A naar 120 graden stand
  delay(100);                // Wacht 0,1 seconden (100 milliseconden)
  motorB.write(120);         // beweeg B naar 120 graden stand
  delay(1000);               // Wacht 1 seconden (1000 milliseconden)
}

Stuur servo naar een positie met de schakelaar

Sluit de servo aan op aansluitpen 13 van de Launchpad, en druk op de linker schakelaar. De servo moet nu tussen twee posities bewegen.

// beweeg-schakelaar.ino: Beweeg een servo tussen twee posities 
// als je op de schakelaar drukt
#include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken

Servo motor1;  // definieer een servo met de naam motor1 
 
void setup() 
{                
  motor1.attach(13); // vebind servo met aansluitpen 13
  pinMode(5, INPUT_PULLUP);
}
 
void loop() 
{
  if ( digitalRead(5) == HIGH )   // als de schakelaar HOOG is (niet ingedrukt):
  { 
    motor1.write(30);             //   beweeg naar 30 graden stand
  }  
  else                            // anders:
  {
    motor1.write(120);            //   beweeg naar 120 graden stand
  }
}



Een functie

Een functie is een manier om 1x iets te schrijven, en meerdere keren te gebruiken. Hier een voorbeeld van een morse code Eerst worden functies gemaakt voor de punt en de streep van de morse code, en vervolgens worden deze functies gebruikt in de morse_s() en morse_o() functie, die in het hoofdprogramma loop() aangeroepen worden om het woord SOS te maken.

// functie.ino - voorbeeld van het gebruik van functies, stuur een morse code (http://nl.wikipedia.org/wiki/Morse)

// Bij het aanzetten: schakel aansluitpen 2 (rode lampje) als uitgang
void setup()
{
  pinMode(2, OUTPUT);
}

// geef een korte flits op de rode lamp
void punt()
{
  digitalWrite(2, HIGH);
  delay(200);
  digitalWrite(2, LOW);
  delay(200);
}

// geef een lange flits op de rode lamp
void streep()
{
  digitalWrite(2, HIGH);
  delay(600);
  digitalWrite(2, LOW);
  delay(200);
}

// stuur de letter "S" 
void morse_s()
{
  punt();
  punt();
  punt();
  delay(600);
}

// stuur de letter "O" 
void morse_o()
{
  streep();
  streep();
  streep();
  delay(600);
}

// stuur de de hele tijd de morse-code "SOS" (HELP!) via het lampje 
void loop()
{
  morse_s();
  morse_o();
  morse_s();
  delay(1400);
}

Een herhaling

Een herhaling is een manier om een functie een aantal keer uit te voeren. Dat doe je met het for() commando.

Het for() commando gebruik je zo: for( begin; test; ophogen; ) commando;. In het begin stuk maak je geheugen aan voor een teller. In het test stuk controleer je of je nog door moet gaan. Als dit waar is, dan wordt het commando nog een keer uitgevoerd. Als het niet waar is stop de herhaling. Bij het ophogen stuk kan je ieder keer de waarde van de variabele veranderen.

// forlooop.ino
//
void setup()
{
  pinMode(2,OUTPUT);  // groene led is een uitgang
}

// deze loop
void loop()
{
  // 10 keer snel knipperen
  for(int teller=0; teller<10; teller = teller + 1 )
  {  
    digitalWrite(2, HIGH); // groen aan
    delay(100);
    digitalWrite(2, LOW); // groen uit
    delay(100);
  }

  // 5 keer langzaam kipperen
  for(int teller=0; teller<5; teller = teller + 1 )
  {  
    digitalWrite(2, HIGH); // groen aan
    delay(200);
    digitalWrite(2, LOW); // groen uit
    delay(200);
  }
}

Een afloop

Een afloop is een manier om verschillende dingen achter elkaar te doen. Het wordt vaak gebruikt in robots.

// afloop.ino
int stap; // de stap variabele
void setup()
{
  stap = 1; // we beginnen met stap = 0
  pinMode(2,OUTPUT);  // groene led is een uitgang
  pinMode(5, INPUT_PULLUP); // de schakelaar is een ingang
  pinMode(14,OUTPUT); // rode led is een uitgang
  Serial.begin(9600);
}
 
void loop()
{
  switch( stap )  // doe iets, afhankelijk van de waarde van stap
  {
    case 1:  // als stap 1 is dan:
      digitalWrite(2, HIGH); // groen aan
      digitalWrite(14, HIGH); // rood aan
      stap = 2; // de volgende keer is stap 2
      break; // stop en ga verder na het einde van de switch }
    case 2:  // als stap 2 is dan:
      digitalWrite(2, LOW); // groen uit
      stap = 3; // de volgende keer is stap 3
      break; // stop en ga verder na het einde van de switch }
    case 3: // als stap 3 is dan:
      if ( digitalRead(5) == LOW ) // als we op de linker knop drukken dan:
        stap = 4; // ga naar stap 4
      else
        stap = 1; // de volgende keer is stap 1
      break;
    case 4: // als stap 4 is dan:
      digitalWrite(14, LOW); // rood uit 
      delay(4000); // wacht
      stap = 1; // de volgende keer is stap 1
      break;
    default: // als stap een andere waarde heeft dan 1 van de eerder case waarden, dan:
      stap = 1;
  }
  delay(500); // wacht 1/2 seconde
  Serial.print("Stap is: ");
  Serial.println(stap);
}

Variabelen

Met variabelen kan je getallen bewaren in de microcontroller. Je kan dit getal meerdere keren gebruiken in je programma en er ook mee rekenen. Als je de waarde van een variabele verandert, dan verander je de waarde op alle plekken waar deze variabele gebruikt wordt. Met int definieer je een variabele van het type integer. Dat is een geheel getal dat een waarde kan hebben van -32768 tot 32767.

// variabelen.ino
// Zet een variabele en gebruik 'm meerdere keren in je programma
#include <Servo.h>  // Gebruik de Servos

int pos1 = 30;  // maak een variabele met de naam pos1 en zet hem op de waarde 30
int pos2 = 60;  // maak een variabele met de naam pos2 en zet hem op de waarde 60
int t1 = 1000;  // t1 wordt waarde 1000;
int t2 = 2000;  // t2 wordt waarde 2000;
Servo s1;       // maak een servo met de naam s1

void setup()
{
  s1.attach(10); // verbind s1 met pin 10
}

void loop()
{
  s1.write(pos1); // ga naar pos1  
  delay(t1);      // wacht t1
  s1.write(pos2); // ga naar pos2
  delay(t1);      // wacht t1
  s1.write(pos1); // ga naar pos1
  delay(t2);      // wacht t2
  s1.write(pos2); // ga naar pos2
  delay(t2);      // wacht t2
}

Berichten sturen naar de computer

Met Serial kan je berichten sturen naar de computer

Berichten sturen via infrarood licht

Met IR kan je berichten sturen met onzichtbaar infrarood licht. Dit kan je gebruiken om verschillende robots met elkaar te laten praten. Je kan het bijvoorbeeld gebruiken om verschillende microcontrollers gelijk te starten, of even snel te laten lopen. Zie ook Dirigent voor meer voorbeelden.

Verzenden

Dir programma verstuurt een IR signaal als je op de linker knop drukt. Het rode ledje gaat uit als je drukt.

/*
 * irstuur.ino
 * Stuur een puls naar de IR led als je op de knop drukt
 */
void setup() 
{
  pinMode(6,OUTPUT); // IR led
  pinMode(2,OUTPUT); // rode LED
  pinMode(5, INPUT_PULLUP); // schakelaar
}

void loop() 
{
  if ( digitalRead(5) == LOW ) // Als je op de linker knop drukt
  {
    digitalWrite(2,LOW); // zet rode LED UIT
    tone(6,36000,1);     // Stuur puls op de IR van 36khz en 1miliseconde lang
    delay(1);            // Wacht 1 miliseconde
  }  
  else // Anders (als knop niet ingedrukt is):
  {
    digitalWrite(2,HIGH); // zet rode LED AAN 
  }
}

Ontvangen - Simpel

Als er IR signaal ontvangen wordt, gaat de rode led aan. Kijk met een afstandsbediening (of andere launchpad die staat te zenden) of je signaal ontvangt.

/*
 * ir.ino
 * Simpele IR ontvanger: de rode led gaat aan als IR signaal ontvangen wordt 
 * het nummer van de knop wordt niet ingelezen (alleen IR AAN/UIT)
 */
void setup() 
{
  pinMode(7,INPUT_PULLUP); // IR sensor
  pinMode(2,OUTPUT); // rode LED
}

void loop() 
{
  if ( digitalRead(7) == HIGH )  
    digitalWrite(2, LOW);
  else
    digitalWrite(2, HIGH);
}


Ontvangen - Wachten op IR

Dit programma wacht tot er een IR signaal ontvangen wordt, bijvoorbeeld van een afstandsbediening of andere launchpad die staat te zenden.

/*
 * irwacht.ino
 * IR ontvanger: wacht op IR signaal. De rode led gaat uit als IR signaal ontvangen is,
 * en dan begint de loop() functie pas  
 */
void setup() 
{
  pinMode(7,INPUT_PULLUP); // IR sensor: deze ingang wordt LAAG als er een signaal ontvangen wordt.
  pinMode(2,OUTPUT); // Rode LED
  pinMode(14,OUTPUT); // Groene LED
  digitalWrite(2, HIGH); // Zet rode led aan
  digitalWrite(14, LOW); // Zet groene led uit
  while ( digitalRead(7) == HIGH ); // Herhaal loop zolang IR signaal HOOG is (en doe niets).  
  digitalWrite(2, LOW); // Zet rode led uit
}
 
void loop() 
{
  delay(500); // wacht 0.5 sec
  digitalWrite(14, HIGH); // Zet groene led aan
  delay(500); // wacht o.5 sec
  digitalWrite(14, LOW); // Zet groene led uit
}

Ontvangen - Met uitlezen van afstandsbedienings knop

Dit programma leest de IR sensor uit, en kijkt welke knop er van een (TV, DVD of versterker) afstandsbediening ingedrukt wordt. Hij stuurt de waarde van de knop naar de PC via de Serial poort. Het rode ledje gaat knipperen als er een code ontvangen is. Hij maakt daarvoor gebruik van de IRremote Bibliotheek. Je kan hiermee met de afstandsbediending meerdere knoppen herkennen. Let op: Werkt niet met alle aftsandsbedieningen van alle merken. Als hij het niet doet: zoek dan een andere afstandsbediening.

/*
 * irdump.ino
 * ontvang IR signalen, en laat de code zien op het scherm.
 * Open het serial window (ctrl+shift+m). Zorg dat de seriele poort goed staat en de jumpers 'horizontaal' staan.
 * Richt een afstandsbediending van een TV op de ontvanger en druk op een knop.
 * De rode led knippert als er iets ontvangen wordt
 */
 
#include <IRremote.h>
 
IRrecv irrecv(7); // maak een IR ontvanger, verbonden met pin 7
decode_results results; // geheugen voor het ontvangen van codes
 
void setup()
{
  Serial.begin(9600);  // zet communicatiesnelheid met pc
  irrecv.enableIRIn(); // Start de ontvanger
  pinMode(2,OUTPUT);
  digitalWrite(2,HIGH);
}
 
void loop() {
  if (irrecv.decode(&results)) { // als er een code ontvangen is, 
    digitalWrite(2,LOW);  // Geef een flits op de led 
    delay(100);           //
    digitalWrite(2,HIGH); //
    Serial.print("IR code: "); // schrijf naar scherm
    Serial.println(results.value, HEX); // laat de code dan zien
    irrecv.resume();      // ontvang volgende code  
  }
}

Ontvangen - led knippert afhankelijk van de afstandsbediening toets

Dir programma leest de IR sensor uit, en kijkt welke knop er ingedrukt wordt. Als je een 1 indrukt gaat de led 1x kinpperen, als je een 2 indrukt gaat de led 2x knipperen enzovoort. Je kunt in de functies doKey1 .. doKey9 je eigen programma code toevoegen!

/*
 * infraroodToets.ino
 * ontvang IR signalen, en laat de code zien op het scherm.
 * Open het serial window (ctrl+shift+m). 
 * en zorg dat de seriele poort goed staat en de jumpers 'horizontaal' staan.
 * Richt een afstandsbediending van een TV op de ontvanger en druk op een knop.
 * De rode led knippert het aantal keren van de toets die ingedrukt wordt
 */
#include <IRremote.h>
 
IRrecv irrecv(7); // maak een IR ontvanger, verbonden met pin 7
decode_results results; // geheugen voor het ontvangen van codes
 
void setup()
{
  Serial.begin(9600);  // zet communicatiesnelheid met pc
  irrecv.enableIRIn(); // Start de ontvanger
  pinMode(2,OUTPUT);
  digitalWrite(2,HIGH);
}
 
void loop() {
  if (irrecv.decode(&results)) { // als er een code ontvangen is, 
    Serial.print("IR code: "); // schrijf naar scherm
    Serial.println(results.value, HEX); // laat de code dan zien

    int key = results.value % 16;   // haal het laatste cijfer op van de code
    Serial.print("key: "); // schrijf toets naar scherm
    Serial.println(key); 
    
    switch (key){
      case 1:
        doKey1();
        break;
      case 2:
        doKey2();
        break;
      case 3:
        doKey3();
        break;
      case 4:
        doKey4();
        break;
      case 5:
        doKey5();
        break;
      case 6:
        doKey6();
        break;
      case 7:
        doKey7();
        break;
      case 8:
        doKey8();
        break;
      case 9:
        doKey9();
        break;
      default:
        break;
    }
    irrecv.resume();      // ontvang volgende code  
  }
}

void doKey1(){
  flashLed(1);
}  

void doKey2(){
  flashLed(2);
}  

void doKey3(){
  flashLed(3);
}  

void doKey4(){
  flashLed(4);
}  

void doKey5(){
  flashLed(5);
}  

void doKey6(){
  flashLed(6);
}
  
void doKey7(){
  flashLed(7);
}  

void doKey8(){
  flashLed(8);
}  

void doKey9(){
  flashLed(9);
}  

void flashLed(int nr)
{
  Serial.print("Flashled: "); // schrijf naar scherm
  Serial.println(nr);         // laat de code dan zien
    
  for (int i = 0; i < nr; i++)
  {
    digitalWrite(2,HIGH);  // Geef een flits op de led 
    delay(100);          
    digitalWrite(2,LOW);
    delay(100);
  }    
}



Dirigent

Een [dirigent] zorgt ervoor dat alle muzikanten in een orkest gelijk beginnen en in hetzelfde tempo spelen. Als we met ons robot orkest gaan spelen, moeten we ook zorgen dat iedereen op het zelfde moment start en in hetzelfe tempo speelt.

Probleem

Hebben wij ook een dirigent nodig bij onze robot orkesten? Robots zijn toch heel precies en doen altijd exact hoe ze geprogrammeerd zijn. Dus waarom zouden ze naar een dirigent moeten luisteren?

Doe het volgende experiment om dat uit te zoeken:

  • Zet het programmatje Led aan en uit in twee launchpad microcontrollers
  • Zet de twee launchpads naast elkaar en druk bij beide op de RESET (S1) knop.
  • Laat op hetzelfe moment beide reset knoppen los
  • Beide ledjes knipperen als het goed is nu even snel en gelijktijdig
  • Wacht ongeveer 2 minuten
  • Kijk nu of de ledjes nog steeds gelijktijdig knipperen. Ja? Of hebben we een probleem?

Wat gebeurt hier?

Iedere microcontroller heeft zijn eigen klok en die loopt op een vast tempo (hij telt 16miljoen keer per seconde), maar niet iedere klok loopt exact gelijk (je kent het probleem wel van je eigen horloge of wekker) sommige lopen een beetje sneller, andere lopen een beetje langzamer. Dus als je een tijdje wacht, dan zal de klok van de ene microcontroller iets voor gaan lopen, en de andere iets achter. Dan lopen ze dus uit de maat.

Oplossing

De oplossing is het maken van een dirigent die de andere robots in de maat kan houden. Hiervoor moeten de microcontrollers met elkaar kunnen praten dit kan bijvoorbeeld met de infrarood zender en ontvanger. Kijk hiervoor ook naar de voorbeeld programmas Verzenden en Ontvangen. Dat kan je gebruiken om alle microcontrollers gelijk te laten starten (net zoals bij de knop), maar dat lost het probleem nog niet op, want daarna kunnen ze alsnog uit de maat gaan lopen, omdat hun klokken niet even snel lopen.

Een aanpassing van dit programma kan gebruikt worden om (net als een dirigent) steeds de maat aan te geven.

Dirigent (zender)

/*
 * dirigent.ino
 * Wacht op indrukken van knop S2 en stuur dan continue IR pulsjes, met een snelheid van 1000 per seconde
 * Deze pulsjes kunnen ontvangen worden door andere robots (zorg dat de zender en ontvanger elkaar goed zien!)
 */
void setup() 
{
  pinMode(6,OUTPUT); // pen 6: IR led (uitgang)
  pinMode(2,OUTPUT); // pen 2: rode LED (uitgang)
  pinMode(14,OUTPUT); // pen 14: groene LED (uitgang)
  pinMode(5, INPUT_PULLUP); // schakelaar (ingang)
 
  digitalWrite(14,HIGH); // Zet groene led aan
  while ( digitalRead(5) == HIGH ); // Loop zolang de knop S2 NIET is ingedruk (groene led is aan) en doe niets
  digitalWrite(14,LOW); // Zet groene led uit
}
 
 
void loop() 
{
  digitalWrite(2,HIGH); // zet rode LED UIT
  tone(6,36000,1);     // Stuur puls op de IR van 36khz en 1miliseconde lang
  delay(1); // wacht 1 milliseconde
  digitalWrite(2,LOW); // zet rode LED AAN
}


De ontvanger

/*
 * ontvanger.ino
 * IR ontvanger. Telt pulsjes die deze binnenkomen via de IR ontvanger
 * Met de wacht() functie kan je wachten tot er een aantal pulsen ontvangen zijn
 * Verschillende microcontrollers kunnen nu exact even lang wachten als ze allemaal naar dezelfde zender kijken.
 *
 */
#include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken, anders kan hij die niet vinden
 
Servo motorA;  // definieer een servo met de naam motorA 


// wacht tot er een aantal pulsen ontvangen is (iedere overgang van LAAG naar HOOG wordt geteld)
void wacht(int pulsen)
{
  while ( pulsen > 0 ) // Zolang we nog niet op nul zijn
  {
    while( digitalRead(7) == LOW ); // wacht zolang IR ingang LAAG is   
    while( digitalRead(7) == HIGH ); // wacht zolang IR ingang HOOG is
    pulsen = pulsen - 1;  // trek 1 af van de pulsen teller 
  }
}
 
// setup: initialiseer de IO's en verbind de signaal functie met de ingang
void setup() 
{
  pinMode(7,INPUT_PULLUP); // IR sensor op pen 7 als ingang schakelen
  pinMode(2,OUTPUT); // rode LED op pen 2 als uitgang schakelen
  motorA.attach(13); // vebind servo met aansluitpen 13
}


// loop: wacht steeds op een aantal pulsjes, en zet de servo in een andere stand
void loop() 
{
  wacht(250); // wacht totdat er 250 pulsjes ontvangen zijn
  digitalWrite(2,HIGH); // Rode led aan
  motorA.write(40); // Zet de servo op stand 40
  wacht(100); // Wacht totdat er nog 100 pulsjes ontvangen zijn
  motorA.write(80); // zet de servo op stand 80
  digitalWrite(2,LOW); // Rode led uit
}


Drumloop

Dit is een programma wat veel mogelijkheden van de microcontroller gebruikt:

  • de posities zijn opgeslagen in variabelen
  • Het drumprogramma is opgeslagen in een tabel

Het is bedoeld voor een tweearmige robot. Je kan het ritme aanpassen met de tabel, en de posities van de armen met a_op, a_neer, b_op en b_neer.

// drum2.ino // een geavanceerd drum programma met 2 servos. Heeft variabelen voor positie en een tabel met het drumritme
#include <Servo.h>    // zeg de computer dat we de servo functies willen gebruiken, anders kan hij die niet vinden
 
Servo motorA;  // definieer een servo met de naam motorA 
Servo motorB;  // definieer een servo met de naam motorB 
 
void setup() 
{          
  pinMode(5, INPUT_PULLUP); // drukknop, als input
  motorA.attach(13); // vebind servo met aansluitpen 13
  motorB.attach(10); // vebind servo met aansluitpen 10
 
  while ( digitalRead(5) == HIGH ) // zolang de schakelaar HOOG is (niet ingedrukt)
  {
    ; // doe niets (en doe de while loop nog een keer)
  } 
}
// arm posities
int a_neer = 115; // hoger getal is stokje lager
int b_neer = 25; // lager getal is stokje lager
int a_op = 100;
int b_op = 40;

// tabel met drumritme
int a[] = { 1,0,1,0,1,0,0,0,  1,0,1,0,1,0,0,0, 1,0,1,0,1,0,1,0, 1,0,1,0,1,0,1,0}; //rechts (kort)
int b[] = { 1,0,0,0,1,0,0,0,  1,0,0,0,1,0,0,0, 1,0,1,0,1,0,0,0, 1,0,1,0,1,0,0,0}; //links (lang)
int i = 0; // teller om door de tabel te lopen

// Beweeg motor A en B op en neer 
void loop() 
{
  i++; // hoog teller 1 op
  if ( i > sizeof(a) / sizeof(a[0]) ) // als teller voorbij de laatste waarde van de tabel is:
    i = 0; // zet de teller weer op nul (begin van de tabel)

  if ( a[i] == 1 ) // Als waarde in tabel a "1" is:
    motorA.write(a_neer);          // beweeg A naar beneden
  else
    motorA.write (a_op);         // beweeg A omhoog

  if ( b[i] == 1) // Als waarde in tabel b "1" is:
    motorB.write(b_neer);          // beweeg B naar beneden
  else
    motorB.write (b_op);         // beweeg B omhoog

  delay(100);               // Wacht 0.1 seconden (100 milliseconden)
}