tonen generator

Leden,

Ik heb me terug een idee...
Ik zou graag een tonen generator maken.

Ik weet er bestaat een link op arduino.cc

Maar dit lijkt me te omslachtig voor mijn doel.
Ik heb maar 12 frequenties nodig.

(doel, een honden klik systeem maken met verschillende tonen
440HZ => Zit
etc...)

Ik vond deze formule op internet
formula -> f(n) = 2 ^ (n - 49/12) * 440 Hz

Ik heb ook een 12 toetsenkeyboard.

En elke toets zou een CASE aanspreken, die dan de tonen genereert.

Echter ik heb geen idee hoe alles in elkaar te zetten...

een zetje aub.

in feite het probleem opdelen in 3 stappen:

a) lees toetsenbord
b) bepaal de ingedrukte toets
c) afhankelijk van gekozen toets stuur frequentie uit

Let wel dat je het uitgangssignaal waarschijnlijk moet versterken.

En als je helemaal nog geen kennis hebt van de arduino, eerst een zooi tutorials doen. Daarna nadenken hoe je het programma wilt gaan maken en dan pas coderen.
Een andere volgorde geeft een zeer grote kans op falen van het project.

ivanflo:
Ik vond deze formule op internet
formula -> f(n) = 2 ^ (n - 49/12) * 440 Hz

En wat stelt n voor in deze formule ?
Is n een integer of een float en wat zijn de grenzen waartussen n zich mag bewegen ?

Enkele vragen die in mij opkomen als ik een formule zie.
Zonder input is deze formule nietszeggend.

Bovendien ligt het veel meer voor de hand om die 12 tonen uit een 'lookup table' , (gewoon een lijstje met de gewenste frekwenties) te pakken.

Ik weet er bestaat een link op arduino.cc
Maar dit lijkt me te omslachtig voor mijn doel.
Ik heb maar 12 frequenties nodig.

Het voorbeeld op http://arduino.cc/en/Tutorial/tone blinkt uit in zijn eenvoud en is mogelijk precies geschikt voor jouw doel.

(edit:link aangepast tussen code tags)

idealiter maak je een tabel met de frequenties in octaaf 7 en deelt die een aantal keren (voor ieder octaaf lager) door 2.

Hier een experimentele sketch die 3 verschillende methoden van frequentie gebruik vergelijkt.

  • float tabel van 12 met look up formula
  • float tabel van 128 10+octaven
  • unsigned tabel van 128 met deling door 8.

De float tabel is snelste en nauwkeurigste en grootste (Zou naar PROGMEM moeten eigenlijk)
216 usec voor 128 lookups == 1.7 usec per lookup (588 000/sec)

de unsigned integer tabel is 8 keer trager maar tabel is 2x kleiner.
verder is hoogste octaaf niet correct.
1672 usec voor 128 lookups == 13.1 usec per lookup (75 000/sec)

float tabel met lookup formula, kleinste footprint maar sloomste.
5968 usec voor 128 lookups == 46.6 usec per lookup (21 400/sec)

//
//    FILE: MusicFequencyTable.pde
//  AUTHOR: Rob Tillaart
//    DATE: 2011-08-12
//
// PUPROSE: generate a frequency table for musical notes
//

float ft[12];
float freqtab[128];
uint16_t f[128];

//#define FREQ(t) (ft[t%12]/(1 << (10-(t/12)))) 
float FREQ(uint8_t t)
{
  uint8_t n = t/12;
  uint8_t o = t - n*12;
  return (ft[o]/(1 << (10-(n))));
}

