Saturday, January 19, 2019

Front Panels: The Technique So Far

Not only am I learning about electronics but also working with metal?

Here's a quick post about how I do this, hope I don't forget this in a couple of years. This technique (?) is good for drilling holes, reasonably accurately lined up, in flat metal prototype panels.

First: I get my aluminum blanks from PCBWAY in China ("Alubase PCB").  Personally I use FrakRac format for my Audiodiwhy craziness but this should work for 5U, Euro, a one-off front panel for a preamp, a 19" 2U panel for a power amp, or whatever.

Today I am building an modular synthesizer ADSR and need extra drills for SPDT switches and the PCB bracket's 4/40 screws....


Using Eagle (but any illustration program should work) I create a 1:1 drawing of the existing blank with existing holes, and add any extra holes that are needed.

Next I see if it all lines up--this one is getting close.



More alignment, but still not there.



Once aligned (or before) I can add pencil marks for anything else I want to drill. I am basically being lazy--it makes more sense to put this on the CAD drawing, but, oh well. Here, it's for the brackets to hold the PCB. A straightedge and ruler are friends for this.


In the words of my personal hero, Frank Zappa: here is the "crux of the biscuit": The glue on the left will attach the paper print out to the front of the panel, with enough stick to not come loose or tear during drilling. The solvent on the right will completely remove the paper template and any glue that doesn't come up when it's time to ditch the paper. Warning: the solvent stinks to high heaven, so wear gloves or whatever, work outdoors, and as a last resort, try not to breathe the fumes.

All can be purchased at amazon, craft stores, hobby stores and the like.


I use a very small hand drill to create the pilot holes. These can be found on line or in hobby shops--the model airplane folks apparently use them quite a bit for instance. I have found that punches and the like can distort the metal panel's shape.


I invested in a small drill press and put it in my garage. Highly recommended. But!! Caution: Use sharp bits, and always wear gloves and eye protection with this tool--seriously, I have had some close calls here.



Here's a mock up of how things ended up this time. Pretty good, but not perfect! The left hole for the PCB got screwed up; the drill press skittered because I didn't have the bit tightened down enough.  Damn! Glad I was wearing gloves!  This time, I am going against every fiber of my mild OCD; I am going to try to leave it as-is. It's good for me!


Final mock up. Not bad for a prototype, in spite of the screwed up goof on the left. Damn! Oh well. I need to finish the ADSR, and it's a 3 day weekend here in the US so maybe I will do some Lazertranning.

Moving on....happy drilling!

Friday, January 11, 2019

Programming Arduino in "Pure C": Now We're Playing with Power! First steps!!

Let's jump right into the why. 

I have been corresponding a bit with an audio DIY master: Grumble, from the electro-music DIY audio forum. Just when I think I've done something cool, I see what Grumble comes up with and shake my head: this guy has extraordinary DIY skill!

A lot of Grumble's projects (but not all) are digital in nature, using Atmel CPU's.

I was curious how some of his code works and Grumble was nice enough to send me some of his Atmel C code for study.

Hmm, not entirely what I expected. It seems his projects are too advanced to be easily crafted from Arduino's super friendly sketch programming language.  I started to dig; Grumble uses what professional microprocessor programmers call "pure C" or "AVR-C" or "Embedded C" instead.



Pure C: not a Citrus Product. I've also seen it called "raw C". Or maybe "Embedded Microprocessor C/C++".   For AVR/Atmel Processors, I also hear this called "AVR-C"

What's all this then? Arduino's sketch language is a library, written in C and C++, allowing us DIYers to do hard things quickly with user friendly code. If you dig deeper into the libraries that comes with the Arduino IDE however, you begin to see a lot of code like Grumble's. That's because the Arduino sketch language itself is written in C and C++, C++ being arguably more modular due to its object oriented nature but rooted in C.

I read that this is what pros do when programming these chips.  Why? Pure C unlocks every capability of the MPU (Atmel 328P for instance), not just the features and peripherals exposed by friendly open source coders at Arduino and elsewhere. 

