Apr 19, 2023

Eliminate audio pops when bypass-switching

What really causes switch pop

Why a pair of switches is not enough for a clean solution. 
There are two separate problems to be addressed.

Mr. Black explains...
https://www.mrblackpedals.com/blogs/straight-jive/6629778-what-really-causes-switch-pop 

Feb 18, 2023

Add Arm Cortex Boards to Arduino 1.8.x

For boards not in the Boards Manager  

1) go to Preferences to add path of specialty boards (Arduino Feather)

https://learn.adafruit.com/add-boards-arduino-v164/installing-boards

2) Then go to boards manager and search Adafruit, Install SAMxx 32-bit boards (It will take several minutes to load)

instructions:  https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython/using-with-arduino-ide

 


Dec 2, 2022

Faster PWM DAC Using Two lower-resolution PWM Signals Added

Faster PWM DAC using parallel lower res PWM. 

Create two PWM outputs, and analog scale & sum to get result 20x faster than with a longer PWM clock interval. 

Divide by 4 to go from 8 bits to 6 bits.
Two scale to two 3-bit numbers, 
lower: & 111,  higher: >>3 & 111

The Circuit 







Reference from EDN Design Ideas by Stephen Woodward

How to do the math algebraically to down-scale:  

Divide and truncate, find remainder


The formulas






Feb 13, 2022

Gyrator theory and a Working Circuit

Lots of discussions about gyrators (synthetic inductors and filters) reference a very few of the same pages. Here are two linked articles. https://www.scribd.com/document/51284494/Gyrator-Theory
But finding an actual circuit with actual values and comments on selecting them is harder to find.

I provide this LTspice model circuit showing a circuit and a way to select reasonable values for an example.

put schematic in github...


added: thorough discussion 
 Elliott Sound Products
https://sound-au.com/articles/gyrator-filters.htm

simulated inductors
https://sound-au.com/articles/active-filters.htm#s12


Jan 7, 2022

Teensyduino Features and Techniques [Part 1]

The Teensyduino is a high-performance Arduino-compatible microcontroller family. In addition to the hardware, developer Paul Stoffregen has contributed substantially to the development of extended capabilities of the Arduino's “tailored C++” language for the Teensy family and made these capabilities compatible and usually applicable to other Arduino hardware boards. This article applies to the 32-bit Teensy 3.x and 4.x hardware.

The Teensyduino 3 (T3.2) is a standard, extremely versatile model, and is my goto choice for most hardware development. (Recent models (~2021) extend IO and peripherals (T3.5 T3.6) and faster models in similar form factors (T4.x), each with at least one tradeoff.)

Excellent combined feature suite

This combination of features are most relevant to me and distinguish it from other arduino-esque platforms:
  • Small (~ 0.8 x 1.5")
  • Fast (96 MHz)
  • Runs on 3.3V or 5V, and I/O is 5V tolerant
  • Includes a DAC 
  • 32-bit processor
  • Multiple UARTs and USB direct programming
  • Supports formatted printing including floats printf() & sprintf()
also nice:
  • real-time clock (RTC), just add 32kHz xtl on bottom
  • auto-incrementing timer variable types (elapsedMillis, elapsedMicros) [example...]

Quirks

  • 1st time it is programmed, usually requires an extra step (manual btn press to load)
  • The button is not a Reset, but rather a program Load. (There is a reset pin on bottom side of the board to which a button may be added)

Particularly useful specialty libraries

  • u8g2    (fast lib for nearly all OLED displays; includes multiple fonts)
  • TeensyStepper (very fast pulse rates, synchronous across multiple motors)
  • SoftPWM (allows PWM on any digital pin)
  • FastLed & its fast math routines (8 & 16-bit sin, cos, random)

Dec 21, 2021

Arduino IDE: setting tab indent to another value

Change default tab setting to four (4) spaces in IDE (applies to version 1.6.10 and later.)

Steps:

  1. Exit Arduino IDE. (otherwise the closing of application will overwrite preferences file.)

  2. Edit preferences.txt on two lines:

  3. editor.tabs.expand=true

    editor.tabs.size=4

    Save and exit.

  4. Create new file:

    • formatter.conf

    in your Arduino directory (in the same location as preferences.txt)

    • in windows: 
      C:\Program Files (x86)\Arduino\lib = C:\Users\{USRNAME}\AppData\Local\Arduino15

    • on mac: it's /Users/{USRNAME}/Library/Arduino15/

      Add this one line:

      indent=spaces=4
  5. Then save and relaunch.

     Tabbing and auto-formatting (^t) will indent consistently.



    References:

    Information source: (https://github.com/arduino/Arduino/issues/5012)

Aug 26, 2021

Python 3: run a script, string and number formatting

Python Language techniques

 

To run a python script from the terminal

1) create python script “cow.py”
2) Execute with
    python3 cow.py

