Help for schem mod (quantizer)

i found this project for a Ribbon controler.
Here’s the original link of the vid :https://www.youtube.com/watch?v=DDEq7wIxaC8

Ribbon does not really interest me but the possibility of using it as Quantizer with a CV input much more because the code includes several scales and that seem very simple to built.
Many DIY Quantizers are made with PIC and this one with an Arduino simplifies the thing.

here’s the original schem :

And i have a few questions for its adaptation.

  • The first one is for the CV in.
    The original circuit work between 0 to 5V with the ribbon, if i delete the ribbon controler and replaces it by an attenuator pot and a jack socket,
    should I add some resistors (voltage divider) to the ground, so as not to damage something because the incoming CVs go I think beyond 5V ?

  • The second is about the code.
    If i decide to use only Out 1, Gate 1 , Trigger 1 and In 1, should i delete everything related to Out 2, gate 2 trigger 2 and input 2 in the code
    or it doesn’t really matter to leave it like that even if there is nothing connected to these outputs

thank you in advance and here is the code for those interested to see or test …



int quant1 = -1;
int quant2 = -1;

int tmp_midi_note1;
int tmp_midi_note2;

byte holdValue1;
byte holdValue2;


RBD::Timer timer;
RBD::Timer trigger1;
RBD::Timer trigger2;
byte count = 0;
byte hold1[5];
byte hold2[5];
byte countplus = 1;
byte tracker1;
byte tracker2;


//--------------------------------------------
//ROUTINES!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//--------------------------------------------



byte majTable[] = {
  0,  2,  4,  5,  7,  9, 11, //scale01 Major
  12, 14, 16, 17, 19, 21, 23,
  24, 26, 28, 29, 31, 33, 35,
  36, 38, 40, 41, 43, 45, 47,
  48, 50, 52, 53, 55, 57, 59,
  60
};

int minTable[] = {
  0,  2,  3,  5,  7,  8, 10, //scale02 Minor
  12, 14, 15, 17, 19, 20, 22,
  24, 26, 27, 29, 31, 32, 34,
  36, 38, 39, 41, 43, 44, 46,
  48, 50, 51, 53, 55, 56, 58,
  60
};

int pentaTable[] = {
  0,  2,  3,  5,  7, 10,     //scale03 Pentatonic
  12, 14, 15, 17, 19, 22,
  24, 26, 27, 29, 31, 34,
  36, 38, 39, 41, 43, 46,
  48, 50, 51, 53, 55, 58,
  60
};

int dorianTable[] = {
  0,  2,  3,  5, 7,  9,  10, //scale04 Dorian
  12, 14, 15, 17, 19, 21, 22,
  24, 26, 27, 29, 31, 33, 34,
  36, 38, 39, 41, 43, 45, 46,
  48, 50, 51, 53, 55, 57, 58,
  60
};

int maj3rdTable[] = {
  0, 4,  7, 11,              //scale05Maj7(9)
  12, 16, 19, 23,
  24, 26, 31, 35,
  36, 40, 43, 47,
  48, 50, 54, 55,  59,
  60
};

int min3rdTable[] = {
  0,   3,   7,  10,          //scale06 Minor7(9,11)
  14,  15,  19,  22,
  24,  26,  27,  31,  34,
  36,  39,  41,  46,
  48,  50,  51,  55,  58,
  60
};

int whTable[] = {
  0,   2,   4,   6,   8,  10, //scale07 (WholeTone)
  12,  14,  16,  18,  20,  22,
  24,  26,  28,  30,  32,  34,
  36,  38,  40,  42,  44,  46,
  48,  50,  52,  54,  56,  58,
  60
};

int chromaTable[] = {
  0,
  1,  2,  3,  4,  5,  6,  7,  8, 9,  10, 11, 12, //scale08 Chromatic
  13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
  37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
  60
};



int mapMaj(int input) {
  byte value = (input) / 36;
  //  Serial.print("   ");Serial.print(majTable[value]);Serial.print("   ");
  return (majTable[value]);
}

int mapMin(int input) {
  byte value = (input) / 36;
  return (minTable[value]);
}

int mapPenta(int input) {
  byte value = (input) / 42;
  return (pentaTable[value]);
}

int mapDorian(int input) {
  byte value = (input) / 36;
  return (dorianTable[value]);
}

int mapMaj3rd(int input) {
  byte value = (input) / 61;
  return (maj3rdTable[value]);
}

int mapMin3rd(int input) {
  byte value = (input) / 59;
  return (min3rdTable[value]);
}

int mapWh(int input) {
  byte value = (input) / 42;
  return (whTable[value]);
}

int mapChromatic(int input) {
  byte value = (input) / 21;
  return (chromaTable[value]);
}



