Wednesday, October 3, 2018

Audio Test Gadget

While I was waiting on some parts and a set of boards to come in from China, I decided to try making an audio frequency test gadget.
Since I had some of what I wanted to do already done for a Nano, I will see if I can quickly port that over to the Nano Test Gadget mother board.  The mother board is set up for a I2C LCD that I quickly replaced with a 1.3" OLED  display that is also I2C.   Only software required is a driver library from Adafruit, and their graphics library.  This is small but its 128 x 64 pixel display gives fairly good resolution for displaying things like a simulated analog meter and a simple AF spectrum analyzer.  These are things that I have already working on a pro-mini as a stand alone simulated analog meter for a transceiver.

The upper limit for the spectrum analyzer software with this display is about 4Kkz.  which is fine for the audio frequencies usually found in normal HF transceivers.  With that in mind I decided to limit the display range and the tone generator to 4500 Hz.  Using an Arduino tone library, I wrote a small function to generate tones from 50 to 4500 Hz.  This is a square wave output, so I will have to calculate the values for a low pass filter to make the output appear to be more of a sine wave. 


 A function similar to what I used in other projects is used to display the frequency set the value sent to the tone() function. To make it a little easier I just chose 50Hz. as the step size as a compromise between speed and resolution.

Next thing I waned was a AC voltmeter with a frequency response up to 4.5 KHz. at least.  I found some code from Adafruit  for a sound level meter and used  part of that to get the peak to peak value of the AC signal.  This code samples the input pin for  50 ms. and finds the highest and lowest values and uses the difference as the peak to peak value.  After I had it working I checked the values compared to that of a scope over the desired 4.5 KHz. frequency range and found it to be very accurate.

unsigned int  getACVolts( char inputPin) {
#define sampleWindow  50  //  50 ms  20 Hz. sample rate 
  unsigned long startMillis = millis();  // start of sample window
  unsigned int PeaktoPeak = 0;          // peak-to-peak level
  unsigned int SignalMax = 0;
  unsigned int SignalMin = 1024;
  while ( millis() - startMillis < sampleWindow ) {
    sample = analogRead( inputPin);
    if (sample < 1024) {
      if (sample > SignalMax) {
        SignalMax = sample;                                
// saves just the max levels
      }
      else if (sample < SignalMin) {
        SignalMin = sample;                               
// saves just the min levels
      }
    }
  }
  PeaktoPeak = SignalMax - SignalMin;                      
// max - min = peak-peak amplitude
  return  PeaktoPeak ;

}


Since most of what I work on has a peak to peak value of less than 5 volts I am going with a single range for now.  I could easily switch between the 5 volt reference and the 1.1 volt internal reference for the ADC If I want a more sensitive range,
I decided to just use a current limiting  resistor and forget about a voltage divider for the input.  After getting the p-p value from the ADC, I used that as the value  to find the position of the needle on the simulated display.  This is the same code I have used in several projects detailed in earlier Blog posts.  I decided to convert this to rms for the display scale, and also a digital display on the meter face.  


While I was working on the simulated analog meter for a Bitx, I added some code to do a audio frequency spectrum analyzer display.  While I found this would be mostly useless for a transceiver, it will fit in nicely with this test gadget.  


The code ported over very easily, and after adding a rough frequency scale to the display I was very pleased with the result.  Using the simple menu system I have used on most of my recent projects, I wrapped these up into a fairly simple multifunction test gadget for working with audio frequency circuits.  One thing I did find while trying to get this working is that the combination of the OLED display with its screen buffer stored in the Arduino RAM and the buffers used by the FFT, I quickly started to run out of memory.   It took quite a bit of playing to get every thing to play well together.  But now I can set a frequency on the tone generator and read it with either the voltmeter or the spectrum analyzer.

I have a little work to do on the hardware before this is finished, but it is coming along nicely so far.  The other day I saw a article on a
small Arduino based oscilloscope.  Just thinking about seeing if I can cram another function into this test gadget.

Wednesday, September 5, 2018

CWTD.ORG Test Gadget mother boards

In the last CWTD.org podcast, we discussed 3 possible implementations of a standard 'Test Gadget' platform.  There seems to be a desire for a basic platform using a Nano and another more powerful version using either a Teensy or a ESP32.  One thing that is needed to be standardized is a common 'bus' configuration for the 'gadget' modules.  My original 'test gadget' platform, had started out as a test bed for evaluating the ESP32 as the primary processor I will use for some of my upcoming projects.  Later, after I saw the CWTD project I started building modules along that line.