Reference: https://howchoo.com/python/run-python-terminal

Python 3 string and number formatting: f-strings

A new, more compact and clear formatted print syntax appears in Python 3. 
  • Use the operator “f” in a print()
  • enclose variables in braces
  • Add number format modifiers after the variable, preceded by a “:”
    ex: formatting floats

        print(f'{x:5.2f}\t{y:6.2f}\t\t{z:8.2f}

f-strings: formatting large numbers with commas

Commas are often needed when formatting large numbers. The following shows the use of commas when numbers are aligned.
Example:

    number = 1000000  
    # print with comma separators  
    print(f'The number:, 1000000 {number:,.2f}')  
    # formatted with commas and right-aligned   
    print(f'The number, 1000000, in a width of 15 {number:>15,.2f}')
  
Also do... Example: The output of this code snippet is:
     TBD
?? missing


References:

https://cis.bentley.edu/sandbox/wp-content/uploads/Documentation-on-f-strings.pdf

Aug 25, 2021

Arduino: Creating asynchronous timed events auto-increment variables, the convenient elapsedMillis() function

Code snippets to demonstrate use and a clear way to name the variables.

See also the source information from the code function author Paul Stoffgren at: https://www.pjrc.com/teensy/td_timing_elaspedMillis.html

... Here’s one way to have multiple events occurring at different time intervals and not impede other functions like ADC reads and printing. It’s all based on monitoring variables that keep track of relative time (in milliseconds). You create a variable for each event you want to control, and a constant for the update interval for each thing, whether it’s reading pins, printing a message or blinking an LED. It took me a little while to grok the syntax and come up with a consistent way to name variables. It works for milliseconds or hours in the same loop. Here’s an example of what I use now in almost every program I write. The original documentation about it from the author is here.*

This is an excerpt from a program that uses a sensor to read magnetic flux and update the OLED display and the serial port. There are four functions that are accomplished at asynchronous intervals.

 . . . 
const uint16_t LED_INTERVAL  = 1000;
const uint16_t HES_INTERVAL  = 5;                   // fast rate to capture changes
const uint16_t OLED_INTERVAL = 200;
 . . .
const uint16_t status_led_flash_duration = 12;
 . . .
elapsedMillis since_msec    = 0;                        // ms to count a sec
elapsedMillis since_hes     = 0;                        // Hall-Effect magnetic sensor
elapsedMillis since_oled    = 0;
elapsedMillis since_led     = 0;

 . . .
void loop() {
 . . .
    if (since_hes >= HES_INTERVAL) {                 // make flux measurement
        since_hes = 0;

measureFlux();
    }

    if (since_oled >= OLED_INTERVAL) {               // update Gauss value on OLED screen
        since_oled = 0;

        oledUpdateValue(G);
    }

    if (since_msec >= 1000) { // each second, update the time
        since_msec = 0;

        total_sec ++;
        uint16_t sec  = total_sec % 60;
        uint16_t min  = (total_sec % 3600)/60;
        uint16_t hour = total_sec / 360

 . . .
        sprintf(msg, " %02d:%02d:%02d", hour, min, sec);// update time field on OLED   
        display.print(msg);
       
    }
}     


To do PWM, you start (set digital output high) at the beginning of each interval, and then set the pin low at time equal to the desired duty-cycle.
EX: for 33% duty cycle of 100ms period

    if (since_period >= 100) { since_period = 0; LED = ON; } 
    if (since_period == 33)  { LED = OFF; }


Aug 24, 2021

R-C Snubber: How to Calculate Values

To damp the ringing in an inductor such such as a relay or solenoid, a series R-C circuit or a diode may be added. 

R-C Snubber

(Image from Mercury Relays)


  



Diode and Zener+Diode Damping

Generally, a silicon diode across the coil opposite to direction of current flow is sufficient (shown in 1st example).

To minimize the off-switching time for a DC solenoid or relay, use a zener instead, which allows a larger voltage to exist across the coil in reverse. Adding the additional diode (as shown in the 3rd example) puts its relatively low capacitance in series with the much larger zener capacitance, thereby reducing the net value to just the C of the diode.

Experimentally I've found the optimum Vz to fall between 1x and 2x of the supply voltage. Further explanation is here on Electronics Stack Exchange, where 2x is recommended.


For power switching circuits

To reduce ringing at a node in a pulsed or switching circuit, a snubber can also be used across the switching element. A procedure to calculate values for R and C is described in this TI article by John Betten. Further discussion in this Maxim article.




The graph shows the trade-off between amount of damping and amount of power loss.


Note: To insert a formatted equation, see this LaTeX online equation editor.


Aug 8, 2021

Measuring Fast and Slow Pulses on the Teensyduino Microcontroller

I wanted to measure small frequency changes with the Teensy 3.x. I used the interrupt-driven code from user "tni" that reads the entire port for greater speed. 

I added conversion equations to display time directly in time units.
It operates to beyond 1MHz with about 0.1 or 0.2us resolution (depending on the microcontroller's speed). 

It is equally capable at very low frequencies (< 0.05Hz)-- signals with pulse widths of 30 seconds or more. (I didn't have the patience or the need to test lower frequencies.)

See original code and my additions on the PJRC.com forum here.

addendum T3.2, T3.6, usec conversion for fast pulse measurement



Jul 23, 2021

Assessing Reliability, Statistical Failure rates

MTBF: calculate series and parallel

Example: If there are two power supplies in a system, with the 2nd for redundancy, what does that do to the resulting statistical failure rate?

With each having an MTBF of 100 hrs, that's 1% chance of failure in 100 hrs.
But both is 0.01 x 0.01 = 0.01% or 10,000 hrs

See this detailed explanation below.

http://answers.google.com/answers/threadview?id=390140

Oct 3, 2020

Use a Voltage Detector to Create a Fast, Clean Input to your Microcontroller

The question was asked of how to fix a very slow-rising power supply which is causing a poor start of micro?


The basic function you're looking for is a comparator; something that looks at a change (that may be slow) and makes a quick change at a set threshold. Furthermore, most designs have some amount of hysteresis to avoid rapid on-off switching.


You can solve it by fixing the power supply or forcing the MCU to wait until the power is good.

The problem of a poor startup on circuits especially microcontrollers is a long-standing one. There is a family of inexpensive 3-terminal devices specifically for this problem from most companies. They are usually used to hold the Reset line of the processor in the Reset state until the voltage has reached stability at the desired voltage. They will often include a time-delay as well after the threshold before releasing the reset line to assure a clean start. They are called "Power On Reset" or "IC Supervisors" or "Voltage Detector" or simply "PMIC" and they are just a comparator in a transistor-looking package. For example: some devices at Digikey.

You'll see that you select the device to match the polarity of the reset, and the desired fixed voltage to switch.


Similar functions are built into many voltage regulators: it's the input for "under-voltage lockout."
If you have full control of the design you could use either of these methods to control the regulator or the MCU on the board. However, if you want to add this "after market" to an existing system, and if you can access the reset line directly, then connect drive it with one of these. 

Here's how I think I would do it.

Use the Voltage Detector as your comparator, but use its output to drive the ENable of a load switch IC; this is basically a mosfet transistor optimized for pass-through function. An example of one is an ADP1290ACBZ-R7 from analog devices. The input of the load switch is the slow supply; the output is a clean switch at V_threshold of ~ 2.8 - 3.0V.

[todo: pair with a suitable voltage divider and show circuit...]

Mar 15, 2020

solid-state relays AC, DC, and reed relays

SSR parts

*** VO2223a DC to AC (opto-coupled triac) 0.5A, Vishay

CPC1020N 30V SPST 4-Pin SOP OptoMOS® Relay. IXYS

leadless transistor pkg
PMBT3904M,315       TRANS NPN 40V 0.2A SOT883, NXP Semiconductor


reed relays can be a good choice; wide voltage; AC or DC output 0.5ms response. 

Coto or similar items

Dec 28, 2019

eeprom read/write functions

Read and write
one, four-byte variables and character strings
to eeprom in Arduino C++

Create functions for a consistent interface for single and multi-byte variable rd/wr to non-volatile ram using the EEPROM library.


// single byte read
uint8_t eepromReadByte(uint16_t addr) {              
    return EEPROM.read(addr);
}

// single byte write
void eepromWriteByte(uint16_t addr, uint8_t data) {
    EEPROM.update(addr,data);                   // "update" only writes if byte is different
}

// four-byte read
uint32_t eepromReadInt32(uint16_t addr) {
    uint32_t data = 0;
    byte b;
    for (uint8_t i = 0; i < 4; i++) {
        b = EEPROM.read(addr);
        data |= 0x000000FF & (b << 4*i);
        data |= b;
    }
    return data;
}

// four-byte write
void eepromWriteInt32(uint16_t addr, uint32_t data) {
    for (uint8_t i = 0; i < 4; i++) {
        uint8_t aByte = 0x000000FF & (data >> 4*i);
        EEPROM.update(addr+i,aByte); 
    }
}

// write character array 
void eepromWriteChars(uint16_t addr, char str[16], byte num_chars) {
    for (byte i=0; i<num_chars; i++) {
        EEPROM.update(addr+i,str[i]);    
    }
}

Usage:

     eepromWriteByte(ADDR_COUNTDOWN_SECONDS,g_secords);

Initialize EEprom memory: 

Test if memory has been written to;
if yes, read values; else write default values


// update eeprom values
int init_marker = 42;
    if (eepromReadByte(ADDR_EEPROM_INIT) == init_marker) {   // some unique value
        readCountdownIntervalFromEEprom();
    }
    else    {   // first-time init
        eepromWriteByte(ADDR_EEPROM_INIT,  init_marker);
        writeCountdownIntervalToEEprom();   // write defaults
    }
 

Nov 13, 2019

function to increment/decrement and cycle through a range

Cycle through values in C++/Arduino



Increment or decrement by an integer value, (normally +1 or -1)  but cycle between min and max constraints. Test code at gitHub

        EX: dec by -1    4  3  2  1    4  3  2  1
            inc by +2   -4 -2  0  2   -4 -2  0  2


int16_t cycleIncDec(int16_t x, int16_t dir, int16_t xmin, int16_t xmax) {

    // inc/dec with constrained range

    // supplied xmax must be greater than xmin

    x += dir;

    if      (x > xmax) x = xmin;

    else if (x < xmin) x = xmax;

    return x;

}

Sep 24, 2019

modify formatting settings in Visual Studio Code

To change formatting preferences, in particular, to put leading brace on the same line, use the folling.

To modify code formatting settings in vsc,

search C_Cpp.clang_format_fallbackStyle

add the follwing to User tab

Change the default
from   Visual Studio
to       {BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0, SpacesBeforeTrailingComments: 8}

I found this info at:
https://stackoverflow.com/questions/46111834/format-curly-braces-on-same-line-in-c-vscode

and  more at
https://medium.com/@zamhuang/vscode-how-to-customize-c-s-coding-style-in-vscode-ad16d87e93bf

Sep 7, 2019

getting filename and path of current program [arduino]

Capture and extract the filename and path for the current file within an Arduino program. 

There are a few variables available at compile time including compile time and date. The filename is also available and supplied with its full path. The code below shows a way to separate them into String variables.

Code:


/* get the file name and path of this program */

const char this_file[] PROGMEM = __FILE__;          // provided by system
const String file_and_path = String(this_file);     // convert to a String

int n = file_and_path.length();
int i = file_and_path.lastIndexOf("\\") + 1;        // escaped backslash for Windows paths
String filename = file_and_path.substring(i,n);     // from last '\' to end
String filepath = file_and_path.substring(0,i);     // from begin to last '\'


void setup()  {
    Serial.begin(115200);
    while (!Serial) {}

    Serial.println(file_and_path);
    Serial.println(filepath);
    Serial.println(filename);
}


void loop() {
   
}


Output:


C:\Users\david1\Desktop\test\test.ino
C:\Users\david1\Desktop\test\

test.ino
 


Jul 26, 2019

mapFloat(): Arduino's map() function extended to allow float variables

A function to extend range mapping to float/double variables.


// map one numerical span to another with floating point values
double mapFloat (double x, double in_min, double in_max, double out_min, double out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

EX:  map an ADC range to normalized decimal:

    x_norm = mapFloat(adc_val, 0, 4095,  0.00, 1.00);



Feb 13, 2019

Using hobbytronics USB Flash Drive breakout board with Arduino

To log data from a test system running a microcontroller, I found a flash drive reader (only) from Hobbytronics.  https://www.hobbytronics.co.uk/usb-host-flash-drive  I used the smaller "mini" version.

To get the device to write to a file from demo code (first example at btm of pg) seemed to work ok.
To send a command and read back responses, some hours of testing and several modifications were needed for my configuration to work.

Things to check first:

  • Is the baud rate to the USB Drive Host board set to default of 9600 to start?
  • Is the Tx of the board connected to the Rx of the MCU and vice versa?
  • Are command strings terminated with a Serial1.write(13) or '\r' ?

The example uses softwareSerial library. I used a hardware port, preferred if available. (Serial1 on Teensyduino 3.x)

If no response comes from your command, you'll need additional delay. I had to add time after the command, and a time between each character sent. In the example code, a while(!Serial.available()) is used to wait until the first character starts.

While troubleshooting, I connected directly to the board from a TTL-to-USB interface to TeraTerm terminal program. Once the first 3 items above were correct, Commands (such as DATE, CD, DIR) worked just fine.

By adding:

  •    delay(100) after each sent command
  •    adding a delay(1) before each character read in the while loop, 

...

sprintf(mystring,"$TIME \r");
mySerial.write(mystring);
delay(100);   // ***
getFromFlash();

...

}


void getFromFlash() {
    char c;
    // Hang out here
    while(!mySerial.available());        // Wait for data to be returned

    // loop waiting for a character for each line separately
    // Read and display contents of line returned
    while (mySerial.available() > 0) {
        c = mySerial.read();
        delay(1);   // ***
        Serial.write(c);
    }
    if (c != '\r' && c != '\n') {
        // Serial.write(13);
        Serial.write(10);
    }
}

Other notes


asdf

Aug 30, 2017

When can adding noise increase signal resolution?

Did you know that there are cases where you can add noise to your signal to get more resolution? It is referred to as dithering and works well, provided a few conditions are true in your system. (This explanation assumes you understand averaging/filtering to smooth data and what an analog-to-digital converter does.)
  • If there is time to average multiple samples
  • If the signal is quiet relative to ADC resolution
  • If there is a way to generate and combine a noise source with signal before the ADC sampling.
Here's an example.
Your system consists of a temperature sensor providing a voltage output proportional to temperature in degrees. Its output is connected to the microcontroller's ADC input. Actual voltage for eight successive measurements is
   22.4  22.4  22.5  22.4  22.3  22.4  22.4  22.4
The ADC is 8 bits, accurate to << 1 LSB, and has a 2.56V reference. So each bit = 10mV. The temperature is fairly steady moving slowly in the lab, hovering at 22.4C. The voltage is 224mV. What does the ADC measure? It would truncate to its resolution and read:
   22    22    22    22    22    22    22    22 
Clearly averaging would not improve the value because the actual values are always between 1 LSB (either 22 or 23 in this case).

Now suppose I add a random value of  one bit (1 LSB)
   22.4  22.4  22.5  22.4  22.3  22.4  22.4  22.4    
+   0.0   1.0   0.0   0.0   1.0   0.0   1.0   0.0
----------------------------------------------------- 
   22.4  23.4  22.5  22.4  23.3  22.4  23.4  22.4    
The ADC would read these (again truncating) as:
   22    23    22    22    22    23    23    23     avg = 22.5
So eight measurements will have some 22 and some 23, with the ratio close to the fractional value. In this example I only used values of 0 or 1, but a wider range of values between and shaping the noise distribution can further improve the estimate.
The smoothed value (purple) of the noisy samples (green) is closer to the actual value (blue).

In practice, any random or pseudorandom source will work. 4x oversampling is enough to get a benefit, and 8 or 10 is quite good. If the signal is noisy more than 1-2 LSB (as it usually is), then there is no benefit to adding noise. Just average as you would normally to get better effective resolution.

Here's another description at electronics.stackexchange.com.

Aug 29, 2017

The Sigmoid or Logistic Function

A function to smoothly transition from one level to another. It can't be done with polynomial fit. When it's what you need, nothing else will do.

See https://en.wikipedia.org/wiki/Logistic_function

Aug 23, 2017

Markdown editor uses split-screen web page for real-time rendering

Github-Flavored Markdown (GFM) supports embedded code formats

Web-based editor is correct and displays instantly.
https://jbt.github.io/markdown-editor/

References this comprehensive suite of code syntax highlighting languages and styles https://highlightjs.org/

Lag filter for control systems, calculating the filtering constant k

This article clarifies each parameter that goes into filter design, and provides an analytical solution to calculate k value. Site of Jeff Steidl.

This is the same equation as that for an exponential smoothing filter which is a highly useful and low-computation smoothing technique similar to, but generally better than, an N-point average. A starting point for k is 0.5, which is roughly equal to a 4-point average.]

The formula for a first order lag filter is fairly simple:
new_filtered_value = k * raw_sensor_value + (1 - k) * old_filtered_value
The "magic" is determining an approprate value for k.

Calculate k

To calculate k, enter Tr, Ts and Frac from above into the following equation:
k = 1 - eln(1 - Frac) * Ts / Tr
For details, see http://my.execpc.com/~steidl/robotics/first_order_lag_filter.html


Aug 17, 2017

additional high quality random numbers xoroshiro128+

About generating and assessing quality random numbers


MT Mersenne Twister





Aug 9, 2017

transistor noise generator circuit with lots of gain

Noise generator circuit


http://www.eeweb.com/blog/extreme_circuits/simple-white-noise-generator



application: add a passive summer to include dither to small sensor signal before quantizing

application: characterize a filter

Aug 2, 2017

Bayesian weighted probabilities

Here's a good synopsis by Jim Stone: CH 1 of Bayes Rules
He provides software links as well.

Another look on wikipedia for Bayes' Theorem. Thomas Bayes worked this out around 1740.

Jun 22, 2017

output a data stream to screen and a file using tee

In linux, process an incoming serial data stream (from program a.out) which appears on screen (stdout) and route to a file at the same time.
./a.out | tee > logfile.txt
It is not smooth, as the terminal is buffering data. To change that, use 
unbuffer ./a.out | tee > logfile.txt
To use unbuffer, you must install the "expect" package*


References

https://stackoverflow.com/questions/11337041/force-line-buffering-of-stdout-when-piping-to-tee 

*to get it on Mac unix, the package installer recommended is homebrew.
1) install homebrew if you don't have it.
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 
2) Search for the desired package "expect"
brew search expect
 3) it's found, so install it.