For example, for 328P 10 bit ADC conversion, using Pure C you can increase the gain of an incoming analog signals before being presented to the MPU for processing. See how to set that up here. As far as I know, Arduino sketch language can't do this.
 
You also potentially gain better control of a program's size since you only use code space for features you need. 

So--enough introduction!.....let's look at some of the common code fragments you see in Pure C MPU programming.

Here's an example of Pure C. What the hell does this mean?

DDRD |= ( 1 < DDD4);  // answer: same in Sketch as pinMode(4,OUTPUT);

Why read when there is YouTube? A really good (albeit lengthy) vid about "why to use pure C, what is pure C, how do I get Pure C, how do I make Pure C go", is here. For anyone with previous Arduino Sketch programming experience, I think the the vid is clear and easy to follow. Worth a look.



I watched the vid a couple of times and began to experiment with Pure C. here's what I've found so far:
  • You can code with the usual Arduino Sketch feel-good stuff in the Arduino IDE, and throw in dashes of Pure C as needed. It all works; the two can mix. UPDATE: not quite. I noticed to mix analogRead() statments into your pure C plus arduino library mixed masterpiece, you need to use void setup() for initialization, not int main() as shown in the code example below. I figure there are other exceptions as well.
  • Does the usual SIM suspect, Tinkercad, work for Pure C development? Sort of. A vid showing Pure C on Tinkercad to get the immortal blinking LED to blink is here. But I could not get Tinkercad to work reliably beyond simple blink tests--for instance, using pure C to set up one of the simulated Atmel CPU's built in timers--all programmed in Pure C--caused the simulation to bog down in terms of performance, to the point where I felt it wasn't useful.
  • Virtual Breadboard, as described in this post, works. Oddly, using VBBs IDE to talk to an Amtel ATmega328P directly didn't, but using a Nano SIM, it did.  The developer told me a patch will be needed to have the Atmel SIM work but it's not available yet. Update: in version 6.08 of VBB I have verified that this is fixed.  Update 2-1-21: VBB appears to be EOL.  Oh well

Blink LED written entirely in C.  Doesn't work.  My fault.


If you want to play along at home: here's a rundown of some essentials I needed to get started with Pure C:

I needed the datasheet for the Atmel chip that describes the Atmel 328P MPU, which powers the  Arduino Uno R3 on my bench.  Get the ATMEGA328P data sheet hereYes, this datasheet has over 300 pages.  

Why all the reading? This will seem rudimentary to a real Embedded programmer, but maybe not for Arduino programmers? Embedded C is all about finding bits in an MPU's registers and manipulating them. These registers hold essential information like "is this pin an input or output?" "Do you want this pin go to binary high or low?" "How should this timer work?" and so on. 

You flip bits in these registers--akin perhaps to turning on and off physical switches--to make things work the way you want. That means, to master this pure C business, I needed to understand at a very basic level what many of the AVR MPU's registers really do. No way around that. It's a pretty steep uphill climb.

However, to make it easier, Atmel supplies tons of #define designations behind the scenes to allow you to use names of registers and bits directly in your Pure C code; these macros match the data sheet, making things a bit easier to keep straight.

1 << TWDS ; // set this bit to zero, see the datasheet for what in tarnation that does....

And--there are a whole lot of registers and #defined bits in these Atmel MPUs. There are also a weaoth of  Internet videos and web pages going over MPU specifics, like timers, peripherals, serial protocols, and so on. You can learn more about this craft from those--Get reading.

I needed to see how my Arduino board is wired--really.  If an Arduino board has a different pin designation your Pure C code may not work unless you keep which MPU pin goes to which external GPIO pin straight.

For instance, for the Nano I found its schematic here, which clearly shows which pin on the ATMEGA chip goes to which pin on the Arduino board. You will need that to interface things like LEDs, switches, etc. to your MPU as you write your code.

I needed to understand the strange statements you see over and over when reviewing pure C code. 

