0.1.1 WaveMix

This commit is contained in:
rob tillaart 2022-03-26 11:33:27 +01:00
parent fb3838a4b8
commit e8cfa49171
12 changed files with 314 additions and 45 deletions

View File

@ -8,4 +8,6 @@ compile:
- m4
- esp32
- esp8266
# - mega2560
# - mega2560
libraries:
- "DHTNEW"

View File

@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.1] - 2022-03-26
### Added
- add **setGain()** and **getGain()**
- add examples
### Changed
- updated readme.md
- removed constraints on weight and percentage
### Fixed
- minor edits and clean up
## [0.1.0] - 2022-03-24
### Added

View File

@ -15,7 +15,9 @@ WaveMix is an Arduino library to mix two signals (A and B) with an adaptive weig
WaveMix is a very simple library to mix two signals (A and B) with an adaptive weight.
Depending on the weights applied the output signal (O) looks more on signal A or on signal B.
Depending on the weights applied the output signal (O) looks more on signal A or on signal B.
A gain can be applied to amplify weak signals or to be used for modulation.
Inspired by - https://www.codeproject.com/Articles/5323200/On-how-to-mix-two-signals-by-using-Spectral-Foreca
@ -24,25 +26,92 @@ Differences
- WaveMix works on streams of measurements too.
## Interface
The main functions of the WaveMix
The main functions of the WaveMix:
- **explicit WaveMix()** Constructor
- **void setWeight(float weight1, float weight2)** set the weight of the channels A and B.
The weights do not need to be normalized, so one can use e.g **setWeight(7, 13)** See below.
- **float getW1()** return the normalized weight for channel A.
- **float getW2()** return the normalized weight for channel B.
- **void setPercentage(float percentage)** sets the weight for channel A preferably to 0 <= percentage <= 100.
Channel B will have 100 - percentage.
- **void setGain(float gain)** sets the gain factor.
An important use of gain is to amplify weak signals but one can also use it as a modulator of a signal.
See examples.
- **float getGain()** return the gain set.
- **float mix(float s1, float s2 = 0)** returns the weighted average of signal1 and signal2.
Signal2 is made optional to allow single signal processes e.g. modulation by **setGain()**.
## Operation
See examples.
#### Weights
**setWeight()** typically uses positive weights, e.g. **setWeight(7, 13)**
counts A for 7/20 part and B for 13/20 part.
It is also possible to use one or two negative weights.
Using negative weights means effectively the input value is inverted before it is added.
E.g. **setWeight(-1, 0)** would effectively invert signal A.
Only restriction to the weights is that the sum of the weights may not be zero.
#### Amplification
Weights cannot be used to amplify the signal in absolute sense, use **setGain()** for that.
By constantly updating the gain (0..max) one can implement **Amplitude Modulation**.
When the gain is negative, the output is effectively inverted.
## Future ideas
#### 0.2.0
- make a N channel variant.
- modulator
- 3rd signal? ==> adjust weight runtime.
- separate modulator class?
- add gain()
- add (fixed) offset
- add increment() / decrement() ?
- percentages
- add **setValue(uint8_t channel, float value)** allow update of channels at a different frequency.
- add **getValue()**, read the current output given the value of the channels. OR
- add **getValue(uint8_t mask = 0xFF)**, read the current output given the value of selected channels.
- add **setMask(uint8_t mask = 0xFF)**, select channels. ease of use? **getValue(mask)** still needed?
- add **getMask()**, read back \_mask;
- note that **mix()** can be implemented with the above functions.
- add **setWeight(uint8_t channel, float weight)** need internal array of weights and \_sum
- add **float getWeight(uint8_t channel)**
- add constructor **WaveMix(uint8_t channels = 8)** with parameter to set the nr of channels?
- or do we need **WaveMix2()**, **WaveMix4()**, **WaveMix8()**, or even **WaveMix16()**, **WaveMix24()**, **WaveMix32()** class?
**WaveMix4()** and **WaveMix8()** seems to be realistic in terms of performance.
**WaveMix8()** can be used for 2-8 channels, using a uint8_t mask.
More channels will be much slower, so upon request the 16 and 32 variant?
#### Medium
- add **void setOffset(float)**
- add **float getOffset()**
- add top clipping
- add **setMaximum(float)**
- add **setMinimum(float)**
- performance test.
#### Low
- think of integer version
- performance
- integer weights
- math in **int32_t** with last moment float conversion
- Templated version
- float vs double vs int
- maybe upon request.
- dynamic weights
- add **increment(float)**
- add **decrement(float)**
- percentages? hard for multichannel?

