mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.1.1 WaveMix
This commit is contained in:
parent
fb3838a4b8
commit
e8cfa49171
@ -8,4 +8,6 @@ compile:
|
||||
- m4
|
||||
- esp32
|
||||
- esp8266
|
||||
# - mega2560
|
||||
# - mega2560
|
||||
libraries:
|
||||
- "DHTNEW"
|
@ -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
|
||||
|
@ -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?
|
||||
|
||||
|
||||
|
@ -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 --
|
||||
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 --
|
@ -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 --
|
@ -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 --
|
@ -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 --
|
@ -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)
|
||||
|
@ -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": "*",
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user