One we already saw:

DDRD |= ( 1 << DDD4);

This means, for register DDRD, put a 1 (high) into bit DDD4.  This specifically tells the Nano's CPU that pin D4 is going to be an Output.

Getting further into beginner's stuff:

You can OR these "bit shift" statements together:

DDRD =  ( 1 << DDD4) | ( 1 << DDD5) | ( 1 << DDD6) ;

Same idea, but we are putting a 1 in for bits 4, 5, and 6.  So D4, D5, D6 are outputs.

You can use binary notation:

DDRD = 0b11111111;  // all 8 bits of port D all outputs.

So how to make DDD4 a zero?  Setting DDD4 is an input? Use a NOT, also known as an XOR:

DDRD ^=(1 << DDD4); 

And another way to change DDD4 from 1 to a zero (so, flip things?)  This tests DDD4, if DDD4 already contains a 1, it makes DDD4 a zero. If it's a zero, make it a one.

DDRD &=~(1 << DDD4);

You also set the entire register--for instance, make every pin in the Pin Group D inputs. Here 0x00 means use hex (base 16) to set all the bits to zero.

DDRD = 0x00;

And this sets them all to one:

DDRD = 0xFF;

Another common thing you see all the time with Pure C code: you can mask bits using "&".  This means to the compiler: pay attention to certain bits and set others to 0.  

Best shown with an example:

#include <iostream>

using namespace std;

int main()
{
char x = 0;
char result = 0;
char b = 0b11001111;

result = b & 0b00000011;

printf("result is: %x",result);
// result is 3
}


The other thing I see all the time is bit shift: you use << or  >> .  This shifts bits left or right.  

Again best shown with an example:

#include <iostream>

using namespace std;

int main()
{
char x = 0;
char result = 0;
char b = 0x01;

result = b << 2;

printf("result is: %x",result);
// result is 4
}

Tip (for me anyway?) Remember that even after you power cycle, the CPU chip "remembers" your register settings. Compiling and uploading code again won't change registry bits unless you specifically twiddle them. Not so with a blank Arduino sketch, which behind the scenes (as far as I can tell) resets everything to null before applying new code.

I needed to understand some basics about the C language and how it's different than anything else I've ever seen before. For me, taking an online C++ programming class, combined with studying open source C code that's everywhere, was necessary. 

For example: in python, if you want to use a function, you can think it up, type it into your IDE, and start using it. Not so with C.  In the C language, you have to declare your function in the same sort of manner as you declare a variable. Then you define your function, telling the compiler how you want it to work.  Details here. For me that was unexpected, but I quickly found if I skipped these steps or made a mistake in this two step process my code wouldn't compile and my function was useless. 

Enough for now? Just with these few discoveries, I can already read small chunks of Grumbles code and maybe see what he's after. 

To wrap up: Here is a Pure C program I wrote that compiles in Arduino IDE and flashes an LED.  Didn't work at first, now, works on my bench anyway. 

Remove comments, change 1's to 0's, etc., and have fun.

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



#include<avr/io.h>
#define F_CPU16000000UL
#define myPin DDD2 //change 2 to whatever D group in you are using
#include<util/delay.h>

/*
my expanded pure C blink demo.  
Nano V3,0, with LED tied to pin D4; 
1K resistor between LED cathode and ground so to not fry the LED.
uncomment stuff to experiment.
*/

