Sunday, May 17, 2020

Noise! Lunetta Circuit Part IV: adding dual VCAs for Audio GranTuring-smos

Back again. I'm stuck at home with damn covid Shelter in Place and it's raining. Fortunately the PCB fab shop I use in China is still cranking and I got another set of boards for my Noise! Lunetta stack last week.

Built 'em up rawhide. Worked first time.  Here's all 6 PCBs to date.  The little switch on the left chooses the overall frequency range.

The project so far.....

About Noise!: It's an ongoing project I've been building for many months. I've tried to keep things organic: I think some damn thing, crank it out in Eagle, send it off, get it back, solder it up and see if and how it works. Like the Winchester Mystery House this project may never be completely finished.

It started when Martijn Verhallen from reverselandfill.org and I did a board swap. I really got into his Noise! tone generator and started adding to it, my goal being a full Lunetta type synth for oddball sound generation (I refuse to call this "Sound Design").

Part I--where I build up the base VCO and logic board is here.  Part II: resized and revised, here.  Part III: Adding a quad mux, here.  I created a quad digital pot board and added it to the stack, here.

AD5254 based quad digital pot board, Arduino controlled.  Post is here.

As I was messing with the interconnected PCBs: patching the stack to a bench VCA frequently came up as strange repeating patterns of audio bleeps and blurps. In the mod synth world this is not quite referred to as a "Turing machine"; as Turing modules (a popular one has a demo vid here) produce CV, not audio, and on my bench it's the audio patterns that tend to repeat over and over. But whatever. Is a frequency to CV board coming next? Perhaps.

So why not add a couple of VCAs to the stack?  OK, easy, I already have built up a 2164 based dual VCA board (here), I just needed to lay it out again to fit the 3750x2000 mil footprint I am using for the project.

Got em back, built 'em up. Worked--yeh baby. You can get eagle files, PDFs of schematics, Updated PDFs, Eagle files etc. are here.

OK now the bench photos--sorry--some folks take photos of their dogs and cats, but I don't have dogs nor cats, so you get circuit boards.

The 3750x2000 dual VCA board.  

Ready to test....

The front facing board is a jacks PCB for the 3750x2000 dual VCA. While I was at it I added buffered CV inputs for the MUX board using the usual opamp/zener thing.




I used my usual super-low-parts-count zener clamp/buffer to keep the Arduino CV inputs from frying:



However I am curious about this clever fragment I lifted from a Mutable Instruments design--looks to me like it allows more stages with only one zener reference; didn't use it this time, will use it down the road.


After that, it became a matter of wiring it all up and testing.





OK so how does it sound?  I still need to record the damn stack for real but you can see a vid of some of the repeating patterns at work here.

Is it for everyone?  Nope. Time to keep moving. Might do a powersupply and LFO and call it done.  I guess we'll see.  Until next time, don't breathe the fumes.

Monday, May 11, 2020

Transmitting 32 bit longs between Arduinos using I2C

No soldering this time--let's get on the bench and get going!

From a previous post, I've been messing with new old stock NSA1166 bubble displays for an upcoming audio project, the "Part I" post about retro bubble displays is here.


The 70's era stuff is all cool, but who wants a ton of wires running from whatever to the display?  I want to make these bubbles respond to I2C commands, as you might see in an OLED display like the one here.  I2C has 2 wires to transmit, 3 if you include ground so not too much wiring. Like it. 

I won't go over nuts and bolts of I2C in this post; there is a ton of information all over the Internet about I2C already; you can read more about I2C protocol here--or watch this really good vid here--in short, it's a super easy way to move data between digital dookies.

This time I'll focus on one tid-bit:  I2C wants us to send bytes of data (8 bits) down the wire, one at a time, but for this project I need 24 bits on the slave side; since this 6 digit bubble can display 0-999999. How do we do that?

Wait--let's transmit 32 bits, since that will be a common need for other projects. So: my goal is to be able to enter a long value in decimal on the master Arduino and have it show up in decimal on the slave.

I set up a Proof of Concept on the bench to figure this out. An Arduino UNO was used as I2C master and ProMicro cheapo clono as I2C slave--the ProMicro uses D2 for SDA and D3 for SCL. You knew that right? I didn't. Read more about that here. The Arduino IDE gives us the extremely useful wire.h library right out of the box, greatly simplifying I2C programming so let's use that.

Here's how I wired it up:

(Somewhat unbelievably,  I couldn't find an Eagle device for a 20 pin Pro Micro anywhere so I created an eagle device (how-to for that is here)--the 20 pin ProMicro Eagle thingy you see in the schematic above. Comment if you want a copy of the lbr file for this.)



Bench Press: I used 2 old laptops each with the Arduino IDE running. The iPad on the far right is used to look up Interweb things I'm stuck on. The 3 hosts take up a lot of bench space which is hard on my OCD brain but for me I guess it works....whatever.  To get this going the I2Cscanner sketch (here) proved its worth again, I used that to make sure the physical side of everything worked before digging into creating new code.


Very little wiring for any of this.  I am not 100% sure the pull up resistors are needed, but, whatever....



Rope-a-scope: turns out my bang for the buck Siglent 1202X-E scope (8VA teardown dude vid is here) can accurately analyze and show me I2C data, which i didn't know before doing this proof of concept. This feature proved invaluable as I debugged my crap code--for Siglent users, check out the vid on  getting this going here. Wish I knew about this feature before....

A couple of reminders for myself: bytes, ints, and chars are not the same thing.  For the master code I could get sloppy with variable types, but not with the slave code. I'll have to think about that, but overall, for Arduino, bytes and chars are 8 bits; ints are 16 bits, and longs are 32 bits. Doh!

Shut up and show us the code! 

The POC code sends a sample long value to slave 10000 times over I2C then quits, which should be enough to see if the damn thing is working!


///////////////////MASTER/////////////////////////
#include <Wire.h>


// next line, put any decimal # here 0 to 999999



unsigned long int longInt = 333456;  
//on arduino unsigned long goes to 4 billion something

unsigned char byteArray[4];
   
int c = 0;


void setup() {
// put your setup code here, to run once:
Wire.begin();
//Serial.begin(9600);
}


void loop() {


 

Wire.beginTransmission(0x4);

byteArray[0] = (int)((longInt >> 24) & 0xFF) ;
byteArray[1] = (int)((longInt >> 16) & 0xFF) ;
byteArray[2] = (int)((longInt >> 8) & 0XFF);
byteArray[3] = (int)((longInt & 0XFF));


for (c = 0; c < 10000; c++)
    {
    Wire.write(byteArray, 4);
    delay(10 );
//    Serial.println("Sending");
//    Serial.println(c);
Wire.endTransmission();
    }


}


///////////////////////////////////////
//////////////////SLAVE/////////////////////////


#include <Wire.h>

long value = 0;

byte byteArray[4];

byte x = 0;



void setup() {
  // put your setup code here, to run once:
Wire.begin(0x4);
Wire.onReceive(receiveEvent);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
delay(100);    

}

void receiveEvent(byte)
{
  Serial.println("received");
  while(1 < Wire.available()) // loop through all but the last
  {
   
    for(int i=0; i<4; i++)
        {
         byteArray[i] = Wire.read();
        
     //    Serial.println(byteArray[i], HEX);
   
        }

  }
/////// convert back to long
delay(100);
for (int q = 0; q < 4; q++)
{
  value = (value << 8 ) + (byteArray[q] & 0xff);
}
Serial.println(value); 
}



  //////////////////


I am also working on a PCB for the I2C slave arduino, bubble display, shift registers, pull up resistor array, etc., so far it looks like this; I might send it off for fab this week.



Enough! If anyone has questions about the code, bubbles, PCB, and all else, comment away, but for now, on the bench the POC works; putting a long value in the master code will make it show up in serial out on the slave side. Joy!  For the PCB, who knows--more bubble stuff coming up, as well as an audio chaos generator, just in time for the global chaos we are going through right now. Back to soldering soon. See ya.

Saturday, April 25, 2020

Audio Mixer as Opposed to Social Mixer

You'd think with Shelter in place I'd have a lot of time for electronics noodling around, and I do, but I am not sure my heart is fully in it. I must be more social than I thought.



I finished a 4x1 mixer I designed back in 2005, but mixers are so simple that I can't really say "designed".  For whatever reason, I replaced the 2005 era module in my rack with an new version, complete with new PCB and Front Panel Express expensive front panel. 

Whatever.

The original idea goes like this:


Nice schem eh? Um...no. Have I improved any in 15 years?  15 years ago everything was hand drawn and then built on perf. I look back at this work and marvel that it ever worked.  So maybe I've improved a bit, at least I don't duct tape things together nowadays, at least not often.

Anyway I replaced the hand built mixer module with the one you see on the left, the new one looks a bit more pro perhaps?


I dunno I kinda like the one on the right. 

Anyway with all this time I should be building tons of stuff but instead I find myself reading about politicians telling me to drink disinfectant. Pass the Lysol, Elmo! That's the good thing about electronics--unlike people, they work, or they don't, always in the same way, and above all they don't golf.



My psychiatrist girlfriend's college and high school kids are trapped at home, feeling sad and ripped off, and blame us old farts for all of shelter in place, their missed graduation, their boredom, and everything else. Maybe they are right about that. 

But we gave you iPhones!



My mom and dad talk to me via Zoom each week--they have been holed up at their place in the Central Valley for years, so what the hell does Shelter in Place mean to them anyway?  Their lifestyle hasn't changed much in the past few weeks compared to the last five years. But they are old and I worry about them.  



It's oddly quiet and peaceful outside, when I go out to buy groceries or whatever everyone is walking around with masks on, giving each other suspicious looks. I'm coughing because I breathed too many fumes and they look at me like I am contagious, but no, I explain: it's not those kinda fumes. 

 I am not so sure how bad it is out however, in my neighborhood I can hear birds sing better than before, there are less trains rumbling by, and less planes flying over my house all the time. As long as we all stay healthy, and not go crazy, perhaps it's a tiny bit OK.




I get some comfort from the symbols and right angles, and the idea of things being mixed together kinda reminds me of what we, as humans, aren't doing right now. Wait, no, that's crap. Schemos appeals to my need for order maybe?  Banishing life's chaos? They make me realize how much I love anything with right angles? Not sure.

 But there is something comforting about it, so maybe I'll get back into it today.

Anyway it beats ingesting UV light sources. Whatever you're up to, I hope you are surviving this very strange time with a degree of sanity.  Hang on, the ride is just starting up.





Thursday, April 16, 2020

Turn On the Bubble Machine!

I have no idea what hit me upside the head: for my next audio DIY project in need of a numeric readout, no OLED rubbish, let's go retro. I always liked those little LED bubble displays growing up so how about those?


I looked around and found a bunch on Ebay that were quite expensive, but I managed to spouse up some New Old Stock National Semiconductor NSA1166 seven segment displays--6 bubbles for numbers + decimals--at Jameco, for less than $3 each--cheap.


Those showed up fast!

OK first thing I did was dig into the NSA1166 datasheet, which seems a bit, well, brief?--you can see it here

I knew zilch, and I mean zilch, about 7 segment LED displays, they had never crossed my path before. Wait, where is VCC and GND?  Turns out: doesn't work that way. You get a configuration like the one below (without the current limiting resistors). This is called, for obvious reasons, "Common Cathode"--in this case 8 LED anodes per bubble, but one shared cathode for all of 'em:


That means: current sourced to A1-A8 light up segments of the LEDs in a single bubble, which are laid out like this:


The idea is that an MPU (Arduino for instance--could also be a driver chip, transistors, electro-cups and string, or whatever) sends current to one set of LEDs, that is, one bubble, say LEDs "B" and "C" in the leftmost bubble, to make the number "1", then the MPU moves on to the next bubble--fast. The persistence of vision in your eye make each of the six bubbles look like they are always on even though they aren't. Marvey. Turn on the Bubble Machine!!

OK with that super basic knowledge under my belt, it was time to see if anyone had already written up an easy way to hook 7 segment displays up to Arduino type MPUs. Why reinvent the wheel? 

Answer: yes and yes and yes--this has been done many times before in Arduinoland....

But so far no perfect fit I could find, for me anyway.

The post here is a very cool implementation but appears to work with 3 different Arduinos, none of which I had.  

Or the one here, but it uses HP NOS bubbles which seem expensive and hard to find. 

Or...well....there are tons of other designs out there, but since I have lots of time on my hands, had never touched a seven segment display before, and needed a project to waste time on, I said the same thing Nixon did--I'll erase it myself!

Some design goals: 
  • My implementation must work with a wide range of Arduinos and other Arduino-like MPUs
  • It had to work with the NSA1166 since that's all I had in terms of 7-seg displays
  • The finished design had to be as modular (i.e., reusable in other projects) as possible.
  • It can't flicker, stutter, or looks obvius crap-like
  • It can't show the wrong numbers (duh)
  • A 3 digit number is shown from the far right bubble; and in that case, the left 3 digits must blanked--same idea for any "blank" needed. So no 000333. I want to just see 333.
  • The display had to be reasonably fast to respond to new values at input--10ms?
  • It has to take up as few pins as possible on the Arduino (since I might want to drive this from an ATTINY85 someday, or just have other things I want to use the Arduino for in addition to this display?).
  • OK to use external jellybean parts, but let's keep it reasonable.
OK, let's motorize this pursuit.....

I already had an UNO (easy to develop with) about 3 clono nanos (Ditto) and maybe 5 clono Pro Minis in my junk box. The latter meant finding, untangling, and then hooking up the tiny USB to Serial adapter for programming so let's forget that this time.  

A Leonardo might be a good fit, but I don't have any; I bought 5 cheapos Leonardos from Ebay but they won't be here for about another 6 million months. 

So I developed with the trusty UNO. Will probably make slight changes to accommodate a smaller MPU down the road.

Turns out the UNO has enough I/O pins for entire this project but then I'd be out of pins for anything else fun--so let's use a shift register such as the venerable 74HC595 to free up pins; I used two 595 breakout boards from Sparkfun for my POC:


No Shift, Sherlock! There is a ton of information about using shift registers with Arduinos on Youtube (here and here for instance) as well as the forums etc. (post here was very useful for this project). I won't repeat how it all works, the only thing: I had issues with the fact that pins in 595-land aren't always called the same thing from chip to document to breakout board to forum page...which got me feeling stupid and frustrated from time to time. I'll live.

Here is the "595 Cheat sheet" I came up:

HOW IT WORKS:
  • Bits of data--two bytes total in our case, come in the SERIAL in port.
  • Each HIGH on Serial Clock shifts everything over one to the right. The arduino "shiftOut()" function handles that and the timing. Yeh!
  • Each LATCH going high says "we are done with the bullshift, present everything to the world, ready to use".
  • You can put x number of 595s in series and it all works! I used 2x 595s for this, but you don't have to stop there; you can get as many digital I/O pins as you could ever need by putting still more registers in series, flowing your SER bits through all of them, then LATCHing when you're ready to go. And through it all--even if you have 10 of the damn things lined up, that's 80 I/O pins, you'll never consume more than than 3 Arduino digital pins for the whole enchilada! YEH!!!!

WHAT THE 595's PINS DO:

  • Q0-Q7 outputs. What we want to use to drive our bubble display's LEDs.  These pins can source or sink current and light up the LEDs (with current limiting resistors) A-OK; I didn't find anything definitive about the current limits for the NS1166 in the NS datasheet--whatever; 5V with 330ohm-ish resistors did the trick, and 3V worked w 330ohm albeit a bit dimmer. No smoke!
  • DS-Serial data. Seen it as "SER" on some CMOS data sheets, and called "SER IN" on Sparkfun breakout. Your serial data--the 8 on/offs you want to blow into the shift register--goes in here.
  • OE--output enable. Active Low. Called /OE on the Sparkfun breakout board. We want our outputs enabled eh? Well Yes we do or else nothing happens! So, tie this to ground.
  • SH_CP is clock pin. Each time the clock goes low to high, the bits shift in the device one to the right. Called "CLOCK" on Sparkfun board.
  • MR--master reset. Active low. This clears everything in the register, and we don't want to clear everything ever for this application, so tie it to 5V. Called /RESET on the Sparkfun.
  • ST_CP "Latch" pin.  When that goes high, everything in the shift register is presented to the outside world. Called L_CLOCK on the Sparkfun device.
  • Q7' (Q7 prime) is SER_OUT on the Sparkfun. Use to daisy chain your 595s, so serial going into one IC can feed as many 595s in series as you need for your project. I've seen this called "QH" or "QH*" on some chips and data sheets.

SHUT UP AND BUILD THE THING ALREADY!

OK dammit!

I ended up bread boarding this:



Some bench photos:

I had to modify a cheap breadboard to accommodate the 595's. Sparkfun needed to make these breakout boards about 200mils wider!

I added extra LEDs in parallel with the bubbles to better see what was going on with the 595s. 

Final POC was to have the pot make the display read from 0-1023 based on the pot's wiper position. Works! No flicker!

OK how about the code? Here is what I was using to get the pot to go--I wrote other variations to try out other things, comment if anyone wants to see those.

This wasn't toooo hard--it took a couple of evenings. I got stuck for maybe an hour on one strange thing--the bubbles wouldn't work reliably if I was using Serial.write to debug. Commenting the serial stuff out, the bubbles worked again. So I was introducing a bug by debugging? Not to be a pest, but yes.

A few >'s instead needed to be <' s but overall, not bad at all.


//////////******************************

long testnumber = 0;

//testnumber is what I want to show up on the NSA1166.
//you have to use long. int only goes to 32000 or something close!

//////////******************************


unsigned long startMillis;  //start millis timer
unsigned long currentMillis;
const unsigned long period = 10;

//each item in the array below ground a given pin of a 595, so the Bubble can display.

int mybubble[] = {124,188,220,236,244,248};


int c = 0; /* used to hold number of elements in the array */
long n;
int p = 0; // counter for filling array with elements.

int numberArray[6];

//this holds each value of number we are trying to display
// bubble zero is leftmost bubble!

long bubble5 = 0;
long bubble4 = 0;
long bubble3 = 0;
long bubble2 = 0;
long bubble1 = 0;
long bubble0 = 0;




//pins used to feed shift regs
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;



//pot wiper connected to A0.  gnd AND 5V for the rest
int pot = A0;


void setup() {
              // put your setup code here, to run once:
              //set pins to output so you can control the shift register
              pinMode(latchPin, OUTPUT);
              pinMode(clockPin, OUTPUT);
              pinMode(dataPin, OUTPUT);

// debug using serial
//Serial.begin(9600);  
// BE CAREFUL serial stuff can step on Bubble display and make it mysteriously not work.

// initialize array

             numberArray[0] = 0;
             numberArray[1] = 0;
             numberArray[2] = 0;
             numberArray[3] = 0;
             numberArray[4] = 0;
             numberArray[5] = 0;
 }





            
void loop() 
{

//do a analog read every 10ms

currentMillis = millis();
   if (currentMillis - startMillis >= period)  //test whether the period has elapsed
    {
    testnumber = analogRead(pot);
    startMillis = currentMillis;
    }


c = 0;   


// turn that number into an array.  Note: ARRAY is backwards!


//first we need to determine how many digits the number in ques\ton has.  We need that to send //blanks out later
n = testnumber;

         while (n != 0)
     
           {
            n /= 10;
            c++;

           }
      /*      Serial.println("testnumber variable value is: ");
            Serial.println(testnumber);       
            Serial.println("length of array is: ");
            Serial.println(c);

*/
/////////////////

n = testnumber;
p = 5;
//now fill an array with each digit.

while ((p > -1) && (n != 0))
          
    {

          numberArray[p] = n % 10;
          n /= 10; 
 /*   
          Serial.print("----------");

          Serial.println("We are seeing output of array value");
          Serial.println(p);
          Serial.println(numberArray[p]);
          Serial.println("");
 */     
          
      p--;
    }
 
//wanted to time more CRAP then realized it wasn't needed, comment that!
//Leaving it here in case I remember what I was thinking.

////currentMillis = millis();
//if (currentMillis - startMillis >= period)  //test whether the period has elapsed

//{  

//startMillis = currentMillis;  //update current millis.


/////////////////////////////////////////////////

//YEH next part can be simplified and made into a single function.
//I am too lazy to do this. you do it!

//AND--I don't accommodate decimal points at all.
//Again I am too lazy.....

////////////////////////////////////////////

bubble5 = getbyte(numberArray[5]);        
 //write to shift reg. rightmost digit.

    
    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    

    // next line puts numeric data onto shift register
    shiftOut(dataPin, clockPin, LSBFIRST, bubble5);
   
    
    // then pick which bubble to impact
    
     shiftOut(dataPin, clockPin, LSBFIRST, mybubble[5]);
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);



//write to shift reg digit. 2nd from right 

if (c < 2)

   {
    bubble4 = 0;
   }
   else
   {
    bubble4 = getbyte(numberArray[4]);        
   }

    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    

    // next line puts numeric data onto shift register
    shiftOut(dataPin, clockPin, LSBFIRST, bubble4);
   
    
    // then pick which bubble to impact
    
     shiftOut(dataPin, clockPin, LSBFIRST, mybubble[4]);
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);

    
 //write to shift reg digit. 3rd from right 

