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.







Thursday, May 31, 2018

ESP32 and the CWTD 'Test Gadget' Update 6/3/18

I have several projects in the early stages of development that I am working on.  Most of them require more program and sram memory then available in the Nano or Pro-Mini that I have been using for my projects.  This has led me to do some testing of a  several Arduino compatible boards.  I tried the Mega2560 and the Mega mini, but decided that the form factor would be hard to work with in my projects.  I also did some experimenting with the STM32 'Blue Pill' and was very satisfied with the results I found.  For around $2 it is a very powerful board.  Recently I saw some information on  ESP32 development boards that look really interesting.  Along with WiFi and Bluetooth capabilities they have an amazing amount of IO capabilities.  I found one from EzSBC.com that appears to have just about any IO type you could need.
Here is a list of what is available on the module.  Of course many of the pins are multipurpose so all of these functions are not available at the same time.  The module can be programmed directly from the Arduino environment without pushing any buttons.  The upload speed is 921600 bps, which makes program upload very fast.
  • 240 MHz dual core Tensilica LX6 microcontroller with 600 DMIPS  
  • Integrated 802.11BGN HT40 Wi-Fi transceiver, baseband, stack and LWIP   
  • Integrated dual mode Bluetooth (classic and BLE) 
  • 4 MByte flash 
  • 3 x UARTs, including hardware flow control 
  • 3 x SPI
  • 2 x I2S
  • 12 x ADC input channels
  • 2 x DAC
  • 2 x I2C
  • PWM/timer input/output available on every GPIO pin
  • SDIO master/slave 50 MHz
  • SD-card interface support
What I liked about this version is that all the IO pins are brought out to single row headers on each side of the module, that is only slightly larger than a Nano.  That and the fact that they are under $10, made this something I wanted to try.



I ordered ordered one and after it arrived I configured my Arduino IDE environment to support the ESP32.   I first compiled an empty sketch to see just how much program and variable space is available.  I was a little surprised at first to see how large the core  was that it compiled. 
Sketch uses 159060 bytes (12%) of program storage space. Maximum is 1310720 bytes.
Global variables use 10756 bytes (3%) of dynamic memory, leaving 284156 bytes for local variables. Maximum is 294912 bytes.
But after checking around several sites, I found that this includes all the functions associated with Wifi and Bluetooth and most of the functions available in the ESP32 SDK.  It also includes FreeRTOS, a real time operating system that allows you to do multi-tasking and  use both cores at the same time.  So even though it takes nearly 160K program space and around 11K sram, there is still over 1.1 MB program space and  280K sram available for variables.  I think it will take a while before I can come up with a program to use all of that. 

Next I attached a 2.8"  320 x 240 TFT display to see how fast it was.  Using the Adafruit graphic library and drivers the speed for the standard graphics test using the SPI bus was about the same as using a 8 bit interface on a Nano.  Not going to be any problem with display speed that I can see.  

Looking around for information on the ESP32, I found a great series of YouTube videos by G6EJDThey range from basic Arduino IDE install and setup to advanced web servers.  There are many other great YouTube videos available from others that cover many advanced topics.

I have been following a series of podcasts from 'Chatting with the Designers'  CWTD.ORG that cover building simple Arduino based test equipment.  I decided that this would make a nice way to get into development with the ESP32.  The CWTD 'Test Gadget' is basically an Arduino Nano with a 2 line LCD display, and a breadboard area where small modules can be plugged in to make different types of instruments.  My version will use the ESP32 and the TFT display.  I am also replacing their rotary encoder with a joystick for the user interface device.  I am bringing all the pins from the ESP32 module out to two pairs of female headers, that should allow me to plug in two small modules at the same time.  I also added a couple extra pins to the headers to supply 12 V. to the modules and a couple pins that allow signals from one module to be connected to another with out having to run jumper wires.  The use of female headers will also allow me to connect to a wireless breadboard for initial testing of module prototypes.

I designed a simple board to provide two pairs of headers so I could plug in two  4x6 or 5x7 cm. modules at a time, or allow the use of a single 8x12 cm. module.  To keep the size down I have the ESP32 module mounted on the back of the board along with a 5 V regulator to bring the 12 V supply I plan on using down to  5 V to power the ESP32 board.  This allowed me to keep the board size down to the 10x10 cm. size that qualifies for the inexpensive rate from multiple Chinese board houses.