int main()
  {   

/* all pins in D pin group are now input. For DDRD, 1 means output and 0 means input. */  
DDRD = B00000000;

/* we are putting a 1 into bit DD4 in the DDRD //register, making D4 on the nano an output. */  

DDRD |= (1<<myPin);  


/* make DDD4 (pin D4 on Nano) a zero, now it won't flash because it's an input.  So do the opposite of what I say. */
 // DDRD &=~(1 << myPin); 

/*test DDD4 to see if it's a one. If it's a zero, toggle the //bit to one.  If it's one, toggle to zero  */  
 // DDRD ^=(1 << myPin ); 


// BONUS COMMAND USING HEX vs. BIT TWIDDLING.

/* this will set all D pins but leave TX RX to output */
  //DDRD = DDRD | 0x00 ; 

/* this will set all D pins but TX RX to input */
  
  //DDRD = DDRD | 0xFF ; 

  /*Note: if you screw up TX and RX, 
   * which are part of the DDDx, DDRX, PINx" pin group mishpucha,
   * upload into your arduino a normal sketch with serial.begin().  this fixes it.
*/


/* WHILE(1) is the same as the main repeat forever loop you see on arduino  */
  
     while(1)
     {

 /*     PORTD=B11111111; 
//all port D pins (0-7) are now high.  
      _delay_ms(1000);  
      /* I put in 200 to make sure I'm not running the default "blink" sketch. */
/*
       PORTD=B00000000; //D2 is now low.  same exercise.
      _delay_ms(200);
*/

/* same way to do what we just did with 2 lines!  Go Pure C!
 */

PORTD ^=(1 << myPin ); 
     _delay_ms(1000); 
     }
  }

/* don't breathe the fumes */

UPDATE 4-6-21 I am using C a lot (vs. sketch) these days. Once you start you can't stop! Here is a cheat sheet I use for bit twiddling the I refer to a lot. Structs, not mentioned above, are explained here.

////C PROGRAMMING LOGIC CHEATSHEET

///x and y are uint8_t's:

x |= (1 << 2);  // set bit 2 in x to 1

x &= ~(1 << 2);  // Set bit 2 in x to 0

x ^= (1 << 2);   //flip existing value of bit 2, 
                 //so 1 becomes 0, 0 becomes 1. 

y = (x >> 2) & 1;  //check value of bit 2 in x 
                   //and put what you find into y.


//SAME IDEA USING STRUCT 

struct bits {
    uint8_t a0:1;
    uint8_t a1:1;
    uint8_t a2:1;
    uint8_t a3:1;
    uint8_t a4:1;
    uint8_t a5:1;
    uint8_t a4:1;
    uint8_t a5:1;
};

struct bits mybits;  //instantiate new struct

//set values
mybits.a0 = 1;
mybits.b0 = 0; (etc)

//To toggle bits, these 3 examples do the same thing.

mybits.a0 = !mybits.a0;  
mybits.a2 = ~mybits.a2;
mybits.a4 ^= 1;   