if (c < 3)
  {
  bubble3 = 0;  
  }
  else
  {
  bubble3 = getbyte(numberArray[3]);        
  }
    

    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    

    // next line puts numeric data onto shift register
    shiftOut(dataPin, clockPin, LSBFIRST, bubble3);
   
    
    // then pick which bubble to impact
    
     shiftOut(dataPin, clockPin, LSBFIRST, mybubble[3]);
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);



  //write to shift reg digit. 4th from right 


if (c < 4)
  {
    bubble2 = 0;
  }
  else
  {
  bubble2 = getbyte(numberArray[2]);        
  }  
    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    

    // next line puts numeric data onto shift register
    shiftOut(dataPin, clockPin, LSBFIRST, bubble2);
   
    
    // then pick which bubble to impact
    
     shiftOut(dataPin, clockPin, LSBFIRST, mybubble[2]);
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);       



  //write to shift reg digit. 5th from right 


if (c < 5)
  {
    bubble1 = 0;
   }
else
{
  bubble1 = getbyte(numberArray[1]);        
}   
    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    

    // next line puts numeric data onto shift register
    shiftOut(dataPin, clockPin, LSBFIRST, bubble1);
   
    
    // then pick which bubble to impact
    
     shiftOut(dataPin, clockPin, LSBFIRST, mybubble[1]);
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);       


  //write to shift reg digit. leftmost