void setup() 
{
  Serial.begin(115200);

  // make frequency (Hz) table
  double k = 1.059463094359;	// 12th root of 2;
  double A9 = 14080;
  A9 *= k;
  A9 *= k;		// a
  for (int i = 11; i >=0; i--)
  {
    ft[i] = A9;
    A9 /= k;
  }

  // make frequency (Hz) table
  double a = 6.875;		// a
  a *= k;	// b
  a *= k;	// bb
  a *= k;	// c, frequency of midi note 0
  for (int i = 0; i < 128; i++)
  {
    freqtab[i] = (float)a;
    f[i] = (freqtab[i] * 8 + 0.5);
    a *= k;
  }

  for (int i = 0; i<128; i++)
  {
    Serial.print(i, DEC); 
    Serial.print(" \t"); 
    Serial.print(FREQ(i));
    Serial.print(" \t"); 
    Serial.print(freqtab[i]);
    Serial.print(" \t"); 
    Serial.print((float)f[i]/8.0, 2);
    Serial.print(" \t"); 
    Serial.println(100*abs((FREQ(i)-(float)f[i]/8.0)/FREQ(i)), 2);
  }

  unsigned long before = micros();
  volatile float x;
  for (int i = 0; i<128; i++)
  {
    x = FREQ(i);
  }
  Serial.println(micros()-before);

  before = micros();
  for (int i = 0; i<128; i++)
  {
    x = freqtab[i];
  }
  Serial.println(micros()-before);

  before = micros();
  for (int i = 0; i<128; i++)
  {
    x = f[i]/8.0;
  }
  Serial.println(micros()-before);
}

void loop() 
{
}

snippet that can be added to the previous sketch to generate Table definition in C.

  Serial.print("uint16_t freq[128] = {");

  for (int i = 0; i<8; i++)
  {
    Serial.print("\n\t");
    for (int j = 0; j < 16; j++)
    {
      Serial.print(f[i*16+j]);
      Serial.print(',');
    }
  }
  Serial.println("};\n");

Nu Rob demonstreert hoe de frequenties van de toonladder te berekenen zijn,
help ik de vraagsteller met het skelet voor zijn programma.

Er is niet zoveel commentaar maar ik hoop dat de namen van de variabelen veel verduidelijken.

int ToetsDruk;
byte pinNummer;        //pinNummer = pin welke is ingedrukt
byte lastPinNummer;    // geheugen voor welke toets laatst was ingedrukt
byte Buzzer = 19;      // A5 of 19 uitgang voor buzzer, niet in de range van ingang
//12 tonen in de range. 2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,
byte lowPinNummer = 2;     // bv pin 2
byte highPinNummer = 6;    // b.v pin 13 

void setup() {
  for (pinNummer = lowPinNummer; pinNummer <= highPinNummer; pinNummer++){
    pinMode(pinNummer,INPUT_PULLUP);                                  // 12 input keys
  }
  pinMode (A5,OUTPUT);                                                // Buzzer uitgang
}

void loop() {
 for (pinNummer=lowPinNummer;pinNummer<=highPinNummer;pinNummer++){  
   ToetsDruk = digitalRead(pinNummer);                               // lees stutus pin pinNummer
   if (ToetsDruk == 0)
   { 
   lastPinNummer = pinNummer;
     switch (pinNummer)
       {
       case 2:
         tone(Buzzer,440);
         break;
       case 3:
         tone(Buzzer,622);
         break;
       case 4:
         tone(Buzzer,880);
         break;
       case 5:
         tone(Buzzer,1245);
         break;
       case 6:
         tone(Buzzer,1760);
         break;
       /* enz enz*/
       default:              // indien andere toets toon uitzetten
         noTone(Buzzer);
         break;
       } // end switch
     
    } //end if
    /*   schakelt toon uit als Toets pinNummer losgelaten is */
   else if (ToetsDruk == 1 & lastPinNummer == pinNummer){noTone(Buzzer);} 
  } //end for loop
}

Alvast bedankt voor de antwoorden.

Ik het voorbeeld gebruikt van Arduino.cc
ik krijg echter volgende fouten:

core.a(main.cpp.o): In function main': C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/main.cpp:34: undefined reference to setup'
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/main.cpp:44: undefined reference to `loop'

Ik gebruik een Arduino 2560 Mega.
En elk ander voorbeeld van arduino kan ik "afspelen"

Waar kan mijn fout zitten?

post de code toch maar want het lijkt niet te kloppen.
Jantje

Maar dat is de identieke code van Arduino.cc
Uiteraard is de tone.h ook aangepast van naam. (origineel pitches.h) op de juiste plaats.

/*
  Melody
 
 Plays a melody 
 
 circuit:
 * 8-ohm speaker on digital pin 8
 
 created 21 Jan 2010
 modified 30 Aug 2011
 by Tom Igoe 

This example code is in the public domain.
 
 http://arduino.cc/en/Tutorial/Tone
 
 */
 #include "tone.h"

// notes in the melody:
int melody[] = {
    NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4,4,4,4,4 };

void setup() {
  // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second 
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000/noteDurations[thisNote];
    tone(8, melody[thisNote],noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(8);
  }
}

void loop() {
  // no need to repeat the melody.
}

Als dit de code is dan zou je die fout niet mogen krijgen.
Tenzij je toon.h kaduk is.
Jantje

En toch is alles al gekopieerd zoals het hoort.
Twee, drie, vijf keren al, niets lukt om deze code in mijn arduinootje te stoppen...

Driewerf helaas...

De foutmelding die je hebt laten zien, geeft fouten op regels 34 en 44.
De code die je hebt laten zien, heeft op regel 34 een commentaarregel waar dus die fout nooit vandaan mag komen.
Regel 44 verwijst naar de library dus ik weet niet wat daar fout zou kunnen zijn (heb m niet geïnstalleerd).

Welke versie van de IDE gebruik je ?

@MAS
de fout is een linker fout die zegt dat setup en loop niet bestaan.
Daar setup en loop gebruikt worden in main.cpp in de arduino core komt de fout -en dus ook de lijnnr van main.cpp- wat niks met de code die op hier zet te maken heeft.
Het lijkt wel of een lege sketch wordt gebruikt.
Een mogelijke verklaring is een niet gesloten commentaar in toon.h
Jantje

ivanflo:
Maar dat is de identieke code van Arduino.cc
Uiteraard is de tone.h ook aangepast van naam. (origineel pitches.h) op de juiste plaats.

Je zult toch wel ergens een fout hebben gemaakt.
Op de pagina http://arduino.cc/en/Tutorial/tone staat onderaan:

To make the pitches.h file, click on the "new Tab" button in the upper right hand corner of the window. It looks like this:

Dus je moet pitches.h zelf maken door een tab in je sketch te openen , die je pitches.h moet noemen, en daar de lijst met alle #defines van tonen en frequenties in copieren.

Of anders ga je op zoek naar tone.h, waar in principe dezelfde data in staat. Ik kom dan uit op Google Code Archive - Long-term storage for Google Code Project Hosting. .
Hier hetzelfde verhaal, je moet een folder maken in je libraryfolder genaamd " tone " en in die folder zet je het bestand tone.h wat je van die bladzijde kunt copieeren.

Alle mogelijkheden om fouten te maken dus. Het copieren kun je niet met iedere tekstverwerker doen omdat die soms de tekst formatteren waardoor je compilatiefouten zoals door jou beschreven zou kunnen krijgen.

[edit: tag gewijzigd]

Over de IDE => 1.0.6
Ik dacht dat dat de "stabiele" IDE is/was

Over het inladen van de code.
Er is een folder met daarin de

  • tone.ino
  • tone.h

Code.
Ik vermoed niet dat het daaraan zou kunnen schelen.

ivanflo:
Over de IDE => 1.0.6
Ik dacht dat dat de “stabiele” IDE is/was

Het is heel eenvoudig te testen. Voeg de volgende 4 defines toe, helemaal bovenin het demoprogramma.

#define NOTE_C4  262
#define NOTE_G3  196
#define NOTE_A3  220
#define NOTE_B3  247

en verwijder de #include “pitches.h” en/of #include <tone.h>
Dan kan het niet daaraan liggen.

Als je dan nog een foutmelding krijgt bij het compileren dan zou ik die ide 1.0.6 opnieuw installeren.

Wat er net gebeurd is, ik kan het helaas niet zeggen...

Na mijn dagelijks controle op updates...
En even een ccleaner te hebben losgelaten (ik was bezig aan de koffie, en met de belgische stakingen) nog even opgeladen.
En het werkt...

Geen idee wat er gewijzigd is.
De wondere wereld van Micro$hoft?