Since I had a circuit board layout that would be workable with a few changes, I decided to modify it slightly.  This will bring out most of the available pins, that could be configured to closely match those available if using an Arduino Nano.  I came up with two board layouts and ordered 10 of each from a Chinese board house that I have been using for some time now.  After they arrived I started putting together the Nano version.  


Because of the memory available and processing power of the Nano, I decided to only have two connectors for the 'gadgets'. Everything is pretty standard for a simple Nano project, except that I added a separate 3.3 volt regulator instead of using the 3.3 volts from the Nano.  On the Nano the 3.3 volts is provided by the USB serial converter, and has limited current capability. The ESP32 is a 3.3 volt only processor, so I will power some of the 'gadgets' directly from 3.3 volts.  Since I want to be able to swap 'gadgets' between the Nano and the ESP32 system,  I added the additional regulator to take care of any 'gadgets' that need a hefty 3.3 volt supply.  The board has a connector that brings out the I2C signals and power for a I2C LCD display, could also be used with a small I2C OLED display if limited graphics are desired.  I also have pads for directly mounting a rotary encoder on the board.

While I was waiting for the boards to arrive, I had designed a case to hold the 'gadget rack' main frame.  And set my great new 3D printer to getting a home ready for the boards when they arrive.
It took a couple tries to get everything fitting the way I want them, but well worth the effort.  That is the thing I really love about using a 3D printer, the ability to make something that fits your project exactly, not just something you had to cobble up to make things kind of fit.

When I assembled the board I decided to mount the 'gadget' header connector on the side by the Rotary Encoder flush with the board instead of vertical like the other side.  This makes it easier to use the encoder, and allows any 'gadget' to be plugged in on either side without having to wire them up for a specific side.  

One thing I found was that the only I2C LCD display I had on hand was only a 8 x 1 display.  It worked for the initial test but have a couple 16x2 on order.  Now to get started on putting together the ESP32 version and then building a couple 'gadgets' to check them out with.

Monday, August 6, 2018

SI5351 Signal Generator Test Gadget

I have been spending way too much time playing with the new 3D printer, so have to get back to some electronics.  Since the next CWTD.ORG episode is coming up, I decided to build another 'Test Gadget'.  This time it is a Signal Generator based on the SI5351 clock generator.  I had purchased a couple Chinese versions of the Adafruit 5351 module when I was working on the 'Sweeperino Jr. ' and wanted to see how  well they worked.  


This time I decided to mount the board vertical and only use half of the connections.  Since the module only uses power and the I2C bus this made construction very easy.  And, only using one set of connector pins makes connecting the board much easier.  And also left plenty of room to mount an AD8307 log detector, so I can later use it as a SNA or Wattmeter.

For the software I decided to use some in-line code instead of one of the libraries that are available.  I grabbed the SI5351 code from the uBITX by Jerry , KE7ER , and only had to make a couple minor changes to get it to work as a 3 channel signal generator.  This was just removing a couple things that are specific to the uBITX. This code limits the frequency range from .5 to  just over 100 MHz., but that covers everything I am interested in.  The range can be lowered by a changing a value if desired, but you will have to change that value back to get the higher range again.

The use of a Joystick makes frequency selection very easy.  A horizontal movement changes the increment, while a vertical movement increments or decrements the frequency.  A test of the increment value being changed, sets the color/background of the frequency display for that column.  This makes frequency changes very fast.  A short press on the Joystick button toggles through the three channels and a long press brings you back to the main menu. The code is mainly contained in a while loop , with a couple support functions to 
display the frequency, or display frequency being edited.

 boolean   siggen = true;
 while (siggen) {
    ReadJoyStick();
    if (jstickH < 0) {
      increment = increment * 10;
      if (increment > 10000000) increment = 10000000;
      jstick = false;
    }
    if (jstickH > 0) {
      increment = increment / 10;
      if (increment < 1)increment = 1;
      jstick = false;
    }
    if (jstickV > 0) {
      if (freq + increment > 99999999)
        freq = 99999999;
      else freq = freq + increment;
      freqChn[si5351_ActiveChn ] = freq ;
      si5351bx_setfreq(si5351_ActiveChn,  freq );
      jstick = false;
    }
    if (jstickV < 0) {
      if (freq - increment < 0)
        freq = 0;
      else freq = freq - increment;
      freqChn[si5351_ActiveChn ] = freq ;
      si5351bx_setfreq(si5351_ActiveChn, freq );
      jstick = false;
    }
    if (jstickSW == ShortPress) {
      jstick = false;
      freqChn[si5351_ActiveChn ] = freq ;
      si5351_ActiveChn ++;
      if ( si5351_ActiveChn > 2)si5351_ActiveChn = 0;
      freq = freqChn[si5351_ActiveChn ];
      DrawSigGenScreen();
    }
    if (jstickSW == LongPress) {
      jstick = false;
      siggen = false;
    }
    ypos = 60 + (si5351_ActiveChn * 38);
    tft.setCursor(80, ypos - 10);
    edit_Freq(freq);
    jstick = false;

  }