if (c < 6)
  {
  bubble0 = 0;
  }
  else
  {
  bubble0 = getbyte(numberArray[0]);        
  } 
    // take the latchPin low so 
    // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
    

    // next line puts numeric data onto shift register
    shiftOut(dataPin, clockPin, LSBFIRST, bubble0);
   
    
    // then pick which bubble to impact
    
     shiftOut(dataPin, clockPin, LSBFIRST, mybubble[0]);
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);       


  
   
} // end main loop

//shiftOUT does not seem to accommodate bxxxxxxx typle format?
//whatever, I am using decimal values for this.

byte getbyte(long x)
{
  int a;
  
 if (x == 0)
   {
   a = 252; //11111100
   return a;
   }
  
if (x == 1)
   {
  a =  96; //011000000
  return a;
   }

if (x == 2)
   {
  a =  218; //11011010
  return a;
   }
if (x == 3)
   {
  a =  242; //11110010
  return a;
   }

if (x == 4)
   {
  a =  102; //01100110
  return a;
   }

if (x == 5)
   {
  a =  182; //10110110
  return a;
   }

if (x == 6)
   {
  a = 190 ; //10111110
  return a;
   }

if (x == 7)
   {
  a =  224; //11100000
  return a;
   }

if (x == 8)
   {
  a = 254 ; //11111110
  return a;
   }

if (x == 9)
   {
  a = 230 ; //11100110
  return a;
   }


}