View File

@ -1,8 +1,8 @@
//
// FILE: WaveMix.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: WaveMix library for Arduino
// VERSION: 0.1.1
// PURPOSE: Arduino library to mix two signals (A and B) with an adaptive weight.
// URL: https://github.com/RobTillaart/WaveMix
//
@ -12,36 +12,34 @@
WaveMix::WaveMix()
{
_w1 = 0.5;
_w2 = 0.5;
_weight[0] = 0.5;
_weight[1] = 0.5;
}
void WaveMix::setWeight(float w1, float w2)
void WaveMix::setWeight(float weight1, float weight2)
{
float t = 1.0 / (w1 + w2);
_w1 = w1 * t;
_w2 = w2 * t;
float factor = 1.0 / (weight1 + weight2);
_weight[0] = weight1 * factor;
_weight[1] = weight2 * factor;
}
void WaveMix::setPercentage(float p)
void WaveMix::setPercentage(float percentage)
{
if (p > 100) p = 100;
else if (p < 0) p = 0;
_w1 = p * 0.01;
_w2 = 1.0 - _w1;
_weight[0] = percentage * 0.01;
_weight[1] = 1.0 - _weight[0];
}
float WaveMix::mix(float s1, float s2)
{
// are these optimizations efficient?
if (_w1 == 0) return s2;
if (_w2 == 0) return s1;
return _w1 * s1 + _w2 * s2;
if (_gain == 0) return 0;
if (_weight[0] == 0) return s2 * _gain;
if (_weight[1] == 0) return s1 * _gain;
return ((_weight[0] * s1) + (_weight[1] * s2)) * _gain;
}
// -- END OF FILE --

View File

@ -2,15 +2,15 @@
//
// FILE: WaveMix.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: an Arduino library to mix two signals (A and B) with an adaptive weight.
// URL: https://github.com/RobTillaart/CountDown
// VERSION: 0.1.1
// PURPOSE: Arduino library to mix two signals (A and B) with an adaptive weight.
// URL: https://github.com/RobTillaart/WaveMix
//
#include "Arduino.h"
#define WAVEMIX_LIB_VERSION (F("0.1.0"))
#define WAVEMIX_LIB_VERSION (F("0.1.1"))
class WaveMix
@ -18,19 +18,23 @@ class WaveMix
public:
explicit WaveMix();
// w1 >= 0 && w2 >= 0 && (w1+w2) > 0
void setWeight(float w1, float w2);
float getW1() { return _w1; };
float getW2() { return _w2; };
// 0 <= p <= 100
void setPercentage(float p);
// weight1 + weight2 != 0
void setWeight(float weight1, float weight2);
float getW1() { return _weight[0]; };
float getW2() { return _weight[1]; };
// preferably 0 <= percentage <= 100
void setPercentage(float percentage);
void setGain(float gain) { _gain = gain; };
float getGain() { return _gain; };
float mix(float s1, float s2 = 0);
float mix(float s1, float s2);
private:
float _w1 = 0.5;
float _w2 = 0.5;
float _weight[2] = { 0.5, 0.5 };
float _gain = 1.0;
};

View File

