Sunday, September 14, 2025

Arduino GPS Clock

This project started on a whim -- years ago I'd done some work with GPS receivers and decoding their NMEA-0183 serial data stream, and recently I thought it might be fun to make a very accurate clock using the "Time" field contained within the NMEA-0183 message stream.

The GPS receivers I've used in the past sent a packet of NEMA-0183 messages from their serial port once a second.  These messages contain information such as data and time, longitude and latitude of the receiver, and the satellites that it is receiving.  

The GPS time field contains a very accurate representation of time, formatted as HHMMSS.xxx, where HH is hours, MM is minutes, SS is seconds, and xxx represents fractions of a second.  Hours is referenced to GMT.

I only wanted to display hours and minutes -- displaying ever-changing seconds, too, would make the display too "busy", in my opinion.  So although I receive a new time from the GPS satellite network every second, the display only changes on a minute-by-minute basis.

On the front panel, in addition the four digit time display, I've mounted a photoresistor for measuring the ambient light level at the clock's front panel.  This measurement allows the display brightness to change with a room's ambient light level, i.e. minimum brightness for a dark room to maximum brightness for a very bright room.  There are four brightness steps.

I've also included a software menu system that lets me, via the front panel's four digit numerical display and two switches on the receivers back panel, select and change the following clock parameters:

  • Standard-Time offset, in hours, from UTC (e.g. set to -8 hours in California).
  • Select 12 or 24 hour format.
  • Select the Display Brightness Level (1 of 4 steps).
  • Enable Display Brightness to change with ambient light level (or remain fixed).
  • Enable the display's colon (":") between the Hour and Minute fields to "blink" (on for a second, off for a second), or remain ON constantly.
  • View the number of satellites the GPS receiver is tracking (for debugging).
  • View the analog value representing the ambient light level (for debugging).

In addition, there is a third 3-position toggle switch on the back panel that lets me select between Standard Time, Daylight Savings Time, or GMT.  Although these could have been menu items, I preferred the convenience of using a switch to select between them.

The clock is powered by +5 VDC via the Arduino Nano's mini-USB port.


Project Description:

Hardware:

GPS satellite data is received via a u-blox GY-NEO6M Rev2 GPS module using a NEO6M GPS receiver (purchased from Amazon -- interestingly, the seller disappeared several weeks later!).

This module sends a serial data-stream once a second to an Arduino Nano processor, which decodes the data-stream, strips out the time field, and displays it on a 4-digit seven-segment TM1637 numerical display.

Although the Nano receives serial data from the NEO6M receiver, the Nano does not transmit data back to the NEO6M (there really is no need to do this during normal operation of the clock).  

However, for changing the NEO6M receiver's parameters, such as its baud rate, I've included a 5-pin header onto which a CH340 USB adapter can be temporarily mounted (for this application, I use a SparkFun Serial Basic Breakout CH340G board):


The Nano's and the GPS receiver's Serial Ports operate at different logic levels -- the Nano's is 5V logic while the Receiver's is 3.3V logic.  Given the voltage drop introduced by the Nano's 5V regulator, etc., the signaling-voltage margins can be on the edge of acceptability. I did not feel comfortable with the narrowness of these margins, and so I decided it better to include simple 3-component bi-directional level shifters between the Nano's 5V I/O and the GPS Receiver's 3.3V I/O.

Such level shifters consist of two resistors and a single MOSFET transistor (e.g. BSS138) per channel: 

They can be purchased, pre-assembled on PCBs, from Amazon:

There is a photoresistor, whose resistance changes with the level of ambient light, mounted on the front panel.  The Nano reads an analog value representing a voltage generated with this photo resistor, and, using this, it can adjust the display's brightness accordingly.

I wasn't sure what value of resistance for normal ambient light I'd need, so I purchased a selection of 5 different types of photoresistors to allow for experimentation:


I chose to use the "5506" (i.e. GL5506) photoresistor because its resistance, of the five choices, seemed the least likely to be loaded-down by the inherent resistance of the Nano's Analog port.

The display is a TM1637 Module, which uses a 2-wire Clock/Data interface (there is an Arduino library of TM1637 functions).  Unsure of what color to use, I purchased a pack of five modules, each with a different color:


