Starting Over, Again

June 30th, 2022 was the worst day of my life. My wife of almost 30 years passed away in the nursing home overnight, and I got the call in the morning from the medical staff. I hope she passed peacefully in her sleep, but when I came in later in the day to start to make final arrangements, I found her lying there with her eyes and mouth open. I’ve been told this isn’t uncommon, but she looked like the infamous ‘screaming mummy’, almost as if it was a horrible last few minutes for her. I sure hope that was not the case.

Ever since we arrived in Massachusetts, Janis had been going down hill faster. She had just become dependant on her wheelchair when we left Florida, but was still able to briefly stand and walk short distances using a walker for support. Within a month of settling in to our rental apartment in Chelmsford, she was no longer able to do this, and it became impossible for me to help her from the wheelchair to her lift chair – recliner or to use the commode. I had to call 911 several times for assistance, and the paramedics ended up talking her to the hospital.

We were promised that the hospital staff could help us find a solution for her home care, or a bed at a nursing home that could handle the demands of someone with ALS, but this was not to be. We finally did find a nursing home that had a bed available, and was willing to tend to her special needs. I was hoping that they would be able to dress her, and get her back into the wheelchair long enough to allow her some assisted mobility. Janis had never been outside of our apartment, except for transport to a few doctor’s appointments, she would never see the outside world again.

Now I am trying to pick up the pieces and continue with my life, but it isn’t easy. I’m alone by myself, most of the time. I do have my daughters nearby within a short drive from the apartment, and I’ve joined a nearby temple, and have found the local senior center. But I still need to make new friends in the area, and find local activities to take my mind off of being alone. I also need to concentrate on getting all of our accounts under my control, as my wife had taken care of most of those things. It had been a fair compromise between us, my being the breadwinner, and she keeping track of it all. Now it’s up to me to make sure my retirement funds last.

I do have my hobbies to keep me occupied, but I did have to give up quite a bit of all the ‘junk’ I’ve accumulated over many years, and was only able to take a small cache of stuff knowing we’d be down sizing quite a bit. I’ll try to keep posting here, but for now I need to get to the task of cleaning things up so I will be able to go on. While I don’t feel so mired down in depression that I would feel suicidal, I am having difficulty in getting things done. Lack of drive, maybe due to not sleeping well, and some health issues I need to get over.

Hopefully, we’ll have something better to write about soon.

I

Advertisement

Starting Over, New Oscilloscope

When we were packing up to move I had to downsize myself big time. I sold two Tek oscilloscopes that I’d had for many years (a tek 454, and a tek 465). Both of these old analog CRT scopes would be considered boat anchors today. I had the roll around cart for the Tek 454 too, and a set of probes for both of them. Also the user manuals, and shop manuals, plus some spare nuvistor tubes for the 454. These were 150mhz and 100mhz scopes respectively, though they would trigger and show a waveform quite a bit over their rated top response frequencies. Of course they lacked the math and decode functions that modern digital scopes have, but they were quite useful for debugging and repair of equipment.

They were, of course, too large and heavy to move north, and I knew I’d have no room for them in the apartment we’d be renting. So I figured I’d order a new digital scope with the money I sold the old ones for. I was considering the Rigol DS100Z or Z-E series, or the Siglent SDS1100 or SDS1200 series. I decided that the mixed signal scopes, though really nice, were too expensive. I also decided that the 4 channel scopes were also too pricey compared to the 2 channel models. In all the years I’ve used those Teks, I never once wished I had a 4 channel scope, though I did use both of the available channels at the same time very often. For the few occasions I might need to see 3 or more digital signals side by side (like for SPI debugging) one of those cheap Chinese clone 8 channel PC based logic analyzers would be more than good enough.

The Siglent scopes are a bit more expensive than the Rigol though they do have separate knobs for the positioning and settings for each of the two channels, (the Rigol switch these between the channels), but on paper the Rigol scopes have a bit more memory specs. Both of them have very good reviews, so I knew one from either series would be suitable. Both are available in either 100mhz or 200mhz versions. For the Rigol, it is a no brainer, the 200mhz version is only $10 more than the 100 mhz one. Telequipment had an open box (demo unit?) of the 100mhz DS-1102Z-E available for $50 less than the new in the box DS1202Z-E, but even that savings didn’t seem to be enough to offset the difference. Still all of them have ‘only’ a 1Gs/S’ sample speed, which while more than enough for a single channel at 100mhz, would be a bit less than ideal at 200mhz. Also, this sample rate is shared between the two channels, dropping it to 0.5Gs/S per channel in two channel mode. At 200mhz, that’s BARELY Niquest. So, that 200mhz model is really only good as a single channel scope at over 100 mhz. (Which explains why the 4 channel scopes are so much more expensive. They NEED a sample rate of AT LEAST 2Gs/S, or be limited to 50mhz.) So in reality, the 100 mhz models make a bit of sense, but the price bump to the 200 mhz models is so small, that it will pay for the few times I’d need to look at a signal over 100 mhz in single channel mode.

So, now I have a Rigol DS-1202Z-E on order from Telequipment. Hint…Hunt on the evblog forums for the 6% discount code from Telequipment, and don’t forget to add the ‘freeship’ code as well.

I’ll report in when I get my new toy.

HT16K33

“Old School” 7 and 14 segment LED displays may seem a bit out of place today, as graphical LCD and OLED displays have become available. However these displays have their advantages. They are large and bright, easily readable from across a room. They are still the choice for digital clocks, and many builders still prefer them for projects that don’t require a lot of information displayed in a graphical format.

LED displays are usually packaged in common anode or common cathode blocks, in single, dual, or quad digit display units. They are usually provided with left or right hand decimal points (sometimes both). The seven segment types are intended for numeric displays (though they can also display some of the alphabet, and are useful as hexadecimal displays with the ‘B’ and ‘D’ being displayed in lower case). Fourteen segment displays do a good job as alphanumeric displays, the extra seven segments make creating a good font for the alphabet possible.