With the signal generator working, next I want to add an 8307 log amplifier to the board.  I have several circuit boards left from a stand alone AD8307 power meter I did for an article in QQ.  I plan on cutting just the isolated power meter circuit out of this board and attaching it to the test gadget board.  Should be a very easy way to add  power meter functionality to the test gadget.  I will probably write software for use as a Wattmeter, with  a 40 dB. tap to get from the milliwatt range up to around the 100 watts. Also thinking about building a simple high impedance probe to use for in-circuit testing.
After that I can use the nice 320x240 display for a SNA.

Friday, July 20, 2018

A new 3D printer- getting back to the uBITX

Since I had not followed my own advise after I got my first 3D printer.  Who doesn't need another hobby!  
I had planned on building a larger printer for some of the projects I have planned.  For this printer I ordered a set of motors and electronics through one of the Chinese suppliers.  After waiting more than the estimated time for delivery, I contacted the seller and received a full refund.  That left me with the decision, order another set from a different supplier or look for a completed printer the size I wanted in a reasonable price range. 


After watching a YouTube video by my favorite 'Cyborg', Naomi Wu building the new Creality 'Ender 3' 3D printer.  I checked several other videos that showed the assembly and operation of this printer.  Reviews were mostly very positive, and it had the specifications I was looking for.  From a e-mail flyer I found that Gearbest had them on sale for less than $210 including shipping, so I placed a order. Gearbest now has a warehouse in the US, it only took about a week and a half for it to arrive.

Since I had watched several videos on the assembly, it only took about a hour to get it put together and check the alignment.  The first print was the test file that came on the included SD card, the print quality was very nice.  After that I visited Thingiverse.com and grabbed some of the accessories such as a fan cover and accessory tray that have been created for the 'Ender 3'.  They all turned out quite well, even though I was playing with the slicer settings as I went along.

After I finished them, it was time to get back to what I wanted a larger printer for in the first place.  Printing a case for the uBITX, I modified my standard 'clam shell' case design for the size I desired and added a set of mounting posts for the uBITX circuit board.  Since I was still playing with some of the slicer settings, I printed the piece at a quite slow speed.  So after about 14 hours I had the bottom half of a case for my uBITX.  Print quality was fine for what I wanted for the case, but I can still tweek the settings to get even better results. And since this was printed with some generic brand filament I got for $12 a kilogram, I don't know how much that had to do with the minor finish issues I found.  The size of the case at 200 x 190 mm takes most of the 230 x 230 mm print area of the printer.  I am quite pleased with this printer, and do not think it would be a bad choice for those wanting to try 3D printing without investing a lot of money.






Friday, July 6, 2018

DC Voltmeter Test Gadget UPDATE 7/14/2018