brew install expect

Add comma separators to large numbers

It was hard to read a column of large numbers, so here's a function to add the commas. It is implemented in liveCode.


// make big integers readable by adding commas 
function addCommas z delim
  -- 4567 -> 4,567
  -- TTD make for for floats
  -- include option for european or other delimiter "."
  if delim is empty then put "," into delim
  put the number of chars of z into N
  put trunc((N - .01) / 3) into numCommas
  if numCommas > 0 then
    repeat with j = 1 to numCommas
      put delim before char (N - (j*3) + 1) of word 1 of z
    end repeat
  end if
  return z    -- z has been modified to contain commas
end addCommas

Use:

put addCommas(11456789)

Returns:

11,456,789

Long example:

on mouseUp
  put "" into fld "out1"
  repeat with i = 1 to 20
    put fibonacciNumber(i+31) into n  -- make big numbers
    put addCommas(n) into line i of fld out1
  end repeat
end mouseUp

// Returns the number at 1-based index pIndex >= 2 in the Fibonacci sequence
function fibonacciNumber pIndex
  local tFirst = 1, tSecond = 1
  local tCounter, tSum
  repeat with tCounter = 3 to pIndex
     put tFirst + tSecond into tSum
     put tSecond into tFirst
     put tSum into tSecond
  end repeat
  return tSecond