These displays are normally driven in a sequential or multiplexed mode, with each digit displayed one at a time very rapidly. The eye doesn’t notice the scanning of the display. This cuts down on the power, and allows driving the displays more brightly without overheating them. It also cuts down on the number of wires needed to interface the displays. For an eight digit seven segment display we would need one wire for each segment (including the decimal point), and one wire for each digit. This totals 16 connections. We can encode the segments and digits, which means 4 wires for the encoded values (0-9, and A-F in a hexadecimal display), and 3 wires for the 8 digits. We’d need one more wire in the digit encode if we want to be able to blank the display. That’s a total of 8 lines. The fourteen segment display would require more lines, of course.

The microcontroller can perform the necessary multiplexing of the display, if it has enough interface lines. However low pinout devices such as the ATmega328 and the AVR128DB-28 barely have enough I/O lines and need some help.

The HT16K33 driver chip is a driver for multiplexed LED array of 8×16 units (max of 128 LEDs). Both discrete LEDS wired up in a matrix, or a packaged display (or a combo of both) can be used. From a register programming point of view, it is a common cathode display driver, with 8 cathode drivers, and 16 anode drivers. However, it can support both common cathode and common anode display blocks, though the way the display data will be written to the chips internal display ram will be different. This chip has an I2C interface that connects to the microcontroller with just two I/O .lines. It internally handles the multiplexing of the display, and stores the data for which display segments are to be lit. The brightness of the display can be set to any of 16 levels.

Adafruit sells a breakout board that has this part already soldered to it (it’s an SMT part), as well as boards that include both the chip and an LED display. I’ve used their breakout board to construct display modules with both 7 segment and 14 segment displays for 8 digits. The seven segment module also includes a 12 level bar graph display. My boards were hand wired on perfboard using surplus wire wrap sockets to hold the displays, the wiring was done with #30 wire wrap wire. While this is an ‘old school’ method of wiring, it is still a valid quick and easy way to prototype, and the wire wrap tool, sockets, and wire are still available.

My seven segment display module has 8 digits worth of 0.56″ tall red common anode displays with right hand decimal points. The segment lines are all connected together, and are wired to the HT16K33 cathode lines (C0-C7). Each of the common anode lines from the displays are wired to the HT16K33 anode lines (A0-A7). Three of the remaining anode lines are wired to a 12 segment bar graph.

This bar graph has 12 LEDs (4 Green, 4 Red, and 4 Amber). the anodes of the 4 Red LED’s are wired together, as are the anodes of the Green and Amber giving 3 common anode leads. The cathodes of the LEDs are wired into four groups of three, with C0 being the first LED of each group, C1 the second LED, and so on. The bar graph display I had in the junk box isn’t too bright, I might replace it with 12 discrete LEDs selected for high brightness.

Here is some test code for the display.

//
// 7 segment common anode LED display using HT16K33 led matrix I2C controller
// This will be an 8 digit/character display.
//

#include <Wire.h>

// the HT16K33 can be jumpered to one of seven addresses
// the default is ADDR1
#define ADDR0  0x70
#define ADDR1  0x71
#define ADDR2  0x72
#define ADDR3  0x73
#define ADDR4  0x74
#define ADDR5  0x75
#define ADDR6  0x76
#define ADDR7  0x77

/* seven segment display
 * 
 *     -A-
 *    |   |
 *    F   B
 *    |   |
 *    - G -
 *    |   |
 *    E   C
 *    |   |
 *    - D -
 */   
// segment 'fonts'
//This array ASSUMES that the segments are wired correctly with segment A connected to C0, 
//segment B to C1, and so on.  I had a small goof wiring the HT33k16 to the displays so I added the 'fix[]'
//array below to remap things in software rather than rewire the connections
//
const uint8_t SevenSegmentFont[16] = {
    0b00111111, /* 0 */
    0b00000110, /* 1 */
    0b01011011, /* 2 */
    0b01001111, /* 3 */
    0b01100110, /* 4 */
    0b01101101, /* 5 */
    0b01111101, /* 6 */
    0b00000111, /* 7 */
    0b01111111, /* 8 */
    0b01101111, /* 9 */
    0b01110111, /* A */
    0b01111100, /* B */
    0b00111001, /* C */
    0b01011110, /* D */
    0b01111001, /* E */
    0b01110001, /* F */
};

//remap the buffer addresses because the board was misswired!
//segment A SHOULD be connected to C0, segment B to C1, .... Segment G to C6 and DP to C7
//I obviously viewed the connections to the displays upside down from the rear. Rather than
//rewire the connections I fixed the boo boo in software with the following re-mapping array.
const uint8_t fix[8] = {6,8,10,0,2,4,14,12};

const uint8_t addr = 0x71; // HT16K33 default address

//allow us to define an array of bytes or words 
union Buffer {
    uint16_t  w[8];
    uint8_t   b[16];
};


#include <stdio.h>

//
// Will need to define a character font matrix.
// Only capital letters, and numbers will be defined.


#define PH 2
#define PL 0
#define IRQ 1

char displayBuffer[16];

void BarGraph(int bars)
{
  const char barseg[5]={0,1,3,7,15};
  int segs = 0;

  //clear buffer
  displayBuffer[1] = displayBuffer[3] = displayBuffer[5] = 0;
  show();
  
  if(bars == 0) return;

  if(bars < 5){
    displayBuffer[1] = barseg[bars];
  }
  else if(bars < 9) {
    displayBuffer[3]=barseg[bars-4];
    displayBuffer[1]=barseg[4];
  }else{
    displayBuffer[1]=displayBuffer[3]=barseg[4];
    displayBuffer[5] = barseg[bars-8];
  }
  show();
 
}