/*  Every pot has a different resistive curve. So wire up the
    scale select pot, uncomment the Serial.println line below,
    turn the pot, watching the numbers on the serial monitor,
    and adjust the numbers below to reflect where you want the
    pot to be pointing to when you're selecting the modes.

    Oh, also uncomment the Serial.begin(115200); line in the
    void setup() section.
*/
byte ScaleSelect(int input) {
  //Serial.println(analogRead(A5));
  int value;
  if (input > 0)    value = 0;
  if (input > 12)   value = 1;
  if (input > 174)  value = 2;
  if (input > 352)  value = 3;
  if (input > 511)  value = 4;
  if (input > 664)  value = 5;
  if (input > 858)  value = 6;
  if (input > 1016) value = 7;
  return (value);
}

int deJitter(int v, int test) {
  if (abs(v - test) > 3) {
    return v;
  }
  return test;
}


//--------------------------------------------
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//ROUTINES!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//--------------------------------------------













void setup() {
  // Serial.begin(115200);
  pinMode(2, OUTPUT);     //trigger out for #1
  pinMode(3, OUTPUT);     //gate out for #1
  pinMode(5, OUTPUT);     //trigger out for #2
  pinMode(6, OUTPUT);     //gate out for #1
  pinMode(9, OUTPUT);     //analog output for CV #1
  pinMode(10, OUTPUT);    //analog output for CV #2
  timer.setTimeout(10);
  trigger1.setTimeout(10);
  trigger2.setTimeout(10);


}



void loop() {

  if (timer.onRestart()) {
    count++;
    countplus++;
    hold1[count] = tmp_midi_note1;
    hold2[count] = tmp_midi_note2;
    if (count > 4) count = 0;
    if (countplus > 4) countplus = 0;
  }

  int tmp_read1 = (deJitter(analogRead(A0), quant1) + 20);
  int tmp_read2 = (deJitter(analogRead(A3), quant2) + 20);


  byte tmp_scale = ScaleSelect(analogRead(A5));

  //  Serial.print("   tmp_midi_note1 = ");
  //  Serial.print(tmp_midi_note1); Serial.print("    tmp_midi_note2 = ");
  //  Serial.println(tmp_midi_note2);

  quant1 = tmp_read1;
  quant2 = tmp_read2;


  if (tmp_read1 < 40) {
    tmp_midi_note1 = hold1[countplus];
    for (byte i = 0; i < 4; i++) {
      hold1[i] = tmp_midi_note1;
      tracker1 = 1;             // UNTESTED CODE
      digitalWrite(3, LOW);     // UNTESTED CODE
    }
  }

  else {
    digitalWrite(3, HIGH);      // UNTESTED CODE
    if (tracker1 == 1) {        // UNTESTED CODE
      trigger1.restart();       // UNTESTED CODE
      tracker1 = 0;             // UNTESTED CODE
    }                           // UNTESTED CODE
    if (trigger1.onActive() ) digitalWrite(2, HIGH);         // UNTESTED CODE
    if (trigger1.onExpired() ) digitalWrite(2, LOW);         // UNTESTED CODE
    switch (tmp_scale) {
      case  0:
        tmp_midi_note1 = mapMaj(tmp_read1);
        break;

      case  1:
        tmp_midi_note1 = mapMin(tmp_read1);
        break;

      case  2:
        tmp_midi_note1 = mapPenta(tmp_read1);
        break;

      case  3:
        tmp_midi_note1 = mapDorian(tmp_read1);
        break;

      case  4:
        tmp_midi_note1 = mapMaj3rd(tmp_read1);
        break;

      case  5:
        tmp_midi_note1 = mapMin3rd(tmp_read1);
        break;

      case  6:
        tmp_midi_note1 = mapWh(tmp_read1);
        break;

      case  7:
        tmp_midi_note1 = mapChromatic(tmp_read1);
      default:
        break;
    }
  }



  if (tmp_read2 < 40) {
    tmp_midi_note2 = hold2[countplus];
    for (byte i = 0; i < 4; i++) {
      hold2[i] = tmp_midi_note2;
      tracker2 = 1;             // UNTESTED CODE
      digitalWrite(6, LOW);     // UNTESTED CODE
    }
  }
  else {
    digitalWrite(6, HIGH);      // UNTESTED CODE
    if (tracker2 == 1) {        // UNTESTED CODE
      trigger2.restart();       // UNTESTED CODE
      tracker2 = 0;             // UNTESTED CODE
    }                           // UNTESTED CODE
    if (trigger2.onActive() ) digitalWrite(5, HIGH);         // UNTESTED CODE
    if (trigger2.onExpired() ) digitalWrite(5, LOW);         // UNTESTED CODE
    switch (tmp_scale) {
      case  0:
        tmp_midi_note2 = mapMaj(tmp_read2);
        break;

      case  1:
        tmp_midi_note2 = mapMin(tmp_read2);
        break;

      case  2:
        tmp_midi_note2 = mapPenta(tmp_read2);
        break;

      case  3:
        tmp_midi_note2 = mapDorian(tmp_read2);
        break;

      case  4:
        tmp_midi_note2 = mapMaj3rd(tmp_read2);
        break;

      case  5:
        tmp_midi_note2 = mapMin3rd(tmp_read2);
        break;

      case  6:
        tmp_midi_note2 = mapWh(tmp_read2);
        break;

      case  7:
        tmp_midi_note2 = mapChromatic(tmp_read2);
      default:
        break;
    }
  }
  // Serial.print("  this is getting sent to pin 9 -- "); Serial.print((tmp_midi_note1 * 20) + 100);
  analogWrite(9, (tmp_midi_note1 * 4) + 200);
  analogWrite(10, (tmp_midi_note2 * 4) + 200);


  //------------------------------------------------------
} //THIS ENDS THE VOID LOOP() RIGHT HERE!!!!!!!!!!!!!!!!!!
//------------------------------------------------------```
2 Likes