end fibonacciNumber

// make big integers readable by adding commas 
function addCommas z delim
  -- 4567 -> 4,567
  -- TTD make for for floats
  -- include option for european or other delimiter "."
  if delim is empty then put "," into delim
  put the number of chars of z into N
  put trunc((N - .01) / 3) into numCommas
  if numCommas > 0 then
    repeat with j = 1 to numCommas
      put delim before char (N - (j*3) + 1) of word 1 of z
    end repeat
  end if
  return z    -- z has been modified to contain commas
end addCommas

(find in livecode related ds/fibonacci_random_commas.livecode)

Dec 11, 2016

Arduino 3 & 5 point running median

Functions for fast 3-point and 5-point median filter, for either integer or float/double var types.
Example shows random data stream with real-time running median filtering.


 Snippet   (Full current code on github at https://github.com/davidsmith99/median )

// the function (calls another function 'swap()' not shown here
double median3( double a0, double a1, double a2 ) {
  swap(&a1, &a2); // swaps values  if arg1 > arg2
  swap(&a0, &a2);
  swap(&a0, &a1);

  return a1; // median value

}

//using in a loop
void loop() {
  // generate random data with outliers to observe median filtering

  // use 3 most recent values
  // drop val_prev2 value and update the latest value
  fval_prev2 = fval_prev1;
  fval_prev1 = fval_new;
  fval_new = 0.99 * (10 + random(-2, 8) + (random(0, 4) == 0) * 4 * (random(0, 5))); // small variation plus occasional spikes

 double fmedian = median3(fval_prev2, fval_prev1, fval_new);

 Serial.print(fval_new); Serial.print("\t");
 Serial.print(fmedian);  Serial.print("\n");
 delay(200);
}

Other related links:

http://playground.arduino.cc/Main/RunningMedian

reference on function overloading c++
http://www.programmingsimplified.com/cpp/source-code/cpp-function-overloading-example-program

Nov 21, 2016

Scan for I2C Devices on Bus [arduino function]

Update in 2018:
Here's a much shorter version of this as a function call (no args, no return value). Maintained on github here.


void i2cScan() {
    Serial.println ("\ni2cScan...\n");
    static int count = 0;

    Wire.begin();
    for (int i = 8; i < 120; i++)
    {
        Wire.beginTransmission(i);          // probe this i2c address
        if (Wire.endTransmission() == 0)
        {
            Serial.print ("  device at: 0x" + String(i, HEX) + "  [" + String(i) + "] \n");            count++;
            delay (1);
        }
    }
    Serial.print("\nTotal devices:  " + String(count) + "\n");
}


Updated a diagnostic script to be a function with optional outputs [Arduino]

n = i2cScan(0);   // prints nothing; returns 0|1 for successful read of at least one device

n = i2cScan(1);  // prints address of successfully read devices (arg of 2 prints result of every address)

output:
I2C device at 0x19     25
I2C device at 0x1E     30
I2C device at 0x3C     60
I2C device at 0x40     64
I2C device at 0x6B     107
I2C device at 0x77     119
6 devices found.



code:


// --------------------------------------------------
int i2cScan(int printFlag) {
  int nDevices = 0;
  int error = 0;

  for (int address = 1; address < 127; address++ ) {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      if (printFlag > 0) {
        Serial.print("I2C device at 0x");
        if (address < 0x10) Serial.print("0");  // leading zero
        Serial.print(address, HEX);
        Serial.print("\t "); Serial.println(address); // dec
      }
      nDevices++;
    }
    else if (error > 0 && error != 99) {     // 2 = no device
      if (printFlag == 2) {
        Serial.print("   Error:"); Serial.print(error); Serial.print(" at 0x");
        if (address < 0x10) Serial.print("0");   // leading zero
        Serial.print(address, HEX);
        Serial.print("\t "); Serial.println(address); // dec
      }
    }
  }
  if (nDevices == 0) {
    if (printFlag > 0)  Serial.println("No devices found.\n");
  }
  else {
    if (printFlag > 0) {
      Serial.print(nDevices); Serial.println(" devices found.\n");
    }
  }
  return (nDevices == 0); // 0 for no errors and at least one device;
}