void DisplayFrequency(long int Number)
{
  long int number = Number;

//    number = number / 100;  //will display frequency to nearest 100hz only
    
    for(int i=0;i<15;i++){
        displayBuffer[i++]=0;  //zero the buffer
    }
    int dig = 0;
    while(number >= 10) {   //reduce number by power of 10 till only most sig digit is left
        int num = number % 10;  //need remainder from power reduction as LSD
        number = number / 10;   //divide number by 10 to reduce power
        // fill each digit with 7 seg represntation
        for(int seg = 0; seg < 7; seg++){   //set each segment byte at digit bit
            if(SevenSegmentFont[num] & (1 << seg)){ //if segment is lit
                displayBuffer[fix[seg]] |= (1 << dig); //set digit bit in segment byte in buffer
            }
        } // all segments accounted for
        dig++;  //next digit
    } // number now less than ten, is final remainder
    if(number) //final most sig digit, ignore if now zero
    {
        //fill msd with 7 seg representation
        for(int seg = 0; seg < 7; seg++){   //set each segment byte at digit bit
            if(SevenSegmentFont[number] & (1 << seg)){ //if segment is lit
                displayBuffer[fix[seg]] |= (1 << dig); //set digit bit in segment byte in buffer (last time!)
            }
        } // all segments accounted for
    }
    displayBuffer[12] |= 0x2; //set decimal point at 100hz point, display is in KHZ

}


void show(){
    Wire.beginTransmission(addr);
    Wire.write(0x00); // start at address 0x0
    
    for (int i = 0; i < 16; i++) {
        Wire.write(displayBuffer[i++] & 0xFF);    
        Wire.write(displayBuffer[i] & 0xFF);    
    }
    Wire.endTransmission();  
}



void clear(){
    for(int i = 0; i < 16; i++){
        displayBuffer[i] = 0;
    }
}

void setBrightness(uint8_t b){
    if(b > 15) return;
    
    Wire.beginTransmission(addr);
    Wire.write(0xE0 | b); // Dimming command
    Wire.endTransmission();
}

void blank(){
    static boolean blankOn;  
    
    Wire.beginTransmission(addr);
    Wire.write(0x80 | blankOn); // Blanking / blinking command
    Wire.endTransmission();
    
    blankOn = !blankOn;
}

void blink(uint8_t b){
    if(b > 3) return;
    
    Wire.beginTransmission(addr);
    Wire.write(0x80 | b << 1 | 1); // Blinking / blanking command
    Wire.endTransmission();
}

//setup includes test code.
void setup() {
    Serial.begin(9600);
    pinMode(6,INPUT_PULLUP);  
    Wire.begin();
    Wire.beginTransmission(addr);
    Wire.write(0x20 | 1); // turn on oscillator
    Wire.write(0x80); //  display off?
    
    Wire.write(0xA0 + IRQ + PL); //set interrupt output
    
    Wire.endTransmission();

    clear();  //zero display ram 
    show(); //clear displays
    
    setBrightness(15); //full brightness
    blink(0); //no blinking
    
    Serial.println("7 segment and bar graph test code!");

    for(int S=0 ; S<15 ; S++){
      displayBuffer[S++]=0xff;
      show();
      delay(1000);
    }
    clear();
    
    DisplayFrequency(21430123L); // display 21,430,123 as 21,430.000 khz
    show();

    delay(1000);
    for(int bb = 0; bb < 13; bb++)
    {
      BarGraph(bb);
      delay(1000);
    }
}



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

The fourteen segment display is also an 8 digit unit, and it is constructed in a similar way. This module has common cathode red LED displays about the same size as the 7 segment one. The displays were found surplus at Marlin P Jones. These are wired with the segments (including right hand decimal point) to the A0-A14 pins on the driver chip. The Common Cathode pins go to C0-C7. This just about uses up all of the available output pins, so adding a bar graph display with more than 8 leds would be impossible. However I could add 8 discrete LEDS as panel indicators if I find a use for them.

Here is the test code for the 14 segment display, based on the arduino driver from Adafruit.

//
// 14 segment LED display using HT16K33 led matrix I2C controller
// This will be an 8 digit/character display.
// The chip also supports a keyscan function.  We will wire up a 3 column x 4 row
// telephone style keypad.  Interrupt output is supported.
//

#include <Wire.h>

const uint8_t addr = 0x70; // HT16K33 default address
uint16_t displayBuffer[8];
char keybuff[6];  //store key data here


#include "14-SegmentFont.h"
#include <stdio.h>

//
// Will need to define a character font matrix.
// Only capital letters, and numbers will be defined.


#define PH 2
#define PL 0
#define IRQ 1
void setup() {
    Serial.begin(9600);
    pinMode(6,INPUT_PULLUP);  
		Wire.begin();
		Wire.beginTransmission(addr);
		Wire.write(0x20 | 1); // turn on oscillator
    Wire.write(0x80); //  display off?

    Wire.write(0xA0 + IRQ + PL); //set interrupt output
    
		Wire.endTransmission();
		setBrightness(15);
		blink(0);
    Serial.println("hello moose");
}