///////////////////////////////////////////////

OK so this all works!  What is next?

It would be cool to use some pins on the Arduino (Something w/ a smaller form factor than an uno) to make this into a I2C slave device. Then, I could use the NSA1166 as an I2C driven display and never have to think very hard about adding bubble displays to my projects again.

Also, would be nice to get decimals going, but I don't have an immediate need for that, so for now, wah-wah.

That's it, no smoke, no fumes, bubble up the covid and leave it behind!

Sunday, April 12, 2020

Using PCB material for a Front Panel: I said it wouldn't work, and I have no idea why I said this. It works.

Before all this bizarre and tragic COVID hibernation stuff began, I was at a local geeky synth meetup discussing (of course) DIY front panels, going through my usual diatribe about using PCBWAY "alubase" material to provide my inexpensive metalwork. I was pretty damn proud of myself. But then! one of the much smarter members told me that's stupid--and expensive--why not just use PCB material for this? Much cheaper! Much Easier! Mo Better!

I said, well you can't because--because.....because??



Turns out there is no because!! Of course, PCB material works great for front panels.

Yeh, and any PCB fab shop can make these. You already have the board layout right?  Just throw another gerber in there in the same run for the front panel. Viola.

So who came up with this DIY breakthrough? No idea, but the Meetup tech I was talking to was turned onto using PCB material for front panels because LMNC uses it in his VCO kit (oh no!!).

So it must work, right?

All Hail this dude?


Let's motorize this pursuit! Using Eagle CAD, I created a front panel design for a NOISE! board from Reverselandfill that, after many PCB level repairs to fix some of traces I savagely busted, worked again. It desperately needed a front panel--Orig. post about this module is here.