Tip: enclose code in triple back tics (```)

2 Likes

You should be able to just leave the code as is, but it seems a shame to not keep it a dual quantizer.

3 Likes

thanks for the trick ```

for the quantizer, it’s question of space it must be housed in a 5 cm wide

You could do that, or you could set up the attenuator so that the jack sockets connect to the opposite sides of the attenuator pots from ground and run the wipers out to the ADC (A0/A3) pins so that the potentiometers becomes their own voltage dividers-but you’d still have to be very careful. Another approach is to use a voltage clamp (something like this but replace the 3.3 for 5v):

You could put it in series with the attenuator to put an absolute limit on the voltage just in case the attenuation lets a signal go too high, or in place of it if you don’t mind clipping the top off of the range of the cv in (which I guess you might be doing a little bit even if it is in series with the attenuators.)

2 Likes

thanks !
the down arrow go to GND or -12 plz ?

1 Like

Good callout, @Dud! That should go to ground. Make sure that you don’t connect the -12 to anything going into the Arduino. I can’t make out what op-amp this is calling for, but if it’s not one that requires both rails then I’d simply leave the -12 from the power rails not connected to the PCB.

2 Likes

ok thank you, I thought I would use a TL074 (since it takes at least 3 input / output for what I want to do and 6 if we want the 2 out as on the full schem) , and therefore connect it to +12 and -12 and a 5V regulator for the arduino

2 Likes

I’ve got an Arduino based multi-scale quantizer in the works. Hopefully done by end of month or not much later. Plans are for a 10 cm dual module, the PCB’s just under that wide, but maybe you could adapt it with perpendicular mounting for a single 5 cm module. Tentative panel layout:

5 Likes

You bet! What are you using for your power bus? If it’s a FC, I thought that had a 5v line built in, which if I remember right you could run directly into the 5v line of the Arduino. If it’s a custom that’s just +12, GND, -12 then you still may not need the regulator if it’s a pre-made development board, since most of those have on-board regulators that can easily handle 12v through the Vin pin (but check that against the documentation for your board.)

Assuming a Nano, you can run it off +12V no problem, connected to Vin. Or a regulated 5V source connected to VCC (5V), not to Vin.

2 Likes

yes it’s FC, on my 1st box I installed the 5V, but never using it because I put regulators on the modules directly, so on my other FC I only have the +12 and - 12.
it’s a simple nano not a pre made dev… board

yes thanks i remember the thread about that :wink:

what circuit have you do for CVin of your future Quantizer ? (if you already have it)

Good! A decent Nano Vin should take +12v without any issues, saving you on build time, parts, heat and wasted amps. I can understand wanting to use the regulator anyway, though.

I would surely use a regulator since I will also need 5V for the CVin schem with the diodes that you posted :slight_smile:

1 Like

Provide de 12v to vin of the arduino and it will hapily provide the 5v you need :slight_smile:

3 Likes

which nano pin can produce 5V plz ?

1 Like

The 5V pin (!), if you feed the unregulated voltage to VIN; see the drawing here:

Not sure how well the onboard regulator is “heat sinked” on an average Nano, but an LM1117 has a thermal resistance of around 60 °C/W junction to air, so you have (125 − 25) / 60 = ~1.5 W to play with worst case, which at 12 V is 1.5 / (12 − 5) = just over 200 mA. You’d want a bit less because 125 °C is crazy hot, but otoh the PCB will distribute some of the heat over a bigger area.

2 Likes

yes I had read it and remembered that it was nbetter to connect 5V regulated to the 5V of nano than to Vin, but I no longer remembered that 5V on the nano could also be an output
thanks!
is it as safe (regulated) as with an external regulator?

1 Like

I’m not too sure you can provide 5v to the arduino on the 5v pin. It is on the other hand sure that you must provide more that 5v to vin since there is a regulator, so you probably need to provide something like 6v. And it can take up to 12v (or even a bit more)

2 Likes