void loop() {
		const int dTime = 50;
    char me[9];
    char ch;
    sprintf(me, " WA2MZE");
//wa2mze
    for(int x=0;x<strlen(me);x++)
    {
      ch = me[x];
      displayBuffer[x] =  FourteenSegmentASCII[ch-0x20];
    }
    blink(0);
    show();
    delay(2000);
    if(digitalRead(6))
      blink(1);
    show();
    delay(2000);
    clear();		
    
#if 0    
//show all fonts		
		for(int f = 0; f<96;){
				for(int d=0; d<8; d++){
						displayBuffer[d] = FourteenSegmentASCII[f++];
						show();
						delay(dTime*10);
				}
        delay(dTime*10);
				clear();
		}

    sprintf(me, "21.430.000");
    int bp = 0;
    for(int x=bp;x<strlen(me);x++){
      ch = me[x];
      if(ch == '.'){
         displayBuffer[--bp] |= FourteenSegmentASCII[ch-0x20];  //set RHDP on previous position
         bp++; //ready for next char
      }else
        displayBuffer[bp++] = FourteenSegmentASCII[ch-0x20];
    }
		show();
    delay(4000);
    clear();
   
	
		// Loop through all segments
		for(int i = 0; i < 8; i++){
				for(int k = 0; k < 16; k++){
						displayBuffer[i] = 1 << k;
						show();
						delay(dTime*10);
				}
				clear();
		}
		
		// Turn on all segments, one at a time
		for(int i = 0; i < 8; i++){
				for(int k = 0; k < 16; k++){
						displayBuffer[i] |= 1 << k;
						show();
						delay(dTime);
				}
		}
		
		// Test blinking
		for(int i = 3 ; i > 0; i--){
				blink(i);
				delay(2000);
		}
		blink(0); // Turn blinking off
		
		// Test blanking
		for(int i = 0; i < 10; i++){
				blank();
				delay(dTime * 2);
		}
		
		// Test dimming
		for(int i = 15; i >= 0; i--){
				setBrightness(i);
				delay(dTime * 2);
		}
		clear();
		setBrightness(15);
#endif    
}

void show(){
		Wire.beginTransmission(addr);
		Wire.write(0x00); // start at address 0x0
		
		for (int i = 0; i < 8; i++) {
				Wire.write(displayBuffer[i] & 0xFF);    
				Wire.write(displayBuffer[i] >> 8);    
		}
		Wire.endTransmission();  
}

//read key buffer, return number of bytes read
int getKeys(char *keybuff)
{
		int ptr = 0;
		Wire.beginTransmission(addr);
		Wire.write(0x40);	//key buffer address
		Wire.endTransmission();
		Wire.requestFrom(addr,6); //request 6 bytes from keybuffer
		while(Wire.available() && ptr < 6)
		{
				keybuff[ptr++] = Wire.read();
		}
		return(ptr);
}

char getKeyStat()
{
  char stat;
    Wire.beginTransmission(addr);
    Wire.write(0x60); //key buffer address
    Wire.endTransmission();
    Wire.requestFrom(addr,1); //request 6 bytes from keybuffer
    while(Wire.available())
    {
        stat = Wire.read();
    }
    return(stat);
}


void clear(){
		for(int i = 0; i < 8; i++){
				displayBuffer[i] = 0;
		}
}

void setBrightness(uint8_t b){
		if(b > 15) return;
		Wire.beginTransmission(addr);
		Wire.write(0xE0 | b); // Dimming command
		Wire.endTransmission();
}

void blank(){
		static boolean blankOn;  
		
		Wire.beginTransmission(addr);
		Wire.write(0x80 | blankOn); // Blanking / blinking command
		Wire.endTransmission();
		blankOn = !blankOn;
}

void blink(uint8_t b){
		if(b > 3) return;
		Wire.beginTransmission(addr);
		Wire.write(0x80 | b << 1 | 1); // Blinking / blanking command
		Wire.endTransmission();
}

The GD chip shortages (and the AVR128DB)

Unless you’ve been living under a rock for the past few years, you’re probably well aware of the current parts shortage. Go look for any semiconductors on Digi-Key or Mouser’s web pages and there’s a good chance that the exact part you are looking for might not be available. Lead times for the seller to restock their supply can run as long as a year, or even more. What’s going on here?

Everyone blames the pandemic for this, and while that’s certainly where this mess started, it doesn’t explain why we still have this problem. While the pandemic isn’t totally done with, things have gotten better, at least for the sane people that have gotten vaccinated. Hospitalization rates for Covid are way done, as are deaths and serious illness, though rates of infection are still rising and falling as the virus mutates.

During the worst part of the pandemic many people started to work from home, and demand for computers skyrocketed, particularly laptops. Chip makers were not able to keep up with demand as computer makers doubled or tripled their orders, and shortages became common. Many companies started ordering way more parts than they needed, just to have them in on hand to meet future demand. This only increased the shortage as chip makers had to put parts on allocation. The situation isn’t unlike the way there was a shortage of toilet paper after Johnny Carson jokenly predicted one, and everyone believed him and started to stock up. If electronics makers would go back to only ordering enough parts to keep a supply for a month or two, ordering parts as needed (as used to be common practice), the shortages would probably be over now.

I posted some time ago about my experiences using the Microchip / Atmel AVR128DB series micro controllers. These parts are available in memory sizes of 32k, 64k, and 128k, and in 28, 32, 48, and 64 pinout versions (28 pin PDIP, TSOP TSSOP; and 32,48, and 64 pin TQFTP and TQFN packages). Some of the memory sizes in various packages are now in short supply (or have long lead times), but there are still options available for the experiment to purchase. I hadn’t given any consideration to the smaller memory footprints, however the 64K parts are a bit more available, and they are also good replacement / upgrades for the ATmega328 used on the Arduino Uno.

In any event, I did manage to order a 5 each of the 28 pin TSSOP, and TSOP parts, and 2 of the 32 pin TQFP parts in the 128K memory footprint. I had been playing around with learning KiCad V6, and I’d like to attempt to design a ‘Feather’ format board around the AVR128DB part. I should certainly be able to fit the TSSOP package in this format, and maybe the 32 pin TQFP, though the pinout limitation of the Feather design probably makes the 28 pin package about as large as you’d want to go without loosing the use of some i/o pins to connect external to the board. Normally for development boards I like to buy the largest sized memory footprint, as you can always downsize later once you’ve coded your application and know how much memory you really need. However it does seem that the 64k parts are more available, and they might even have fewer ‘errata’ issues as they came out after MC did the first round of bug fixes.