Creating the new raw front panel was easy--I measured the board, created a quickee PCB with just the dimensions and drills (and nothing else), created a gerber, and off it went to JLCPCB along with some other "real" PCB layouts. 

You can try adding Gerberized silkscreens for the legends, but for this project I didn't do that. I used Mr. Label instead (blog post about Mr. L is here--and the more I employ the honorable Mr. Label for front panel graphics work, the happier I am--1001 uses?)  Yeh, I get all graphics and fonts etc. I can dream up and are easily printed out on my super cheap laser printer.


Mr Label ready to apply

Say What? JLCPBC didn't process the order right away (it was "Under review" for at least a couple of days) They figured that I forgot to put traces and a soldermask in the gerber and didn't want me to go wah-wah. But I emailed them again: this was for a front panel! And after they pretty quickly gave me the thumbs up. So I paid 'em and waited.

The PCB for "front panel only" showed up in Sunny N. California about 6 days later. After a serious amount of Howard Hughes ready Covid scrub downs I was ready to work.

So what: a few things about this--first, the PCB material is more brittle than aluminum, and maybe a bit harder to work with, so best you can, make sure you get the layout right or close to right the first time.

Second, you might need a large metal file (I did anyway) to file away excess material, for me, it appeared that the panel shipped back to me was maybe 1mm-2mm off on one side. But it was pretty easy to file the PCB stuff down to size.

Third, you can paint it black. Yeh! Since I was working with a black background in Illustrator, I used black PCB material. This turned out to be a good thing, because even though the Mr. Label didn't quite fit because I put his jock strap on crooked, the colors matched and everything looked good.



While I was at it, I created a better Mr. Label for one of the modules from my CEM VCO project, to replace the one that burned up rel good:


Look Mum, No Covid?  Damn I hope so. I will be using a lot more PCB material for front panels in the near future.  If there's a reason to get back to aluminum I'll let you know, but for now, PCB works and I'm happily taking in the fumes. You should do the same, but not the Corona Kind, rather, the good kind. Stay safe!

Monday, March 30, 2020

Smoke on the Forty--3340 that is--Actually a TL074--Burned up Sir!

Before any of this Covid/Corona Shelter in Place thing I could still invite friends to my studio. So I was showing off my CEM VCOs when all of a sudden SMOKE started pouring out of one of them.

Good work Elmo--nice craftsmanship--impressive job on this.

The OCD in me hates electrical smoke but I guess it gets us all at some point.

Here's the VCO PCB that blew up real good:

 I-IV-V: "wuz a TL074SMD.....now charcoal...."

Question: what happened?  The fried VCO was a CEM3340 based "prototype"--but then everything us DIYers build is a prototype right--anyway, the smoked VCO was the first 3340 VCO I built based on the design here. It didn't work at first, de nada, so I added kludge buffer daughter boards, a floating octave selector circuit, and extra 22 gauge wiring fixes affixed with hot glue, and more, all to correct my own design and fab screw ups; see the the previous post here....a horror show.

The front panel wasn't much better....

The other two CEM VCOs I built (post here) fared better--I used a "rev 2" PCB, correcting the mistakes of rev 1. That means: no kludges--and no smoke (yet) from either of these two (yet).



Lucky I was in the studio when the first VCO smoked right? Otherwise this could have really gotten bad.

So the question is, what happened? 

Well being not 100% sure....I dug in a bit.

The TL074 IC used as a quad buffer in the VCO has built in short circuit protection, here is the schemo of a TL071 shamelessly lifted from TIs datasheet:


This means that any current going in or out of a TL07x hits a few resistors first. I didn't know these resistors were there at all, but even so.....as I see it, with +15/-15V power, you're going to be sinking a max of something like 75mA of current through this tiny resistor if you create a dead short to Edison ground. That's over one watt. Since this is an itty-bitty-IC-in-chip resistor, not the honking 2W power resistors you'd find in a tube amp, the resistor can't be take that much punishment in terms of dissipating heat before saying good night.

There are also resistors between the + and - rails I can see in the TL071 schematic as well. Same sort of thing--you get a smidge of protection from overdoing the current from + to - from the looks of things, but there has to be limits to how much current you can put through any of these resistors before blowing up the FETS, transistors, or something else.

I like experimenting with innocent components....so I put a sacrificial TL071 on my bench, created a dead short from its output to ground (through an ammeter) than started cranking up the current from my bench supply.  WARNING: do not try this at home!!! The op amp will heat up very fast, you could burn your house down. PLEASE ALWAYS BE CAREFUL!

Here is my test circuit if you can even call it a circuit? The downward arrow represents my Fluke DVM set to read and display current:
The op amp became hot very quickly when wired up like this.....and could easily have smoked if I left it a few more minutes, possibly taking other things with it, like my entire lab. Again PLEASE DO NOT TRY THIS AT HOME!

AudioDiWhy's lab dungeon of Op Amp Pain.


The data sheet says a max for the FK package (not sure what FK means, perhaps FK-U since this is TI? Help me out here?) is 260C for one minute. I didn't record exactly how hot the TL071 got in my experiments but within a few seconds it was too hot to touch. Probably way less than 260C.