@ -0,0 +1,47 @@
//
// FILE: waveMix_demo_adaptive_weight.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/WaveMix
//
// to be viewed by Serial plotter
#include "WaveMix.h"
WaveMix wm;
float n = 0;
uint8_t perc = 0;
void setup()
{
while(!Serial);
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("WAVEMIX_LIB_VERSION: ");
Serial.println(WAVEMIX_LIB_VERSION);
wm.setPercentage(perc);
}
void loop()
{
float squareWave = int(n) % 2;
Serial.println(wm.mix(sin(n), squareWave) * 100);
n = n + 0.05;
if (n > perc)
{
perc++;
if (perc == 101)
{
perc = 0;
n = 0;
}
wm.setPercentage(perc);
}
// delay(10);
}
// -- END OF FILE --

View File

@ -0,0 +1,56 @@
//
// FILE: waveMix_demo_modulator.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/WaveMix
//
// modulated sinus signal
// view with serial plotter
#include "WaveMix.h"
WaveMix wm;
float modulate = 0.30; // square wave modulate = 1.0 - dutyCyle
void setup()
{
Serial.begin(230400);
Serial.println(__FILE__);
Serial.print("WAVEMIX_LIB_VERSION: ");
Serial.println(WAVEMIX_LIB_VERSION);
wm.setWeight(95, 5); // 5% noise add.
wm.setGain(100);
}
void loop()
{
uint32_t start = millis();
float n = 0;
while (n < (2 * PI))
{
// square modulation with setGain();
if ((PI * modulate) < n && n < PI) wm.setGain(100);
else if ((PI * (1 + modulate)) < n) wm.setGain(100);
else wm.setGain(0);
// mix the signals
Serial.println(wm.mix(sin(n), random(10) * 0.1));
// stepsize determines frequency (numbers UNO)
// 0.01 => ~5 Hz
// 0.1 => ~25 Hz
n = n + 0.1;
}
n = 0;
// modulate += 0.05;
if (modulate >= 1.0) modulate = 0;
Serial.print("\t\t\t\tMILLIS:\t");
Serial.println(millis() - start);
}
// -- END OF FILE --

View File

@ -0,0 +1,35 @@
//
// FILE: waveMix_demo_modulator_2.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/WaveMix
//
// modulated sinus signal
// view with serial plotter
#include "WaveMix.h"
WaveMix wm;
float n = 0;
void setup()
{
Serial.begin(230400);
Serial.println(__FILE__);
Serial.print("WAVEMIX_LIB_VERSION: ");
Serial.println(WAVEMIX_LIB_VERSION);
wm.setWeight(1, 0);
wm.setGain(100);
}
void loop()
{
wm.setGain(100 * sin(n * 0.03)); // modulating sinus
Serial.println(wm.mix(sin(n))); // signal sinus.
n = n + 0.3;
}
// -- END OF FILE --

View File

@ -0,0 +1,39 @@
//
// FILE: waveMix_demo_temperature.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/WaveMix
//
// needs 2x DHT22 sensors
#include "WaveMix.h"
#include "dhtnew.h"
WaveMix wm;
DHTNEW living(5);
DHTNEW kitchen(6);
void setup()
{
while(!Serial);
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("WAVEMIX_LIB_VERSION: ");
Serial.println(WAVEMIX_LIB_VERSION);
wm.setPercentage(75); // inside counts for 75%
}
void loop()
{
living.read();
kitchen.read();
float mixed = wm.mix(living.getTemperature(), kitchen.getTemperature());
Serial.println(mixed);
delay(2000);
}
// -- END OF FILE --

View File

@ -6,9 +6,14 @@ WaveMix KEYWORD1
# Methods and Functions (KEYWORD2)
setWeight KEYWORD2
getW1 KEYWORD2
getW2 KEYWORD2
setPercentage KEYWORD2
mix KEYWORD2
setGain KEYWORD2
getGain KEYWORD2
mix KEYWORD2
# Constants (LITERAL1)

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/WaveMix.git"
},
"version": "0.1.0",
"version": "0.1.1",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=WaveMix
version=0.1.0
version=0.1.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library to mix two signals (A and B) with an adaptive weight.