More info about i2c at http://www.gammon.com.au/i2c

Oct 31, 2016

printBits() prints formatted binary numbers, Arduino code


When diagnosing embedded code, it's often convenient to see the individual bits of a variable. There is no formatting function for this in C. Wiring does have an option to format as BIN, but I wanted to see leading zeros and separate long numbers with spaces.

Here is a routine to print an integer variable in a formatted binary format including leading 0s. 
Would work with C/C++ if print command is changed appropriately.


// prints N-bit integer in this form: 0000 0000 0000 0000
// works for 4 - 32 bits
// accepts signed numbers
void printBits(long int n) {
  byte numBits = 16;  // 2^numBits must be big enough to include the number n
  char b;
  char c = ' ';   // delimiter character
  for (byte i = 0; i < numBits; i++) {
    // shift 1 and mask to identify each bit value
    b = (n & (1 << (numBits - 1 - i))) > 0 ? '1' : '0'; // slightly faster to print chars than ints (saves conversion)
    Serial.print(b);
    if (i < (numBits - 1) && ((numBits-i - 1) % 4 == 0 )) Serial.print(c); // print a separator at every 4 bits
  }
}


(latest at gitHub.)   

Example usage with the number of bits set to 16.

 printBits(0x51f);   0000 0101 0001 1111

 printBits(-1);      1111 1111 1111 1111

 int k = 65;
 printBits(k);       0000 0000 0100 0001
 

Example with the number of bits set to 10 and delimiter set to a period.

printBits(0x2A5);           10.1010.0101


A nicely implemented conversion calculator is here. http://www.binaryconvert.com/

Additional solutions are at stackoverflow.com

  

Aug 1, 2016

Consistent system for software versioning [SemVer]

Semver.org Summary 2.0.0

Given a version number MAJOR.MINOR.PATCH, increment the:
  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
http://semver.org


Multi layer air core inductor calculator

www.circuits.dk




http://www.circuits.dk/calculator_multi_layer_aircore.htm





LC filter web design tool

passive LC filter design, Tee and Pi

http://www.wa4dsy.net/filter/filterdesign.html



Mar 15, 2016

Lua language is basis for a nice parser in Arduino

Information about: Lua (Wikipedia) and at the official site: http://www.lua.org
A script language to extend other languages, in particular C and its derivatives.
A sensible grammar and syntax.

Re-discovered while looking into string parsing. Nick Gammon has made a nice extension library for arduino using a lua syntax.