So what happened inside the IC during the torture test? Not sure exactly. There might be clamping circuitry I don't see in the schematic....or maybe I am missing something, but when first powering up my torture test the ammeter read around 20mA, I figure because I wasn't reading true Edison ground, so about what I'd expect as the max source output current from the IC, for a few seconds. But then the Fluke read 0A and the chip started to heat up fast. Even at 5V V+ and GND, in the config you see above, once the IC clamped, things heated up, to the point where I couldn't touch the IC, after maybe 15-20 seconds. Not good.

So I think it's safe to assume that in spite of the short protection the TL07x IC will get really hot if you present the output with a dead short to ground. The heat has to go somewhere.....

I didn't bother testing things like reverse voltage present at V+ vs. V-, since I know that will kill the IC straight away (been there, done that). So: don't do that either.

So I figure, what could have killed the vco was simple: one of the outputs of the VCO's TL074 buffer must have gotten shorted to ground by a wire or kludge or solder bit or something. From the burn marks it might have been a short on pin 8 pulling way too much current through V-.


All Hail Richie Blackmore!


So what is my takeaway from all of this?

First--for modular applications, always use series output resistors for your output buffer op amps--at least 1K, on a TL0xx even though there is already a resistor inside. It isn't going to hurt to increase your short circuit protection.

Second--don't over kludge! This module was a horror show of daughter boards, hot glue, and 22 gauge bungies. Something was bound to go wrong, even though at first it "worked". Resist the urge--toss the overly kludged module and start over.

Third--Turn that sh*t off! YEP! always shut off all your DIY stuff when you are out of the studio, it's not UL listed and can blow up any time.


"Home, Charles": I took the smoked VCO out of the rack; time to rebuild it eh? I had left over extra rev 2 CEM VCO PCBs for this project--it was a pretty easy single evening job of using my rework tool to remove any parts I wanted to save from the blown out board and building up another main PCB, mounting it to remaining VCO guts, and calibrating it. Worked pretty much first time.

I also made the existing front panel a bit more presentable using "Mr Label", a vinyl sticker front panel process you can read about here.

Overall, good to have the 3rd VCO back, but I hope there isn't some sort of flaw in my VCO layout.  I guess we will see; if I indeed screwwed it up I will be breathing many more fumes at some later date.

Such is life sheltered in place.

Tuesday, March 24, 2020

Noise! Part III: Quad 4051 CMOS Mux

If you're like me, sheltering in place is a geek's dream, you can work at the bench all day and no one will bug you, since you might sneeze on them?

OK, I have been using this strange time to further expand and enhance the Noise! Lunetta circuit (read part I--basic board layout here; part II--digital quad pot control of 4x LunettaVCOs here).

This time I'm extending the Lunetta design from the creative mind of Martijn Verhallen/reverselandfill.org to respond to a 8x4 arduino controlled Mux.  This adds more audio oddness on 2x more output jacks.

The extra board allows CMOS "patching"--which Martijn's original design accomplishes with a jack bay--using CV control of an Arduino Pro Mini and 4x CMOS 4051 MUX SMD IC's.

Turns out, as with most things in Arduinoland, it was really easy to MUX this way.....I see this as a useful thing for any number of CMOS audio projects and I don't why I wasted so much time trying to do this with more complexity. 4051s are easy.

Here is the finished mux board (in front) buttoned up (???) on the bench.


CMOS fun and 4051 for audio is nothing new to this blog--see the voltage controlled switch synth  module here for instance. Yes the 405x chips are endlessly useful to what we do. BTW it wouldn't be hard to redo this board to use +12/-5 power and +5 logic, which should allow seamless switching of +/- 5V P/P audio signals--I have not messed with 405x powered this way, but it should work? The board would need to be modified to accommodate more voltage regulators, but really that shouldn't be too hard right? Maybe one of these days......


Prototype PCB for the Mux. $2 for 5x from China. Why stripboard or wirewrap, ever?


Once all the various pieces of the Noise! Lunetta are done (really, one of these days!) I'll post 'em on my website....

LOONETTA: The mux output goes to 2 output jacks--again thanks to Martijn's creative work--one an OR of each of 2x 4051s in the mux, the other, each 2 more 4051's outputs are fed through a series of 4070 CMOS XOR logic stages for some Korg inspired ringmod craziness.

The Mux CV is supplied right now by a 0-5V tall trimmer set up as a voltage divider, but I will add jacks and buffers for true CV of mux control in the next few weeks--for that I need yet another PCB. The post on "board # whatever" for the NOISE! project is coming up. Sorry I just can't stop!

OK, What does it sound like? --it sounds STRANGE.

I plan to do more sound clips one of these days, but take a look at this quick vid....it starts with a Turing circuit sort of situation, then inexplicably morphs into some audio farting, then back to Turing. This pattern continues forever. odd. More sound clips to come.....but not today, I am too busy working on the next PCBs for this project....





OK, on to the obligatory and possibly useless bench photos:




Here's the sketch that makes the whole thing go.  I can see many ways to improve this but for now hey it works:

  int CV0 = 0;
  int CV1 = 0;
  int CV2 = 0;
  int CV3 = 0;

  int MAP0 = 0;
  int MAP1 = 0;
  int MAP2 = 0;
  int MAP3 = 0;