I don’t know when I’ll actually get to play around with the KiCad Feather design due to my current problems. I will again be making a visit to the hospital today to see my wife, and we still have to find a place outside the hospital for her care, otherwise the hospital bills will slowly bleed my dry. At the moment, any spare time I have to take my mind off of my problems helps with my sanity, but the available moments are short.

73’s WA2MZE

Starting Over

It’s been awhile since I’ve posted anything here. A lot has been happening in my life, and there have been some great changes, most of which have not been for the better.

My wife was diagnosed with ALS in 2020. At first her symptoms were minor, but she gradually has been going down hill. The doctor’s told us that most patients with her type of onset usually don’t last more than 4 or 5 years from being diagnosed. For her it started with slurring of speech, and difficulty in swallowing pills. The tongue was the first thing to be affected, and the loss of muscle strength gradually travelled to her arms and legs. She still has the ability to use a stylus to text on her phone, and currently can still communicate via a writing pad or her smart phone in text mode. However, her left hand is now only good for holding the phone, and her right hand is starting to fail her. Her neck muscles have locked up, and she no longer can raise or rotate her head.

Soon after her diagnosis, we decided to sell our house in Florida, and move north to the Boston area. Neither of us have any family left in the South Florida area, and our twin daughters who went to college in the Boston area, now live there. I have a brother in Sharon Mass, along with other family in New Jersey, and Long Island. In addition, the Boston area has some very good medical institutions. So, the move in the reverse direction from the one that most retiree’s take, made perfect sense for us. Having grown up in Brooklyn NYC, the winter isn’t an unknown to me, and the Eastern Massachusetts winters are not unlike those in NYC, though perhaps a bit longer. Being closer to the arctic circle, the sun rises quite a bit earlier and sets quite a bit later in the summer than in Florida, which does upset my sleep cycle. However days will be quite a bit shorter in the winter! We didn’t make the move until April 6th of this year. I wish we had moved sooner, but it took a while to convince my wife of the necessity of it, and she didn’t want to move in the winter. And then there was the pandemic which sorta made travel impossible. The only way she could travel would be by air, and only American Airlines would grant a medical exception for wearing a mask, something her ALS demanded. American was also the only airline that kept their phone lines accessible to passengers needing special help, both Delta and Jetblue either abandoned answering their phones by human beings (only stupid robots), or had hold times HOURS long. If I ever travel by air again, I know what airline will be my first choice. And I’ll probably fly first class with them again too (had to for my wife’s comfort and ease of access). While a first class ticket is as much as 3 or 4 times the price of coach, it comes with two free bags (vs $25-$75 per checked bag in coach) with a 70 lb limit (vs 50 lb in coach), free meals, and much more comfortable seating. Yeah you get what you pay for!

For the moment, we’re renting an apartment while our home is on the market (though we should be closing on a sale as I write this). Our plan was to then look for a house (the Boston area housing market is insane at the moment due to lack of inventory, but as interest rates rise maybe those that don’t have to qualify for a mortgage will have a slight edge). However, as my poor wife can no longer stand at all, even with the help of a walker, I am no longer to care for her by myself. She will have to be transferred to a facility with available nursing care, or we will need in home help. At the moment she’s in the hospital, the paramedics I had to keep calling on 911 everytime she almost fell and I couldn’t move her from wheelchair to commode or recliner (where she had been sleeping as we could no longer get her into or out of a bed), suggested taking her to the emergency room for evaluation. She’s been admitted, but at this point we don’t know how long medicare will continue to pay for her hospital stay. The case workers at both Lowell General and Mass General hospitals are (perhaps somewhat half heartedly) looking to find us a solution, but I fear she will be discharged and I’ll be back to square one having to call 911 several times a day for assistance moving her about at home. If the power wheelchair she has been fitted for would only show up, that would be a big help…..

As I type this I’m home alone. I will make the 20 minute drive to the hospital to visit my wife after lunch, visiting hours start at 1 PM. I can’t spend more than a few hours there, I don’t want to drive home towards night time, and I need some time for myself to take care of basic chores at home, shopping, and to prepare my dinner. It’s almost like I’m back to my bachelorhood days, and I realize just how much I’ve become dependant on my wife for many little things I’ve taken for granted over the last 30 years. Very depressing.

As you may have noticed, I’ve changed the title of this blog. I’ve always enjoyed the wood working of PBS’s Norm Abrams, and I used to build furniture following his methods. Alas, that, and most of my extensive shop tools have no place in my apartment, and this major downsizing accounts for the ‘microscopic’ term in the description. I can still play around with small electronics projects, and may even be able to attach a mobile style whip antenna to the balcony terrace railing to use the HF amateur bands. So I’d like to continue this blog, if for no other reason but to share.

73’s for now……WA2MZE

A homebrew Microcontroller development board

Among AVR microcontrollers, the most popular ‘goto’ chip has been the atmega328. This is the part that drives the Arduino Uno and Nano boards, plus a lot of various clones from Adafruit, Sparkfun, and various Chinese suppliers. As the 28 pin DIP part is configured on the UNO, it has 20 available I/O pins (there are two extra analog input pins available on the 32 pin SMT parts). If you were to use the internal oscillator you would gain two more pins, and one more if you didn’t need the reset pin. However, that would require that you use a high voltage programmer, and no boot strap loader.

The new AVR128Dx-28 device has 21 available I/O pins when its internal oscillator is used. You lose two pins, if you want to use either the 32khz or high frequency crystal oscillators, and four pins if you need both. You can gain one input pin by not enabling the reset line, this loses you the bootstrap, but you can still use the UDPI programmer. The crystal oscillator isn’t needed with this part, even without calibration the built in oscillator is factory tuned well enough to provide an accurate enough frequency to provide a USART serial clock, even at the fastest common baud rates (such as 115 or 250 khz). About the only time you would need an external crystal would be to use the device as a real time of day clock.