Now that I have the basic display and menu routines working on the ESP32 Test Gadget main frame, it is time to build an actual 'Test Gadget'.  The  cwtd.org version started with a simple DC voltmeter, so that sounds like a good place for me to start.  I could use a simple Analog input pin on the ESP32 to use for the voltmeter, but I wanted more than one channel and also a higher input impedance .  This would require a input buffer amplifier on each channel along with some switching to provide several full scale ranges. 
I have several ADS1115 16 bit four channel ADC modules that I got to use to add additional analog inputs to a uBITX.  They are a very small module that uses I2C to communicate with the processor. This module is also available in a 12 bit version called the ADS1015, and there is a library from Adafruit.  They have the capability of being used as four single ended or two differential channels,and also have a programmable gain amplifier that can be used to set the input range.  Although they are listed as 16 bit input, one of the bits is used to indicate the sign if used in the differential mode.  Therefor the actual resolution is actually 15 bit.   
The programmable  amplifier has ranges that give +- .25 to +-6.25 volt full scale.  The multiplexer has built in protection diodes from each input to VCC, which limits the maximum signal to about .3 volt over  the VCC voltage.  Powering the module from 3.3 volts, this means I will need to use a voltage divider to raise the maximum voltage that can be measured.  Unlike the 10 K ohm input on the ESP32 or a Nano analog pins, the ADS1115 has an input impedance of several Meg ohms.  This means I can use a voltage divider that will give me an impedance in the Meg ohm range.   I have some 100K and 1 Meg. 1% resistors, so I will use them to give a 1.1 Meg. input divide by 11 voltage divider.  If I just wanted a digital readout, the resolution is good enough for better than 1mV. , but since I also wanted simulated analog meters I will use the programmable amplifier to get several ranges. With this divider and the programmable amplifier I can get full scale ranges of  a little over 5.5 , 11, and 22 volt ranges, with a maximum safe input voltage around 33 volts.

The first thing I did was to connect the module  to one set of the 'Test Gadget' connectors using a wireless breadboard.  I loaded a version of the Arduino 'I2C Scanner' and checked to see that the module was found and its base address.  After I verified that the I2C communications was working, I loaded one of the example programs that came with the Adafruit ADS1015 library. This just read each channel and output its value to the serial monitor.  The only issue I found so far was that there was a little DC off set from zero with the voltage divider, but it is only about 1 mV.  I will do a little more testing to see how consistant it is, but I can probably just add an offset in the software to correct for that.  If I can just do a simple fixed value, or have to add a 'Zero' option to the manu is still to be determained.

I already had the analog meter code written, so the next thing I started working on was a menu to allow me to change display type, number of channels,and range.  The use of a Joystick makes selecting and changing settings very easy.  A vertical  movement selects a different menu item, while a horizontal movement makes changes to the selected menu item.  Here is part of the menu code to show what I mean.

   if (jstickV ) {    // vertical movement selects menu item
        mnuDCVMSel += jstickV ;
        if ( mnuDCVMSel < 0)  mnuDCVMSel = 0;
        if (mnuDCVMSel >= mnuDCVMNum )  mnuDCVMSel = mnuDCVMNum;
        showDCVMMenuItems();
      }
     
   // horizontal movement makes changes to selected menu item    if (jstickH ) {
      // for values that toggle simple if statements are used   
      // change between analog and digital display of voltage
         if (mnuDCVMSel == 0) {  // select analog or digital 
          if (mnuDCVMItems[0] == " Analog     ")
            mnuDCVMItems[0] = " Digital    ";
          else mnuDCVMItems[0] = " Analog     ";
         showDCVMMenuItems();
         jstick = false;
        }
        // for multiple options I use a switch(value)- case to
        // make the selection
        if (mnuDCVMSel == 1) { // select number channels to read
          numChan += jstickH;
          if ( numChan > 4) numChan = 4;  // set limits on value
          if ( numChan < 1) numChan = 1;
          switch (numChan) {   // update menu item display
            case 1:
              mnuDCVMItems[1] = " Chan. = 1  ";
              break;
            case 2:
              mnuDCVMItems[1] = " Chan. = 2  ";
              break;
            case 3:
              mnuDCVMItems[1] = " Chan. = 3  ";
              break;
            case 4:
              mnuDCVMItems[1] = " Chan. = 4  ";
              break;
          }
          showDCVMMenuItems();
          jstick = false;
        }

 Similar code is used to select and modify any additional menu options.

In operation a 'ShortPress' on the Joystick switch brings up the menu, and after selections are completed another 'ShortPress' exits the menu and redraws the screen.  This looks similar  to a 'pop up' menu on a Windows or Linux system with out much of the overhead associated with a full menu system.   

After doing some playing around, I have decided I will not use the programmable gain amplifier for range selection.  A fixed gain will give me more resolution than I need for a 1 mV. display resolution. I will instead work on creating a auto range system for the 'Analog' style meter.  Hope to update soon.
UPDATE 7/14/2018