After the boards arrived, I quickly built one up.  I found that I had to make a small change and add a jumper to get the display to work properly, also needed to add a pull-up resistor for the switch on the joystick.  While I was waiting for the boards to arrive, I had designed and 3D printed a  small case to hold everything.  I had a bezel and mounting plate I had previously done for the TFT display and joystick, so designed the case to use that.  After it was assembled, I wrote a quick sketch to see what the unit will look like with the display active.  


Now I just need to wire up some simple modules and write some code to see how everything will work. If everything goes as I hope using the TFT display, I will think about enabling the WiFi .  This could possibly lead to having some simple Web based instrumentation.  As always I will keep you informed of my progress.

Update 6/3/18
Just a few notes on the 'Test Gadget' mother board for a couple of those who asked.  I have added a schematic of the mother board, and a couple things I had to do to get everything working the way I wanted it to.  
First problem I ran into was with the RESET on the TFT display.  I wanted save the use of a pin on the ESP32, so originally tied the RESET pin on the display to 5V.  I could not get the display to start up consistently.  I removed the pull-up I had on the board and ran a jumper to the LED pin.  It appears that RESET wants to be closer to 3.3 volts.  The only other problem I found was that I had to add a 10K pull-up from the joystick switch to 3.3 volts.  Some joystick modules have pads for this purpose, but I just added an external resistor across  the appropriate contacts on the mother board.
Power to the board is 12 volts that goes to a 1117-5 5 volt regulator.  The 5 volts goes to the VIN on the ESP32 board and to pins on the module connectors.  The 12 volts is also brought out to another pin on the module connectors for use by any analog circuitry that requires a larger voltage.
In most of my previous projects, I used a rotary encoder for the User Interface device.  For this I am going with a small Joystick with switch.  From some of the testing I have done with this, I find it to offer more versatility and speed of use than a Rotary Encoder. The ReadJoystick function stores the V, H and SW values in global variables, and if any changes occur a global status variable is set.  The V and H values are +- 1 or 2 depending on direction and degree of movement.  The SW values are either  1 for a short press or -1 for a long press of over .5 seconds.  
In the setup()  routine the center H and V values are read and used to set a 'deadband' area that determines the how far the Joystick must be moved to get a reading.  This value is also used set the amount of movement required for the two movement values.


void ReadJoyStick() {
  int jsVin;          // variables to hold raw input from joystick
  int jsHin;
  int jsSWin;
  jstick = false;     // clear all global variables
  jstickV = 0;
  jstickH = 0;
  jstickSW = 0;
  // look for input opn vertical axis
  jsVin = analogRead( jsVPin);
  if ( jsVin > jsVcenter + jsDeadBand) {              // maintain dead spot around center position
    jstickV = 1;
    if ( jsVin > jsVcenter + jsX2)                    // large movement so bigger value
      jstickV = 2;
    jstick = true;                                     // set joystick value changed flag
  }
  else if ( jsVin < jsVcenter - jsDeadBand) {              // maintain dead spot around center position
    jstickV = -1;
    if ( jsVin < jsVcenter - jsX2)
      jstickV = -2;                                        // large movement so bigger value
    jstick = true;                                         // set joystick value changed flag
  }
   delay(100);                                           // to prevent noise issues
  // do the same thing for Horizontal axis
  jsHin = analogRead( jsHPin);
  if ( jsHin > jsHcenter + jsDeadBand) {              // maintain dead spot around center position
    jstickH = 1;
    if ( jsHin > jsHcenter + jsX2)
      jstickH = 2;
    jstick = true;
  }
  else if ( jsHin < jsHcenter - jsDeadBand) {              // maintain dead spot around center position
    jstickH = -2;
    if ( jsHin > jsHcenter - jsX2)
      jstickH = -1;
    jstick = true;
  }
   delay(100);                                         // to prevent noise issues
  // check for switch pushed
  jsSWin = digitalRead(jsSWPin);              
  if ( jsSWin == LOW) {
    jstickSW = ShortPress;                              // 1 if short press
    jstick = true;
    delay(500);                               // delay half second to
    jsSWin = digitalRead( jsSWPin);           // see if it was a long press
    if ( jsSWin == LOW)
      jstickSW = LongPress;                  // -1 for a long press
 delay(100);                                         // to prevent noise issues
  }
}
This function is called  repeatedly in the program any time a input is allowed.  After the input is processed the status variable needs to be cleared.  For now this routine is just called from the main program code as needed.  Later when I start playing around with the multitasking  and dual core functionality, I might change this to a background task that runs all the time.










Monday, April 2, 2018

Stand-alone Simulated Analog Meter updated 4/27/18