if (mybits.a0)
{
//do something if .a0==1

/*
POWERS OF 2:
bits: 7      6  5   4   3  2  1  0
vals: 128   64  32  16  8  4  2  1
*/


Saturday, January 5, 2019

ReneDSR: Fastest Envelope in the West: Zen and the Art of Tau

Hello again, just finished a new module based on a custom PCB.  The original design seems pretty well known in the DIY synth audio community already: Rene Schmitz's "Fastest Envelope in the West".

Find his original page for this design here--scroll to the bottom of the page....

FADSRITW Prototype. No LazerTran front Panel Art yet, still testing it.

The Why in AudioDIWHY: I needed more ADSR's in my rig. What I have now works but doesn't always give me the super quick snappy decay I'd like.

I saw Rene's Fastest envelope schematic and thought "this will work!!" Note that to me "fastest envelope" sounds postal; the acroymn is FEITW ("feeet-oo"?) is odorous, so I am calling it "fastest ADSR" or FADSRITW or even FDITW "Fastest Decay in the West". Whatever.

I will use acronyms going forward, I love acronyms.

 Here it is:

Eagle BRD and SCM files, wiring diagrams, PDFs used for my take on FADSRITW are available on my website, click here.

About the module: Rene describes a couple of variations of his design--one with 2.2M A,D,R pots, another with 1M pots. Increase the the cap value if you decrease the pot value. To me, with analog envelope devices, the size of the cap creating the "TAU" (which, my EE brother explained to me, is simply the R*C value used as the heart of the ADSR) matters.

Let's examine this phenomena:

Warning: Math zone ahead. "Math." Did I say math?  Yes, math.  As much as I'd like, I can't do electronics DIY and completely dismiss math. Sorry.

I was pretty good at math in college, when Madonna ruled the airwaves and dinosaurs roamed the earth, and have since forgotten most all of it, still the math here seems relatively easy: No imaginary numbers! Euler's number (I remembered that!!). Exponents, I remember those as well. like it that way.

OK for ReneADSR decay here's the formula to compute your decay control voltage:

V = S*(e^(-t/RC))

where:

V is the voltage at any given time--what we are after.
e is Eular's number (about 2.718), so, a constant
^ means "raised to a power of what follows", so, e raised to -t divided by R*C
-t is (time * -1).
RC is the resistance * capacitance.  That's TAU, baby!
S is the voltage at time = 0

If you plug this into a graphing program like this very cool one you get beautiful curves:


You take that voltage changing over time, and plug it into an appropriately designed VCA or VCF (such as this one, Matohiko Takeda's "Farm VCA") And: Aaaahhhh! The classic Moog/Roland analog synth sound awaits! That's what I am talking about.

I don't know about you, but a good sounding ADSR > VCF curve makes me very happy indeed.

Slighter aside: TAU is a Greek Letter and looks like the PI symbol that is missing a leg or pi cut in half:



It  means something different in mathematics, or biology, or astrophysics, or whatever; ditch the RC crapola if you're not a physicist because Tau means way different things to different scientists. This confused the hell out of me for a bit. You learn something every day eh?

OK back to it: from the equation above, it shouldn't matter if R gets big as long as C gets small. Right? Within reason perhaps. That's basic math. But again, how it sounds is way more important than however things look on paper. So what sounds best, really?

Guess we'll find out.

I built my first FDITW using 2.2M pots I found on Ebay (linear taper). 2.2M pots are not at all easy to find, but I found 'em, they arrived via eBay from China and 5 minutes later were soldered into the prototype. Yep! Worked first time! Update: I looked around for 2M or 2.2M audio taper--forget it, I am not sure they even exist?

Honking big 2M2 linear taper pot. The US dime to left, for nonUSAers playing along at home, is approx. 17.9mm in diameter. 

obligatory on the bench shot.

Can't find the pots? In an ElectroMusic forum post, DIY mensch donpachi lays down a cool trick for getting 2M out of a dual gang 1M audio taper pot:



I put this on the bench, and it works, but, if there is a +/- 20% error on each pot you might have -40% error overall, giving you a < 2M pot not 2M, so choose your pots accordingly.  You may have to try a few 1M AT dual gangs to get some with a rough value of 2MB overall. I dug some 1M dual gang audio tapers out of my junk box and pachi'd them in, replacing the linear taper honkers. To me, the FADSRITW sounds more musical with audio taper pots for A, D and R. I also jammed in a DPDT switch to select 2.2uF and 10uF for C3 to switch-a-tau. Yep that works, and you could use a DPTP switch here with 3 values for C3, a rotary with X values, a 4066 controlled by an MPU, or whatever else works for you. Overall another fun build. You can get the Eagle stuff, etc. here.

One more tid-bit: For some reason, I got the circuit to work w/ a standard 555 IC, but not a CMOS 7555. No idea why. I will build more of these and see if I can track that one down.

Going forward: I went online and bought some 1M audio taper pots from Small Bear. Waiting for those as I write this post.  I will build another FASDRITW with 1M, 100 ohm resistors vs. the 220's and maybe some other TAU-values (taulues?).  I'll also post some sound samples.  But no, no scope snaps. My eyes always confuse matters like these. The question: What sounds best, really? I figure the different RC combos will sound exactly the same but who knows.  Update: they do all sound pretty much the same, part II of this post is here. Until then, DBTF.  See ya.


ProMicro HID Keyboard Emulator

Quick one this time. The Arduino ProMicro (examples here and here ) is based on an Atmel 16u4 MCU and has HID keyboard emulation ready to go...