I wired up the small adc module on a 4x6 cm proto boar and made a quick 4 channel cable with test clips for normal use.  Everything works as expected, except for a little |DC offset from ground.  Since it was consistent across all channels, I decided to just take care of it in software.  If it would have been  significantly different for each channel I would have added a DC zero function to the pop-up menu.  I decided to have a digital display of the voltage along with the simulated analog meter.  Because of this I kept the manual scaling I had originally tried, maybe some  day I will write something to do auto scaling for each individual channel.
The picture shows the completed DCVM test gadget in 4 channel mode measuring the 3 voltages present on the headers used to connect the individual test gadgets.  I was running this off of the PC without the 12 volts connected for external power, so I kept the range down to 5 volts. 

Thursday, June 21, 2018

ESP32 'Test Gadget' Menu System

I decided to go with a menu system very similar to what I had used in several of my other projects.  Now it uses the joystick vertical axis info to move through the menu items and a 'LongPress' on the button to make a selection.  It can be expanded to use the horizontal axis info and a 'ShortPress' if additional capabilities are desired.

Multiple menus can be created by defining different sets of definitions and variables for each menu, along with different versions of the two menu functions.   I use a naming convention of mnuName...   where Name  where NAME specifies which menu.
For the 'Test Gadget' there might be a mnuMain..., mnuVoltmeter...,
mnuSigGen... .

Each menu uses a block of global definitions and variables, with each member using the stated naming convention.  For my main menu they are.

#define  mnuMainNum    3       // number of menu items  0 referenced

#define  mnuMainX      20        // menu x and y position
#define  mnuMainY      20
#define  mnuMainTSize  3                      // text size
#define  mnuMainTCol   YELLOW       // text color
#define  mnuMainTBak   BLUE            // text background color
int    mnuMainSel   = 1 ;                        // selected menu item
// menu looks better if you pad items with spaces to make lengths equal

String   mnuMainItems[] = {" Meters   ", " Waveform ", " LCD      "," Sub Menu "};


For this test example I also have a sub menu that is called from the main menu.  Its global values are.

#define  mnuSubNum    2       // number of menu items  0 referenced

#define  mnuSubX      120     // menu x and y position
#define  mnuSubY     100
#define  mnuSubTSize  3                 // text size
#define  mnuSubTCol   BLUE        // text color
#define  mnuSubTBak   CYAN       // text background color
int    mnuSubSel   = 1 ;                    // selected menu item
// menu looks better if you pad items with spaces to make lengths equal

String   mnuSubItems[] = {" sub1 ", " sub2 ", " sub3 "};

I find it really easy to just do a copy and paste, and then using the Arduino IDE find and replace function to quickly make changes to the names.

Most of the work in the menu function is a function called
showNAMEMenuItems(), as with the definitions and variables you will have to change the name for each menu.  For the Main menu it looks like this. .

void showMainMenuItems() {

  tft.setTextSize(mnuMainTSize);
  for (int i = 0; i <= mnuMainNum ; i++) {
    if (i == mnuMainSel )
      tft.setTextColor( mnuMainTBak ,  mnuMainTCol );  // inverted colors
    else
      tft.setTextColor(mnuMainTCol, mnuMainTBak );     // normal colors
     // calculate proper x y position and set cursor
    tft.setCursor( mnuMainX  , mnuMainX + (i * 8 * mnuMainTSize));
    tft.println(mnuMainItems[i]);
  }

}
 It uses the global values and variables to show the menu items at the correct x,y position on the screen.  Each menu item is tested to see if it is the selected one, and the text/background colors are inverted from the non selected item.

The other function in the menu system is a function called
ShowMenuNAME() . It uses a local variable inMenu to control a while loop that reads the joystick and checks the vertical axis value to select the desired menu item.   It calls showNAMEMenuItems()
to update the menu after any change.  It also tests the joystick switch for a 'LongPress' which causes the while loop to end.