The AVR128Dx series is now supported by the Arduino DXcore add on (https://github.com/SpenceKonde/DxCore/blob/master/megaavr/libraries/Wire/src/Wire.cpp) developed by SpenceKonde. This core supports all of the AVRxxxDx devices (16,32,64, and 128K flash sizes, DA and DB families, and 28,32,48, and 64 pin devices). I decided to work with the AVR128DB-28 device, as it makes a good replacement for the atmega328 used in the Arduino UNO.

Development board, RS232 serial adapter, Atmel ICE programmer with adapter cable

Shown above is my setup. I soldered a 28 pin socket to one of AdaFruit’s 1/2 sized breadboard PCB’s and added some connections for externals. I’m using an Atmel ICE (now a MC ICE ? ) with an adapter from the 20 pin 50m cable connector to a 3 pin female plug to hook to my board. Also visible is a homebrew RS232 to TTL adapter (there is a max3223 level converter inside the heat shrink covered pc board).

The dev board

Here is a close up of the dev board. On the lower left is a common 7805 voltage regulator with two bypass capacitors, and a reset push button switch. The connector to the right of that is for an optical rotary encoder. Then there is a 6 pin female connector (with one pin blocked with solder as a ‘key’). This is for the USART serial connection, two of the pins are power and ground, and one is for the DSR connection that goes to the controller Reset pin via a 0.1 uf capacitor. Below the USART connection is a 3 pin male socket for the UPDI programmer. This was used initially to test the board, and then to ‘burn’ a bootloader into the flash. Now I can program the controller vial a serial connection with the Arduino IDE.. To the right are two sets of I/O connections. There are 3 pins for GP IO functions, and four sets of 4 pin connectors for I2C devices. (power, ground, SDA and SCL). I can hook up to four I2C devices here. There are two 10K ohm pull up resistors on the bottom side of the board. Finally there are two sets of connections on the top of the board, one has 7 GP IO pins and the other has 5 (with matching ground connections). The GP IO pins are not yet assigned, they will be application specific.

My intent is to use this board to control a QRP ham transceiver using an Si5351 as a VFO. The frequency display will be a seven or fourteen segment LED display with 8 digits, using an HT33K16 LED matrix controller (Adafruit breakout board). I will also have a 12 switch ‘keypad’ interfaced via an I2C IO expander chip. Relays to switch band filters in and out will be controlled via another I2C IO expander. The available GP IO on the controller will be used for A/D input to accept PTT and Key input, CW tone output, and CW carrier injection control. A built in CW keyer will also be provided in software. The available second USART serial connection could be used to talk to a Teensy-4 processor that could be used as a DSP for I/Q demodulation and transmit modulation in a software defined radio. The plan would be to use the Si5351 to generate the required I and Q phase split local oscillator for the second mixer, and the vfo for the first mixer. The rig would have a 45 mhz first IF (up conversion) and a 15-20 khz second IF (down conversion). The first roofing filter would use a surplus 45 mhz cell phone IF filter.

In future posts I will describe the HT33K16 based display boards, the optical encoder, and the key pad switch interfaces. Clearly, I2C is a good way to expand the utility of a microcontroller with limited I/O connections. The avr128Dx-28 devices are a bit strange. They have lots of flash and sram space, and a good range of built in peripherals (not all of which can be used at the same time). A controller with only 28 pins and 128k of flash is interesting. It will make a very good upgrade for the UNO!

New AVR’s … Part 2

Some time ago, I wrote a blog entry on the new AVR chips that MicroChip had introduced. Since then, they’ve added a new “family” the AVRxxxDByy family (xxxx being flash memory size of 32 ,64,or 128 and yy being the package pin count of 28, 32, 48 or 64 pins). I just received some sample parts of the “DB” family, though I actually purchased most of them from Mouser, the 64 pin parts are currently sold out, but I had gotten a pair of them some months back AS a free sample for the asking, all in the 128K flash size. (I always buy the largest memory size I can for my experiments, later if I actually were to design and sell a project, I’d use the smallest size that my code would fit in.)

These new parts can’t be programed with my old Atmel tools. Top to bottom and left to right you can see my AVR-ISPmkII, AVR-JTAGmkII, AdaFruit USB-Tiny ISP, and AVR Dragon programmers. None of these includes the UPDI programming interface, and all of these tools are no longer in production. They still work for the older AVR parts.

My collection of old AVR programmers.

More recently, I’ve acquired both anAtmel-ICE, and a PicKit4 progrmmer/debugger. While the Atmel-ICE was developed by Atmel (before they were purchased by MicroChip) to work with AVR and SAMD series microcontrollers, and the PicKit4 was created by MicroChip for their PIC series micro’s, upgrades in their firmware now enable both of them to be used with most all microcontrollers made by the combined company. I’ve tried programming both the atMega4809-40 and the AVR128DB28 with both of these programmers, and they both work fine. I’ve used both the MPLAB-XIDE and Arduino development suites, both also work fine with both programmers. Below you can see the avr128DB28 being programmed by the Atmel-ICE.

Breadboard with atMega4809 and AVR128DB28.

The Atmel-ICE is available in several different kits. You can buy the bare PC board for about $75, about the same price as the PicKit4. The bare PC doesn’t come with any cables, you’ll have to buy those separately. You can 3D print a case for the board, several designs are posted on thingiverse. The cable kits that are available for the Atmel-ICE (or come in the more expensive tool bundles) are somewhat fragile and not ideal for breadboard use (but fine for the dev boards from MicroChip). I made my own programming cable using a 10 conductor 50mil cable from AdaFruit, breadboard cable adapters from Adafruit, and a 6 conductor 100 mil cable. The wiring on the 6 pin cable is compatible with all of the matching programming interfaces supported by AVR processors.
The PicKit4 comes with only a USB cable, the end user will have to make their own interface cable to connect the programmer with the target processor.

Here is the source code for my first test of the AVR128DB28: Just a simple blinking led script, which is the “hello world” first program for microcontrollers.

#define F_CPU 25000000UL
#define <avr/io.h>
#define <util/delay.h>

int main(void) {
/*initialization of the clock and LED output port bit */
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, 3); //external clock or crystal
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0); //no divider
_PROTECTED_WRITE(CLKCTRL.XOSCHFCTRLA,0xC1); //enable external xtal osc
PORTA.DIRSET = 0x80;
/* My application code */
while (1) {
_delay_ms(1000); //wait a second
PORTA.OUTTGL = 0x80; //flip output bit
//next two lines were deleted, not needed when using the OUTTGL function, but were in the Arduino
//sketch using the digitalWrite() function with on and off variants.
// _delay_ms(1000); //wait another second
// PORTA.OUTTGL = 0x80; //flip bit again
}
}