void setup() {
  pinMode(1,OUTPUT);
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(13,OUTPUT);
  pinMode(14,OUTPUT);
  pinMode(15,OUTPUT);
  pinMode(16,OUTPUT);
  pinMode(17,OUTPUT);
  pinMode(A0,INPUT); //tie to mux pins D2-D4
  pinMode(A1,INPUT);  //tie to mux pins D5-7
  pinMode(A6,INPUT); //tie to mux pins D8-10
  pinMode(A7,INPUT); //tie to mux pins D11-13


}

void loop() {

 digitalWrite(17,LOW); //enable IC5
 digitalWrite(16,LOW); //enable IC3

 CV0 = analogRead(A0);
MAP0 = map(CV0,0,1023,0,7);

 CV1 = analogRead(A1);
MAP1 = map(CV1,0,1023,0,7);

 CV2 = analogRead(A6);
MAP2 = map(CV2,0,1023,0,7);

 CV3 = analogRead(A7);
MAP3 = map(CV3,0,1023,0,7);

////////////////////////////////////
//IC2

switch(MAP0)
{
case(0):
digitalWrite(2,LOW);
digitalWrite(3,LOW);
digitalWrite(4,LOW);
break;

case(1):
digitalWrite(2,HIGH);
digitalWrite(3,LOW);
digitalWrite(4,LOW);
break;

case(2):
digitalWrite(2,LOW);
digitalWrite(3,HIGH);
digitalWrite(4,LOW);
break;

case(3):
digitalWrite(2,HIGH);
digitalWrite(3,HIGH);
digitalWrite(4,LOW);
break;

case(4):
digitalWrite(2,LOW);
digitalWrite(3,LOW);
digitalWrite(4,HIGH);
break;

case(5):
digitalWrite(2,HIGH);
digitalWrite(3,LOW);
digitalWrite(4,HIGH);
break;

case(6):
digitalWrite(2,LOW);
digitalWrite(3,HIGH);
digitalWrite(4,HIGH);
break;

case(7):
digitalWrite(2,HIGH);
digitalWrite(3,HIGH);
digitalWrite(4,HIGH);
break;

}

/////////////////////////
// IC3
switch(MAP1)
{
case(0):
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
break;

case(1):
digitalWrite(5,HIGH);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
break;

case(2):
digitalWrite(5,LOW);
digitalWrite(6,HIGH);
digitalWrite(7,LOW);
break;

case(3):
digitalWrite(5,HIGH);
digitalWrite(6,HIGH);
digitalWrite(7,LOW);
break;

case(4):
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,HIGH);
break;

case(5):
digitalWrite(5,HIGH);
digitalWrite(6,LOW);
digitalWrite(7,HIGH);
break;

case(6):
digitalWrite(5,LOW);
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
break;

case(7):
digitalWrite(5,HIGH);
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
break;

}

/////////////////////////
// IC4
switch(MAP2)
{
case(0):
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(10,LOW);
break;

case(1):
digitalWrite(8,HIGH);
digitalWrite(9,LOW);
digitalWrite(10,LOW);
break;

case(2):
digitalWrite(8,LOW);
digitalWrite(9,HIGH);
digitalWrite(10,LOW);
break;

case(3):
digitalWrite(8,HIGH);
digitalWrite(9,HIGH);
digitalWrite(10,LOW);
break;

case(4):
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(10,HIGH);
break;

case(5):
digitalWrite(8,HIGH);
digitalWrite(9,LOW);
digitalWrite(10,HIGH);
break;

case(6):
digitalWrite(8,LOW);
digitalWrite(9,HIGH);
digitalWrite(10,HIGH);
break;

case(7):
digitalWrite(8,HIGH);
digitalWrite(9,HIGH);
digitalWrite(10,HIGH);
break;
}


/////////////////////////
// IC5
switch(MAP3)
{
case(0):
digitalWrite(11,LOW);
digitalWrite(12,LOW);
digitalWrite(13,LOW);
break;

case(1):
digitalWrite(11,HIGH);
digitalWrite(12,LOW);
digitalWrite(13,LOW);
break;

case(2):
digitalWrite(11,LOW);
digitalWrite(12,HIGH);
digitalWrite(13,LOW);
break;

case(3):
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
digitalWrite(13,LOW);
break;

case(4):
digitalWrite(11,LOW);
digitalWrite(12,LOW);
digitalWrite(13,HIGH);
break;

case(5):
digitalWrite(11,HIGH);
digitalWrite(12,LOW);
digitalWrite(13,HIGH);
break;

case(6):
digitalWrite(11,LOW);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);
break;

case(7):
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);
break;
}


} //end loop

In CMOS we trust!! Yeh Elmo, turns out something simple like this works just fine.

Next up, I am going to add some VCAs to this; more tall trimmers for CV adjustomatic, I have a few other ideas for more add-ons.

One of these days the NOISE! synth will be done and racked up, but for now, it's just too much fun building more stuff for it much like the winchester mystery house. Stay safe!

Noise! Lunetta Circuit Part IV: adding dual VCAs for Audio GranTuring-smos

Back again.  I'm stuck at home with damn covid Shelter in Place and it's raining. Fortunately the PCB fab shop I use in China is sti...