void ShowMenuMain() {
  boolean inMenu = true;
  showMainMenuItems();
  delay(200);
  while (inMenu) {
    ReadJoyStick();
    delay(20);
    if (jstick) {
      if (jstickV ) {
        mnuMainSel += jstickV ;
        if ( mnuMainSel < 0)  mnuMainSel = 0;
        if (mnuMainSel >= mnuMainNum )  mnuMainSel = mnuMainNum;
        showMainMenuItems();
      }
      if (jstickSW == LongPress)
        inMenu = false;         // long press gets you out of the menu loop
    }
    jstick = false;
  }

After the while(inMenu) loop ends you can use either a series of if statements , or a switch- case function to select what is done for each menu item.  For this test example I used a series of if statements , mainly because I was just copying existing code for testing.  If I had already written specific functions for each menu item, I would probably have gone with a switch-case instead.

if (mnuMainSel == 0) {
    tft.fillScreen(BLACK);
    drawMeter(MTR1_X, MTR1_Y, MTR1_W , MTR1_H, WHITE, WHITE, BLACK,
     "  1 2 3 4 5 6 7 8 9 10");
    drawMeter(MTR2_X, MTR2_Y, MTR2_W , MTR2_H, WHITE, BLUE, YELLOW,
    "  1 2 3 4 5 6 7 8 9 10");
    plotNeedle(MTR1_X, MTR1_Y, MTR1_W , MTR1_H, 150, 300,  BLACK);
    plotNeedle(MTR2_X, MTR2_Y, MTR2_W , MTR2_H, 250, 400, BLUE);
  }
  if (mnuMainSel == 1) {
    tft.fillScreen(BLACK);
    DrawWaveformScreen(BLUE, CYAN, 10);
    DrawYScale(0 , 10, 10);
  }
  if (mnuMainSel == 2) {
    tft.fillScreen(BLACK);
    lcd_begin(10, 60, 16, 4, 3,  BLUE,  YELLOW) ; // text and background color
    tft.setCursor(0, 0);
    tft.setTextColor(lcdTxtColor);
    tft.setTextSize(lcdTxtSize);
    for (int i = 0; i < lcdRow; i++) {
      lcd_setCursor(0, i);
      lcd_print("12345");
      lcd_setCursor(5, i);
      lcd_printNum(6, 0);
      lcd_print("7890123456");
    }
  }
  if (mnuMainSel == 3) {
    ShowMenuSub();
  }

}


This test code this shows a simple menu, which lets you select one of the test graphic display types from the last blog entry.  The other option is a sub menu that only exits when you do a 'LongPress'.
In each case the display stays around for 5 seconds then clears the screen and shows the main menu again.The two functions for the sub menu are basically the same as the main menu code with the names changed.

void ShowMenuSub() {
  boolean inMenu = true;
  showSubMenuItems();
  delay(200);
  while (inMenu) {
    ReadJoyStick();
    delay(20);
    if (jstick) {
      if (jstickV ) {
        mnuSubSel += jstickV ;
        if ( mnuSubSel < 0)  mnuSubSel = 0;
        if (mnuSubSel >= mnuSubNum )  mnuSubSel = mnuSubNum;
        showSubMenuItems();
      }
      if (jstickSW == LongPress)
        inMenu = false;         // long press gets you out of the menu loop
    }
    jstick = false;
  }
  // out of menu item selection now do selected item
  // you can do as multiple if statements
  // or a switch  -  case
  //  FOR THIS DEMO JUST EXIT
}

void showSubMenuItems() {
  tft.setTextSize(mnuSubTSize);
  for (int i = 0; i <= mnuSubNum ; i++) {
    if (i == mnuSubSel )
      tft.setTextColor( mnuSubTBak ,  mnuSubTCol );  // inverted colors
    else
      tft.setTextColor(mnuSubTCol, mnuSubTBak );     // normal colors
    tft.setCursor( mnuSubX  , mnuSubX + (i * 8 * mnuSubTSize));
    tft.println(mnuSubItems[i]);
  }
}


Here is a picture of what the menu looks 
like after the sub menu was selected.  
The same code can be easily modified to use a rotary encoder with switch instead of the joystick.  I have found this to be a relatively simple menu system to implement.  It may use more program space than some of the complete menu management sytems, but most of my applications have only need one or two menu selections and in that case may be smaller.


Sunday, June 17, 2018

ESP32 'Test Gadget' starting on software Update 6/19/18

I got back from visiting with family at a wedding, and finally getting time to work on the software for the 'Test Gadget'
After getting the drivers for the TFT display and the Adafruit graphics library working along with the Joystick, I started porting some of my existing software over to the ESP32.  It has turned out to be nearly a direct drop-in from the code I have for the Nano and Pro-mini I have used before.