Now that I have the latest QQ article finished, I have a little more time for some of my other projects.  One of them is working on the graphic display for the uBITX, I came up with a simple simulated analog meter that worked quite well.  Only problem is with the Raduino, board there is only one available analog pin. Thinking about ways to get around this I looked at some of the inexpensive I2C ADC baords available on e-Bay.  That would do for the uBITX, but I also wanted something I could use with the BITX 40 and a couple of other projects I have been thinking about doing.  I started to wonder how hard it would be to build a stand alone simulated analog meter with several input channels and control lines to select what values are being read and displayed. I wanted it to be small, and simple to construct.  Looking around I found aYou-Tube video showing a Arduino Nano based VU meter using one of the small .96" OLED displays.  Since I had several of those displays' from another project I thought I would try something based on it. 

https://www.youtube.com/watch?v=qoLsynwssLI

 The video comments had links to the source code and instructions for building the meter.  I thought this would make the basis for a nice little meter that could be added to almost any transceiver.

Thinking about what values I would like to display, I came up with three basic items.  A S-meter when in receive, and a power output display when in transmit.  In transmit, I would also like to have the capability of measuring VSWR.  Thinking about the switching functions required for this I will need one control line that monitors  transmit/receive, this can come from the PTT or key line in the transceiver.  Then  I use a second control line to select either power or VSWR when the T/R line is in transmit.  Another control line can do the same for the S-meter or some other display when in receive.  Since this is based on a VU meter, I will use that for the secondary function in receive.  Now looking at the signal lines I need to measure, they are the AGC line for S-meter, audio signal for VU meter.  And in transmit, the forward and reverse power levels will take care of power and a computed VSWR reading.

I can easily get the 4 analog and digital lines I need from my favorite Arduino for embedding in systems, the Pro-mini.  I like it because of its smaller size since it does not have the USB interface built in like the Nano.  This also means that it takes a little less current than the Nano.  Looking at the physical layout of pins on the Pro-mini, I can get 4 digital, and 4 analog pins in a row that I can use for my control and input signals. 


 I have some pre-made 8 wire cables with a connector, and matching jack that fits the pin spacing on the Pro-mini.  And since I only need 4 wires for I2C OLED display, it was easy to solder a short cable directly from the Pro-mini to a 4 pin connector for the display.
I will be able to supply 5 volts to power everything through the programming pins at the end of the Pro-mini.  If needed I can build a small board with a 5 v regulator and possibly some filtering, so I can run everything off the 12 volts in the transceiver.

After everything was wired up, I loaded the VU-Meter sketch and was very happy with the response of the meter.  Since the display is basically monochrome, it only takes a 1 kilobyte image file to completely redraw the screen.  This allows for a very fast update, and a realistic looking needle movement. The OLED display I had has a two color effect, that is created by two different colors of plastic in its construction.  I have ordered several additional displays that have only the blue overlay. Following the procedure mentioned in the original article, I drew a set of the meter faces I would need for the basic functions of the meter.
 For the power meter function, I decided on a maximum reading of about 15 watts.  The uBITX is rated at about 10 watts on 12 volts, and a little bit more if a higher supply voltage is used on the final amplifier stage.
 Not sure what I plan on using for the S-meter, for now I will probably just rectify the audio output of the preamplifier stage and read that directly.  Later I will see about some sort of an AGC circuit that I can use for the S-meter reading.   The display function I wrote for all except the original VU reading, have provisions for using simple constants to set the full scale movement of the needle, and any DC offset in the circuit at the being measured.


The VSWR display goes up to about 1:3.8 which should be more than adequate for most use.  I think I can use the same directional coupler, without its amplifier that I have in my QRP power/SWR meter. Since I am measuring both forward and reverse power, I can compute the VSWR without having to worry about the power output. 

As far as the signal levels being measured, I can take anything up to 5 volts without having to add in a adjustment pot or voltage divider.  The software should be able to manage full scale and offset values with simple defined constants.

I still have one extra control signal I can use for selecting the display function.  Now what else can I do with this display? Possibly an audio frequency spectrum display, so I can join those on 40M with their SDR rigs that are quick to let everyone know exactly how too wide your signal is.  Lets see what I can come up with, stay tuned.

UPDATE  4/4/18
Finished up the software to select the desired display screen, and modified one of the Audio spectrum analyzer sketches I found on line to fit in the program space available.  It works, but after playing with it, I don't know how useful it would be.  With the memory available, it is only possible to do a FFT that will cover to about 5 KHz. , and I would probably have to add a preamp to get enough voltage for a usable display.  
But It works and feeding a fairly large tone in from a signal generator, I could get a reliable display of the spectrum of that tone.  Trying it on a normal SSB signal did not give anything I found to be usable.  I guess if you were doing CW and had a narrow audio filter in line, you could use the FFT display to see what other signals are around you.  Here is a photo of the response with a 1200Hz. signal from a signal generator. 

