erledigt Arduino als DCO

trouby

....
Macht es Sinn, einen Arduino per tone() derart anzusprechen, dass noch ein Teiler /32 (2^5) notwendig ist, also Präzision im Bass?
tone() kann nur ganzzahlige Hz bis 65k, ist ja uint16 bzw. WORD.
Sind die Timer genau genug?
Tune per poti am analogeingang.
evtl. nen DAC per SPI ran oder PWM zur saw-konvertierung über stromquelle...
 
Zuletzt bearbeitet:
Baugruppe funktioniert, die Oktavreinheit lässt in den oberen Lagen nach. Ursache ist die Dividerberechnung für den 8-bit-Timer mit Vorteiler.
Frequenzen mit Multimeter nachgemessen und die Frequenzliste per Dreisatz als Iteration korrigiert.
Habe als Dateityp WORD genommen.

TUNE funktioniert über einen AnalogIN, ein bißchen Mathe mit Fliesskomma :)
Der DAC für SAW ist ebenfalls keine Liste, sondern eine Formel, Kennlinie ist ja linear und kleine Abweichungen wirken sich nur unwesentlich auf den Pegel aus.

PS: auch als Poly-Version vorstellbar, den Atmega328P gibts als DIP28, grosses 5U-Modul...

arduino-dco.gif

// MIDI DCO w/ tone(); & saw DAC

#include <SPI.h>

word value; // actual DAC value
byte note = 7; // note pin
byte mid[3]; // MIDI data
byte cs = 10; // DAC CS pin
byte gate = 8; // gate pin
byte mute = 9; // mute the SAW
float tune; // tune value
int pot; // tune pot
const word freq[]{0, // note() value (17-89), F0 - F6, 32'F - 1/4'F
698,740,784,831,880,932,988,
1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976,
2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951,
4186,4435,4699,4978,5274,5588,5920,6272,6645,7040,7459,7902,
8372,8870,9397,9956,10548,11175,11840,12544,13290,14080,14917,15804,
16744,17740,18795,19912,21096,22351,23680,25088,26580,28160,29834,31609,
33488,35479,37589,39824,42192,44701};

const word divider[]{0,
11454,10811,10204,9631,9091,8581,8099,
7645,7215,6810,6428,6067,5727,5405,5102,4816,4545,4290,4050,
3822,3608,3405,3214,3034,2863,2703,2551,2408,2273,2145,2025,
1911,1804,1703,1607,1517,1432,1351,1276,1204,1136,1073,1012,
956,902,851,804,758,716,676,638,602,568,536,506,
478,451,426,402,379,358,338,319,301,284,268,253,
239,225,213,201,190,179};


void setup()
{
pinMode(cs,OUTPUT);
pinMode(gate,OUTPUT);
pinMode(note,OUTPUT);
pinMode(A0,INPUT);
pinMode(mute,OUTPUT);

digitalWrite(gate,LOW);
digitalWrite(cs,HIGH);
digitalWrite(mute,LOW);

Serial.begin(31250);
SPI.begin();
DAC(0);
}

void DAC(word value)
{
digitalWrite(cs,LOW);
SPI.beginTransaction(SPISettings(4000000,MSBFIRST,SPI_MODE0));
bitWrite(value,15,LOW); // bit 15 - dual DAC selector - LOW
bitWrite(value,14,LOW); // bit 14 - buffer - LOW
bitWrite(value,13,HIGH); // bit 13 - double GAIN - HIGH
bitWrite(value,12,HIGH); // bit 12 - output shut down - HIGH
SPI.transfer(highByte(value));
SPI.transfer(lowByte(value));
SPI.endTransaction();
digitalWrite(cs,HIGH);
bitClear(value,15);
bitClear(value,14);
bitClear(value,13);
bitClear(value,12);
}

// noteOn = 144
// noteOff = 128

void loop()
{
pot = (analogRead(A0) / 4) - 128 ;
tune = 1 / ((float(pot) / 1100) + 1);

midicomm:
if (Serial.available() == 1)
{
mid[0] = Serial.read();
if (bitRead(mid[0],7) == HIGH && bitRead(mid[0],6) == LOW && bitRead(mid[0],5) == LOW) goto midinote;
}
else
{
goto midicomm;
}

midinote:
if (Serial.available() == 1)
{
mid[1] = Serial.read();
if (bitRead(mid[1],7) == HIGH && bitRead(mid[1],6) == LOW && bitRead(mid[1],5) == LOW)
{
mid[0] = mid[1];
goto midinote;
}
}
else
{
goto midinote;
}

midivol:
if (Serial.available() == 1)
{
mid[2] = Serial.read();
if (bitRead(mid[2],7) == HIGH && bitRead(mid[2],6) == LOW && bitRead(mid[2],5) == LOW)
{
mid[0] = mid[2];
goto midinote;
}
}
else
{
goto midivol;
}

if (bitRead(mid[0],4) == HIGH && mid[2] > 0 && mid[1] >= 17 && mid[1] <= 89)
{
// note ON
tone(note,word(freq[mid[1] - 16] * tune));
value = ((mid[1] - 16) * 34) + 1000 ;
DAC(value);
digitalWrite(gate,HIGH);
digitalWrite(mute,HIGH);
}
else
{
// note OFF
digitalWrite(mute,LOW);
digitalWrite(gate,LOW);
noTone(note);
DAC(0);
}
}
 
Zuletzt bearbeitet:


News

Zurück
Oben