For some of the test functions a digital read out of values is OK, but when you are making adjustments I prefer some sort of a analog display.  In my early projects I used a bar-graph as a analog display, but recently I came up with a very small set of functions that simulate a analog meter.  With the speed of the processor and memory available, I could probably make one that is more accurate in appearance, but this simple one is adequate for what I want.


As a test I drew two meters on the screen, and have room for four if I would ever need them.  With this size, there is plenty of room on the screen to display multiple digital values, such as instantaneous reading, and peak readings.  I could also make one  large meter that would cover the entire display area.

Some of the other test instruments I plan on making with the 'Test Gadget' will have frequency scans shown as a wave-form.  I ported over my basic waveform screen with programmable grid sizes, and Y-axis scales.  They look very nice on this size display, and can redraw with very little flicker.

I have just a few more of these routines to port over in the next few days.
Then I have to decide if I want to incorporate a full menu management system, or just use the simple menus I have used in the past.
Thats all for now  check back for updates.

UPDATE 6/19/18

Thinking about what it will take to port some of the CWTD.org 'TestGadget' programs to the ESP32 version, I thought it would be nice to emulate the 2 X 16 LCD display used with their Nano version.

From the 'Gadget Rack' code I found the description of the the basic lcd commands.
Gadget codes have access to the 2 row by 16 character LCD.  The LCD is initialized in
*   the main setup code.  The LCD is accessed with the following functions:

*   void lcd.clear(void)  // clears the lcd display and set cursor to 0,0
*   void lcd.setCursor(int column, int row)
*   int  lcd.print(char *text)
*   int  lcd.print(type n, BASE)  // n is a number (char, byte, int, long, or string,
*                                 // BASE (optional) is BIN, DEC, OCT, HEX or an integer
*                                 // specifying the number of digits to print following
*                                 // the decimal point.


 I found there was also an lcd.begin(int column, int row) function that is called in setup() to initialize the lcd.  With just a little modification to these functions, I could emulate a LCD from a 2x16 to a 4x20 display. Some of these are dependent on the text size used. The first thing I did was define some global variables that are initialized in the begin function. For these I decided on

int lcdX; int lcdY; int lcdCol; int lcdRow;       // position on screen and size of lcd to simulate

int lcdTxtSize; int lcdTxtColor; int lcdBakColor;   // text size color and background color of                                                                                                  //simulated lcd
Since I didn't want to bother rewriting anything from the lcd library, I just wrote some simple functions to translate the LCD functions to something understood by the tft library I use.  To keep the format similar I changed the name from lcd.function to lcd_function. This should make it easier to rewrite any existing code. 
First and most import function to write was the lcd_begin().
The original function only requires it be passed the number of columns and rows in the LCD display.  For my version I need to also pass the X and Y location of the display on the screen, the text size to use, and the text color and background color for the simulated LCD.  The lcd_begin()  first copies the passed values to the global variables, and from those values define and draw a filled rectangle that is the emulated LCD display. The next function I wrote was the lcd_clear() which just uses the global variables set in lcd_begin() to compute and redraw the filled rectangle.

The lcd_setCursor(column,row) translates the LCD column and row information to X and Y coordinates on the tft display and calls the tft.setCursor(x,y) function.  I had to make two different versions of the lcd.print() function, one for text and another for numbers.
The first is used as lcd_print( "text") to print text at the current cursor position on the LCD. The next is lcd_printNum(6,2) which in this case prints the number 6 followed by ".00" .
Here are a couple pictures of what the emulated LCD looks like
first a 16 x 4 display using this code

 lcd_begin(10, 60, 16, 4, 3,  BLUE,  YELLOW) ; // text and background color

  tft.setTextColor(lcdTxtColor);
  tft.setTextSize(lcdTxtSize);
  for (int i = 0; i < lcdRow; i++) {
    lcd_setCursor(0, i);
    lcd_print("12345");
    lcd_setCursor(5, i);
    lcd_print("7890123456");
  }

 The second picture shows the use of the lcd_setCursor(),
lcd_print() and lcd_printNum() functions using this code.

 lcd_begin(10, 80, 16, 2, 3,  BLUE,  YELLOW) ;

  lcd_setCursor(0, 0);
  lcd_print("12345");
  lcd_setCursor(5, 1);
  lcd_printNum(6, 2);




Hopefully these simple functions might make any porting of the CWTD 'TestGadget' or any other code written for a LCD display to the tft display I am using for my ESP32 version a little easier.