In summary -- a very basic design consisting of three HW modules mounted on a thru-hole board (Nano, Level-Shifter, and GPS Receiver), and a separate Display module.

I brought the antenna connection out to the clock's back panel (via a uFL-male to SMA-female cable), rather than mounting a small antenna module within the clock's case the inside of the this case (scavenged from a product) had been sprayed with a conductive paint (I'm sure for EMC reasons), and I doubted an antenna mounted inside the resulting Faraday cage would have worked very well.

Below is the schematic of the clock.

Notes:

1.  There are two jumpers on the board, JP1 and JP2.  For normal operation, these should be installed on header J1 per the schematic.

  • JP1 connects the NEO6M's serial output pin to the Nano's serial input.  
  • JP2 connects the board's +5VDC to the NEO6M receiver
2.  To test a different receiver module with the board, remove Jumper's JP1 and JP2, then connect the new Receiver's module to the board as follows:
  • New Receiver's GND to J1.1.
  • New Receiver's TXD (serial data out, 3.3V level) to J1.3.
  • New Receiver's VCC (+5VDC) to J1.5.
With these connections made, the new GPS receiver should communicate with the Nano (be sure to ensure that the Nano's and the Receiver's baud rates are identical).


Software:

There are two timing loops in the software.  

The first loop is a 20 msec loop, and its primary task is switch debouncing and performing the resulting required actions.  

Note that if a clock parameter (e.g. 12/24 hour display formatting, GPS baud rate, etc.) is changed during this 20 msec loop, the Nano's EEPROM is updated with the new value.  These EEPROM values are used for system initialization upon power-up.

The second loop is a 1 second loop, and its tasks are:

  • Receive the NMEA-0183 message stream, strip off the time field, and write the time to the front panel display.
  • If displaying a menu item in lieu of time, update the menu's display with any changes to a menu's selection that occurred during the 20 msec loop.
  • Blink (if enabled) the display's "colon" between the hour and minutes fields.
  • Read ambient light level via the Nano's analog input A0.

Note that this code only  receives data from the GPS receiver, it does not transmit data back to it.  Therefore, to change any of the receiver's parameters, such as its baud rate (from its default of 9600 baud to, say, 38,400 baud), this change must be done using an external CH340 USB-to-Serial adapter and external software such as u-block's u-center (a very useful tool, by the way, for verifying if the receiver is working, if you are unsure of your Arduino code).

There are 9 possible menu items that can be displayed via the 4-digit front panel display.  These menu items can be stepped through using the momentary-contact MENU toggle switch.  Within each menu item there are usually a number of  choices available (such as different baud rates in the baud rate menu).  These choices can be stepped through using the NEXT pushbutton. 

The MENU items, and the range of possible choices for each MENU item, are shown, below:

  • Menu Item 1:
    • Displays current Time.
    • The NEXT button does not function for this menu item.
    • Display:

  • Menu Item 2:
    • Allows setting of the local time zone's offset, in hours, from GMT.  Note that the offset is per Standard Time, not Daylight Savings Time.  E.g. it would be -8 for California, irrespective of the month.
    • The NEXT button steps from 0 to -23, then wraps back around to 0.
    • Display

  • Menu Item 3:
    • Allows setting of the "Brightness" of the 4-digit LED display.
    • The NEXT button steps through the 4 possible brightness values, from 0 to 3, and then wraps back around to 0.
    • Display:

  • Menu Item 4:
    • Selects displaying time in a 12 or a 24 hour format.  "12" will be displayed if the 12-hour format is selected, and "24" will be displayed if the 24-hour format is selected.
    • The NEXT button toggles between the 12 and 24 hour selections.
    • Display:

  • Menu Item 5:
    • Determines if the colon dividing the 2-digit hours field from the 2-digit minutes field will blink (1 second ON followed by 1 second OFF), or if it is ON continuously.
    • The NEXT button toggles between the BLINK or ON states.
    • Display:

  • Menu Item 6:
    • Selects of one of five possible baud rates to use for the Nano's Software UART that communicates with the GPS Receiver.
    • The NEXT button steps through the following baud rates, and then wraps around to the start:
      • 9,600
      • 19,200
      • 38,400
      • 57,600
      • 115,200
    • Display:

  • Menu Item 7:
    • Displays the number of satellites tracked by the GPS receiver (used for debugging).
    • The NEXT button does not function for this menu item.
    • Display:

  • Menu Item 8:
    • Enables the display brightness to change as a function of the ambient light level, or keeps the display brightness fixed at the level set in Menu item 3, irrespective of the ambient light level.
    • The NEXT button toggles between enabling the display brightness to track ambient light levels, or the display brightness remaining fixed.
    • Display:

  • Menu Item 9:
    • Displays the Nano's ADC input value from the Ambient Light detector (useful for debugging).  Values range from 0 (dark) to 1023 (max light).
    • The NEXT button does not function for this menu item.
    • Display:


The MENU switch steps through the items from 1 to 9, and then will cycle back to 1. 

Similarly, the NEXT button steps through a menu item's possible values from first to last, and then cycles back to the first. 

Note that my GPS Clock Arduino code can be found here, on GitHub:  Arduino Clock Code.


Mechanical:

I used a small plastic box within which I mounted the electronics and the display.  I'd purchased this box (which apparently had been a shipping product) sometime in the dim-past, I'm sure because I thought I might someday be able to its case for a project.

For my new application of this case, I constructed both the front panel and the back panel from blank double-sided PCB stock.

The front panel simply has the time display and a small photoresistor, the latter is used to detect a room's ambient light level and with it, adjusts the display's brightness accordingly (i.e. max display brightness for a bright room, to minimum display brightness for a dark room).

The rear panel (see image below) has three switches, an SMA connector for the GPS antenna, and a hole to allow a mini-USB connector to be attached to the Nano within the box.

The three switches on the back panel are:

Leftmost switch:  3-position single pole toggle.  This switch selects between the following items:

  • UP:  Display time as Daylight Savings time (add an hour to Standard Time).
  • MID: Display time as Standard Time (no Daylight Savings Offset).
  • DOWN:  Display GMT time with 24-hour format.
Middle switch:  3-position momentary contact single pole toggle which is the MENU switch. This switch performs the following functions:
  • MID (default position): Idle
  • UP or DOWN (momentary contact):  Upon moving the switch to either its up or down position and then releasing it back to its idle (mid) position, the menu will increment to the next menu item on the list of menu items.  At the end of the list it will wrap around to the first menu item, which simply display's time.

Rightmost switch:  Normally Open push-button, called the "NEXT" switch.  Upon the press-and-release of this pushbutton, software will increment to the next value choice for the menu-item that has been selected..  For example, if in the "GPS Baudrate Select" menu and the current entry is 9600, upon the press-and-release of this pushbutton, the baud rate will increment to the next choice, in this case 19,200.  At the last choice the next press-and-release will wrap back around to the first choice.

The electronics are mounted on a small prototyping board:


This board, in turn, is mounted onto another piece of raw double-sided PCB stock that is large enough to let me attach it to the case's four mounting holes).




An overhead view of the final build:


Regarding the front-panel display, I found it unattractive that unilluminated segments of the display's numerals were visible from the front, so I mounted a small piece of "smokey" colored Gel Film between the display and the front panel to better hide any non-illuminated display segments.


Note that if using this type of Gel film, there is a protective layer on each side of the Gel film that will need to be peeled off.


Software Generation:

My wife suggested that I use ChatGPT to create the Arduino's code, so I thought, 'Why not', and gave it a try, wondering what the experience would be like.

I created a free account on the ChatGPT website and decided I would start by prompting ChatGPT to create code that would read and debounce two buttons (my MENU and NEXT switches).  Without any forehand knowledge on how best to use ChatGPT to write code, I plunged right in.

I quickly discovered that using the "Enter" key, in an attempt to format my request, immediately sends whatever I'd typed to ChatGPT, as you can see in the first line below.  My next attempt you can see right below it -- a long paragraph written "stream-of-consciousness" fashion.  But it worked!


I continued in the same vein, incrementally adding features and then testing them.  I was amazed at how quickly I was generating code with ChatGPT as a partner (although perhaps I should rephrase that as being amazed at how quickly ChatGPT was generating code with me as a partner).  I figured I'd have the complete sketch finished by the afternoon.

Almost, but not quite...ChatGPT is not without its flaws!

As ChatGPT continued to generate code as I added features or asked it to move things around, errors began to creep into already established code.

For example, when stepping through the menus, I usually defined the first two characters to be a shorthand ID for that menu item, e.g. 'br' would display for the "Brightness" menu.  And I specified for ChatGPT which display segments (e.g. segments E, F G, etc.) of the first two seven-segment numbers, to turn on for each menu item that a shorthand ID .

The resulting code looked great -- and when tested, the ID characters were properly displayed on the 4-digit seven-segment display, and I continued on my way, working on a different part of the code...

Later I went back to test some function that required I first step through the menus, and I noticed that for the menus for which I had defined ID characters for the first two digits, the letters had become gobbledygook.

Somehow, while I had ChatGPT adding other features to the code, ChatGPT had decided to replace the working "letters-defined-with-segments" code to instead define the letters with Hex values that it seemed to believe represented the same segments as I had specified.

Except these Hex values did not represent those same segments, as I show, below:

Returning the code to the original "define-with-segments" code fixed the problem, but it should never have occurred in the first place.

Another issue that took me a frustrating amount of time to debug had to do with switch-case statements.

In the Menu code, ChatGPT initially defined the menu selection tree using nested if-else statements.  I much prefer to use case statements, and I requested that ChatGPT change its code do so, as you can see by the following conversation.

First, ChatGPT's original code:


Next, my request to use Case statements and ChatGPT's reply...


...and the code it generated:


Looks good and it worked as expected.

Much later, during the verification of some other code that ChatGPT had added, I needed to step through my menus to get to the appropriate item to verify.  But as I stepped through them, I could not step from the Brightness menu to the next menu item.  What was going on?

After scratching my head for awhile, I finally throw up my hands in frustration and instead queried Google's AI as to what the problem might be.  Its reply:


Aha!  I looked at ChatGPT's code again -- it had declared a variable within a Case statement (it actually had done this in two case statements), as I show below.


I moved the two declarations to the top of the sketch to make it a global variable, not local, and the problem went away.

This isn't a problem I would have had if I'd written the code myself.  I usually define most of my variables as globals and place them at the top of my code, and whenever I do define local variables, they are at the start of a function call (i.e. subroutine), rather than in-line within the body of the code.

And because it's something I wouldn't do, myself, I didn't realize that it shouldn't be done.  Thank goodness for Google.

Anyway...by this time I decided that I was spending too much time fixing ChatGPT errors and I'd be better off completing the code myself.  And so I did.

In summary...

I'd estimate that the coding effort was 90% ChatGPT and 10% me.  With ChatGPT, it took about a full day to create my first fully-featured version of the code (Rev. 1).  I'm sure it would have taken me longer if I had had to write all of the code, myself.

In my opinion, ChatGPT is an incredibly useful aid for creating code -- I avoided all the usual typos I would normally generate (and would have to find) if I had been typing the code in.

But, surprise surprise, ChatGPT can create errors -- especially frustrating was its rewriting of already working code into failing code.

Also -- there's a certain "I know it in the core of my being" sense that I get from writing my own code.  If something isn't working properly, I know right where to start looking for the cause, because I'd thought about, and written, the code.

With ChatGPT's code I don't have the same sense of familiarity.  Which means that coding errors, if they exist, could be more difficult to uncover.


Other Issues with the Clock:

Incorrect Time (Infrequent):

With my first version of code, I noticed that sometimes (very infrequently), there'd be an error in the displayed, for example, time appearing as 5:22 when it was actually a different time of day.

Could this be a problem with the Nano's software serial port somehow losing data?

The GPS receiver's baud rate had been set to 9600 baud.  I hypothesized that NMEA 0183 data might be being dropped (corrupted) by the Nano's software serial port because other software tasks might have had temporary priority in lieu of serial port reception and decoding.

So I decided to bump up the baud rate from 9600 to 38,400 baud and see if the errors still occurred.  

I've seen no errors since the modification.  That seems to have fixed the problem.

Only 4 levels of Display Brightness:

Documentation suggests (or states?) that the TM1637 displays have 8 steps of brightness (0 to 0x7).  The displays that I purchased only seem to have 4 steps (0 to 0x3), and brightness seems to be unchanged when incrementing the brightness field from 0x3 to 0x7.  So I limited the brightness adjustment range to the four steps from 0 to 3.


That's all!


Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Saturday, December 14, 2024

Do Common-mode Currents Split Equally across Circuit Conductors?

This post discusses common-mode currents in circuits, examining the commonly-held belief that a cable's common-mode currents are divided equally among the cable's conductors.  It is a companion piece to my blog post on transmission-line common-mode currents:  https://k6jca.blogspot.com/2024/12/do-common-mode-currents-split-equally.html

Introduction:

When designing electronic circuitry for products, one requirement is to ensure that any unintentionally radiated EMI (Electromagnetic Interference) is below limits set by EMC (Electromagnetic Compatibility) specifications.

Although EMI emissions can sometimes be generated by a voltage (e.g. high voltage nodes in off-line switching power supplies), in my experience EMI emissions are more often created by unintentional currents within the electronic system. These EMI-creating currents are commonly known as "common-mode currents," and they can have current-loop paths (the complete path that a current take, outbound from the source and then back again) whose encompassed-area is large, resulting in significant magnetic-field induced EMI.

On the other hand, "differential-mode" currents are currents of intentionally created signals and, if their routes are well designed, both the signal's path to its load and its return path will be in close proximity.  The loop area enclosed by the entire differential-mode current path should be small and thus magnetic-field EMI radiation from this signal minimized.

Given a two wire cable, it is commonly accepted that the differential-mode currents on such a cable will be of equal magnitude and flow in opposite directions, while common-mode currents, if they exist, will be of equal magnitude but flow in the same direction, as shown in the diagram, below (adapted from Introduction to Electromagnetic Compatibility, C. R. Paul, Wiley Interscience, NY, 1992):


But must common-mode currents across multiple conductors always be equal?


Unequal Common-mode Currents in Electronic Systems:

Below is an image (from a Murata Manufacturing Company, Ltd. document) illustrating how differential-mode and common-mode currents might exist within an electronic system.

Note that the differential-mode currents are equal in magnitude and travel in opposite directions on well-defined circuit paths.  They are driven by the "Signal Source," which is a differential-mode voltage.

In the circuit above, the "Noise Source" is a common-mode voltage.  The combination of this common-mode voltage (Vcm) and the differential-mode voltage (Vdm) would be modeled per the illustration below, such that Vcm attaches to the midpoint of Vdm, making Vdm balanced with respect to Vcm:

The circuit's common-mode currents, in this case generated by an unwanted noise voltage, travel in the same direction on the two conductors along a path that includes parasitic capacitance coupling of the load to ground.  But are these two common-mode currents equal?

In the diagram below I've added parasitic capacitances to ground at the load-end of each wire.  Note that the common-mode currents on the two wires will only be equal if the capacitances are equal -- that is, if the circuit load is balanced with respect to ground.  


Therefore, if the impedance-to-ground seen by Vcm looking into one wire is different from the impedance Vcm sees looking into the other wire, the common-mode currents will not be equal.


Analysis of the Circuit's Currents:

The following images provide a more in-depth analysis of the circuit:










So, we have shown that the equations: I1 = Ic + Id and I2 = Ic - Id (and therefore the equations Ic = (I1 + I2)/2 and Id = (I1 - I2)/2) are not always true, but instead their applicability is a function of circuit component values and the balance-about-ground of the differential-voltage driving the circuit.


Another Interesting Observation:

Recall that R3 is the load for our differential-mode signal, Vdm.  Let's examine the equation for the current through R3:


We do not want Vcm (i.e. a noise source) to corrupt the Vdm signal across R3!  To prevent this from occurring in the circuit above, R2*R4 should equal R1*R5.


SPICE Simulations:

The following SPICE simulations can give us actual values of the currents in each component.  With these currents, we can test if and when Ic = (I1 +I2)/2 and Id = (I1-I2)/2 are true.  


Note that the following values for current calculated with LTSpice are the same values as would be calculated using the equations derived with MATLAB, shown earlier in this post.

LTSpice with Balanced Vdm and Balanced Load:

In the circuit below Vdm equals 1 volt (i.e. Vdm1 = Vdm2 = 0.5V), and it is balanced with respect to ground (e.g. when Vcm is set to 0 for Vdm analysis).  That is, its midpoint is referenced to ground.

Also, the "parasitic loads to ground," R4 and R5, are of equal value and balanced with respect to ground.

To analyze the currents when driven by Vcm alone, Vdm is set to 0 (i.e. the Principle of Superposition) and the circuit simulated.

Similarly, to analyze the currents when the circuit is driven by Vdm, Vcm is set to 0 and the circuit is simulated.

Total currents are calculated with both Vdm and Vcm set to 1 volt .  Note that the total currents should equal the sum of the Vcm-driven currents plud the Vdm-driven currents.


Recall our equations Ic = (I1 + I2)/2 and Id = (I1 - I2)/2.  I1 is equal to the total current through R1, which is 0.0131 Amps.

Similarly, I2 is equal to the total current through R2, which in the circuit above is -0.0087 Amps (negative because I2 is defined to travel from left-to-right, while the current through R2 is actually traveling right-to-left).

Per the equations for Ic and Id:

     Ic = (I1 + I2)/2 = (0.0131-0.0087)/2 = 0.0022 A

     Id = (I1 - I2)/2 = (0.0131+0.0087)/2 = 0.0109 A

Note that the calculated value for Ic exactly matches the simulated values of the Vcm-driven currents through R1 and R2.

Similarly, the calculated value for Id exactly matches the simulated values of the Vdm-driven currents through R1 and R2.

Therefore, for the circuit above, the equations Ic = (I1+I2)/2 and Id = (I1-I2)/2 are TRUE.


LTSpice with Unbalanced Vdm and Balanced Load:

Now let's examine the same circuit, but with the Vdm source unbalanced (i.e. single-ended drive).  Note that the Vdm drive remains unchanged at 1V.


Calculating Ic and Id, recall that I1 = IR1 and I2 = IR2.  Using the "Total Current" values from the LTSpice simulation:

     Ic = (I1 + I2)/2 = (0.0142-0.0075)/2 = 0.0034 A

     Id = (I1 - I2)/2 = (0.0142+0.0075)/2 = 0.0109 A

If we compare these values to the values generated with LTSpice, we can easily see that the common-mode currents through R1 and R2 ae each 0.0022 A, not the calculated value of Ic = 0.0034 A.

Similarly, the circuit's Vdm-driven currents through R1 and R2 do not equal Id.  In fact, a portion of the differential-mode current travels out through the parasitic resistors R4 and R5 and takes the long way back to Vdm (i.e. via Vcm), rather than returning via R2.

Therefore, for the circuit above, the equations Ic = (I1+I2)/2 and Id = (I1-I2)/2 are FALSE.


LTSpice with Balanced Vdm and Unbalanced Load:

Finally, suppose that, with respect to ground, Vdm is balanced but the load is unbalanced -- in this case, R4 = 500 ohms and R5 = 400 ohms.


Calculating Ic and Id, recall that I1 = IR1 and I2 = IR2.  Using the "Total Current" values from the LTSpice simulation:

     Ic = (I1 + I2)/2 = (0.0128-0.0085)/2 = 2.15 mA

     Id = (I1 - I2)/2 = (0.0128+0.0085)/2 = 10.65 mA

If we compare these values to the Vcm-driven values of IR1 and IR2 generated with LTSpice, we can easily see that the common-mode currents through R1 and R2 are 2.0 and 2.5 mA, respectively, not each 2.15 mA.

Similarly, the Vdm-driven currents through R1 and R2, are also unequal.  In fact, a portion of the differential-mode current travels out through Vcm and takes the long way back to Vdm2 via the parasitic resistor R5.

Also, in this circuit we can see that a small portion of the Vcm-driven current goes through R3.  If R3 is our load for the differential-drive signal Vdm, then, if Vcm is an unwanted noise source, we have corrupted Vdm's signal across R3 with this noise.

Therefore, for the circuit above, the equations Ic = (I1+I2)/2 and Id = (I1-I2)/2 are FALSE.


Conclusions:

Although there is often an assumption that common-mode current in a cable must be equally distributed across the cable's conductors, in fact it is possible for the conductors to have different amounts of common-mode current.  Ditto for the differential-mode current.

In addition, if a circuit is not perfectly "balanced", it is possibly for a common-mode noise voltage to add unwanted noise to a differential-signal's load.


Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.