UPDATE  4/4/27
I spent a little time working on a directional coupler to measure forward and reflected power for the Power/SWR display functions.
I went with the same basic design I had used in my SWR meter, without the amplifier.  This should give decent sensitivity with normal output levels on the uBITX.  

I need to test it with one of my other transmitters to see what power range I have and if I need to do anything to scale the values before I feed them to the pro-mini ADC.  
Here is a link to the software so far if anyone is interested in playing with one of their own.

https://www.dropbox.com/sh/at3ymvlz8sfhefl/AADWlDpcdjlBc2P30TiWva-qa?dl=0



Monday, March 5, 2018

Sweeprino Jr revisited Update 3/16/18

Well after three weeks of feeling terrible and not having the ambition to do anything, I finally got over what ever version of the 'flu' I had.  This has put me quite a bit behind in working on the next article in the series of Arduino building blocks for QQ.  Over a year ago I had started on a version of Farhan's Sweeperino project. at  http://hfsignals.blogspot.com/p/sweeperino.html  I knew this would make a great basis for the next article

Since this was  to be a stand alone instrument or connect to a PC to use Farhan's  'Specan.exe' software, I made some changes to my Arduino/display building block.  I changed from a pro-mini to a Arduino Nano.  This gave me the USB interface to a PC, brought out the I2C lines that do not have dedicated pins on the pro-mini.  The Nano also has a heavier duty voltage regulator on the 5 volt line.  This will allow me to run a Adafruit SI5351 board with out having to add additional voltage regulation. I also added a rotary encoder with push button to use as the interface to the software.

Doing the board layout for these changes was very easy.  Mainly because except for the form factor, it is very near to what I did to make the stand alone VFO/BFO board for Pete's Simpleceiver project.  Instead of making my own boards this time, I took advantage of a promotional offer by one of the Chinese board houses.  For a limited time they had offered 10 boards for a little over $5 and free shipping. 
 I couldn't even buy the raw pcb material for that price.  After they arrived and I built one up, I found a small error I had made in the board layout.  One end of a resistor was grounded that should not have been.  After discovering the error, about 30 seconds with a hobby knife took care of the problem.  Also modified the 3D printed case I had designed for earlier projects in the series to fit the new board


I pulled a copy of Farhans sketch, and made changes to use a tft display instead of the 2 line LCD he had in his original unit.  The first cut of the software worked with the PC interface, and a simulated two line  LCD display on the TFT display.  


After making sure everything was working I decided to use the graphic capabilities of the TFT display.  In previous projects, I had used simple bar graphs to give a analog representation of values, to make tuning easier than just a digital value.  I was real happy with the simulated analog meter I came up with for the uBITX, so I incorporated it in the new display screen for the manual operation mode.   I made a few changes to the basic code  so I could also display the actual value as a number along with the analog meter.    Still trying to decide if I want to add a sticky needle in a slightly different color to indicate the peak reading for the last few seconds.  Will only take a couple lines of code, but not sure if it will be necessary.  For the frequency setting display, I decided to show the digit that is changed by the rotary encoder in a different color than the rest of the value.  So a short push on the encoder button moves the active digit around in a circular manor.

Need to do a little more checking of the software so far. Then the only other thing I want to add is a graphic sweep waveform very similar to what I have on my SNA Jr.  Just going to be very basic, so everyone can add any additional functions they want.

Will keep you informed, but I also have to hurry up and write the article for QQ to have it ready for the next issue.  Maybe this time they can get the author correct.

Update 3/16/2018


Finally finished the QQ article on the Sweeperino Jr so far.  I decided to make this two articles instead of just one.  The first one will have the Sweeperino Jr with the same basic functionality as the original.  In the next article, I will add a graphical sweep function similar to the SNA Jr.  I have the latest Eagle file Gerber files , and Arduino sketch in a dropbox folder for any one interested in building one of these.  

https://www.dropbox.com/sh/ek4gfb5ub5l5fqq/AADYkVzSJDmj5pFWmLJ7_vVpa?dl=0

It works quite well, if you understand that there are going to be some issues with harmonics because of the square-wave output.  I am working on a method to get rid of that problem, and mostly finished with the preliminary design for the SNA Jr. version III.  Hope to get around to finishing that in the near future.