This was compiled using MPLAB-XIDE. Note that the max clock speed for the AVR-DB series is 24mhz, but I had some 25mhz crystals in the junkbox. So I’m slightly overclocking the part. It works fine (others have tried clocks up to 48mhz with the extended temp range parts, though mine is the industrial temp range that is rated for lower temperatures. What’s one mhz among friends?)

The _delay_ms() function in avr_libc that comes with the MicroChip compiler (probably GCC based) seems to use the value of F_CPU to calculate the length of timing loops. A similar function in the Arduino tools has a series of #ifdef …#else blocks for a number of clock frequency choices, but 25mhz isn’t one of them. I didn’t get an error or warning when I specified the ‘bastard’ clock rate (by editing boards.txt), but the blink rate of the LED was totally wrong! I didn’t post the Arduino sketch code I used, but it was almost exactly the same as above, except that the code for setting the clock was done behind the scenes in the Arduino library init code. So, for now, if I use the Arduino I’ll have to either lie about the clock speed (use the 25mhz crystal but set it for 24mhz), or use a slower 20mhz crystal.

Nothing exciting to see yet, except that I have the tools to put code on these chips.

Coffee or Tea?

I remember as a kid my parents taking the family to the local Chinese restaurant. With every meal they served an endless pot of tea, and small cups to drink it in. I’d keep refilling my cup during the meal, and always put huge amounts of sugar into the cup to drown out the slight bitter taste of the tea. What I ended up with was a very sugary, hot beverage.

I’d drink tea at home (mostly when I was sick). Like most families we bought Lipton tea bags. Lipton isn’t your “gourmet” tea (more like gourmand). It’s pretty much of a low grade British origin, nothing to write home about. Later in life, I’d discover better varieties of tea, such as Earl Grey (favorite of John Luc Picard), green matcha (used by the Japanese in their tea ceremony), oolong (very nice Chinese tea, a teabag of this is good for more than a single cup), green, black, and white teas. White tea has the least caffeine, good for an early evening drink without keeping you awake at night.

Then in the ’90’s I started working at Coulter in Miami. Coulter is the inventor of the famous ‘Coulter Counter’, a device that counts particles suspended in a fluid. It’s primarily used in medical work to count blood cells, a task that was once performed by a lab technician using a microscope. Coulter was located in Hialeah Fl, also known as ‘Little Havana’ due to the Cuban immigrants that live there. Most of the factory workers are Hispanic, and around 10am every day they took a Cuban Coffee break. Cuban coffee is made sorta like espresso, but with LOTS of sugar. I soon became addicted to the stuff, it was the first coffee of any kind that I’ve ever had.

Sometimes I’d order a cup of black coffee with a meal when I ate out. Not as strong as the Cuban espresso, but I had acquired the taste. I wanted to be able to make something similar to the Cuban at home, but I didn’t want to spend the bucks on an espresso machine. Then I discovered the Moca pot.

Sometimes known as an Italian Coffee pot, the Moca pot is a pressure coffee brewer like the true espresso machine. It doesn’t use nearly as high a pressure, brewing with forced hot water rather than steam. The pot consists of three pieces: the bottom is the water boiler, it has a safety valve that will vent open if the steam pressure gets too high. Above this is the coffee funnel – filter. It has small holes in the bottom to allow the water to seep up into the coffee. The funnel sits on top of the boiler. The top of the pot is where the coffee is pushed up into though a tall ‘straw’. The top screws onto the boiler just above the funnel. It has a spout for pouring.

While many people use espresso ground coffee in the Moca pot, it actually is intended for something between ‘fine drip’ grind and espresso in size. The so-called Cuban espresso coffee (Pilon) sold in the yellow, black and red ‘bricks’ is actually a bit courser ground than true espresso, and is perfect for use in the Moca pot. These days I buy ‘bulk’ organic coffee from shops like Whole Foods, and set the store grinder in the middle between ‘fine’ and ‘espresso’. It works perfectly.

I found a stainless steel ‘2 cup’ moca pot on ebay. It’s a Chinese knock off of the original Italian brand, but works fine. The size of a Moca pot is given in demitasse’ cups, NOT 8 oz cups!!!! My favorite way to drink the strong coffee from the Moca pot is with some ‘milk’. I add equal amounts of plant based ‘milk’ and coffee. I usually use either Soy or Almond milk rather than the kind that comes from a cow. I heat the 1/2 cup of milk in the microwave first, then ‘froth’ it using a battery operated frother (a wire spring that spins). This gives me one cup of ‘latte’. You can use real milk of course. I don’t know if I’m lactose intolerance (I don’t think so, but as you age you can develop this). I also add about one teaspoon of sugar to the coffee. Just enough sweetness to taste.

Much cheaper than a trip to Starbucks, and it tastes good. Enjoy!

Longtime no see … Cad Software

I’ve been away for awhile, mostly due to personal/family reasons. However, I’ve been working on several projects, one of which is a QRP transceiver that I’ve been evolving. The first thing I needed to do was to come up with the basic design, and capture the schematics. For simple projects we can resort to the old fashioned pencil and paper draftsmen approach. However, we would still like to have a better archive solution than a file cabinet with envelope folders in a drawer, certainly not while we have our computer! Rather than drawing our schematics on paper, and then scanning them into image files, why not bite the bullet and learn some CAD? The advantage of computer aided design, is that you can go from schematics to printed circuit boards using the CAD software, and then order boards from one of many low cost offshore circuit board houses. But which cad software?

At the top of the heap is Altium. This is a professional package, designed for big projects. The professional Altium packages are subscription based, and are priced monthly. Clearly for ham maker hobby use this isn’t for us. However Altium DOES have their Circuit Maker package. This is a cloud based application that is free for use. I’m not sure if the PC resident portion of the package will work on Linux directly or under WINE. However, running Windows 10 inside of Virtual Box is one solution. (I have a Windows install under Virtual Box on my computer running Kubuntu, I currently use this for iTunes, and a few other applications). I haven’t looked into the Altium Circuit Maker, but on the surface it looks interesting.

The long time favorite PC Cad Software is EagleCad. This is still available at no cost, but the “Freeware” version is limited to the board size, layers, and number of schematic pages per project. Still, I did design my first circuit board using Eagle. Both Adafruit and Sparkfun design their boards using the ‘pro’ versions of Eagle and they publish their cad files on their websites for their open source boards. Eagle is a good way to learn CAD, and the software runs on Windows, Linux, and Mac.

Finally, there is KiCad. KiCad is a totally open source package, and runs on all platforms. In the past few years (since version 4 came out) KiCad has become more mainstream, with many parts vendors and component makers now providing KiCad design libraries for the parts they sell. While the user IDE is different in many ways from both Eagle and Altium, KiCad is easy to learn. Many PC board houses now directly support KiCad, without the need to create Gerber files (which you CAN do in KiCad). The software is now in version 5, with version 6 due out later this year, or early next.

I’ve used KiCad on and off after Eagle changed their sales model and raised prices. I was using the freeware version of Eagle, but the cost (back then) of upgrading was still reasonable for hobby use. Not so much today! To give you an idea of what you can do in KiCad schematic capture, I’ve attached the schematic of my in progress NanoBitX transceiver IF module below. (I will present a full write up of this project once I get things working).

KiCad comes with a library of basic parts, and many contributed library symbols. It is also easy to create your own. In the schematic below, I’ve designed symbols for the ERA-1 amplifiers, NE602 mixer IC’s, 74HC4053 fet switches, IF crystal filters, MC1350 IF amplifier, toroid transformer, and coax/shielded wire. Symbols for some of these were available either in the supplied library, or on line, but they didn’t fit in with my circuit flow. For example, the NE602 symbol I created shows the separate mixer and oscillator portions, and the pin placements follow the signal flow NOT the package outline. My symbol for the 74HC4053 is divided into 4 blocks (a,b,c,&d) with separate symbols for each of the three switches and the power/enable pins. Also, I’ve shown the switches with NO and NC contacts to make the signal flow more obvious. There wasn’t any symbol (that I could find) to show a coaxial cable line, so I drew one.

Schematic of NanoBitx IF module, done in Kicad

The IF amplifier block has a 45mhz bilateral gain block, second mixer (from 45mhz to 10.7 mhz), 10.7mhz crystal filter, receiver IF amplifier (10.7mhz) with AGC, receiver product detector, and microphone pre-amplifier. The block is bilateral (functions in different directions during receive and transmit), and the product detector also functions as the transmitter balanced modulator.

More on the NanoBitX to come, hopefully in the near future. 73’s for now.

Yet more new AVRs

In a previous blog I mentioned the new atmega4809 and AVR128DA parts. Well, it seems I missed two other new families, the AVR128DB and AVR128DD series. I’ve requested some engineering samples of the AVR128DB64, and will attempt to solder one to a breadboard adapter. Will update on that later…..

The AVRxxxDB family is very similar to the DA but adds an external HF crystal oscillator (up to 32mhz), a level translator for one of the ports (so if you run the chip at 3.3volts it will be able to interface with 5v logic), and some OP amp stages that can be used as buffer amps for the A/D input, or D/A output. Only the 64 pin 128k flash variant is currently available, the rest of the variants will be shipping some time late this year, or early next year (I’m guessing).

The AVRxxDD family is a cut down version of the DB with less memory, and is only available in low pin count packages. It’s another option for those who would otherwise turn to the atTiny line of microcontrollers. The DD’s will be available in SMT 14, 20, 28, and 32 pin packages, as well as a 28 pin DIP (300 mil) package. These parts were recently announced, but are not yet available, even as samples.

No, I’m not associated with Microchip, but I’ve been following their AVR family having used these parts for years. I have also looked at the SAMD family of ARM Cortex M devices for use in ham projects. These microcontrollers offer much in memory size and processor speed, but they are much more complex than the AVR line. Except for DSP (SDR) applications, there is simply no need to go 32 bits, and the 8 bit AVR solution is usually the preferred option. The new SAMD parts did have a cost vs feature advantage over the older atMega devices, but the newest AVR parts, which are spin offs from the ‘failed’ Atmel Xmega offerings have caught up to the ARM Cortex M devices in this regard.

I had wondered if the sale of Atmel to Microchip would spell the end of the AVR. I guess I shouldn’t have worried, the product line seems to be in good hands.