mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
update libraries R-Z
This commit is contained in:
parent
9abe1508b1
commit
72861821fc
21
libraries/Radar/LICENSE
Normal file
21
libraries/Radar/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,17 +1,14 @@
|
||||
//
|
||||
// FILE: radarDemo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.00
|
||||
// PURPOSE:
|
||||
// DATE:
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo of the radar library
|
||||
// DATE: 29-03-2015
|
||||
// URL: https://github.com/RobTillaart/RADAR
|
||||
|
||||
#include "radar.h"
|
||||
|
||||
uint32_t del = 250;
|
||||
uint32_t del = 150;
|
||||
|
||||
RADAR radar(10, 11);
|
||||
|
||||
@ -22,36 +19,71 @@ void setup()
|
||||
Serial.println(RADAR_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
|
||||
gohome();
|
||||
Serial.println();
|
||||
Serial.print(millis());
|
||||
Serial.println("\tdone...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
void test1()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t1. home position");
|
||||
radar.setHomePosition(0, 0);
|
||||
radar.gotoHomePosition();
|
||||
wait();
|
||||
}
|
||||
|
||||
void test2()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t2. gotoPan 20");
|
||||
radar.gotoPan(20);
|
||||
wait();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void test3()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t3. gotoTilt 60");
|
||||
radar.gotoTilt(60);
|
||||
wait();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void test4()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t4. gotoPanTilt 60 20");
|
||||
radar.gotoPanTilt(60, 20);
|
||||
wait();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void test5()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t5. home position");
|
||||
radar.gotoHomePosition();
|
||||
wait();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void test6()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t6. setPosition");
|
||||
for (int i = 0; i < 10; i++)
|
||||
@ -59,14 +91,17 @@ void setup()
|
||||
radar.setPosition(i, random(90), random(90));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void test7()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t7. gotoPosition");
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
radar.gotoPosition(i);
|
||||
int p, t;
|
||||
radar.getPosition(i, &p, &t);
|
||||
int16_t p, t;
|
||||
radar.getPosition(i, p, t);
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.print(i);
|
||||
@ -78,32 +113,34 @@ void setup()
|
||||
wait();
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
void gohome()
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println("\t8. home position");
|
||||
Serial.println("\tgo home position");
|
||||
radar.gotoHomePosition();
|
||||
wait();
|
||||
Serial.println();
|
||||
|
||||
Serial.println();
|
||||
Serial.print(millis());
|
||||
Serial.println("\tdone...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
Serial.println("\nTIME\t\tPAN\tTILT");
|
||||
do
|
||||
{
|
||||
int p = radar.getPan();
|
||||
int t = radar.getTilt();
|
||||
Serial.print(millis());
|
||||
Serial.print("\t*\t");
|
||||
Serial.print(p);
|
||||
Serial.print(radar.getPan());
|
||||
Serial.print("\t");
|
||||
Serial.println(t);
|
||||
Serial.println(radar.getTilt());
|
||||
delay(del);
|
||||
} while (radar.isMoving());
|
||||
Serial.print(millis());
|
||||
Serial.print("\t*\t");
|
||||
Serial.print(radar.getPan());
|
||||
Serial.print("\t");
|
||||
Serial.println(radar.getTilt());
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Radar",
|
||||
"keywords": "Pan,tilt,radar",
|
||||
"description": "Experimental library for a pan tilt radar.",
|
||||
"name": "RADAR",
|
||||
"keywords": "Pan,tilt,radar,ping",
|
||||
"description": "Arduino library for a pan tilt radar. Experimental",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/RADAR"
|
||||
},
|
||||
"version":"0.1.1",
|
||||
"version":"0.1.3",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/Radar"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Radar
|
||||
version=0.1.1
|
||||
name=RADAR
|
||||
version=0.1.3
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Experimental library for a pan tilt radar.
|
||||
paragraph=
|
||||
category=Device
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
sentence=Arduino library for a pan tilt radar.
|
||||
paragraph=Experimental
|
||||
category=Uncategorized
|
||||
url=https://github.com/RobTillaart/RADAR
|
||||
architectures=*
|
||||
includes=radar.h
|
||||
depends=
|
||||
|
@ -1,14 +1,14 @@
|
||||
//
|
||||
// FILE: radar.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.01
|
||||
// PURPOSE: demo pan tilt radar framework
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
// VERSION: 0.1.3
|
||||
// PURPOSE: Arduino library for a pan tilt radar.
|
||||
// URL: https://github.com/RobTillaart/RADAR
|
||||
//
|
||||
// 0.1.00 - 2013-09-30 (?) outline
|
||||
// 0.1.01 - 2015-03-06 updated some code, still not functional
|
||||
// 0.1.2 - 2017-07-16 refactor & review
|
||||
// 0.1.3 2020-07-06 refactor, clean up and some documentation
|
||||
|
||||
#include "radar.h"
|
||||
|
||||
@ -16,111 +16,124 @@
|
||||
//
|
||||
// CONSTRUCTOR
|
||||
//
|
||||
RADAR::RADAR(uint8_t pinPan, uint8_t pinTilt)
|
||||
RADAR::RADAR(const uint8_t pinPan, const uint8_t pinTilt)
|
||||
{
|
||||
_pinPan = pinPan;
|
||||
_pinTilt = pinTilt;
|
||||
_homePan = 0;
|
||||
_homeTilt = 0;
|
||||
_pan = _prevPan = 0;
|
||||
_tilt = _prevTilt = 0;
|
||||
_lastPanTime = _lastTiltTime = millis();
|
||||
|
||||
_pinPan = pinPan;
|
||||
_pinTilt = pinTilt;
|
||||
_homePan = 0;
|
||||
_homeTilt = 0;
|
||||
_pan = _prevPan = 0;
|
||||
_tilt = _prevTilt = 0;
|
||||
_panPerSecond = 15;
|
||||
_tiltPerSecond = 15;
|
||||
_lastPanTime = _lastTiltTime = millis();
|
||||
for (uint8_t i = 0; i < RADAR_POSITIONS; i++)
|
||||
{
|
||||
_panArray[i] = 0;
|
||||
_tiltArray[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// PUBLIC
|
||||
void RADAR::gotoPan(int pan)
|
||||
void RADAR::gotoPan(const int16_t pan)
|
||||
{
|
||||
if (pan == _pan) return;
|
||||
_prevPan = getPan();
|
||||
_pan = pan;
|
||||
analogWrite(_pinPan, _pan);
|
||||
_lastPanTime = millis();
|
||||
if (pan == _pan) return;
|
||||
_prevPan = getPan();
|
||||
_pan = pan;
|
||||
analogWrite(_pinPan, _pan);
|
||||
_lastPanTime = millis();
|
||||
}
|
||||
|
||||
int RADAR::getPan()
|
||||
int16_t RADAR::getPan()
|
||||
{
|
||||
// ESTIMATE current position on time it takes to go from previous to new
|
||||
if (_pan == _prevPan) return _pan;
|
||||
// if (enough time passed to move to new position) return new position
|
||||
unsigned long duration = millis() - _lastPanTime;
|
||||
if ( abs(_pan - _prevPan) <= (duration * PAN_PER_SEC)/1000UL) return _pan;
|
||||
// else estimate by linear interpolation
|
||||
if (_pan > _prevPan) return _prevPan + (duration * PAN_PER_SEC)/1000UL;
|
||||
return _prevPan - (duration * PAN_PER_SEC)/1000UL;
|
||||
// ESTIMATE current position on time it takes to go from previous to new
|
||||
if (_pan == _prevPan) return _pan;
|
||||
|
||||
// if (enough time passed to move to new position) return new position
|
||||
uint32_t duration = millis() - _lastPanTime;
|
||||
uint32_t movement = round(duration * _panPerSecond * 0.001);
|
||||
if ( abs(_pan - _prevPan) <= movement) return _pan;
|
||||
|
||||
// else estimate PAN by linear interpolation
|
||||
if (_pan > _prevPan) return _prevPan + movement;
|
||||
return _prevPan - movement;
|
||||
}
|
||||
|
||||
void RADAR::gotoTilt(int tilt)
|
||||
void RADAR::gotoTilt(const int16_t tilt)
|
||||
{
|
||||
if (tilt == _tilt) return;
|
||||
_prevTilt = getTilt();
|
||||
_tilt = tilt;
|
||||
analogWrite(_pinTilt, _tilt);
|
||||
_lastTiltTime = millis();
|
||||
if (tilt == _tilt) return;
|
||||
|
||||
_prevTilt = getTilt();
|
||||
_tilt = tilt;
|
||||
analogWrite(_pinTilt, _tilt); // 0..180
|
||||
_lastTiltTime = millis();
|
||||
}
|
||||
|
||||
int RADAR::getTilt()
|
||||
int16_t RADAR::getTilt()
|
||||
{
|
||||
// comments see getPan()
|
||||
if (_tilt == _prevTilt) return _tilt;
|
||||
unsigned long duration = millis() - _lastTiltTime;
|
||||
if (abs(_tilt - _prevTilt) <= (duration * TILT_PER_SEC)/1000UL) return _tilt;
|
||||
if (_tilt > _prevTilt) return _prevTilt + (duration * TILT_PER_SEC)/1000UL;
|
||||
return _prevTilt - (duration * TILT_PER_SEC)/1000UL;
|
||||
// ESTIMATE current position on time it takes to go from previous to new
|
||||
if (_tilt == _prevTilt) return _tilt;
|
||||
|
||||
// if (enough time passed to move to new position) return new position
|
||||
uint32_t duration = millis() - _lastTiltTime;
|
||||
uint32_t movement = round(duration * _tiltPerSecond * 0.001);
|
||||
if (abs(_tilt - _prevTilt) <= movement) return _tilt;
|
||||
|
||||
// estimate TILT by linear interpolation
|
||||
if (_tilt > _prevTilt) return _prevTilt + movement;
|
||||
return _prevTilt - movement;
|
||||
}
|
||||
|
||||
void RADAR::gotoPanTilt(int pan, int tilt)
|
||||
void RADAR::gotoPanTilt(const int16_t pan, const int16_t tilt)
|
||||
{
|
||||
gotoPan(pan);
|
||||
gotoTilt(tilt);
|
||||
gotoPan(pan);
|
||||
gotoTilt(tilt);
|
||||
}
|
||||
|
||||
void RADAR::setPosition(uint8_t n, int pan, int tilt)
|
||||
bool RADAR::setPosition(const uint8_t n, const int16_t pan, const int16_t tilt)
|
||||
{
|
||||
_parray[n] = pan;
|
||||
_tarry[n] = tilt;
|
||||
if (n >= RADAR_POSITIONS) return false;
|
||||
_panArray[n] = pan;
|
||||
_tiltArray[n] = tilt;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RADAR::getPosition(uint8_t n, int *pan, int *tilt)
|
||||
bool RADAR::getPosition(const uint8_t n, int16_t & pan, int16_t & tilt)
|
||||
{
|
||||
if (n > 10) return false;
|
||||
*pan = _parray[n];
|
||||
*tilt = _tarry[n];
|
||||
return true;
|
||||
if (n >= RADAR_POSITIONS) return false;
|
||||
pan = _panArray[n];
|
||||
tilt = _tiltArray[n];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RADAR::gotoPosition(uint8_t n)
|
||||
bool RADAR::gotoPosition(const uint8_t n)
|
||||
{
|
||||
if (n > 10) return false;
|
||||
gotoPan(_parray[n]);
|
||||
gotoTilt(_tarry[n]);
|
||||
return true;
|
||||
if (n >= RADAR_POSITIONS) return false;
|
||||
gotoPan(_panArray[n]);
|
||||
gotoTilt(_tiltArray[n]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RADAR::setHomePosition(int pan, int tilt)
|
||||
void RADAR::setHomePosition(const int16_t pan, const int16_t tilt)
|
||||
{
|
||||
_homePan = pan;
|
||||
_homeTilt = tilt;
|
||||
_homePan = pan;
|
||||
_homeTilt = tilt;
|
||||
}
|
||||
|
||||
void RADAR::gotoHomePosition()
|
||||
{
|
||||
gotoPan(_homePan);
|
||||
gotoTilt(_homeTilt);
|
||||
gotoPan(_homePan);
|
||||
gotoTilt(_homeTilt);
|
||||
}
|
||||
|
||||
bool RADAR::isMoving()
|
||||
{
|
||||
return ((getPan() != _pan) || (getTilt() != _tilt));
|
||||
}
|
||||
|
||||
unsigned long RADAR::ping()
|
||||
uint32_t RADAR::ping()
|
||||
{
|
||||
// TODO ping code here - playground or teckel's improved ping)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long RADAR::ping(int pan, int tilt)
|
||||
uint32_t RADAR::ping(const int16_t pan, const int16_t tilt)
|
||||
{
|
||||
gotoPan(pan);
|
||||
gotoTilt(tilt);
|
||||
|
@ -1,68 +1,72 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: radar.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: see RADAR_LIB_VERSION
|
||||
// PURPOSE: pan tilt radar framework
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// PURPOSE: Arduino library for a pan tilt radar.
|
||||
// URL: https://github.com/RobTillaart/RADAR
|
||||
|
||||
#ifndef Radar_h
|
||||
#define Radar_h
|
||||
#include "Arduino.h"
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#define RADAR_LIB_VERSION "0.1.3"
|
||||
|
||||
#ifndef RADAR_POSITIONS
|
||||
#define RADAR_POSITIONS 10
|
||||
#endif
|
||||
|
||||
#define RADAR_LIB_VERSION "0.1.01"
|
||||
|
||||
#define PAN_PER_SEC 25 // TODO determine emperically
|
||||
#define TILT_PER_SEC 25 // TODO determine emperically
|
||||
|
||||
class RADAR
|
||||
{
|
||||
public:
|
||||
RADAR(uint8_t, uint8_t);
|
||||
public:
|
||||
RADAR(const uint8_t, const uint8_t);
|
||||
|
||||
void gotoPan(int pan);
|
||||
int getPan();
|
||||
void gotoTilt(int tilt);
|
||||
int getTilt();
|
||||
void gotoPanTilt(int pan, int tilt);
|
||||
// no valid range checking or negative value check.
|
||||
void setPanPerSecond(float pps) { _panPerSecond = pps; };
|
||||
float getPanPerSecond() { return _panPerSecond; };
|
||||
void setTiltPerSecond(float tps) { _tiltPerSecond = tps; };
|
||||
float getTiltPerSecond() { return _tiltPerSecond; };
|
||||
|
||||
// memory positions
|
||||
void setPosition(uint8_t idx, int pan, int tilt);
|
||||
bool getPosition(uint8_t idx, int *pan, int *tilt);
|
||||
bool gotoPosition(uint8_t idx);
|
||||
void setHomePosition(int pan, int tilt);
|
||||
void gotoHomePosition();
|
||||
// basic moves
|
||||
void gotoPan(const int16_t pan);
|
||||
int16_t getPan();
|
||||
void gotoTilt(const int16_t tilt);
|
||||
int16_t getTilt();
|
||||
void gotoPanTilt(const int16_t pan, const int16_t tilt);
|
||||
|
||||
//
|
||||
bool isMoving();
|
||||
// memory positions - store / recall?
|
||||
uint8_t getMaxPositions() { return RADAR_POSITIONS; };
|
||||
bool setPosition(const uint8_t idx, const int16_t pan, const int16_t tilt);
|
||||
bool getPosition(const uint8_t idx, int16_t & pan, int16_t & tilt);
|
||||
bool gotoPosition(const uint8_t idx);
|
||||
void setHomePosition(const int16_t pan, const int16_t tilt);
|
||||
void gotoHomePosition();
|
||||
|
||||
unsigned long ping();
|
||||
unsigned long ping(int pan, int tilt);
|
||||
// feedback on positions.
|
||||
bool isMoving() { return isPanMoving() || isTiltMoving(); };
|
||||
bool isPanMoving() { return getPan() != _pan; };
|
||||
bool isTiltMoving() { return getTilt() != _tilt; };
|
||||
|
||||
uint32_t ping();
|
||||
uint32_t ping(const int16_t pan, const int16_t tilt);
|
||||
|
||||
private:
|
||||
int _pinPan;
|
||||
int _pinTilt;
|
||||
private:
|
||||
int16_t _pinPan;
|
||||
int16_t _pinTilt;
|
||||
|
||||
int _prevPan;
|
||||
int _pan;
|
||||
int _homePan;
|
||||
unsigned long _lastPanTime;
|
||||
int16_t _prevPan;
|
||||
int16_t _pan;
|
||||
int16_t _homePan;
|
||||
uint32_t _lastPanTime;
|
||||
|
||||
int _prevTilt;
|
||||
int _tilt;
|
||||
int _homeTilt;
|
||||
unsigned long _lastTiltTime;
|
||||
int16_t _prevTilt;
|
||||
int16_t _tilt;
|
||||
int16_t _homeTilt;
|
||||
uint32_t _lastTiltTime;
|
||||
|
||||
int _parray[10];
|
||||
int _tarry[10];
|
||||
int16_t _panArray[RADAR_POSITIONS];
|
||||
int16_t _tiltArray[RADAR_POSITIONS];
|
||||
|
||||
float _panPerSecond = 15;
|
||||
float _tiltPerSecond = 15;
|
||||
};
|
||||
|
||||
#endif
|
||||
// -- END OF FILE --
|
@ -1,12 +1,43 @@
|
||||
|
||||
WARNING: not working version !!!
|
||||
# Radar
|
||||
|
||||
Arduino library for a pan tilt radar based upon 2 servo's.
|
||||
|
||||
## Warning
|
||||
**WARNING: not extensively tested**
|
||||
There are stil a lot of things to be tested.
|
||||
The example code is now working to show the concept.
|
||||
|
||||
## Description
|
||||
|
||||
radar is a concept library not elaborated yet that implements a Ping))) based Radar
|
||||
with the use of a pan/tilt servo's. Was written after a question on the forum but
|
||||
never finished it. Still, it has some interesting concepts wrt determine the position of
|
||||
pan/tilt while in progress.
|
||||
with the use of two pan/tilt servo's. It was written after a question on the forum but
|
||||
never finished or tested it. Still, it has some interesting concepts wrt determine
|
||||
the position of pan/tilt while in progress.
|
||||
|
||||
The idea is that one knows how fast the pan and tilt servos are working in degrees per second.
|
||||
From that number and the start moment one can determine approximately its position.
|
||||
|
||||
Given its position while moving is interesting for radar purposes as one can determine e.g.
|
||||
in which direction a ping is given and which distance belongs to which pair of angles.
|
||||
|
||||
## Interface
|
||||
|
||||
TODO - see radar.h file
|
||||
|
||||
- **RADAR(pan, tilt)** define pan / tilt pins of the radar. These should be PWM pins.
|
||||
|
||||
|
||||
|
||||
|
||||
RADAR_POSITIONS
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
|
||||
|
||||
|
||||
In short a lot todo
|
||||
|
||||
|
||||
|
||||
|
21
libraries/RunningAverage/LICENSE
Normal file
21
libraries/RunningAverage/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
19
libraries/RunningAverage/README.md
Normal file
19
libraries/RunningAverage/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# RunningAverage
|
||||
|
||||
Arduino library to calculate the running average by means of a circular buffer.
|
||||
|
||||
## Description
|
||||
The RunningAverage object gives a running average of the last N numbers, giving them
|
||||
all equal weight. This is doen by adding new data to an internal circular buffer,
|
||||
removing the oldest and replace it by the newest. The size of the internal buffer
|
||||
|
||||
By keeping track of the **_sum** the runningAverage can be calculated fast (only 1 division).
|
||||
This is done with **getFastAverage()**.
|
||||
However the constant adding/subtracting when adding new elements introduces an accumulating error.
|
||||
In tests adding up to 1500000 numbers this error was always small. But that is no proof.
|
||||
In version 0.2.16 there is a fix added that uses the calculation of the sum in **getAverage()** to
|
||||
update the internal **_sum**.
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
@ -1,9 +1,10 @@
|
||||
//
|
||||
// FILE: RunningAverage.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.16
|
||||
// VERSION: 0.3.1
|
||||
// DATE: 2015-July-10
|
||||
// PURPOSE: RunningAverage library for Arduino
|
||||
// PURPOSE: Arduino library to calculate the running average by means of a circular buffer
|
||||
// URL: https://github.com/RobTillaart/RunningAverage
|
||||
//
|
||||
// The library stores N individual values in a circular buffer,
|
||||
// to calculate the running average.
|
||||
@ -31,16 +32,11 @@
|
||||
// 0.2.14 - 2020-01-15 added getValue(n) to retrieve elements in order of addition - see issue #132
|
||||
// 0.2.15 - 2020-01-17 fix overflow in getValue - see issue #139
|
||||
// 0.2.16 2020-04-16 improve _sum - see issue #149 (bourkemcrobbo)
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// 0.3.0 2020-04-16 main refactor
|
||||
// 0.3.1 2020-06-19 fix library.json; minor refactor
|
||||
|
||||
#include "RunningAverage.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
RunningAverage::RunningAverage(const uint8_t size)
|
||||
{
|
||||
_size = size;
|
||||
@ -62,9 +58,9 @@ void RunningAverage::clear()
|
||||
_sum = 0.0;
|
||||
_min = NAN;
|
||||
_max = NAN;
|
||||
for (uint8_t i = 0; i < _size; i++)
|
||||
for (uint8_t i = _size; i > 0; )
|
||||
{
|
||||
_ar[i] = 0.0; // keeps addValue simpler
|
||||
_ar[--i] = 0.0; // keeps addValue simpler
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,14 +95,15 @@ float RunningAverage::getAverage()
|
||||
{
|
||||
_sum += _ar[i];
|
||||
}
|
||||
return _sum / _cnt;
|
||||
return _sum / _cnt; // multiplication is faster ==> extra admin
|
||||
}
|
||||
|
||||
// the larger the size of the internal buffer the greater the gain wrt getAverage()
|
||||
float RunningAverage::getFastAverage() const
|
||||
{
|
||||
if (_cnt == 0) return NAN;
|
||||
|
||||
return _sum / _cnt;
|
||||
|
||||
return _sum / _cnt; // multiplication is faster ==> extra admin
|
||||
}
|
||||
|
||||
// returns the minimum value in the buffer
|
||||
@ -147,7 +144,7 @@ float RunningAverage::getElement(uint8_t idx) const
|
||||
// Return standard deviation of running average. If buffer is empty, return NAN.
|
||||
float RunningAverage::getStandardDeviation() const
|
||||
{
|
||||
if (_cnt == 0) return NAN;
|
||||
if (_cnt <= 1) return NAN;
|
||||
|
||||
float temp = 0;
|
||||
float average = getFastAverage();
|
||||
@ -166,26 +163,29 @@ float RunningAverage::getStandardError() const //++
|
||||
float temp = getStandardDeviation();
|
||||
|
||||
if (temp == NAN) return NAN;
|
||||
if (_cnt <= 1) return NAN;
|
||||
|
||||
float n;
|
||||
if (_cnt >= 30) n = _cnt;
|
||||
else n = _cnt - 1; // TODO fails if _cnt == 0
|
||||
temp = temp/sqrt(n); // TODO fails if _cnt == 1
|
||||
else n = _cnt - 1;
|
||||
temp = temp/sqrt(n);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
// fill the average with a value
|
||||
// the param number determines how often value is added (weight)
|
||||
// number should preferably be between 1 and size
|
||||
// fill the average with the same value number times. (weight)
|
||||
// This is maximized to size times. no need to fill the internal buffer over 100%
|
||||
void RunningAverage::fillValue(const float value, const uint8_t number)
|
||||
{
|
||||
clear();
|
||||
|
||||
for (uint8_t i = 0; i < number; i++)
|
||||
uint8_t s = number;
|
||||
if (s > _size) s = _size;
|
||||
for (uint8_t i = s; i > 0; i--)
|
||||
{
|
||||
addValue(value);
|
||||
}
|
||||
// NOTE: the clear iterates over the buffer,
|
||||
// so merging the clear loop could gain some performance.
|
||||
}
|
||||
|
||||
float RunningAverage::getValue(const uint8_t idx)
|
||||
@ -196,4 +196,5 @@ float RunningAverage::getValue(const uint8_t idx)
|
||||
if (pos >= _cnt) pos -= _cnt;
|
||||
return _ar[pos];
|
||||
}
|
||||
// END OF FILE
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,23 +1,16 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: RunningAverage.h
|
||||
// AUTHOR: Rob.Tillaart@gmail.com
|
||||
// VERSION: 0.2.16
|
||||
// VERSION: 0.3.1
|
||||
// DATE: 2016-dec-01
|
||||
// PURPOSE: RunningAverage library for Arduino
|
||||
// URL: https://github.com/RobTillaart/Arduino/tree/master/libraries/RunningAverage
|
||||
// PURPOSE: Arduino library to calculate the running average by means of a circular buffer
|
||||
// URL: https://github.com/RobTillaart/RunningAverage
|
||||
//
|
||||
// HISTORY: See RunningAverage.cpp
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// backwards compatibility
|
||||
// clr() clear()
|
||||
// add(x) addValue(x)
|
||||
// avg() getAverage()
|
||||
|
||||
#ifndef RunningAverage_h
|
||||
#define RunningAverage_h
|
||||
|
||||
#define RUNNINGAVERAGE_LIB_VERSION "0.2.16"
|
||||
#define RUNNINGAVERAGE_LIB_VERSION "0.3.1"
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
@ -25,7 +18,7 @@ class RunningAverage
|
||||
{
|
||||
public:
|
||||
RunningAverage(void);
|
||||
explicit RunningAverage(const uint8_t);
|
||||
explicit RunningAverage(const uint8_t size);
|
||||
~RunningAverage();
|
||||
|
||||
void clear();
|
||||
@ -34,7 +27,7 @@ public:
|
||||
float getValue(const uint8_t);
|
||||
|
||||
float getAverage(); // iterates over all elements.
|
||||
float getFastAverage() const; // reuses previous values.
|
||||
float getFastAverage() const; // reuses previous calculated values.
|
||||
|
||||
// return statistical characteristics of the running average
|
||||
float getStandardDeviation() const;
|
||||
@ -57,7 +50,6 @@ public:
|
||||
uint8_t getCount() const { return _cnt; }
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
uint8_t _size;
|
||||
uint8_t _cnt;
|
||||
@ -68,5 +60,4 @@ protected:
|
||||
float _max;
|
||||
};
|
||||
|
||||
#endif
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -1,9 +1,9 @@
|
||||
//
|
||||
// FILE: fillValue.pde
|
||||
// FILE: fillValue.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2012-12-30
|
||||
//
|
||||
// PUPROSE: show working of fillValue
|
||||
// PUPROSE: demo + timing of fillValue
|
||||
//
|
||||
|
||||
#include "RunningAverage.h"
|
||||
@ -11,20 +11,29 @@
|
||||
RunningAverage myRA(10);
|
||||
int samples = 0;
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Demo RunningAverage lib - fillValue ");
|
||||
Serial.print("Version: ");
|
||||
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
|
||||
|
||||
myRA.fillValue(100,5);
|
||||
delay(10);
|
||||
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
measure_duration(i);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
long rn = random(0, 100);
|
||||
myRA.addValue(rn/100.0);
|
||||
myRA.addValue(rn / 100.0);
|
||||
samples++;
|
||||
Serial.print("Running Average: ");
|
||||
Serial.println(myRA.getAverage(), 4);
|
||||
@ -35,4 +44,18 @@ void loop(void)
|
||||
myRA.fillValue(100, 10);
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
void measure_duration(int n)
|
||||
{
|
||||
start = micros();
|
||||
myRA.fillValue(100, n);
|
||||
stop = micros();
|
||||
Serial.print("fillValue(100, ");
|
||||
Serial.print(n);
|
||||
Serial.print("): ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: ra_FastAverageTest.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// VERSION: 0.2.0
|
||||
// DATE: 2015-sep-04
|
||||
//
|
||||
// PUPROSE: demo to see if different average algorithm give different result
|
||||
@ -9,11 +9,15 @@
|
||||
|
||||
#include "RunningAverage.h"
|
||||
|
||||
RunningAverage myRA(10);
|
||||
uint32_t samples = 0;
|
||||
RunningAverage myRA(16);
|
||||
|
||||
float avg = 0;
|
||||
float favg = 0;
|
||||
float diff = 0;
|
||||
float maxDiff = 0;
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
@ -23,37 +27,67 @@ void setup(void)
|
||||
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
|
||||
myRA.clear(); // explicitly start clean
|
||||
|
||||
Serial.println("\nCNT\tAVG\tFASTAVG");
|
||||
measure_duration();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
void loop()
|
||||
{
|
||||
long rn = random(0, 1000);
|
||||
myRA.addValue(rn * 0.001);
|
||||
samples++;
|
||||
//
|
||||
float avg = myRA.getAverage();
|
||||
float favg = myRA.getFastAverage();
|
||||
float diff = abs(avg - favg);
|
||||
|
||||
boolean pr = (samples % 10000 == 0);
|
||||
if (maxDiff < diff)
|
||||
{
|
||||
maxDiff = diff;
|
||||
pr = true;
|
||||
}
|
||||
|
||||
if (pr)
|
||||
{
|
||||
Serial.print(samples);
|
||||
Serial.print("\t");
|
||||
Serial.print(avg, 7);
|
||||
Serial.print("\t");
|
||||
Serial.print(favg, 7);
|
||||
Serial.print("\t");
|
||||
Serial.print(diff, 7);
|
||||
Serial.print("\t");
|
||||
Serial.print(maxDiff, 7);
|
||||
Serial.println();
|
||||
}
|
||||
test(1000000);
|
||||
}
|
||||
|
||||
|
||||
void measure_duration()
|
||||
{
|
||||
myRA.fillValue(100, 16);
|
||||
start = micros();
|
||||
favg = myRA.getFastAverage();
|
||||
stop = micros();
|
||||
Serial.print("getFastAverage: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
|
||||
myRA.fillValue(100, 16);
|
||||
start = micros();
|
||||
favg = myRA.getAverage();
|
||||
stop = micros();
|
||||
Serial.print(" getAverage: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void test(long n)
|
||||
{
|
||||
Serial.println("\nCNT\tAVG\t\tFASTAVG\t\tDIFF\t\tMAXDIFF");
|
||||
|
||||
for (long i = 0; i < n; i++)
|
||||
{
|
||||
long rn = random(0, 1000);
|
||||
myRA.addValue(rn * 0.001);
|
||||
if ( i % 1000 == 0)
|
||||
{
|
||||
// the order of the next two lines is important as getAverage() resets the _sum
|
||||
// used by the getFastAverage();
|
||||
favg = myRA.getFastAverage();
|
||||
avg = myRA.getAverage();
|
||||
diff = abs(avg - favg);
|
||||
if (diff > maxDiff) maxDiff = diff;
|
||||
|
||||
Serial.print(i);
|
||||
Serial.print("\t");
|
||||
Serial.print(avg, 7);
|
||||
Serial.print("\t");
|
||||
Serial.print(favg, 7);
|
||||
Serial.print("\t");
|
||||
Serial.print(diff, 7);
|
||||
Serial.print("\t");
|
||||
Serial.print(maxDiff, 7);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -66,4 +66,4 @@ void loop(void)
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -0,0 +1,221 @@
|
||||
//
|
||||
// FILE: ra_performance.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// DATE: 2020-04-16
|
||||
//
|
||||
// PUPROSE: timing of runningAverage
|
||||
//
|
||||
|
||||
#include "RunningAverage.h"
|
||||
|
||||
RunningAverage myRA(50);
|
||||
int samples = 0;
|
||||
|
||||
uint32_t start, stop;
|
||||
volatile float x;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("\nPerformance RunningAverage lib: ");
|
||||
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
myRA.clear(); // explicitly start clean
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
myRA.addValue(random(1000) * 0.001);
|
||||
}
|
||||
|
||||
test_clear();
|
||||
test_addvalue();
|
||||
test_fillValue();
|
||||
test_getValue();
|
||||
|
||||
test_getAverage();
|
||||
test_getFastAverage();
|
||||
|
||||
test_getStandardDeviation();
|
||||
test_getStandardError();
|
||||
|
||||
test_getMin();
|
||||
test_getMax();
|
||||
test_getMinInBuffer();
|
||||
test_getMaxInBuffer();
|
||||
|
||||
test_bufferIsFull();
|
||||
test_getElement();
|
||||
|
||||
test_getSize();
|
||||
test_getCount();
|
||||
|
||||
Serial.println("\ndone...\n");
|
||||
}
|
||||
|
||||
void test_clear(void)
|
||||
{
|
||||
start = micros();
|
||||
myRA.clear();
|
||||
stop = micros();
|
||||
Serial.print("\tclear \t\t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_addvalue()
|
||||
{
|
||||
start = micros();
|
||||
myRA.addValue(3.1415);
|
||||
stop = micros();
|
||||
Serial.print("\taddValue \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_fillValue()
|
||||
{
|
||||
start = micros();
|
||||
myRA.fillValue(1.235, 50);
|
||||
stop = micros();
|
||||
Serial.print("\tfillValue \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getValue()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getValue(4);
|
||||
stop = micros();
|
||||
Serial.print("\tgetValue \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getAverage()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getAverage();
|
||||
stop = micros();
|
||||
Serial.print("\tgetAverage \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getFastAverage()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getFastAverage();
|
||||
stop = micros();
|
||||
Serial.print("\tgetFastAverage \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getStandardDeviation()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getStandardDeviation();
|
||||
stop = micros();
|
||||
Serial.print("\tgetStandardDeviation \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getStandardError()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getStandardError();
|
||||
stop = micros();
|
||||
Serial.print("\tgetStandardError \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getMin()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getMin();
|
||||
stop = micros();
|
||||
Serial.print("\tgetMin \t\t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getMax()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getMax();
|
||||
stop = micros();
|
||||
Serial.print("\tgetMax \t\t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getMinInBuffer()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getMinInBuffer();
|
||||
stop = micros();
|
||||
Serial.print("\tgetMinInBuffer \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getMaxInBuffer()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getMaxInBuffer();
|
||||
stop = micros();
|
||||
Serial.print("\tgetMaxInBuffer \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_bufferIsFull()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.bufferIsFull();
|
||||
stop = micros();
|
||||
Serial.print("\tbufferIsFull \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getElement()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getElement(4);
|
||||
stop = micros();
|
||||
Serial.print("\tgetElement \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getSize()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getSize();
|
||||
stop = micros();
|
||||
Serial.print("\tgetSize \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void test_getCount()
|
||||
{
|
||||
start = micros();
|
||||
x = myRA.getCount();
|
||||
stop = micros();
|
||||
Serial.print("\tgetCount \t: ");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/RunningAverage.git"
|
||||
},
|
||||
"version": "0.2.16",
|
||||
"version": "0.3.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/RunningAverage"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
name=RunningAverage
|
||||
version=0.2.16
|
||||
version=0.3.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=The library stores the last N individual values in a circular buffer to calculate the running average.
|
||||
paragraph=Supports min max average
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino
|
||||
url=https://github.com/RobTillaart/RunningAverage
|
||||
architectures=*
|
||||
includes=RunningAverage.h
|
||||
includes=RunningAverager.h
|
||||
depends=
|
||||
|
28
libraries/RunningAverage/performance.txt
Normal file
28
libraries/RunningAverage/performance.txt
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
--------------------------------------
|
||||
|
||||
Arduino UNO
|
||||
IDE 1.8.12
|
||||
|
||||
Performance RunningAverage lib: 0.3.0
|
||||
|
||||
clear : 80
|
||||
addValue : 24
|
||||
fillValue : 1548
|
||||
getValue : 4
|
||||
getAverage : 512
|
||||
getFastAverage : 36
|
||||
getStandardDeviation : 1832
|
||||
getStandardError : 1896
|
||||
getMin : 4
|
||||
getMax : 4
|
||||
getMinInBuffer : 212
|
||||
getMaxInBuffer : 204
|
||||
bufferIsFull : 8
|
||||
getElement : 4
|
||||
getSize : 8
|
||||
getCount : 8
|
||||
|
||||
done...
|
||||
|
||||
--------------------------------------
|
21
libraries/RunningMedian/LICENSE
Normal file
21
libraries/RunningMedian/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2011-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
24
libraries/RunningMedian/README.md
Normal file
24
libraries/RunningMedian/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# RunningMedian
|
||||
Arduino library to determine the running median by means of a circular buffer.
|
||||
|
||||
## Description
|
||||
|
||||
Running Median looks like a running average with a small but important twist.
|
||||
Running average averages the last N samples while the running median takes
|
||||
the last N samples, sort them and take the middle one, or the average of the middle two.
|
||||
|
||||
Important differences between running average and running median:
|
||||
- Running median will return real data (e.g. a real sample from a sensor)
|
||||
if one uses an odd size of the buffer (preferred).
|
||||
Running average may return a value that is never sampled.
|
||||
- Running median will give zero weight to outliers, and 100% to the middle sample,
|
||||
whereas running average gives the same weight to all samples.
|
||||
- Running median will give often constant values for some time.
|
||||
- As one knows the values in the buffer one can predict to some extend how much
|
||||
the next samples will change the running median.
|
||||
- Running median is a bit harder as one needs to keep the values in order
|
||||
to remove the oldest and keep them sorted to be able to select the median.
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: RunningMedian.cpp
|
||||
// AUTHOR: Rob.Tillaart at gmail.com
|
||||
// VERSION: 0.1.15
|
||||
// VERSION: 0.2.1
|
||||
// PURPOSE: RunningMedian library for Arduino
|
||||
//
|
||||
// HISTORY:
|
||||
@ -21,9 +21,8 @@
|
||||
// 0.1.13 - 2015-10-30 fix getElement(n) - kudos to Gdunge
|
||||
// 0.1.14 - 2017-07-26 revert double to float - issue #33
|
||||
// 0.1.15 - 2018-08-24 make runningMedian Configurable #110
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// 0.2.0 2020-04-16 refactor.
|
||||
// 0.2.1 2020-06-19 fix library.json
|
||||
|
||||
#include "RunningMedian.h"
|
||||
|
||||
@ -53,7 +52,10 @@ void RunningMedian::clear()
|
||||
_cnt = 0;
|
||||
_idx = 0;
|
||||
_sorted = false;
|
||||
for (uint8_t i = 0; i < _size; i++) _p[i] = i;
|
||||
for (uint8_t i = 0; i < _size; i++)
|
||||
{
|
||||
_p[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// adds a new value to the data-set
|
||||
@ -72,17 +74,40 @@ float RunningMedian::getMedian()
|
||||
|
||||
if (_sorted == false) sort();
|
||||
|
||||
if (_cnt & 0x01) return _ar[_p[_cnt/2]];
|
||||
else return (_ar[_p[_cnt/2]] + _ar[_p[_cnt/2 - 1]]) / 2;
|
||||
if (_cnt & 0x01) // is it odd sized?
|
||||
{
|
||||
return _ar[_p[_cnt / 2]];
|
||||
}
|
||||
return (_ar[_p[_cnt / 2]] + _ar[_p[_cnt / 2 - 1]]) / 2;
|
||||
}
|
||||
|
||||
float RunningMedian::getQuantile(float q)
|
||||
{
|
||||
if (_cnt == 0) return NAN;
|
||||
|
||||
if ((q < 0) || (q > 1)) return NAN;
|
||||
|
||||
if (_sorted == false) sort();
|
||||
|
||||
const float id = (_cnt - 1) * q;
|
||||
const uint8_t lo = floor(id);
|
||||
const uint8_t hi = ceil(id);
|
||||
const float qs = _ar[_p[lo]];
|
||||
const float h = (id - lo);
|
||||
|
||||
return (1.0 - h) * qs + h * _ar[_p[hi]];
|
||||
|
||||
}
|
||||
|
||||
#ifdef RUNNING_MEDIAN_ALL
|
||||
float RunningMedian::getAverage()
|
||||
{
|
||||
if (_cnt == 0) return NAN;
|
||||
|
||||
float sum = 0;
|
||||
for (uint8_t i=0; i< _cnt; i++) sum += _ar[i];
|
||||
for (uint8_t i = 0; i < _cnt; i++)
|
||||
{
|
||||
sum += _ar[i];
|
||||
}
|
||||
return sum / _cnt;
|
||||
}
|
||||
|
||||
@ -97,7 +122,10 @@ float RunningMedian::getAverage(uint8_t nMedians)
|
||||
if (_sorted == false) sort();
|
||||
|
||||
float sum = 0;
|
||||
for (uint8_t i = start; i < stop; i++) sum += _ar[_p[i]];
|
||||
for (uint8_t i = start; i < stop; i++)
|
||||
{
|
||||
sum += _ar[_p[i]];
|
||||
}
|
||||
return sum / nMedians;
|
||||
}
|
||||
|
||||
@ -124,34 +152,30 @@ float RunningMedian::getSortedElement(const uint8_t n)
|
||||
// n can be max <= half the (filled) size
|
||||
float RunningMedian::predict(const uint8_t n)
|
||||
{
|
||||
if ((_cnt == 0) || (n >= _cnt/2)) return NAN;
|
||||
if ((_cnt == 0) || (n >= _cnt / 2)) return NAN;
|
||||
|
||||
float med = getMedian(); // takes care of sorting !
|
||||
if (_cnt & 0x01)
|
||||
{
|
||||
return max(med - _ar[_p[_cnt/2-n]], _ar[_p[_cnt/2+n]] - med);
|
||||
}
|
||||
else
|
||||
{
|
||||
float f1 = (_ar[_p[_cnt/2 - n]] + _ar[_p[_cnt/2 - n - 1]])/2;
|
||||
float f2 = (_ar[_p[_cnt/2 + n]] + _ar[_p[_cnt/2 + n - 1]])/2;
|
||||
return max(med - f1, f2 - med)/2;
|
||||
return max(med - _ar[_p[_cnt / 2 - n]], _ar[_p[_cnt / 2 + n]] - med);
|
||||
}
|
||||
float f1 = (_ar[_p[_cnt / 2 - n]] + _ar[_p[_cnt / 2 - n - 1]]) / 2;
|
||||
float f2 = (_ar[_p[_cnt / 2 + n]] + _ar[_p[_cnt / 2 + n - 1]]) / 2;
|
||||
return max(med - f1, f2 - med) / 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
void RunningMedian::sort()
|
||||
{
|
||||
// bubble sort with flag
|
||||
for (uint8_t i = 0; i < _cnt-1; i++)
|
||||
for (uint8_t i = 0; i < _cnt - 1; i++)
|
||||
{
|
||||
bool flag = true;
|
||||
for (uint8_t j = 1; j < _cnt-i; j++)
|
||||
for (uint8_t j = 1; j < _cnt - i; j++)
|
||||
{
|
||||
if (_ar[_p[j-1]] > _ar[_p[j]])
|
||||
if (_ar[_p[j - 1]] > _ar[_p[j]])
|
||||
{
|
||||
uint8_t t = _p[j-1];
|
||||
_p[j-1] = _p[j];
|
||||
uint8_t t = _p[j - 1];
|
||||
_p[j - 1] = _p[j];
|
||||
_p[j] = t;
|
||||
flag = false;
|
||||
}
|
||||
@ -161,4 +185,4 @@ void RunningMedian::sort()
|
||||
_sorted = true;
|
||||
}
|
||||
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -1,72 +1,66 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: RunningMedian.h
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// PURPOSE: RunningMedian library for Arduino
|
||||
// VERSION: 0.1.15
|
||||
// VERSION: 0.2.1
|
||||
// URL: https://github.com/RobTillaart/RunningMedian
|
||||
// URL: http://arduino.cc/playground/Main/RunningMedian
|
||||
// HISTORY: See RunningMedian.cpp
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#ifndef RunningMedian_h
|
||||
#define RunningMedian_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define RUNNING_MEDIAN_VERSION "0.1.15"
|
||||
#define RUNNING_MEDIAN_VERSION "0.2.1"
|
||||
|
||||
// prepare for dynamic version
|
||||
// not tested use at own risk :)
|
||||
// #define RUNNING_MEDIAN_USE_MALLOC
|
||||
|
||||
// conditional compile to minimize lib
|
||||
// by removeing a lot of functions.
|
||||
#ifndef RUNNING_MEDIAN_ALL
|
||||
#define RUNNING_MEDIAN_ALL
|
||||
#endif
|
||||
// not tested ==> use at own risk :)
|
||||
#define RUNNING_MEDIAN_USE_MALLOC
|
||||
|
||||
|
||||
// should at least be 5 to be practical
|
||||
// odd size results in a 'real' middle element.
|
||||
// even size takes the lower of the two middle elements
|
||||
#ifndef MEDIAN_MIN_SIZE
|
||||
#define MEDIAN_MIN_SIZE 1
|
||||
#endif
|
||||
#ifndef MEDIAN_MAX_SIZE
|
||||
#define MEDIAN_MAX_SIZE 19 // adjust if needed
|
||||
#endif
|
||||
// should at least be 5 to be practical,
|
||||
// odd sizes results in a 'real' middle element and will be a bit faster.
|
||||
// even sizes takes the average of the two middle elements as median
|
||||
#define MEDIAN_MIN_SIZE 5
|
||||
#define MEDIAN_MAX_SIZE 19
|
||||
|
||||
|
||||
class RunningMedian
|
||||
{
|
||||
public:
|
||||
explicit RunningMedian(const uint8_t size); // # elements in the internal buffer
|
||||
~RunningMedian(); // destructor
|
||||
// # elements in the internal buffer
|
||||
explicit RunningMedian(const uint8_t size);
|
||||
~RunningMedian();
|
||||
|
||||
void clear(); // resets internal buffer and var
|
||||
void add(const float value); // adds a new value to internal buffer, optionally replacing the oldest element.
|
||||
float getMedian(); // returns the median == middle element
|
||||
// resets internal buffer and var
|
||||
void clear();
|
||||
// adds a new value to internal buffer, optionally replacing the oldest element.
|
||||
void add(const float value);
|
||||
// returns the median == middle element
|
||||
float getMedian();
|
||||
|
||||
// returns the Quantile
|
||||
float getQuantile(const float q);
|
||||
|
||||
// returns average of the values in the internal buffer
|
||||
float getAverage();
|
||||
// returns average of the middle nMedian values, removes noise from outliers
|
||||
float getAverage(uint8_t nMedian);
|
||||
|
||||
#ifdef RUNNING_MEDIAN_ALL
|
||||
float getAverage(); // returns average of the values in the internal buffer
|
||||
float getAverage(uint8_t nMedian); // returns average of the middle nMedian values, removes noise from outliers
|
||||
float getHighest() { return getSortedElement(_cnt - 1); };
|
||||
float getLowest() { return getSortedElement(0); };
|
||||
|
||||
float getElement(const uint8_t n); // get n'th element from the values in time order
|
||||
float getSortedElement(const uint8_t n); // get n'th element from the values in size order
|
||||
float predict(const uint8_t n); // predict the max change of median after n additions
|
||||
// get n'th element from the values in time order
|
||||
float getElement(const uint8_t n);
|
||||
// get n'th element from the values in size order
|
||||
float getSortedElement(const uint8_t n);
|
||||
// predict the max change of median after n additions
|
||||
float predict(const uint8_t n);
|
||||
|
||||
uint8_t getSize() { return _size; };
|
||||
// returns current used elements, getCount() <= getSize()
|
||||
uint8_t getCount() { return _cnt; };
|
||||
|
||||
uint8_t getSize() { return _size; }; // returns size of internal buffer
|
||||
uint8_t getCount() { return _cnt; }; // returns current used elements, getCount() <= getSize()
|
||||
#endif
|
||||
|
||||
protected:
|
||||
boolean _sorted;
|
||||
@ -84,5 +78,4 @@ protected:
|
||||
void sort();
|
||||
};
|
||||
|
||||
#endif
|
||||
// END OF FILE
|
@ -1,18 +1,15 @@
|
||||
//
|
||||
// FILE: RunningMedian.ino
|
||||
// AUTHOR: Rob Tillaart ( kudos to Sembazuru)
|
||||
// VERSION: 0.1.01
|
||||
// PURPOSE: demo
|
||||
// VERSION: 0.1.2
|
||||
// PURPOSE: demo basic usage
|
||||
// DATE: 2013-10-17
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
// URL: https://github.com/RobTillaart/RunningMedian
|
||||
//
|
||||
|
||||
#include <RunningMedian.h>
|
||||
|
||||
RunningMedian samples = RunningMedian(5);
|
||||
RunningMedian samples2 = RunningMedian(9);
|
||||
|
||||
void setup()
|
||||
{
|
||||
@ -50,3 +47,4 @@ void test1()
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,12 +1,10 @@
|
||||
//
|
||||
// FILE: RunningMedian2.ino
|
||||
// AUTHOR: Rob Tillaart ( kudos to Sembazuru)
|
||||
// VERSION: 0.1.01
|
||||
// PURPOSE: demo
|
||||
// VERSION: 0.1.2
|
||||
// PURPOSE: demo most functions
|
||||
// DATE: 2013-10-17
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
// URL: https://github.com/RobTillaart/RunningMedian
|
||||
//
|
||||
|
||||
#include "RunningMedian.h"
|
||||
@ -29,7 +27,10 @@ void loop()
|
||||
|
||||
void test1()
|
||||
{
|
||||
if (count % 20 == 0) Serial.println(F("\nmsec \tAnR \tSize \tCnt \tLow \tAvg \tAvg(7) \tAvg(3) \tMed \tHigh \tPre(1) \tPre(2)"));
|
||||
if (count % 20 == 0)
|
||||
{
|
||||
Serial.println(F("\nmsec \tAnR \tSize \tCnt \tLow \tAvg \tAvg(7) \tAvg(3) \tMed \tHigh \tPre(1) \tPre(2)"));
|
||||
}
|
||||
count++;
|
||||
|
||||
long x = analogRead(A0);
|
||||
|
@ -0,0 +1,40 @@
|
||||
//
|
||||
// FILE: RunningMedianQuantileTest.ino
|
||||
// AUTHOR: f-s ( derived from Rob Tillaart )
|
||||
// VERSION: 0.1.2
|
||||
// PURPOSE: demo basic quantile usage
|
||||
// DATE: 2020-09-02
|
||||
// URL: https://github.com/RobTillaart/RunningMedian
|
||||
//
|
||||
|
||||
#include <RunningMedian.h>
|
||||
|
||||
RunningMedian samples = RunningMedian(5);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Running Median Version: ");
|
||||
Serial.println(RUNNING_MEDIAN_VERSION);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
test1();
|
||||
}
|
||||
|
||||
void test1()
|
||||
{
|
||||
int x = analogRead(A0);
|
||||
|
||||
samples.add(x);
|
||||
// calculate the 5% quantile => 0.05
|
||||
long q = samples.getQuantile(0.05);
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.print("\t");
|
||||
Serial.println(q);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,15 +1,11 @@
|
||||
//
|
||||
// FILE: runningMedianTest1.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.00
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: test functionality
|
||||
// DATE: 2013-10-28
|
||||
// URL:
|
||||
// URL: https://github.com/RobTillaart/RunningMedian
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
// RunningMedianTest1.ino
|
||||
|
||||
#include <RunningMedian.h>
|
||||
|
||||
@ -32,135 +28,136 @@ void setup()
|
||||
delay(1000); // Simply to allow time for the ERW versions of the IDE time to automagically open the Serial Monitor. 1 second chosen arbitrarily.
|
||||
Serial.print(F("Running Median Version: "));
|
||||
Serial.println(RUNNING_MEDIAN_VERSION);
|
||||
#ifdef RUNNING_MEDIAN_ALL
|
||||
Serial.println(F("All methods available"));
|
||||
#else
|
||||
Serial.println(F("Only constructor, destructor, clear(), add(), and getMedian() available"));
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef RUNNING_MEDIAN_USE_MALLOC
|
||||
Serial.println(F("Dynamic version using malloc() enabled"));
|
||||
#else
|
||||
Serial.print(F("Static version, will always allocate an array of "));
|
||||
Serial.print(MEDIAN_MAX_SIZE,DEC);
|
||||
Serial.print(MEDIAN_MAX_SIZE, DEC);
|
||||
Serial.println(F(" floats."));
|
||||
#endif
|
||||
|
||||
test1();
|
||||
|
||||
Serial.println("\ndone..\n");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
test1();
|
||||
while (1);
|
||||
}
|
||||
|
||||
void test1()
|
||||
{
|
||||
unsigned long timerStart = 0;
|
||||
unsigned long timerStop = 0;
|
||||
float resultFLOAT = 0;
|
||||
byte resultBYTE = 0;
|
||||
uint32_t start = 0;
|
||||
uint32_t stop = 0;
|
||||
float result = 0;
|
||||
|
||||
Serial.print(F("Requested median array size = "));
|
||||
Serial.println(sourceSize,DEC);
|
||||
Serial.print(F("Actual allocated size = "));
|
||||
Serial.println(samples.getSize(),DEC);
|
||||
|
||||
Serial.println(sourceSize);
|
||||
Serial.print(F(" Actual allocated size = "));
|
||||
Serial.println(samples.getSize());
|
||||
Serial.println();
|
||||
|
||||
for(byte i = 0; i <= (sourceSize - 1); i++)
|
||||
// 50 iterations !!
|
||||
for (uint8_t i = 0; i <= (sourceSize - 1); i++)
|
||||
{
|
||||
Serial.print(F("Loop number "));
|
||||
Serial.println((i + 1),DEC);
|
||||
Serial.print(F("Loop number : "));
|
||||
Serial.println(i + 1);
|
||||
|
||||
timerStart = micros();
|
||||
start = micros();
|
||||
samples.add(sourceData[i]);
|
||||
timerStop = micros();
|
||||
stop = micros();
|
||||
Serial.print(F("Time to add the next element to the array = "));
|
||||
Serial.print(timerStop - timerStart);
|
||||
Serial.println(F(" microseconds."));
|
||||
Serial.println(stop - start);
|
||||
|
||||
|
||||
Serial.println(F("Cumulative source data added:"));
|
||||
Serial.print(F(" "));
|
||||
for(byte j = 0; j <= i; j++)
|
||||
for (uint8_t j = 0; j <= i; j++)
|
||||
{
|
||||
Serial.print(sourceData[j]);
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println(F("Unsorted accumulated array:"));
|
||||
Serial.print(F(" "));
|
||||
for(byte j = 0; j < samples.getCount(); j++)
|
||||
for (uint8_t j = 0; j < samples.getCount(); j++)
|
||||
{
|
||||
Serial.print(samples.getElement(j));
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
timerStart = micros();
|
||||
resultFLOAT = samples.getSortedElement(0);
|
||||
timerStop = micros();
|
||||
|
||||
start = micros();
|
||||
result = samples.getSortedElement(0);
|
||||
stop = micros();
|
||||
Serial.print(F("Time to sort array and return element number zero = "));
|
||||
Serial.print(timerStop - timerStart);
|
||||
Serial.println(F(" microseconds."));
|
||||
Serial.println(stop - start);
|
||||
|
||||
|
||||
Serial.println(F("Sorted accumulated array:"));
|
||||
Serial.print(F(" "));
|
||||
for(byte j = 0; j < samples.getCount(); j++)
|
||||
for (uint8_t j = 0; j < samples.getCount(); j++)
|
||||
{
|
||||
Serial.print(samples.getSortedElement(j));
|
||||
Serial.print(F(" "));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
timerStart = micros();
|
||||
resultFLOAT = samples.getMedian();
|
||||
timerStop = micros();
|
||||
Serial.print(F("getMedian() result = "));
|
||||
Serial.println(resultFLOAT);
|
||||
Serial.print(F("Time to execute getMedian() = "));
|
||||
Serial.print(timerStop - timerStart);
|
||||
Serial.println(F(" microseconds."));
|
||||
|
||||
timerStart = micros();
|
||||
resultFLOAT = samples.getAverage();
|
||||
timerStop = micros();
|
||||
start = micros();
|
||||
result = samples.getMedian();
|
||||
stop = micros();
|
||||
Serial.print(F("getMedian() result = "));
|
||||
Serial.println(result);
|
||||
Serial.print(F("Time to execute getMedian() = "));
|
||||
Serial.println(stop - start);
|
||||
|
||||
|
||||
start = micros();
|
||||
result = samples.getAverage();
|
||||
stop = micros();
|
||||
Serial.print(F("getAverage() result = "));
|
||||
Serial.println(resultFLOAT);
|
||||
Serial.println(result);
|
||||
Serial.print(F("Time to execute getAverage() = "));
|
||||
Serial.print(timerStop - timerStart);
|
||||
Serial.println(F(" microseconds."));
|
||||
Serial.println(stop - start);
|
||||
|
||||
|
||||
Serial.println(F("getAverage(x) results where:"));
|
||||
for(byte j = 1; j <= samples.getCount(); j++)
|
||||
for (uint8_t j = 1; j <= samples.getCount(); j++)
|
||||
{
|
||||
timerStart = micros();
|
||||
resultFLOAT = samples.getAverage(j);
|
||||
timerStop = micros();
|
||||
start = micros();
|
||||
result = samples.getAverage(j);
|
||||
stop = micros();
|
||||
Serial.print(F(" x = "));
|
||||
Serial.print(j);
|
||||
Serial.print(F(" => "));
|
||||
Serial.print(resultFLOAT);
|
||||
Serial.print(result);
|
||||
Serial.print(F(" Time to execute = "));
|
||||
Serial.print(timerStop - timerStart);
|
||||
Serial.println(F(" microseconds."));
|
||||
Serial.println(stop - start);
|
||||
}
|
||||
|
||||
Serial.println(F("predict(x) results where:"));
|
||||
for(byte j = 1; j <= (samples.getCount() / 2); j++)
|
||||
for (uint8_t j = 1; j <= (samples.getCount() / 2); j++)
|
||||
{
|
||||
timerStart = micros();
|
||||
resultFLOAT = samples.predict(j);
|
||||
timerStop = micros();
|
||||
start = micros();
|
||||
result = samples.predict(j);
|
||||
stop = micros();
|
||||
Serial.print(F(" x = "));
|
||||
Serial.print(j);
|
||||
Serial.print(F(" => "));
|
||||
Serial.print(resultFLOAT);
|
||||
Serial.print(result);
|
||||
Serial.print(F(" Time to execute = "));
|
||||
Serial.print(timerStop - timerStart);
|
||||
Serial.println(F(" microseconds."));
|
||||
Serial.println(stop - start);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,21 +1,13 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map for RunningMedian
|
||||
# "traditional" and template variant
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
RunningMedian KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
add KEYWORD2
|
||||
clear KEYWORD2
|
||||
getMedian KEYWORD2
|
||||
getQuantile KEYWORD2
|
||||
getAverage KEYWORD2
|
||||
getHighest KEYWORD2
|
||||
getLowest KEYWORD2
|
||||
@ -26,8 +18,6 @@ getSortedElement KEYWORD2
|
||||
predict KEYWORD2
|
||||
getStatus KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
OK LITERAL1
|
||||
NOK LITERAL1
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "RunningMedian",
|
||||
"keywords": "running,moving,median,average,outliers",
|
||||
"keywords": "running, moving, median, average, outliers",
|
||||
"description": "The library stores the last N individual values in a buffer to select the median. It filters outliers.",
|
||||
"authors":
|
||||
[
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/RunningMedian.git"
|
||||
},
|
||||
"version":"0.1.15",
|
||||
"version":"0.2.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/RunningMedian"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=RunningMedian
|
||||
version=0.1.15
|
||||
version=0.2.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=The library stores the last N individual values in a buffer to select the median.
|
||||
paragraph=This way it filters outliers.
|
||||
paragraph=This will filter outliers in a chain of samples very well.
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/RunningMedian
|
||||
architectures=*
|
||||
includes=RunningMedian.h
|
||||
depends=
|
||||
|
21
libraries/SHT31/LICENSE
Normal file
21
libraries/SHT31/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
25
libraries/SHT31/README.md
Normal file
25
libraries/SHT31/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# SHT31
|
||||
|
||||
Arduino library for the SHT31 temperature and humidity sensor
|
||||
|
||||
# Description
|
||||
|
||||
The SHT3x family of sensors should work up to 1 MHz I2C
|
||||
|
||||
This library should also work for SHT30 and SHT35 but these are
|
||||
not tested yet.
|
||||
|
||||
| SENSOR | Temperature accuracy | Humidity accuracy |
|
||||
|:----:|:----:|:----:|
|
||||
| SHT30 | ~0.3 | 2 |
|
||||
| SHT31 | ~0.3 | 1.5 |
|
||||
| SHT35 | ~0.2 | 1.5 |
|
||||
|
||||
|
||||
An elaborated library for the SHT31 sensor can be found here
|
||||
https://github.com/hawesg/SHT31D_Particle_Photon_ClosedCube
|
||||
|
||||
# Operation
|
||||
|
||||
See examples
|
||||
|
@ -1,29 +1,36 @@
|
||||
//
|
||||
// FILE: SHT31.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.2
|
||||
// VERSION: 0.2.2
|
||||
// DATE: 2019-02-08
|
||||
// PURPOSE: Class for SHT31 I2C temperature humidity sensor
|
||||
// PURPOSE: Arduino library for the SHT31 temperature and humidity sensor
|
||||
// https://www.adafruit.com/product/2857
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 - 2019-02-08 initial version
|
||||
// 0.1.1 - 2019-02-18 add description readStatus(),
|
||||
// 0.1.0 2019-02-08 initial version
|
||||
// 0.1.1 2019-02-18 add description readStatus(),
|
||||
// async interface
|
||||
// 0.1.2 - 2019-03-05 fix issue #123 - error in humidity
|
||||
// 0.1.2 2019-03-05 fix issue #123 - error in humidity
|
||||
// stable version
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// 0.2.0 2020-05-12 made humidity & temperature private;
|
||||
// support ESP32 I2C
|
||||
// 0.2.1 2020-06-19 fix library.json
|
||||
// 0.2.2 2020-07-05 fix compiling for ESP
|
||||
|
||||
|
||||
#include "SHT31.h"
|
||||
|
||||
// SUPPORTED COMMANDS - single shot mode only
|
||||
#define SHT31_READ_STATUS 0xF32D
|
||||
#define SHT31_CLEAR_STATUS 0x3041
|
||||
|
||||
#define SHT31_SOFT_RESET 0x30A2
|
||||
#define SHT31_HARD_RESET 0x0006
|
||||
#define SHT31_MEASUREMENT_FAST 0x2416
|
||||
#define SHT31_MEASUREMENT_SLOW 0x2400
|
||||
|
||||
#define SHT31_MEASUREMENT_FAST 0x2416 // page 10 datasheet
|
||||
#define SHT31_MEASUREMENT_SLOW 0x2400 // no clock stretching
|
||||
|
||||
#define SHT31_HEAT_ON 0x306D
|
||||
#define SHT31_HEAT_OFF 0x3066
|
||||
|
||||
@ -34,58 +41,57 @@ SHT31::SHT31()
|
||||
_lastRead = 0;
|
||||
temperature = 0;
|
||||
humidity = 0;
|
||||
_heaterStart = 0;
|
||||
}
|
||||
|
||||
bool SHT31::begin(const uint8_t address)
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
bool SHT31::begin(const uint8_t address, const uint8_t dataPin, const uint8_t clockPin)
|
||||
{
|
||||
if (address != 0x44 && address != 0x45) return false;
|
||||
_addr = address;
|
||||
|
||||
_wire = &Wire;
|
||||
if ((dataPin < 255) && (clockPin < 255))
|
||||
{
|
||||
_wire->begin(dataPin, clockPin);
|
||||
} else {
|
||||
_wire->begin();
|
||||
}
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SHT31::begin(const uint8_t address)
|
||||
{
|
||||
return begin(address, &Wire);
|
||||
}
|
||||
|
||||
bool SHT31::begin(const uint8_t address, TwoWire *wire)
|
||||
{
|
||||
if (address != 0x44 && address != 0x45) return false;
|
||||
_addr = address;
|
||||
_wire = wire;
|
||||
_wire->begin();
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SHT31::read(bool fast)
|
||||
{
|
||||
bool rv = true;
|
||||
uint8_t buffer[6];
|
||||
|
||||
if (fast)
|
||||
{
|
||||
writeCmd(SHT31_MEASUREMENT_FAST);
|
||||
delay(4); // table 4 datasheet
|
||||
}
|
||||
else
|
||||
{
|
||||
writeCmd(SHT31_MEASUREMENT_SLOW);
|
||||
delay(15); // table 4 datasheet
|
||||
}
|
||||
|
||||
// TODO 5 read bytes would be sufficient when not fast / no CRC...
|
||||
readBytes(6, (uint8_t*) &buffer[0]);
|
||||
|
||||
if (!fast)
|
||||
{
|
||||
// TODO check CRC here
|
||||
// TODO rv = false;
|
||||
}
|
||||
uint16_t raw = (buffer[0] << 8) + buffer[1];
|
||||
temperature = raw * (175.0 / 65535) - 45;
|
||||
raw = (buffer[3] << 8) + buffer[4];
|
||||
humidity = raw * (100.0 / 65535);
|
||||
|
||||
_lastRead = millis();
|
||||
|
||||
return rv;
|
||||
writeCmd(fast ? SHT31_MEASUREMENT_FAST : SHT31_MEASUREMENT_SLOW);
|
||||
delay(fast ? 4 : 15); // table 4 datasheet
|
||||
return readData(fast);
|
||||
}
|
||||
|
||||
uint16_t SHT31::readStatus()
|
||||
{
|
||||
uint32_t status = 0;
|
||||
|
||||
writeCmd(SHT31_READ_STATUS); // page 13 datasheet
|
||||
readBytes(3, (uint8_t*) &status); // 16 bit status + CRC
|
||||
// TODO CRC check
|
||||
return status;
|
||||
|
||||
return (uint16_t) (status >> 8);
|
||||
|
||||
// bit - description
|
||||
// ==================
|
||||
@ -106,7 +112,7 @@ uint16_t SHT31::readStatus()
|
||||
// 9:5 Reserved '00000’
|
||||
// 4 System reset detected
|
||||
// '0': no reset since last ‘clear status register’ command
|
||||
// '1': reset detected (hard or soft reset command or supply fail)
|
||||
// '1': reset detected (hard or soft reset command or supply fail) - default
|
||||
// 3:2 Reserved ‘00’
|
||||
// 1 Command status
|
||||
// '0': last cmd executed successfully
|
||||
@ -116,20 +122,42 @@ uint16_t SHT31::readStatus()
|
||||
// '1': checksum of last write transfer failed
|
||||
}
|
||||
|
||||
void SHT31::reset()
|
||||
void SHT31::reset(bool hard)
|
||||
{
|
||||
writeCmd(SHT31_SOFT_RESET); // SHT31_HARD_RESET not implemented yet
|
||||
delay(1); // table 4 datasheet // 100ms for hardreset
|
||||
if (hard)
|
||||
{
|
||||
writeCmd(SHT31_HARD_RESET);
|
||||
} else {
|
||||
writeCmd(SHT31_SOFT_RESET);
|
||||
}
|
||||
delay(1); // table 4 datasheet
|
||||
}
|
||||
|
||||
void SHT31::setHeatTimeout(uint8_t seconds)
|
||||
{
|
||||
_heatTimeOut = seconds;
|
||||
if (_heatTimeOut > 180) _heatTimeOut = 180;
|
||||
}
|
||||
|
||||
void SHT31::heatOn()
|
||||
{
|
||||
writeCmd(SHT31_HEAT_ON);
|
||||
_heaterStart = millis();
|
||||
}
|
||||
|
||||
void SHT31::heatOff()
|
||||
{
|
||||
writeCmd(SHT31_HEAT_OFF);
|
||||
_heaterStart = 0;
|
||||
}
|
||||
|
||||
bool SHT31::heatUp()
|
||||
{
|
||||
if (_heaterStart == 0) return false;
|
||||
// did not exceed time out
|
||||
if (millis() - _heaterStart < (_heatTimeOut * 1000UL)) return true;
|
||||
heatOff();
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHT31::requestData()
|
||||
@ -143,35 +171,65 @@ bool SHT31::dataReady()
|
||||
return ((millis() - _lastRequest) > 15);
|
||||
}
|
||||
|
||||
void SHT31::readData()
|
||||
bool SHT31::readData(bool fast)
|
||||
{
|
||||
uint8_t buffer[6];
|
||||
readBytes(6, (uint8_t*) &buffer[0]);
|
||||
|
||||
float raw = (buffer[0] << 8) + buffer[1];
|
||||
if (!fast)
|
||||
{
|
||||
if (buffer[2] != crc8(buffer, 2) ||
|
||||
buffer[5] != crc8(buffer + 3, 2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t raw = (buffer[0] << 8) + buffer[1];
|
||||
temperature = raw * (175.0 / 65535) - 45;
|
||||
raw = (buffer[3] << 8) + buffer[4];
|
||||
humidity = raw * (100.0 / 65535);
|
||||
|
||||
_lastRead = millis();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t SHT31::crc8(const uint8_t *data, int len)
|
||||
{
|
||||
// CRC-8 formula from page 14 of SHT spec pdf
|
||||
const uint8_t POLY(0x31);
|
||||
uint8_t crc(0xFF);
|
||||
|
||||
for (int j = len; j; --j)
|
||||
{
|
||||
crc ^= *data++;
|
||||
|
||||
for (int i = 8; i; --i)
|
||||
{
|
||||
crc = (crc & 0x80) ? (crc << 1) ^ POLY : (crc << 1);
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void SHT31::writeCmd(uint16_t cmd)
|
||||
{
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(cmd >> 8 );
|
||||
Wire.write(cmd & 0xFF);
|
||||
Wire.endTransmission();
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(cmd >> 8 );
|
||||
_wire->write(cmd & 0xFF);
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
void SHT31::readBytes(uint8_t n, uint8_t *val)
|
||||
{
|
||||
Wire.requestFrom(_addr, (uint8_t) n);
|
||||
_wire->requestFrom(_addr, (uint8_t) n);
|
||||
for (uint8_t i = 0; i < n; i++)
|
||||
{
|
||||
val[i] = Wire.read();
|
||||
val[i] = _wire->read();
|
||||
}
|
||||
}
|
||||
// -- END OF FILE --
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,61 +1,80 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: SHT31.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.2
|
||||
// VERSION: 0.2.2
|
||||
// DATE: 2019-02-08
|
||||
// PURPOSE: Class for SHT31 I2C temperature humidity sensor
|
||||
// PURPOSE: Arduino library for the SHT31 temperature and humidity sensor
|
||||
// https://www.adafruit.com/product/2857
|
||||
// URL: https://github.com/RobTillaart/Arduino.git
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#ifndef SHT31_h
|
||||
#define SHT31_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
|
||||
#define SHT31_LIB_VERSION "0.1.2"
|
||||
#define SHT31_LIB_VERSION "0.2.2"
|
||||
|
||||
// fields readStatus
|
||||
#define SHT31_STATUS_ALERT_PENDING (1 << 15)
|
||||
#define SHT31_STATUS_HEATER_ON (1 << 13)
|
||||
#define SHT31_STATUS_HUM_TRACK_ALERT (1 << 11)
|
||||
#define SHT31_STATUS_TEMP_TRACK_ALERT (1 << 10)
|
||||
#define SHT31_STATUS_SYSTEM_RESET (1 << 4)
|
||||
#define SHT31_STATUS_COMMAND_STATUS (1 << 1)
|
||||
#define SHT31_STATUS_WRITE_CRC_STATUS (1 << 0)
|
||||
|
||||
class SHT31
|
||||
{
|
||||
public:
|
||||
SHT31();
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
bool begin(const uint8_t address, uint8_t dataPin, uint8_t clockPin);
|
||||
#endif
|
||||
bool begin(const uint8_t address);
|
||||
bool begin(const uint8_t address, TwoWire *wire);
|
||||
|
||||
// blocks 15 milliseconds + actual read + math
|
||||
bool read(bool fast = true);
|
||||
|
||||
// details see datasheet
|
||||
// details see datasheet; summary in SHT31.cpp file
|
||||
uint16_t readStatus();
|
||||
|
||||
// lastRead is in MilliSeconds since start sketch
|
||||
// lastRead is in milliSeconds since start
|
||||
uint32_t lastRead() { return _lastRead; };
|
||||
|
||||
void reset();
|
||||
void reset(bool hard = false);
|
||||
|
||||
// do not use heater for long periods,
|
||||
// use it for max 3 minutes to heat up
|
||||
// and let it cool down an equal period.
|
||||
void setHeatTimeout(uint8_t seconds);
|
||||
void heatOn();
|
||||
void heatOff();
|
||||
bool heatUp(); // is the sensor still heating up?
|
||||
|
||||
float humidity;
|
||||
float temperature;
|
||||
float getHumidity() { return humidity; };
|
||||
float getTemperature() { return temperature; };
|
||||
|
||||
// ASYNC INTERFACE
|
||||
void requestData();
|
||||
bool dataReady();
|
||||
void readData();
|
||||
bool readData(bool fast = true);
|
||||
|
||||
private:
|
||||
uint8_t crc8(const uint8_t *data, int len);
|
||||
void writeCmd(uint16_t cmd);
|
||||
void readBytes(uint8_t n, uint8_t *val);
|
||||
TwoWire* _wire;
|
||||
|
||||
uint8_t _addr;
|
||||
uint8_t _heatTimeOut; // seconds
|
||||
uint32_t _lastRead;
|
||||
uint32_t _lastRequest; // for async interface
|
||||
uint32_t _heaterStart;
|
||||
|
||||
float humidity;
|
||||
float temperature;
|
||||
};
|
||||
|
||||
#endif
|
||||
// -- END OF FILE --
|
||||
// -- END OF FILE --
|
||||
|
@ -1,10 +1,9 @@
|
||||
//
|
||||
// FILE: SHT31_I2Cspeed
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: demo
|
||||
//
|
||||
// HISTORY:
|
||||
// VERSION: 0.0.2
|
||||
// PURPOSE: testing the performance at different I2C speeds
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SHT31.h"
|
||||
@ -24,8 +23,10 @@ void setup()
|
||||
Wire.begin();
|
||||
sht.begin(0x44);
|
||||
Wire.setClock(100000);
|
||||
|
||||
uint16_t stat = sht.readStatus();
|
||||
Serial.print(stat, HEX);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -47,8 +48,10 @@ void test()
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.temperature, 1);
|
||||
Serial.print(sht.getTemperature(), 1);
|
||||
Serial.print("\t");
|
||||
Serial.println(sht.humidity, 1);
|
||||
Serial.println(sht.getHumidity(), 1);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,16 +1,16 @@
|
||||
//
|
||||
// FILE: SHT31_I2Cspeed
|
||||
// FILE: SHT31_async.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: demo
|
||||
//
|
||||
// HISTORY:
|
||||
// VERSION: 0.0.2
|
||||
// PURPOSE: demo async interface
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SHT31.h"
|
||||
|
||||
uint32_t start;
|
||||
uint32_t stop;
|
||||
uint32_t cnt;
|
||||
|
||||
SHT31 sht;
|
||||
|
||||
@ -24,31 +24,42 @@ void setup()
|
||||
Wire.begin();
|
||||
sht.begin(0x44);
|
||||
Wire.setClock(100000);
|
||||
|
||||
uint16_t stat = sht.readStatus();
|
||||
Serial.print(stat, HEX);
|
||||
Serial.println();
|
||||
|
||||
sht.requestData();
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for (uint32_t I2Cfreq = 100000; I2Cfreq < 900000; I2Cfreq += 50000)
|
||||
if (sht.dataReady())
|
||||
{
|
||||
Serial.print(I2Cfreq/1000);
|
||||
Wire.setClock(I2Cfreq);
|
||||
test();
|
||||
start = micros();
|
||||
bool success = sht.readData(); // default = true = fast
|
||||
stop = micros();
|
||||
sht.requestData(); // request for next sample
|
||||
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
if (success == false)
|
||||
{
|
||||
Serial.println("Failed read");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(sht.getTemperature(), 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.getHumidity(), 1);
|
||||
Serial.print("\t");
|
||||
Serial.println(cnt);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
cnt++; // simulate activity
|
||||
}
|
||||
|
||||
|
||||
void test()
|
||||
{
|
||||
start = micros();
|
||||
sht.read(true); // default = true/fast slow = false
|
||||
stop = micros();
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.temperature, 1);
|
||||
Serial.print("\t");
|
||||
Serial.println(sht.humidity, 1);
|
||||
delay(100);
|
||||
}
|
||||
// -- END OF FILE --
|
||||
|
@ -1,10 +1,9 @@
|
||||
//
|
||||
// FILE: SHT31_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// VERSION: 0.0.2
|
||||
// PURPOSE: demo
|
||||
//
|
||||
// HISTORY:
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SHT31.h"
|
||||
@ -26,6 +25,7 @@ void setup()
|
||||
Wire.setClock(100000);
|
||||
uint16_t stat = sht.readStatus();
|
||||
Serial.print(stat, HEX);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -37,8 +37,10 @@ void loop()
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.temperature, 1);
|
||||
Serial.print(sht.getTemperature(), 1);
|
||||
Serial.print("\t");
|
||||
Serial.println(sht.humidity, 1);
|
||||
Serial.println(sht.getHumidity(), 1);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
63
libraries/SHT31/examples/SHT31_heater/SHT31_heater.ino
Normal file
63
libraries/SHT31/examples/SHT31_heater/SHT31_heater.ino
Normal file
@ -0,0 +1,63 @@
|
||||
//
|
||||
// FILE: SHT31_heater.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: demo heater functions
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SHT31.h"
|
||||
|
||||
SHT31 sht;
|
||||
uint16_t stat;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("SHT31_LIB_VERSION: \t");
|
||||
Serial.println(SHT31_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
sht.begin(0x44);
|
||||
Wire.setClock(100000);
|
||||
|
||||
sht.setHeatTimeout(30); // heater timeout 30 seconds, just for demo.
|
||||
|
||||
stat = sht.readStatus();
|
||||
printHeaterStatus(stat);
|
||||
|
||||
sht.heatOn();
|
||||
|
||||
while (sht.heatUp())
|
||||
{
|
||||
stat = sht.readStatus();
|
||||
printHeaterStatus(stat);
|
||||
sht.read();
|
||||
Serial.println(sht.getTemperature());
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
Serial.println("switched off");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// forced switch off
|
||||
if (stat & SHT31_STATUS_HEATER_ON) sht.heatOff();
|
||||
}
|
||||
|
||||
|
||||
void printHeaterStatus(uint16_t stat)
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.print("\tHEATER: ");
|
||||
if (stat & SHT31_STATUS_HEATER_ON)
|
||||
{
|
||||
Serial.println("ON");
|
||||
} else {
|
||||
Serial.println("OFF");
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,10 +1,9 @@
|
||||
//
|
||||
// FILE: SHT31_lastRead.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// VERSION: 0.0.2
|
||||
// PURPOSE: demo
|
||||
//
|
||||
// HISTORY:
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SHT31.h"
|
||||
@ -24,8 +23,10 @@ void setup()
|
||||
Wire.begin();
|
||||
sht.begin(0x44);
|
||||
Wire.setClock(100000);
|
||||
|
||||
uint16_t stat = sht.readStatus();
|
||||
Serial.print(stat, HEX);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -34,8 +35,10 @@ void loop()
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.lastRead());
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.temperature, 1);
|
||||
Serial.print(sht.getTemperature(), 1);
|
||||
Serial.print("\t");
|
||||
Serial.println(sht.humidity, 1);
|
||||
Serial.println(sht.getHumidity(), 1);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,10 +1,9 @@
|
||||
//
|
||||
// FILE: SHT31_slowRead.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// VERSION: 0.0.2
|
||||
// PURPOSE: demo
|
||||
//
|
||||
// HISTORY:
|
||||
// URL: https://github.com/RobTillaart/SHT31
|
||||
|
||||
#include "Wire.h"
|
||||
#include "SHT31.h"
|
||||
@ -24,8 +23,10 @@ void setup()
|
||||
Wire.begin();
|
||||
sht.begin(0x44);
|
||||
Wire.setClock(100000);
|
||||
|
||||
uint16_t stat = sht.readStatus();
|
||||
Serial.print(stat, HEX);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -36,8 +37,10 @@ void loop()
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(sht.temperature, 1);
|
||||
Serial.print(sht.getTemperature(), 1);
|
||||
Serial.print("\t");
|
||||
Serial.println(sht.humidity, 1);
|
||||
Serial.println(sht.getHumidity(), 1);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,22 +1,32 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For AnalogKeypad
|
||||
#######################################
|
||||
# Syntax Coloring Map For SHT31
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
SHT31 KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
begin KEYWORD2
|
||||
read KEYWORD2
|
||||
readStatus KEYWORD2
|
||||
lastRead KEYWORD2
|
||||
reset KEYWORD2
|
||||
setHeatTimeout KEYWORD2
|
||||
heatOn KEYWORD2
|
||||
heatOff KEYWORD2
|
||||
heatUp KEYWORD2
|
||||
getHumidity KEYWORD2
|
||||
getTemperature KEYWORD2
|
||||
requestData KEYWORD2
|
||||
dataReady KEYWORD2
|
||||
readData KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
SHT31_LIB_VERSION LITERAL1
|
||||
SHT31_STATUS_ALERT_PENDING LITERAL1
|
||||
SHT31_STATUS_HEATER_ON LITERAL1
|
||||
SHT31_STATUS_HUM_TRACK_ALERT LITERAL1
|
||||
SHT31_STATUS_TEMP_TRACK_ALERT LITERAL1
|
||||
SHT31_STATUS_SYSTEM_RESET LITERAL1
|
||||
SHT31_STATUS_COMMAND_STATUS LITERAL1
|
||||
SHT31_STATUS_WRITE_CRC_STATUS LITERAL1
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "SHT31",
|
||||
"keywords": "SHT31 Temperature Humidity I2C",
|
||||
"description": "Class for SHT31 sensor, e.g. Adafruit I2C",
|
||||
"keywords": "SHT31 Temperature Humidity I2C SHT30 SHT35",
|
||||
"description": "Arduino library for the I2C SHT31 temperature and humidity sensor",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/SHT31",
|
||||
},
|
||||
"version":"0.1.2",
|
||||
"version":"0.2.2",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/SHT31"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=SHT31
|
||||
version=0.1.2
|
||||
version=0.2.2
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library for SHT31 Temperature Humidity
|
||||
sentence=Arduino library for the SHT31 temperature and humidity sensor
|
||||
paragraph=Class for SHT31 Temperature Humidity Adafruit I2C
|
||||
category=Signal Input/Output
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries
|
||||
architectures=*
|
||||
category=Sensor
|
||||
url=https://github.com/RobTillaart/SHT31
|
||||
architectures=*
|
||||
includes=Wire.h,SHT31.h
|
||||
depends=
|
21
libraries/Set/LICENSE
Normal file
21
libraries/Set/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
46
libraries/Set/README.md
Normal file
46
libraries/Set/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# SET
|
||||
|
||||
Arduino library to implement simple SET data structure.
|
||||
|
||||
# Description
|
||||
|
||||
The set library implements the set data structure for integers 0..255.
|
||||
This limit is chosen because of the memory limitations of an Arduino UNO,
|
||||
however these numbers can be used as indices to a table of strings or other
|
||||
datatypes.
|
||||
|
||||
Set level
|
||||
- **clr()** empty the set
|
||||
- **invert()** flip all elements in the set.
|
||||
- **count()** returns number of elements
|
||||
- **isEmpty()** idem
|
||||
- **isFull()** idem
|
||||
|
||||
Element level
|
||||
- **add(n)** add element to the Set
|
||||
- **sub(n)** emove element from Set
|
||||
- **invert(n)** flip element in Set
|
||||
- **has(n)** element is in Set
|
||||
- **add(n)**
|
||||
|
||||
Operators
|
||||
- union + +=
|
||||
- diff - -=
|
||||
- intersection * *=
|
||||
|
||||
Equality
|
||||
- equal ==
|
||||
- not equal !=
|
||||
- is subSet <=
|
||||
|
||||
A superSet B is not implemented as one could say B subSet A (B <= A)
|
||||
|
||||
Iterators - all returns value or -1 if not exist
|
||||
- **first()** find first element
|
||||
- **next()** find next element
|
||||
- **prev()** find previous element
|
||||
- **last()** find last element
|
||||
|
||||
# Operational
|
||||
|
||||
See examples
|
@ -1,11 +1,14 @@
|
||||
//
|
||||
// FILE: Set.cpp
|
||||
// FILE: set.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.11
|
||||
// VERSION: 0.2.1
|
||||
// DATE: 2014-09-11
|
||||
// PURPOSE: SET library for Arduino
|
||||
// URL:
|
||||
// URL: https://github.com/RobTillaart/SET
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.2.1 2020-06-19 fix library.json
|
||||
// 0.2.0 2020-05-02 refactored, removed pre 1.0 support
|
||||
// 0.1.11 2017-07-16 fix count() --> 16 bit when set is full !
|
||||
// 0.1.10 2017-07-16 performance refactor. isEmpty()
|
||||
// 0.1.09 2015-07-12 const + constructor
|
||||
@ -20,10 +23,8 @@
|
||||
// 0.1.01 extending/refactor etc (09/11/2014)
|
||||
// 0.1.00 initial version by Rob Tillaart (09/11/2014)
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "Set.h"
|
||||
#include "set.h"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
@ -40,7 +41,7 @@ Set::Set(const bool clear)
|
||||
|
||||
Set::Set(const Set &t)
|
||||
{
|
||||
for (uint8_t i=0; i<32; i++)
|
||||
for (uint8_t i = 0; i < 32; i++)
|
||||
{
|
||||
_mem[i] = t._mem[i];
|
||||
}
|
||||
@ -54,39 +55,42 @@ Set::Set(const Set &t)
|
||||
void Set::add(const uint8_t v)
|
||||
{
|
||||
uint8_t idx = v / 8;
|
||||
_mem[idx] |= masks[v&7];
|
||||
_mem[idx] |= masks[v & 7];
|
||||
}
|
||||
|
||||
void Set::sub(const uint8_t v)
|
||||
{
|
||||
uint8_t idx = v / 8;
|
||||
_mem[idx] &= ~masks[v&7];
|
||||
_mem[idx] &= ~masks[v & 7];
|
||||
}
|
||||
|
||||
void Set::invert(const uint8_t v)
|
||||
{
|
||||
uint8_t idx = v / 8;
|
||||
_mem[idx] ^= masks[v&7];;
|
||||
_mem[idx] ^= masks[v & 7];
|
||||
}
|
||||
|
||||
bool Set::has(const uint8_t v)
|
||||
{
|
||||
uint8_t idx = v / 8;
|
||||
return (_mem[idx] & masks[v&7]) > 0;
|
||||
return (_mem[idx] & masks[v & 7]) > 0;
|
||||
}
|
||||
|
||||
uint16_t Set::count() const
|
||||
{
|
||||
uint16_t cnt = 0;
|
||||
for (uint8_t i=0; i<32; i++)
|
||||
|
||||
uint8_t i = 32;
|
||||
do
|
||||
{
|
||||
// kerningham bit count trick
|
||||
uint8_t b = _mem[i];
|
||||
uint8_t b = _mem[--i];
|
||||
for (; b; cnt++)
|
||||
{
|
||||
b &= b-1;
|
||||
}
|
||||
}
|
||||
while (i != 0);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
@ -97,33 +101,48 @@ void Set::clr()
|
||||
|
||||
void Set::invert()
|
||||
{
|
||||
for (uint8_t i=0; i<32; i++)
|
||||
uint8_t i = 32;
|
||||
do
|
||||
{
|
||||
_mem[i] ^= 0xFF;
|
||||
}
|
||||
_mem[--i] ^= 0xFF;
|
||||
}
|
||||
while (i != 0);
|
||||
}
|
||||
|
||||
bool Set::isEmpty()
|
||||
{
|
||||
for (uint8_t i=0; i<32; i++)
|
||||
uint8_t i = 32;
|
||||
do
|
||||
{
|
||||
if (_mem[i]) return false;
|
||||
}
|
||||
if (_mem[--i] > 0) return false;
|
||||
}
|
||||
while (i != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Set::isFull()
|
||||
{
|
||||
for (uint8_t i=0; i<32; i++)
|
||||
// check two elements per loop
|
||||
// is faster for full sets but slower for empty set.
|
||||
// footprint is ~25 bytese larger
|
||||
// overal performance gain
|
||||
uint8_t i = 32;
|
||||
do
|
||||
{
|
||||
if (_mem[i] != 255) return false;
|
||||
}
|
||||
if ((_mem[--i]) != 255) return false;
|
||||
}
|
||||
while (i != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Set::first()
|
||||
{
|
||||
return findNext(0,0);
|
||||
if (has(0))
|
||||
{
|
||||
_current = 0;
|
||||
return _current;
|
||||
}
|
||||
return findNext(0, 0);
|
||||
}
|
||||
|
||||
int Set::next()
|
||||
@ -135,6 +154,37 @@ int Set::next()
|
||||
return findNext(p, q);
|
||||
}
|
||||
|
||||
// pointer math version ~12% faster but not for previous
|
||||
// needs investigation.
|
||||
// int Set::findNext(const uint8_t p, const uint8_t q)
|
||||
// {
|
||||
// uint8_t * pp = &_mem[p];
|
||||
// uint8_t mask = 1 << q;
|
||||
// uint8_t j = q;
|
||||
// do
|
||||
// {
|
||||
// if (*pp != 0)
|
||||
// {
|
||||
// while (j < 8)
|
||||
// {
|
||||
// if (*pp & mask)
|
||||
// {
|
||||
// _current = (pp - _mem) * 8 + j;
|
||||
// return _current;
|
||||
// }
|
||||
// mask <<= 1;
|
||||
// j++;
|
||||
// }
|
||||
// }
|
||||
// j = 0;
|
||||
// mask = 1;
|
||||
// pp++;
|
||||
// }
|
||||
// while (pp != &_mem[31]);
|
||||
// _current = -1;
|
||||
// return _current;
|
||||
// }
|
||||
|
||||
int Set::findNext(const uint8_t p, uint8_t q)
|
||||
{
|
||||
for (uint8_t i = p; i < 32; i++)
|
||||
@ -142,7 +192,7 @@ int Set::findNext(const uint8_t p, uint8_t q)
|
||||
uint8_t b = _mem[i];
|
||||
if (b != 0)
|
||||
{
|
||||
uint8_t mask = 1 << q;
|
||||
uint8_t mask = 1 << q; // masks[q]
|
||||
for (uint8_t j = q; j < 8; j++)
|
||||
{
|
||||
if (b & mask)
|
||||
@ -170,6 +220,11 @@ int Set::prev()
|
||||
|
||||
int Set::last()
|
||||
{
|
||||
if (has(255))
|
||||
{
|
||||
_current = 255;
|
||||
return _current;
|
||||
}
|
||||
return findPrev(31, 7);
|
||||
}
|
||||
|
||||
@ -192,7 +247,7 @@ int Set::findPrev(const uint8_t p, uint8_t q)
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
m = 1 << 7;
|
||||
m = 128; // 1 << 7;
|
||||
q = 7;
|
||||
}
|
||||
_current = -1;
|
||||
@ -285,6 +340,5 @@ bool Set::operator <= (const Set &t) const // subSet
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// END OF FILE
|
||||
//
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,24 +1,19 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: Set.h
|
||||
// FILE: set.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.11
|
||||
// VERSION: 0.2.1
|
||||
// DATE: 2014-09-11
|
||||
// PURPOSE: SET library for Arduino
|
||||
// URL:
|
||||
// URL: https://github.com/RobTillaart/SET
|
||||
//
|
||||
// HISTORY:
|
||||
// see Set.cpp file
|
||||
//
|
||||
|
||||
#ifndef Set_h
|
||||
#define Set_h
|
||||
|
||||
#if ARDUINO < 100
|
||||
#include <WProgram.h>
|
||||
#else
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#define SET_LIB_VERSION "0.1.11"
|
||||
#define SET_LIB_VERSION "0.2.1"
|
||||
|
||||
class Set
|
||||
{
|
||||
@ -63,11 +58,10 @@ public:
|
||||
private:
|
||||
uint8_t _mem[32]; // can hold 0..255
|
||||
uint8_t masks[8] = {1, 2, 4, 8, 16, 32, 64, 128};
|
||||
int _current;
|
||||
int _current = -1;
|
||||
|
||||
int findNext(const uint8_t, const uint8_t); // helper for first, next
|
||||
int findPrev(const uint8_t, const uint8_t); // helper for last, prev
|
||||
};
|
||||
#endif
|
||||
//
|
||||
// END OF FILE
|
||||
//
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -9,11 +9,13 @@
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "Set.h"
|
||||
#include "set.h"
|
||||
|
||||
Set setA, setB;
|
||||
volatile bool b;
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
@ -42,47 +44,47 @@ void timingTest()
|
||||
|
||||
Serial.println("TIMING TEST");
|
||||
Serial.print("100x clr():\t");
|
||||
uint32_t start = micros();
|
||||
for (uint8_t i=0; i<100; i++) myset.clr();
|
||||
uint32_t stop = micros();
|
||||
Serial.println(stop-start);
|
||||
start = micros();
|
||||
for (uint8_t i = 0; i < 100; i++) myset.clr();
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x add():\t");
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) myset.add(i);
|
||||
for (uint8_t i = 0; i < 100; i++) myset.add(i);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x sub():\t");
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) myset.sub(i);
|
||||
for (uint8_t i = 0; i < 100; i++) myset.sub(i);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x has():\t");
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) b = myset.has(i);
|
||||
for (uint8_t i = 0; i < 100; i++) b = myset.has(i);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x invert(v):\t");
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) myset.invert(i);
|
||||
for (uint8_t i = 0; i < 100; i++) myset.invert(i);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("invert():\t");
|
||||
start = micros();
|
||||
myset.invert();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("count() empty:\t");
|
||||
myset.clr();
|
||||
start = micros();
|
||||
myset.count();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("count() full:\t");
|
||||
myset.clr();
|
||||
@ -90,42 +92,45 @@ void timingTest()
|
||||
start = micros();
|
||||
myset.count();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("100x isEmpty(): empty\t");
|
||||
myset.clr();
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) b = myset.isEmpty();
|
||||
for (uint8_t i = 0; i < 100; i++) b = myset.isEmpty();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x isEmpty(): full\t");
|
||||
myset.clr();
|
||||
myset.invert();
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) b = myset.isEmpty();
|
||||
for (uint8_t i = 0; i < 100; i++) b = myset.isEmpty();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x isFull(): empty\t");
|
||||
myset.clr();
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) b = myset.isFull();
|
||||
for (uint8_t i = 0; i < 100; i++) b = myset.isFull();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("100x isFull(): full\t");
|
||||
myset.clr();
|
||||
myset.invert();
|
||||
start = micros();
|
||||
for (uint8_t i=0; i<100; i++) b = myset.isFull();
|
||||
for (uint8_t i = 0; i < 100; i++) b = myset.isFull();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
Serial.println();
|
||||
|
||||
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
for (int i = 0; i<150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
@ -135,95 +140,101 @@ void timingTest()
|
||||
start = micros();
|
||||
myset = setA + setB;
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a = b - c:\t");
|
||||
start = micros();
|
||||
myset = setA - setB;
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a = b * c:\t");
|
||||
start = micros();
|
||||
myset = setA * setB;
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a += b:\t");
|
||||
start = micros();
|
||||
myset += setA;
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a -= b:\t");
|
||||
start = micros();
|
||||
myset -= setA;
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a *= b:\t");
|
||||
start = micros();
|
||||
myset *= setA;
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a == b:\t");
|
||||
start = micros();
|
||||
b = (setA == setB);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a != b:\t");
|
||||
start = micros();
|
||||
b = (setA != setB);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("a <= b:\t");
|
||||
start = micros();
|
||||
b = (setA <= setB);
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.println();
|
||||
Serial.println("iteration 10 elements");
|
||||
Serial.print("first:\t");
|
||||
setA.clr();
|
||||
randomSeed(1);
|
||||
for (int i=0; i<10; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
}
|
||||
start = micros();
|
||||
int n = setA.first();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("next:\t");
|
||||
start = micros();
|
||||
n = setA.next();
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("first + next until -1 :\t");
|
||||
Serial.print("100x first + next until -1 :\t");
|
||||
start = micros();
|
||||
n = setA.first();
|
||||
while (n != -1)
|
||||
for (uint8_t i = 0; i < 100; i++)
|
||||
{
|
||||
n = setA.next();
|
||||
n = setA.first();
|
||||
while (n != -1)
|
||||
{
|
||||
n = setA.next();
|
||||
}
|
||||
}
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("last + prev until -1 :\t");
|
||||
Serial.print("100x last + prev until -1 :\t");
|
||||
start = micros();
|
||||
n = setA.last();
|
||||
while (n != -1)
|
||||
for (uint8_t i = 0; i < 100; i++)
|
||||
{
|
||||
n = setA.prev();
|
||||
n = setA.last();
|
||||
while (n != -1)
|
||||
{
|
||||
n = setA.prev();
|
||||
}
|
||||
}
|
||||
stop = micros();
|
||||
Serial.println(stop-start);
|
||||
Serial.println(stop - start);
|
||||
Serial.println();
|
||||
|
||||
Serial.println();
|
||||
@ -262,7 +273,7 @@ void intersectionTest()
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
@ -277,7 +288,7 @@ void intersectionTest()
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
@ -292,7 +303,7 @@ void intersectionTest()
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
@ -311,7 +322,7 @@ void intersection2Test()
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
@ -342,7 +353,7 @@ void subsetTest()
|
||||
{
|
||||
Serial.println("SUBSET TEST");
|
||||
Set setE;
|
||||
for (int i=0; i<5; i++) setE.add(i);
|
||||
for (int i = 0; i < 5; i++) setE.add(i);
|
||||
|
||||
Set setF(setE);
|
||||
|
||||
@ -365,33 +376,47 @@ void subsetTest()
|
||||
|
||||
void iterationTest()
|
||||
{
|
||||
Serial.println("ITERATE OVER SET TEST");
|
||||
Serial.println("10x ITERATE OVER SET TEST");
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
for (int i=0; i<10; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
int n = setA.first();
|
||||
while (n != -1)
|
||||
start = micros();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.print('\t');
|
||||
n = setA.next();
|
||||
int n = setA.first();
|
||||
while (n != -1)
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.print('\t');
|
||||
n = setA.next();
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
stop = micros();
|
||||
Serial.println();
|
||||
|
||||
n = setA.last();
|
||||
while (n != -1)
|
||||
Serial.println(stop - start);
|
||||
Serial.println();
|
||||
|
||||
start = micros();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.print('\t');
|
||||
n = setA.prev();
|
||||
int n = setA.last();
|
||||
while (n != -1)
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.print('\t');
|
||||
n = setA.prev();
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
stop = micros();
|
||||
Serial.println();
|
||||
Serial.println(stop - start);
|
||||
Serial.println();
|
||||
}
|
||||
//
|
||||
// END OF FILE
|
||||
//
|
||||
|
||||
// -- END OF FILE --
|
||||
|
53
libraries/Set/examples/equalTest/equalTest.ino
Normal file
53
libraries/Set/examples/equalTest/equalTest.ino
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// FILE: equalTest.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo equality operators
|
||||
// DATE: 2014-11-09
|
||||
// URL: https://github.com/RobTillaart/SET
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "set.h"
|
||||
|
||||
Set setA, setB;
|
||||
volatile bool b;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start set_demo : ");
|
||||
Serial.println(SET_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("\n\nequal test");
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
Serial.println(setA == setB?"true":"false");
|
||||
setB.add(0);
|
||||
Serial.println(setA == setB?"true":"false");
|
||||
Serial.println(setA == setA?"true":"false");
|
||||
|
||||
Set setC(setB);
|
||||
Serial.println(setC == setB?"true":"false");
|
||||
Serial.println(setC.count());
|
||||
|
||||
Set setD = setB;
|
||||
Serial.println(setD != setB?"unequal":"equal");
|
||||
Serial.println(setD == setB?"true":"false");
|
||||
Serial.println(setD.count());
|
||||
|
||||
setD = setA;
|
||||
Serial.println(setD == setB?"true":"false");
|
||||
Serial.println(setD.count());
|
||||
|
||||
Serial.println("done...");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
102
libraries/Set/examples/interSectionTest/interSectionTest.ino
Normal file
102
libraries/Set/examples/interSectionTest/interSectionTest.ino
Normal file
@ -0,0 +1,102 @@
|
||||
//
|
||||
// FILE: set_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo set intersection union and diff
|
||||
// DATE: 2014-11-09
|
||||
// URL: https://github.com/RobTillaart/SET
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "set.h"
|
||||
|
||||
Set setA, setB;
|
||||
volatile bool b;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start set_demo : ");
|
||||
Serial.println(SET_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("\n\nintersection test");
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
Serial.println(setB.count());
|
||||
setA *= setB;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
for (int j=0; j<64; j++)
|
||||
{
|
||||
Serial.print(setA.has(i*64+j));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println("\n\nunion test");
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
Serial.println(setB.count());
|
||||
setA += setB;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
for (int j=0; j<64; j++)
|
||||
{
|
||||
Serial.print(setA.has(i*64+j));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println("\n\ndiff test");
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
setB.clr();
|
||||
for (int i=0; i<150; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
setB.add(random(256));
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
Serial.println(setB.count());
|
||||
setA -= setB;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
for (int j=0; j<64; j++)
|
||||
{
|
||||
Serial.print(setA.has(i*64+j));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
Serial.println();
|
||||
|
||||
Serial.println("done...");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
60
libraries/Set/examples/iterationTest/iterationTest.ino
Normal file
60
libraries/Set/examples/iterationTest/iterationTest.ino
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// FILE: iterationTest.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.00
|
||||
// PURPOSE: demo first, next, last, prev
|
||||
// DATE: 2014-11-09
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "set.h"
|
||||
|
||||
Set myset;
|
||||
Set setA, setB;
|
||||
|
||||
|
||||
volatile bool b;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start set_demo : ");
|
||||
Serial.println(SET_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("\n\niterate over set test");
|
||||
randomSeed(1);
|
||||
setA.clr();
|
||||
for (int i=0; i<10; i++)
|
||||
{
|
||||
setA.add(random(256));
|
||||
}
|
||||
Serial.println(setA.count());
|
||||
int n = setA.first();
|
||||
while (n != -1)
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.print('\t');
|
||||
n = setA.next();
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
n = setA.last();
|
||||
while (n != -1)
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.print('\t');
|
||||
n = setA.prev();
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println("done...");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
50
libraries/Set/examples/subsetTest/subsetTest.ino
Normal file
50
libraries/Set/examples/subsetTest/subsetTest.ino
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// FILE: subsetTest.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo
|
||||
// DATE: 2014-11-09
|
||||
// URL: https://github.com/RobTillaart/SET
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "set.h"
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start set_demo : ");
|
||||
Serial.println(SET_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("\n\nSubSet test");
|
||||
Set setE;
|
||||
for (int i = 0; i < 5; i++) setE.add(i);
|
||||
|
||||
Set setF(setE);
|
||||
|
||||
Serial.println(setE.count());
|
||||
Serial.println(setF.count());
|
||||
|
||||
Serial.println(setE <= setF?"subset":"no subset");
|
||||
Serial.println(setF <= setE?"subset":"no subset");
|
||||
|
||||
setF.add(6);
|
||||
Serial.println(setE <= setF?"subset":"no subset");
|
||||
Serial.println(setF <= setE?"subset":"no subset");
|
||||
|
||||
setF.sub(3);
|
||||
Serial.println(setE <= setF?"subset":"no subset");
|
||||
Serial.println(setF <= setE?"subset":"no subset");
|
||||
|
||||
Serial.println();
|
||||
|
||||
Serial.println("done...");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
81
libraries/Set/examples/timingTest/timingTest.ino
Normal file
81
libraries/Set/examples/timingTest/timingTest.ino
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// FILE: timingTest.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: timing test for set class methods
|
||||
// DATE: 2014-11-09
|
||||
// URL: https://github.com/RobTillaart/SET
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "set.h"
|
||||
|
||||
Set myset;
|
||||
Set setA, setB;
|
||||
|
||||
uint32_t start;
|
||||
uint32_t stop;
|
||||
|
||||
volatile bool b;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start set_demo : ");
|
||||
Serial.println(SET_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("\n\ntiming test");
|
||||
Serial.print("myset.clr():\t");
|
||||
start = micros();
|
||||
myset.clr();
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("myset.add():\t");
|
||||
start = micros();
|
||||
for (int i = 0; i < 256; i++) myset.add(i);
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("myset.sub():\t");
|
||||
start = micros();
|
||||
for (int i = 0; i < 256; i++) myset.sub(i);
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("myset.has():\t");
|
||||
start = micros();
|
||||
for (int i = 0; i < 256; i++) b = myset.has(i);
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("myset.invert(v):\t");
|
||||
start = micros();
|
||||
for (int i = 0; i < 256; i++) myset.invert(i);
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("myset.invert():\t");
|
||||
start = micros();
|
||||
myset.invert();
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("myset.count():\t");
|
||||
start = micros();
|
||||
myset.count();
|
||||
stop = micros();
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.println();
|
||||
|
||||
Serial.println("done...");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Set",
|
||||
"keywords": "Set,union,diff,intersection,equal,subset",
|
||||
"name": "SET",
|
||||
"keywords": "Set,add,sub,union,diff,intersection,equal,subset",
|
||||
"description": "Library to implement SET datastructure.",
|
||||
"authors":
|
||||
[
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/SET.git"
|
||||
},
|
||||
"version":"0.1.11",
|
||||
"version":"0.2.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/Set"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Set
|
||||
version=0.1.11
|
||||
name=SET
|
||||
version=0.2.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library to implement SET datastructure.
|
||||
paragraph=Supports union diff intersection equal subset
|
||||
sentence=Arduino library to implement simple SET datastructure.
|
||||
paragraph=Supports union diff intersection equal subset. Limited to numbers 0..255.
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/Set
|
||||
architectures=*
|
||||
includes=set.h
|
||||
depends=
|
||||
|
21
libraries/Statistic/LICENSE
Normal file
21
libraries/Statistic/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2010-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
81
libraries/Statistic/README.md
Normal file
81
libraries/Statistic/README.md
Normal file
@ -0,0 +1,81 @@
|
||||
# Statistic
|
||||
|
||||
Statistic library for Arduino includes sum, average, variance and std deviation
|
||||
|
||||
# Description
|
||||
|
||||
The statistic library is made to get basic statistical information from a
|
||||
one dimensional set of data, e.g. a stream of values of a sensor.
|
||||
|
||||
The stability of the formulas is improved by the help of Gil Ross (Thanks!)
|
||||
|
||||
The functions implemented are:
|
||||
|
||||
* **clear(useStdDev)**
|
||||
* **add(value)**
|
||||
* **count()** returns zero if count == zero (of course)
|
||||
* **sum()** returns zero if count == zero
|
||||
* **minimum()** returns zero if count == zero
|
||||
* **maximum()** returns zero if count == zero
|
||||
* **average()** returns NAN if count == zero
|
||||
|
||||
These three functions only work id useStdDev == true:
|
||||
|
||||
* **variance()** returns NAN if count == zero
|
||||
* **pop_stdev()** population stdev, returns NAN if count == zero
|
||||
* **unbiased_stdev()** returnsNAN if count == zero
|
||||
|
||||
|
||||
# Operational
|
||||
|
||||
See examples
|
||||
|
||||
# FAQ
|
||||
|
||||
### Q: Are individual samples still available?
|
||||
The values added to the library are not stored in the lib as it would use lots
|
||||
of memory quite fast. Instead a few calculated values are kept to be able to
|
||||
calculate the most important statistics.
|
||||
|
||||
|
||||
### Q: How many samples can the lib hold? (internal variables and overflow)
|
||||
The counter of samples is an **uint32_t**, implying a maximum of about **4 billion** samples.
|
||||
In practice 'strange' things might happen before this number is reached.
|
||||
There are two internal variables, **_sum** which is the sum of the values and **_ssq**
|
||||
which is the sum of the squared values. Both can overflow especially **_ssq**
|
||||
can and probably will grow fast. The library does not protect against it.
|
||||
|
||||
There is a workaround for this (to some extend) if one knows the approx
|
||||
average of the samples before. Before adding values to the lib subtract
|
||||
the expected average. The sum of the samples would move to around zero.
|
||||
This workaround has no influence on the standard deviation.
|
||||
|
||||
!! Do not forget to add the expected average to the calculated average.
|
||||
|
||||
*(Q: should this subtraction trick be build into the lib?)*
|
||||
|
||||
|
||||
### Q: How about the precision of the library?
|
||||
The precision of the internal variables is restricted due to the fact
|
||||
that they are 32 bit float (IEEE754). If the internal variable **_sum** has
|
||||
a large value, adding relative small values to the dataset wouldn't
|
||||
change its value any more. Same is true for **_ssq**. One might argue that
|
||||
statistically speaking these values are less significant, but in fact it is wrong.
|
||||
|
||||
There is a workaround for this (to some extend). If one has the samples in an
|
||||
array or on disk, one can sort the samples in increasing order (abs value)
|
||||
and add them from this sorted list. This will minimize the error,
|
||||
but it works only if the samples are available and the they may be added
|
||||
in the sorted increasing order.
|
||||
|
||||
|
||||
### Q: When will internal var's overflow? esp. squared sum
|
||||
IEEE754 floats have a max value of about **+-3.4028235E+38**
|
||||
|
||||
|
||||
### Q: Why are there two functions for stdev?
|
||||
There are two stdev functions the population stdev and the unbiased stdev.
|
||||
See Wikipedia for an elaborate description of the difference between these two.
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// FILE: Statistic.cpp
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// modified at 0.3 by Gil Ross at physics dot org
|
||||
// VERSION: 0.3.5
|
||||
// VERSION: 0.4.1
|
||||
// PURPOSE: Recursive statistical library for Arduino
|
||||
//
|
||||
// NOTE: 2011-01-07 Gill Ross
|
||||
@ -29,50 +29,49 @@
|
||||
// -------------
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1 - 2010-10-29 initial version
|
||||
// 0.2 - 2010-10-29 stripped to minimal functionality
|
||||
// 0.2.01 - 2010-10-30
|
||||
// added minimim, maximum, unbiased stdev,
|
||||
// changed counter to long -> int overflows @32K samples
|
||||
// 0.3 - 2011-01-07
|
||||
// branched from 0.2.01 version of Rob Tillaart's code
|
||||
// 0.3.1 - minor edits
|
||||
// 0.3.2 - 2012-11-10
|
||||
// minor edits
|
||||
// changed count -> unsigned long allows for 2^32 samples
|
||||
// added variance()
|
||||
// 0.3.3 - 2015-03-07
|
||||
// float -> double to support ARM (compiles)
|
||||
// moved count() sum() min() max() to .h; for optimizing compiler
|
||||
// 0.3.4 - 2017-07-31
|
||||
// Refactored const in many places
|
||||
// [reverted] double to float on request as float is 99.99% of the cases
|
||||
// good enough and float(32 bit) is supported in HW for some processors.
|
||||
// 0.3.5 - 2017-09-27
|
||||
// Added #include <Arduino.h> to fix uint32_t bug
|
||||
//
|
||||
// Released to the public domain
|
||||
// 0.1 2010-10-29 initial version
|
||||
// 0.2 2010-10-29 stripped to minimal functionality
|
||||
// 0.2.01 2010-10-30
|
||||
// added minimim, maximum, unbiased stdev,
|
||||
// changed counter to long -> int overflows @32K samples
|
||||
// 0.3 2011-01-07
|
||||
// branched from 0.2.01 version of Rob Tillaart's code
|
||||
// 0.3.1 2012-11-10 minor edits
|
||||
// 0.3.2 2012-11-10 minor edits
|
||||
// changed count -> unsigned long allows for 2^32 samples
|
||||
// added variance()
|
||||
// 0.3.3 2015-03-07
|
||||
// float -> double to support ARM (compiles)
|
||||
// moved count() sum() min() max() to .h; for optimizing compiler
|
||||
// 0.3.4 2017-07-31
|
||||
// Refactored const in many places
|
||||
// [reverted] double to float on request as float is 99.99% of the cases
|
||||
// good enough and float(32 bit) is supported in HW for some processors.
|
||||
// 0.3.5 2017-09-27
|
||||
// Added #include <Arduino.h> to fix uint32_t bug
|
||||
// 0.4.0 2020-05-13
|
||||
// refactor
|
||||
// Added flag to switch on the use of stdDev runtime. [idea marc.recksiedl]
|
||||
// 0.4.1 2020-06-19 fix library.json
|
||||
//
|
||||
|
||||
#include "Statistic.h"
|
||||
|
||||
Statistic::Statistic()
|
||||
Statistic::Statistic(bool useStdDev)
|
||||
{
|
||||
clear();
|
||||
clear(useStdDev);
|
||||
}
|
||||
|
||||
// resets all counters
|
||||
void Statistic::clear()
|
||||
void Statistic::clear(bool useStdDev) // useStdDev default true.
|
||||
{
|
||||
_cnt = 0;
|
||||
_sum = 0;
|
||||
_min = 0;
|
||||
_max = 0;
|
||||
#ifdef STAT_USE_STDEV
|
||||
_ssqdif = 0.0; // not _ssq but sum of square differences
|
||||
// which is SUM(from i = 1 to N) of
|
||||
// (f(i)-_ave_N)**2
|
||||
#endif
|
||||
_useStdDev = useStdDev;
|
||||
_ssqdif = 0.0;
|
||||
// note not _ssq but sum of square differences
|
||||
// which is SUM(from i = 1 to N) of f(i)-_ave_N)**2
|
||||
}
|
||||
|
||||
// adds a new value to the data-set
|
||||
@ -89,46 +88,48 @@ void Statistic::add(const float value)
|
||||
_sum += value;
|
||||
_cnt++;
|
||||
|
||||
#ifdef STAT_USE_STDEV
|
||||
if (_cnt > 1)
|
||||
if (_useStdDev && (_cnt > 1))
|
||||
{
|
||||
float _store = (_sum / _cnt - value);
|
||||
_ssqdif = _ssqdif + _cnt * _store * _store / (_cnt-1);
|
||||
_ssqdif = _ssqdif + _cnt * _store * _store / (_cnt - 1);
|
||||
|
||||
// ~10% faster but limits the amount of samples to 65K as _cnt*_cnt overflows
|
||||
// float _store = _sum - _cnt * value;
|
||||
// _ssqdif = _ssqdif + _store * _store / (_cnt*_cnt - _cnt);
|
||||
//
|
||||
// solution: TODO verify
|
||||
// _ssqdif = _ssqdif + (_store * _store / _cnt) / (_cnt - 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns the average of the data-set added sofar
|
||||
float Statistic::average() const
|
||||
{
|
||||
if (_cnt == 0) return NAN; // original code returned 0
|
||||
if (_cnt == 0) return NAN; // prevent DIV0 error
|
||||
return _sum / _cnt;
|
||||
}
|
||||
|
||||
// Population standard deviation = s = sqrt [ S ( Xi - µ )2 / N ]
|
||||
// http://www.suite101.com/content/how-is-standard-deviation-used-a99084
|
||||
#ifdef STAT_USE_STDEV
|
||||
|
||||
float Statistic::variance() const
|
||||
{
|
||||
if (_cnt == 0) return NAN; // otherwise DIV0 error
|
||||
if (!_useStdDev) return NAN;
|
||||
if (_cnt == 0) return NAN; // prevent DIV0 error
|
||||
return _ssqdif / _cnt;
|
||||
}
|
||||
|
||||
float Statistic::pop_stdev() const
|
||||
{
|
||||
if (_cnt == 0) return NAN; // otherwise DIV0 error
|
||||
if (!_useStdDev) return NAN;
|
||||
if (_cnt == 0) return NAN; // prevent DIV0 error
|
||||
return sqrt( _ssqdif / _cnt);
|
||||
}
|
||||
|
||||
float Statistic::unbiased_stdev() const
|
||||
{
|
||||
if (_cnt < 2) return NAN; // otherwise DIV0 error
|
||||
if (!_useStdDev) return NAN;
|
||||
if (_cnt < 2) return NAN; // prevent DIV0 error
|
||||
return sqrt( _ssqdif / (_cnt - 1));
|
||||
}
|
||||
|
||||
#endif
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -1,54 +1,45 @@
|
||||
#ifndef Statistic_h
|
||||
#define Statistic_h
|
||||
#pragma once
|
||||
//
|
||||
// FILE: Statistic.h
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// modified at 0.3 by Gil Ross at physics dot org
|
||||
// VERSION: 0.3.5
|
||||
// VERSION: 0.4.1
|
||||
// PURPOSE: Recursive Statistical library for Arduino
|
||||
// HISTORY: See Statistic.cpp
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
// the standard deviation increases the lib (<100 bytes)
|
||||
// it can be in/excluded by un/commenting next line (compile time)
|
||||
#define STAT_USE_STDEV 1
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <math.h>
|
||||
|
||||
#define STATISTIC_LIB_VERSION "0.3.5"
|
||||
#define STATISTIC_LIB_VERSION "0.4.1"
|
||||
|
||||
class Statistic
|
||||
{
|
||||
public:
|
||||
Statistic(); // "switches on/off" stdev run time
|
||||
void clear(); // "switches on/off" stdev run time
|
||||
Statistic(bool useStdDev = true); // "switches on/off" stdev run time
|
||||
void clear(bool useStdDev = true); // "switches on/off" stdev run time
|
||||
void add(const float);
|
||||
|
||||
// returns the number of values added
|
||||
uint32_t count() const { return _cnt; }; // zero if empty
|
||||
float sum() const { return _sum; }; // zero if empty
|
||||
float minimum() const { return _min; }; // zero if empty
|
||||
float maximum() const { return _max; }; // zero if empty
|
||||
float average() const; // NAN if empty
|
||||
uint32_t count() const { return _cnt; }; // zero if count == zero
|
||||
float sum() const { return _sum; }; // zero if count == zero
|
||||
float minimum() const { return _min; }; // zero if count == zero
|
||||
float maximum() const { return _max; }; // zero if count == zero
|
||||
float average() const; // NAN if count == zero
|
||||
|
||||
#ifdef STAT_USE_STDEV
|
||||
float variance() const; // NAN if empty
|
||||
float pop_stdev() const; // population stdev // NAN if empty
|
||||
float unbiased_stdev() const; // NAN if empty
|
||||
#endif
|
||||
// useStdDev must be true to use next three
|
||||
float variance() const; // NAN if count == zero
|
||||
float pop_stdev() const; // population stdev // NAN if count == zero
|
||||
float unbiased_stdev() const; // NAN if count == zero
|
||||
|
||||
protected:
|
||||
uint32_t _cnt;
|
||||
float _sum;
|
||||
float _min;
|
||||
float _max;
|
||||
#ifdef STAT_USE_STDEV
|
||||
float _ssqdif; // sum of squares difference
|
||||
#endif
|
||||
bool _useStdDev;
|
||||
float _ssqdif; // sum of squares difference
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: Average.ino
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// VERSION: 0.3
|
||||
// VERSION: 0.4
|
||||
// PURPOSE: Sample sketch for statistic library Arduino
|
||||
//
|
||||
|
||||
@ -37,15 +37,12 @@ void loop(void)
|
||||
Serial.println(myStats.maximum(), 4);
|
||||
Serial.print(" Average: ");
|
||||
Serial.println(myStats.average(), 4);
|
||||
// uncomment in Statistic.h file to use stdev
|
||||
#ifdef STAT_USE_STDEV
|
||||
Serial.print(" variance: ");
|
||||
Serial.println(myStats.variance(), 4);
|
||||
Serial.print(" pop stdev: ");
|
||||
Serial.println(myStats.pop_stdev(), 4);
|
||||
Serial.print(" unbias stdev: ");
|
||||
Serial.println(myStats.unbiased_stdev(), 4);
|
||||
#endif
|
||||
Serial.print(" time(ms): ");
|
||||
Serial.println(stop - start);
|
||||
Serial.println("=====================================");
|
||||
|
@ -0,0 +1,45 @@
|
||||
//
|
||||
// FILE: StatisticArray.ino
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// VERSION: 0.1
|
||||
// PURPOSE: Sample sketch for statistic library Arduino
|
||||
//
|
||||
|
||||
#include "Statistic.h"
|
||||
|
||||
Statistic stats[4];
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("Demo Statistics lib ");
|
||||
Serial.println(STATISTIC_LIB_VERSION);
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
stats[i].clear(); //explicitly start clean
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
long rn = random(0, 9999);
|
||||
int idx = random(0, 4);
|
||||
stats[idx].add(rn / 100.0 + 1);
|
||||
|
||||
if (stats[idx].count() == 10000)
|
||||
{
|
||||
Serial.print("IDX: ");
|
||||
Serial.println(idx);
|
||||
Serial.print(" Count: ");
|
||||
Serial.println(stats[idx].count());
|
||||
Serial.print(" Min: ");
|
||||
Serial.println(stats[idx].minimum(), 4);
|
||||
Serial.print(" Max: ");
|
||||
Serial.println(stats[idx].maximum(), 4);
|
||||
Serial.print(" Average: ");
|
||||
Serial.println(stats[idx].average(), 4);
|
||||
Serial.println("=====================================");
|
||||
stats[idx].clear();
|
||||
}
|
||||
}
|
60
libraries/Statistic/examples/TimingTest/TimingTest.ino
Normal file
60
libraries/Statistic/examples/TimingTest/TimingTest.ino
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// FILE: TimingTest.ino
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// VERSION: 0.2.0
|
||||
// PURPOSE: measure time difference for runtime stddev toggle.
|
||||
// add is 1024 millis faster for 10K adds ==> ~ 100uSec per add faster.
|
||||
|
||||
#include "Statistic.h"
|
||||
|
||||
Statistic myStats;
|
||||
|
||||
uint32_t start;
|
||||
uint32_t stop;
|
||||
|
||||
bool useStdDev = true;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("Demo Statistics lib ");
|
||||
Serial.println(STATISTIC_LIB_VERSION);
|
||||
myStats.clear(useStdDev);
|
||||
start = millis();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
long rn = random(0, 9999);
|
||||
myStats.add(rn / 100.0 + 1);
|
||||
if (myStats.count() == 10000)
|
||||
{
|
||||
stop = millis();
|
||||
Serial.print(" Count: ");
|
||||
Serial.println(myStats.count());
|
||||
Serial.print(" Min: ");
|
||||
Serial.println(myStats.minimum(), 4);
|
||||
Serial.print(" Max: ");
|
||||
Serial.println(myStats.maximum(), 4);
|
||||
Serial.print(" Average: ");
|
||||
Serial.println(myStats.average(), 4);
|
||||
if (useStdDev)
|
||||
{
|
||||
Serial.print(" variance: ");
|
||||
Serial.println(myStats.variance(), 4);
|
||||
Serial.print(" pop stdev: ");
|
||||
Serial.println(myStats.pop_stdev(), 4);
|
||||
Serial.print(" unbias stdev: ");
|
||||
Serial.println(myStats.unbiased_stdev(), 4);
|
||||
}
|
||||
Serial.print(" time(ms): ");
|
||||
Serial.println(stop - start);
|
||||
Serial.println("=====================================");
|
||||
useStdDev = !useStdDev;
|
||||
myStats.clear(useStdDev);
|
||||
start = millis();
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
21
libraries/Statistic/keywords.txt
Normal file
21
libraries/Statistic/keywords.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Syntax Coloring Map For Statistic
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
Statistic KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
clear KEYWORD2
|
||||
add KEYWORD2
|
||||
count KEYWORD2
|
||||
sum KEYWORD2
|
||||
minimum KEYWORD2
|
||||
maximum KEYWORD2
|
||||
average KEYWORD2
|
||||
variance KEYWORD2
|
||||
pop_stdev KEYWORD2
|
||||
unbiased_stdev KEYWORD2
|
||||
|
||||
# Instances (KEYWORD2)
|
||||
|
||||
# Constants (LITERAL1)
|
||||
STATISTIC_LIB_VERSION LITERAL1
|
@ -16,12 +16,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/Statistic.git"
|
||||
},
|
||||
"version":"0.3.5",
|
||||
"version":"0.4.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/Statistic"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Statistics
|
||||
version=0.3.5
|
||||
name=Statistic
|
||||
version=0.4.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library with basic statistical functions for Arduino.
|
||||
paragraph=Supports
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/Statistic
|
||||
architectures=*
|
||||
includes=Statistic.h
|
||||
depends=
|
||||
|
21
libraries/StopWatch/LICENSE
Normal file
21
libraries/StopWatch/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2011-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,8 +1,10 @@
|
||||
//
|
||||
// FILE: StopWatch.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.5
|
||||
// PURPOSE: Simple StopWatch library for Arduino
|
||||
// VERSION: 0.2.2
|
||||
// DATE: 2011-01-04
|
||||
// PURPOSE: Arduino Library implementing a stopwatch including seconds, milliseconds microseconds
|
||||
// URL: https://github.com/RobTillaart/StopWatch_RT
|
||||
//
|
||||
// The library is based upon millis() and therefore
|
||||
// has the same restrictions as millis() has wrt overflow.
|
||||
@ -15,30 +17,42 @@
|
||||
// By mromani & Rob Tillaart
|
||||
// 0.1.4 2017-07-16 refactored
|
||||
// 0.1.5 2017-09-13 removed const from functions
|
||||
//
|
||||
// Released to the public domain
|
||||
// 0.2.0 2020-05-07 updated metadata, removed pre 1.0 support; setResolution added, minutes added
|
||||
// 0.2.1 2020-06-19 fix library.json
|
||||
// 0.2.2 2020-07-14 fix #3 ESP support
|
||||
//
|
||||
|
||||
#include "StopWatch.h"
|
||||
|
||||
StopWatch::StopWatch(const enum Resolution res)
|
||||
{
|
||||
setResolution(res);
|
||||
}
|
||||
|
||||
void StopWatch::setResolution(const enum Resolution res)
|
||||
{
|
||||
reset();
|
||||
_res = res;
|
||||
switch(_res) {
|
||||
switch(_res)
|
||||
{
|
||||
case MICROS:
|
||||
_gettime = micros;
|
||||
break;
|
||||
case MILLIS:
|
||||
_gettime = millis;
|
||||
_gettime = _micros;
|
||||
break;
|
||||
|
||||
case SECONDS:
|
||||
_gettime = seconds;
|
||||
break;
|
||||
|
||||
case MINUTES:
|
||||
_gettime = minutes;
|
||||
break;
|
||||
|
||||
case MILLIS:
|
||||
default:
|
||||
_gettime = millis;
|
||||
_gettime = _millis;
|
||||
_res = MILLIS; // for default!
|
||||
break;
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
void StopWatch::reset()
|
||||
@ -58,7 +72,7 @@ void StopWatch::start()
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t StopWatch::value()
|
||||
uint32_t StopWatch::elapsed()
|
||||
{
|
||||
if (_state == StopWatch::RUNNING)
|
||||
{
|
||||
@ -75,4 +89,5 @@ void StopWatch::stop()
|
||||
_state = StopWatch::STOPPED;
|
||||
}
|
||||
}
|
||||
// END OF FILE
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,40 +1,47 @@
|
||||
#ifndef StopWatch_h
|
||||
#define StopWatch_h
|
||||
#pragma once
|
||||
//
|
||||
// FILE: StopWatch.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Simple StopWatch library for Arduino
|
||||
// VERSION: 0.2.2
|
||||
// PURPOSE: Arduino Library implementing a stopwatch including seconds, milliseconds microseconds
|
||||
// HISTORY: See StopWatch.cpp
|
||||
// URL: http://playground.arduino.cc/Code/StopWatchClass
|
||||
//
|
||||
// Released to the public domain
|
||||
// URL: https://github.com/RobTillaart/StopWatch_RT
|
||||
// http://playground.arduino.cc/Code/StopWatchClass
|
||||
//
|
||||
|
||||
#define STOPWATCH_LIB_VERSION "0.1.5"
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
|
||||
#define STOPWATCH_LIB_VERSION (F("0.2.2"))
|
||||
|
||||
// note - adjust divider can fix timing inaccuracies (to some extend)
|
||||
#ifndef STOPWATCH_SECONDS_DIVIDER
|
||||
#define STOPWATCH_SECONDS_DIVIDER 1000
|
||||
#endif
|
||||
|
||||
#ifndef STOPWATCH_MINUTES_DIVIDER
|
||||
#define STOPWATCH_MINUTES_DIVIDER 60000
|
||||
#endif
|
||||
|
||||
class StopWatch
|
||||
{
|
||||
public:
|
||||
enum State { RESET, RUNNING, STOPPED };
|
||||
enum Resolution { MILLIS, MICROS, SECONDS };
|
||||
enum Resolution { MICROS, MILLIS, SECONDS, MINUTES};
|
||||
|
||||
explicit StopWatch(const enum Resolution res = MILLIS);
|
||||
void start();
|
||||
void stop();
|
||||
void reset();
|
||||
uint32_t elapsed();
|
||||
|
||||
uint32_t value();
|
||||
uint32_t elapsed() { return value(); };
|
||||
bool isRunning() { return _state == StopWatch::RUNNING; };
|
||||
enum State state() { return _state; };
|
||||
|
||||
void setResolution(const enum Resolution res);
|
||||
enum Resolution resolution() { return _res; };
|
||||
|
||||
bool isRunning() { return _state == StopWatch::RUNNING; };
|
||||
enum State state() { return _state; };
|
||||
enum Resolution resolution() { return _res; };
|
||||
// value will become obsolete in the future, elapsed() is more descriptive
|
||||
uint32_t value() { return elapsed(); };
|
||||
|
||||
private:
|
||||
enum State _state;
|
||||
@ -44,8 +51,10 @@ private:
|
||||
uint32_t _stoptime;
|
||||
|
||||
uint32_t (*_gettime)(void);
|
||||
static uint32_t seconds() { return millis() / 1000; };
|
||||
static uint32_t _micros() { return micros(); }; // wrapper for ESP proc.
|
||||
static uint32_t _millis() { return millis(); };
|
||||
static uint32_t seconds() { return millis() / STOPWATCH_SECONDS_DIVIDER; };
|
||||
static uint32_t minutes() { return millis() / STOPWATCH_MINUTES_DIVIDER; };
|
||||
};
|
||||
|
||||
#endif
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -1,12 +1,10 @@
|
||||
//
|
||||
// FILE: sample.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: sample demo stopwatch class
|
||||
// DATE:
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
// DATE: 2011-01-04
|
||||
// URL: https://github.com/RobTillaart/StopWatch_RT
|
||||
//
|
||||
|
||||
#include <StopWatch.h>
|
||||
@ -35,7 +33,7 @@ void loop()
|
||||
for(int i=0; i<5; i++)
|
||||
{
|
||||
delay(10);
|
||||
Serial.println(MySW.value());
|
||||
Serial.println(MySW.elapsed());
|
||||
}
|
||||
|
||||
MySW.stop();
|
||||
@ -44,7 +42,7 @@ void loop()
|
||||
for(int i=0; i<5; i++)
|
||||
{
|
||||
delay(10);
|
||||
Serial.println(MySW.value());
|
||||
Serial.println(MySW.elapsed());
|
||||
}
|
||||
|
||||
MySW.start();
|
||||
@ -53,7 +51,7 @@ void loop()
|
||||
for(int i=0; i<5; i++)
|
||||
{
|
||||
delay(10);
|
||||
Serial.println(MySW.value());
|
||||
Serial.println(MySW.elapsed());
|
||||
}
|
||||
MySW.reset();
|
||||
Serial.println(MySW.isRunning());
|
||||
@ -65,7 +63,7 @@ void loop()
|
||||
for(int i=0; i<5; i++)
|
||||
{
|
||||
delay(10);
|
||||
Serial.println(MySW.value());
|
||||
Serial.println(MySW.elapsed());
|
||||
}
|
||||
|
||||
switch(MySW.state())
|
||||
@ -88,3 +86,5 @@ void loop()
|
||||
Serial.print(" >>> laptime loop() : ");
|
||||
Serial.println(SWarray[0].value());
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -1,12 +1,10 @@
|
||||
//
|
||||
// FILE: sample2.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: sample demo stopwatch class
|
||||
// DATE:
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
// DATE: 2011-01-04
|
||||
// URL: https://github.com/RobTillaart/StopWatch_RT
|
||||
//
|
||||
|
||||
#include <StopWatch.h>
|
||||
@ -35,4 +33,6 @@ void loop()
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -0,0 +1,50 @@
|
||||
//
|
||||
// FILE: stopwatch_resolution.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: sample demo stopwatch class
|
||||
// DATE: 2020-05-08
|
||||
// URL: https://github.com/RobTillaart/StopWatch_RT
|
||||
//
|
||||
|
||||
#include <StopWatch.h>
|
||||
|
||||
StopWatch MySW;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.println(STOPWATCH_LIB_VERSION);
|
||||
|
||||
MySW.start();
|
||||
delay(5000);
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(MySW.elapsed());
|
||||
Serial.print(" RES: ");
|
||||
Serial.println(MySW.resolution());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
simple_test(StopWatch::MICROS);
|
||||
simple_test(StopWatch::MILLIS);
|
||||
simple_test(StopWatch::SECONDS);
|
||||
simple_test(StopWatch::MINUTES);
|
||||
}
|
||||
|
||||
|
||||
void simple_test(StopWatch::Resolution res)
|
||||
{
|
||||
MySW.setResolution(res); // note: includes an automatic reset()
|
||||
MySW.start();
|
||||
delay(2500);
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(MySW.elapsed());
|
||||
Serial.print(" RES: ");
|
||||
Serial.println(MySW.resolution());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
22
libraries/StopWatch/keywords.txt
Normal file
22
libraries/StopWatch/keywords.txt
Normal file
@ -0,0 +1,22 @@
|
||||
# Syntax Coloring Map for StopWatch
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
StopWatch KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
start KEYWORD2
|
||||
stop KEYWORD2
|
||||
reset KEYWORD2
|
||||
elapsed KEYWORD2
|
||||
isRunning KEYWORD2
|
||||
state KEYWORD2
|
||||
setResolution KEYWORD2
|
||||
resolution KEYWORD2
|
||||
|
||||
# Constants (LITERAL1)
|
||||
RESET LITERAL1
|
||||
RUNNING LITERAL1
|
||||
STOPPED LITERAL1
|
||||
MILLIS LITERAL1
|
||||
MICROS LITERAL1
|
||||
SECONDS LITERAL1
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "StopWatch",
|
||||
"keywords": "StopWatch,start,stop,elapsed,millis,micros,seconds",
|
||||
"description": "Library to implement a stopwatch.",
|
||||
"description": "Arduino Library implementing a stopwatch including seconds, milliseconds microseconds.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/StopWatch_RT"
|
||||
},
|
||||
"version":"0.1.5",
|
||||
"version":"0.2.2",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/StopWatch"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=StopWatch
|
||||
version=0.1.5
|
||||
name=StopWatch_RT
|
||||
version=0.2.2
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library to implement a stopwatch.
|
||||
sentence=Arduino Library implementing a stopwatch.
|
||||
paragraph=Supports millis micros seconds
|
||||
category=Timing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/Stopwatch_RT
|
||||
architectures=*
|
||||
includes=StopWatch.h
|
||||
depends=
|
||||
|
@ -1,4 +1,41 @@
|
||||
# Stopwatch_RT
|
||||
|
||||
Arduino Library implementing a stopwatch including seconds, milliseconds microseconds
|
||||
|
||||
0.1.03 has a breaking interface
|
||||
# Description
|
||||
|
||||
The stopwatch class allows one to create a stopwatch with 4 levels of resolution
|
||||
* MICROS - microseconds
|
||||
* MILLIS - milliseconds (default)
|
||||
* SECONDS - seconds
|
||||
* MINUTES - minutes (added 0.2.0)
|
||||
|
||||
Note that the resolution chosen implies the finest granularity of units measured.
|
||||
E.g. if chosen minutes then one cannot measure half (30 sec) or other part of a minute.
|
||||
|
||||
The resolution is typically set in the constructor, however since 0.2.0 one can call
|
||||
**setResolution()** to change the 'tick unit' of the clock runtime.
|
||||
This way one can reuse the stopwatch object without creating a new one and thereby
|
||||
save some memory.
|
||||
|
||||
**Warning:** Changing the resolution will reset the stopwatch
|
||||
as start time and stop time will become meaningless.
|
||||
The stopwatch will reset even when the resolution is the current resolution.
|
||||
|
||||
The other methods of the stopwatch are trivial
|
||||
* start()
|
||||
* stop()
|
||||
* elapsed() - - will return the time in chosen units since last **start()**
|
||||
* reset()
|
||||
* isRunning()
|
||||
* state()
|
||||
* resolution()
|
||||
|
||||
This library is based upon millis() and micros() and therefore has the same
|
||||
restrictions and limitations as these functions with respect to overflow
|
||||
and precision.
|
||||
This means minutes and seconds will overflow also after about 49 days.
|
||||
|
||||
# Operation
|
||||
|
||||
See examples
|
||||
|
21
libraries/Temperature/LICENSE
Normal file
21
libraries/Temperature/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,75 @@
|
||||
//
|
||||
// FILE: dewpoint_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-04
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
uint32_t start;
|
||||
uint32_t duration1;
|
||||
uint32_t duration2;
|
||||
|
||||
float maxError;
|
||||
volatile float dp;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.println("takes ~40 seconds");
|
||||
|
||||
Serial.println(dewPoint(25, 50), 2);
|
||||
Serial.println(dewPointFast(25, 50), 2);
|
||||
|
||||
Serial.println("\ndewPoint()");
|
||||
start = millis();
|
||||
for (int cel = -40; cel < 80; cel++)
|
||||
{
|
||||
for (int hum = 1; hum < 100; hum++)
|
||||
{
|
||||
dp = dewPoint(cel, hum);
|
||||
}
|
||||
}
|
||||
duration1 = millis() - start;
|
||||
Serial.println(duration1);
|
||||
|
||||
Serial.println("\ndewPointFast()");
|
||||
start = millis();
|
||||
for (int cel = -40; cel < 80; cel++)
|
||||
{
|
||||
for (int hum = 1; hum < 100; hum++)
|
||||
{
|
||||
dp = dewPointFast(cel, hum);
|
||||
}
|
||||
}
|
||||
duration2 = millis() - start;
|
||||
Serial.println(duration2);
|
||||
Serial.print("RATIO:\t");
|
||||
Serial.println((1.0 * duration1) / duration2, 3);
|
||||
|
||||
|
||||
Serial.println("\ndewPointFast() vs dewPoint()");
|
||||
for (int cel = -40; cel < 80; cel++)
|
||||
{
|
||||
for (int hum = 1; hum < 100; hum++)
|
||||
{
|
||||
float x = abs(dewPoint(cel, hum) - dewPointFast(cel, hum));
|
||||
if (x > maxError) maxError = x;
|
||||
}
|
||||
}
|
||||
Serial.print("ERROR:\t");
|
||||
Serial.println(maxError, 3);
|
||||
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,51 @@
|
||||
//
|
||||
// FILE: heatindexC_table.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-04
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
volatile float hi;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println();
|
||||
|
||||
for (int t = 25; t <= 45; t += 1)
|
||||
{
|
||||
Serial.print("\t");
|
||||
Serial.print(t);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
for (int hum = 40; hum <= 100; hum += 5)
|
||||
{
|
||||
Serial.print(hum);
|
||||
for (int t = 25; t <= 45; t += 1)
|
||||
{
|
||||
float hi = heatIndexC(t, hum);
|
||||
Serial.print("\t");
|
||||
Serial.print(round(hi));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,43 @@
|
||||
//
|
||||
// FILE: heatindexC_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-04
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
uint32_t start;
|
||||
uint32_t duration1;
|
||||
|
||||
volatile float hi;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println(heatIndexC(25, 50), 2);
|
||||
|
||||
start = millis();
|
||||
for (int cel = 10; cel < 80; cel++)
|
||||
{
|
||||
for (int hum = 1; hum < 100; hum++)
|
||||
{
|
||||
hi = heatIndexC(cel, hum);
|
||||
}
|
||||
}
|
||||
duration1 = millis() - start;
|
||||
Serial.println(duration1);
|
||||
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,51 @@
|
||||
//
|
||||
// FILE: heatindex_table.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-04
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
volatile float hi;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println();
|
||||
|
||||
for (int t = 80; t <= 110; t += 2)
|
||||
{
|
||||
Serial.print("\t");
|
||||
Serial.print(t);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
for (int hum = 40; hum <= 100; hum += 5)
|
||||
{
|
||||
Serial.print(hum);
|
||||
for (int t = 80; t <= 110; t += 2)
|
||||
{
|
||||
float hi = heatIndex(t, hum);
|
||||
Serial.print("\t");
|
||||
Serial.print(round(hi));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,43 @@
|
||||
//
|
||||
// FILE: heatIndex_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-04
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
uint32_t start;
|
||||
uint32_t duration1;
|
||||
|
||||
volatile float hi;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println(heatIndex(100, 50), 2);
|
||||
|
||||
start = millis();
|
||||
for (int t = 40; t < 110; t++)
|
||||
{
|
||||
for (int hum = 1; hum < 100; hum++)
|
||||
{
|
||||
hi = heatIndex(t, hum);
|
||||
}
|
||||
}
|
||||
duration1 = millis() - start;
|
||||
Serial.println(duration1);
|
||||
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,49 @@
|
||||
//
|
||||
// FILE: humidex_table.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-05
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println();
|
||||
|
||||
for (int cel = 20; cel < 45; cel++)
|
||||
{
|
||||
Serial.print("\t");
|
||||
Serial.print(cel);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
for (int hum = 100; hum > 15; hum -= 2)
|
||||
{
|
||||
Serial.print(hum);
|
||||
for (int cel = 20; cel < 45; cel++)
|
||||
{
|
||||
float dp = dewPoint(cel, hum);
|
||||
float hi = humidex(cel, dp);
|
||||
Serial.print("\t");
|
||||
Serial.print(round(hi));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
44
libraries/Temperature/examples/humidex_test/humidex_test.ino
Normal file
44
libraries/Temperature/examples/humidex_test/humidex_test.ino
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// FILE: humidex_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-04-05
|
||||
//
|
||||
|
||||
#include "temperature.h"
|
||||
|
||||
uint32_t start;
|
||||
uint32_t duration1;
|
||||
|
||||
volatile float hi;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
Serial.println(humidex(25, 50), 2);
|
||||
|
||||
start = millis();
|
||||
for (int t = 25; t <= 45; t++)
|
||||
{
|
||||
for (int hum = 1; hum <= 100; hum++)
|
||||
{
|
||||
float dp = dewPoint(t, hum);
|
||||
hi = humidex(t, dp);
|
||||
}
|
||||
}
|
||||
duration1 = millis() - start;
|
||||
Serial.println(duration1);
|
||||
|
||||
|
||||
Serial.print("Done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Temperature",
|
||||
"keywords": "Temperature,Kelvin,Celsius,Fahrenheit,dewPoint,humidex,heatIndex",
|
||||
"keywords": "Temperature, Kelvin, Celsius, Fahrenheit, dewPoint, humidex, heatIndex, windChill",
|
||||
"description": "Library with weather related functions.",
|
||||
"authors":
|
||||
[
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/Temperature"
|
||||
},
|
||||
"version":"0.1.1",
|
||||
"version":"0.2.3",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/Temperature"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Temperature
|
||||
version=0.1.1
|
||||
version=0.2.3
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library with weather related functions.
|
||||
paragraph=Kelvin Celsius Fahrenheit dewPoint humidex heatIndex
|
||||
paragraph=Kelvin Celsius Fahrenheit dewPoint humidex heatIndex windChill
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/Temperature
|
||||
architectures=*
|
||||
includes=temperature.h
|
||||
depends=
|
||||
|
@ -1,7 +1,21 @@
|
||||
# Temperature
|
||||
|
||||
Small collection of temperature related functions
|
||||
Arduino library with dewPoint, humidex, heatIndex and windchill functions.
|
||||
|
||||
TODO:
|
||||
- make all celsius variants of them
|
||||
- Class with option F / K / C ?
|
||||
## Description
|
||||
|
||||
This library contains some weather related functions. These functions
|
||||
are approximations based on work of NOAA a.o.
|
||||
|
||||
These functions can be used with temperature and humidity sensors e.g.
|
||||
DHT22 or Sensirion ones to make a weather station application.
|
||||
|
||||
|
||||
## Operations
|
||||
|
||||
The functions have a limited scope so one cannot use it for all input values possible.
|
||||
The user should be aware of that. Check the references mentioned in the code and or
|
||||
wikipedia to confirm the applicability of the values generated.
|
||||
The functions do not check the inputs.
|
||||
|
||||
See examples for typical usage.
|
||||
|
@ -1,123 +1,162 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: temperature.h
|
||||
// VERSION: 0.1.1
|
||||
// VERSION: 0.2.3
|
||||
// PURPOSE: temperature functions
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 - 2015-03-29 initial version
|
||||
// 0.1.1 - 2017-07-26 double to float (issue #33)
|
||||
//
|
||||
// 0.2.0 - 2020-04-04 #pragma once, removed WProgram.h, readme.md, comments
|
||||
// replaced obsolete links with new ones,
|
||||
// tested and removed some code
|
||||
// 0.2.1 2020-05-26 added windchill formulas
|
||||
// 0.2.2 2020-06-19 fix library.json
|
||||
// 0.2.3 2020-08-27 fix #5 order of functions, typo, fixed 1 example
|
||||
|
||||
#ifndef TEMPERATURE
|
||||
#define TEMPERATURE
|
||||
|
||||
#include "WProgram.h"
|
||||
#define TEMPERATURE_VERSION "0.2.3"
|
||||
|
||||
#define TEMPERATURE_VERSION "0.1.1"
|
||||
|
||||
//Celsius to Fahrenheit conversion
|
||||
float Fahrenheit(float celsius)
|
||||
inline float Fahrenheit(float celsius)
|
||||
{
|
||||
return 1.8 * celsius + 32;
|
||||
return 1.8 * celsius + 32; // 5.0 / 9.0 = 1.8
|
||||
}
|
||||
|
||||
//Celsius to Kelvin conversion
|
||||
float Kelvin(float celsius)
|
||||
|
||||
inline float Celsius(float fahrenheit)
|
||||
{
|
||||
return celsius + 273.15;
|
||||
return (fahrenheit - 32) * 0.55555555555; // 5.0 / 9.0 = 0.555...
|
||||
}
|
||||
|
||||
// dewPoint function NOAA
|
||||
// reference: http://wahiduddin.net/calc/density_algorithms.htm
|
||||
|
||||
inline float Kelvin(float celsius)
|
||||
{
|
||||
return celsius + 273.15;
|
||||
}
|
||||
|
||||
|
||||
// reference:
|
||||
// [1] https://wahiduddin.net/calc/density_algorithms.htm
|
||||
// [2] https://web.archive.org/web/20100528030817/https://www.colorado.edu/geography/weather_station/Geog_site/about.htm
|
||||
// dewPoint function based on code of [2]
|
||||
// calculation of the saturation vapor pressure part is based upon NOAA ESGG(temp)
|
||||
float dewPoint(float celsius, float humidity)
|
||||
{
|
||||
float A0= 373.15/(273.15 + celsius);
|
||||
float SUM = -7.90298*(A0-1);
|
||||
SUM += 5.02808 * log10(A0);
|
||||
SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
|
||||
SUM += 8.1328e-3*(pow(10,(-3.49149*(A0-1)))-1) ;
|
||||
SUM += log10(1013.246);
|
||||
float VP = pow(10, SUM-3) * humidity;
|
||||
float T = log(VP/0.61078); // temp var
|
||||
return (241.88*T) / (17.558-T);
|
||||
// Calculate saturation vapor pressure
|
||||
// ratio 100C and actual temp in Kelvin
|
||||
float A0 = 373.15 / (273.15 + celsius);
|
||||
// SVP = Saturation Vapor Pressure - based on ESGG() NOAA
|
||||
float SVP = -7.90298 * (A0 - 1.0);
|
||||
SVP += 5.02808 * log10(A0);
|
||||
SVP += -1.3816e-7 * (pow(10, (11.344 * ( 1.0 - 1.0/A0))) - 1.0 );
|
||||
SVP += 8.1328e-3 * (pow(10, (-3.49149 * (A0 - 1.0 ))) - 1.0 ) ;
|
||||
SVP += log10(1013.246);
|
||||
|
||||
// calculate actual vapor pressure VP;
|
||||
// note to convert to KPa the -3 is used
|
||||
float VP = pow(10, SVP - 3) * humidity;
|
||||
float T = log( VP / 0.61078); // temp var
|
||||
return (241.88 * T) / (17.558 - T);
|
||||
}
|
||||
|
||||
// delta max = 0.6544
|
||||
// 5x faster than dewPoint()
|
||||
// reference: http://en.wikipedia.org/wiki/Dew_point
|
||||
|
||||
// dewPointFast() is > 5x faster than dewPoint() - run dewpoint_test.ino
|
||||
// delta mdewPointFastax with dewpoint() - run dewpoint_test.ino ==> ~0.347
|
||||
// (earlier version mentions ~0.6544 but that testcode is gone :(
|
||||
// http://en.wikipedia.org/wiki/Dew_point
|
||||
float dewPointFast(float celsius, float humidity)
|
||||
{
|
||||
float a = 17.271;
|
||||
float b = 237.7;
|
||||
float temp = (a * celsius) / (b + celsius) + log(humidity/100);
|
||||
float Td = (b * temp) / (a - temp);
|
||||
return Td;
|
||||
float a = 17.271;
|
||||
float b = 237.7;
|
||||
float temp = (a * celsius) / (b + celsius) + log(humidity/100);
|
||||
float Td = (b * temp) / (a - temp);
|
||||
return Td;
|
||||
}
|
||||
|
||||
// http://www.ccacac.com/wp-content/uploads/2010/06/Humidex-Graph.pdf -
|
||||
|
||||
// https://en.wikipedia.org/wiki/Humidex
|
||||
float humidex(float celsius, float DewPoint)
|
||||
{
|
||||
float e = 19.833625 - 5417.753 /(273.16 + DewPoint);
|
||||
float h = celsius + 3.3941 * exp(e) - 5.555;
|
||||
return h;
|
||||
float e = 19.833625 - 5417.753 /(273.16 + DewPoint);
|
||||
float h = celsius + 3.3941 * exp(e) - 5.555;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// TF = temp in F
|
||||
// https://en.wikipedia.org/wiki/Heat_index
|
||||
// TODO add valid range for TF & R
|
||||
// TF = temp in Fahrenheit
|
||||
// R = humidity in %
|
||||
float heatIndex(float TF, float R)
|
||||
{
|
||||
const float c1 = -42.379;
|
||||
const float c2 = 2.04901523;
|
||||
const float c3 = 10.14333127;
|
||||
const float c4 = -0.22475541;
|
||||
const float c5 = -0.00683783;
|
||||
const float c6 = -0.05481717;
|
||||
const float c7 = 0.00122874;
|
||||
const float c8 = 0.00085282;
|
||||
const float c9 = -0.00000199;
|
||||
const float c1 = -42.379;
|
||||
const float c2 = 2.04901523;
|
||||
const float c3 = 10.14333127;
|
||||
const float c4 = -0.22475541;
|
||||
const float c5 = -0.00683783;
|
||||
const float c6 = -0.05481717;
|
||||
const float c7 = 0.00122874;
|
||||
const float c8 = 0.00085282;
|
||||
const float c9 = -0.00000199;
|
||||
|
||||
float A = (( c5 * TF) + c2) * TF + c1;
|
||||
float B = (((c7 * TF) + c4) * TF + c3) * R;
|
||||
float C = (((c9 * TF) + c8) * TF + c6) * R * R;
|
||||
float A = (( c5 * TF) + c2) * TF + c1;
|
||||
float B = (((c7 * TF) + c4) * TF + c3) * R;
|
||||
float C = (((c9 * TF) + c8) * TF + c6) * R * R;
|
||||
|
||||
return A + B + C;
|
||||
return A + B + C;
|
||||
}
|
||||
|
||||
// less constants => faster but slightly inaccurate
|
||||
// TF = temp in F
|
||||
// R = humidity in %
|
||||
float heatIndexFast(float TF, float R)
|
||||
|
||||
// https://en.wikipedia.org/wiki/Heat_index
|
||||
// TODO add valid range for TF & R
|
||||
float heatIndexC(float celcius, float humidity)
|
||||
{
|
||||
const float c1 = -42.379;
|
||||
const float c2 = 2.04901523;
|
||||
const float c3 = 10.14333127;
|
||||
const float c4 = -0.22475541;
|
||||
const float c1 = -8.78469475556;
|
||||
const float c2 = 1.61139411;
|
||||
const float c3 = 2.33854883889;
|
||||
const float c4 = -0.14611605;
|
||||
const float c5 = -0.012308094;
|
||||
const float c6 = -0.0164248277778;
|
||||
const float c7 = 0.002211732;
|
||||
const float c8 = 0.00072546;
|
||||
const float c9 = -0.000003582;
|
||||
|
||||
float A = c2 * TF + c1;
|
||||
float B = (c4 * TF + c3) * R;
|
||||
float A = (( c5 * celcius) + c2) * celcius + c1;
|
||||
float B = (((c7 * celcius) + c4) * celcius + c3) * humidity;
|
||||
float C = (((c9 * celcius) + c8) * celcius + c6) * humidity * humidity;
|
||||
|
||||
return A + B;
|
||||
return A + B + C;
|
||||
}
|
||||
|
||||
// integer version
|
||||
// TF = temp in F
|
||||
// R = humidity in %
|
||||
int heatIndexFastInt(int TF, int R)
|
||||
|
||||
// https://en.wikipedia.org/wiki/Wind_chill
|
||||
// US = Fahrenheit / miles
|
||||
// METRIC = Celsius / meter/sec
|
||||
// windspeed @ 10 meter,
|
||||
// if convert is true => windspeed will be converted to 1.5 meter
|
||||
// else ==> formula assumes windspeed @ 1.5 meter
|
||||
|
||||
// US
|
||||
float WindChill_F_mph(const float fahrenheit, const float milesPerHour, const bool convert = true)
|
||||
{
|
||||
// consts multiplied by 1024
|
||||
long c1 = -43396;
|
||||
long c2 = 2098;
|
||||
long c3 = 10387;
|
||||
long c4 = -230;
|
||||
|
||||
long A = c2 * TF + c1; // so A is x 1024
|
||||
long B = (c4 * TF + c3) * R; // and B too
|
||||
|
||||
return (A + B + 512) / 1024; // division becomes a shift; +512 is for rounding
|
||||
float windSpeed = milesPerHour;
|
||||
if (convert) windSpeed = pow(milesPerHour, 0.16);
|
||||
return 35.74 + 0.6125 * fahrenheit + (0.4275 * fahrenheit - 35.75) * windSpeed;
|
||||
}
|
||||
|
||||
#endif
|
||||
//
|
||||
// END OF FILE
|
||||
//
|
||||
// METRIC
|
||||
float WindChill_C_kmph(const float celcius, const float kilometerPerHour, const bool convert = true)
|
||||
{
|
||||
float windSpeed = kilometerPerHour;
|
||||
if (convert) windSpeed = pow(kilometerPerHour, 0.16);
|
||||
return 13.12 + 0.6215 * celcius + (0.3965 * celcius - 11.37) * windSpeed;
|
||||
}
|
||||
|
||||
float WindChill_C_mps(const float celcius, const float meterPerSecond, const bool convert = true)
|
||||
{
|
||||
return WindChill_C_kmph(celcius, meterPerSecond * 3.6, convert);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
21
libraries/Troolean/LICENSE
Normal file
21
libraries/Troolean/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2020 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
25
libraries/Troolean/README.md
Normal file
25
libraries/Troolean/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Troolean
|
||||
|
||||
Arduino Library for a three state logic datatype supporting {True False Unknown}
|
||||
|
||||
# Description
|
||||
|
||||
Troolean is a datatype that implements three state logic with the values
|
||||
{True False Unknown }
|
||||
|
||||
Logic operators are similar to boolean and behave the same for the familiar boolean values.
|
||||
|
||||
Trooleans can be used e.g. to indicate a value is valid, invald or unknown to be valid or not.
|
||||
Imagine a monitoring application which has different sensors e.g. temperature. If the sensor
|
||||
is sampled less than 1 minute ago one could say the value is valid, if the last sample is taken
|
||||
more than an hour ago it could be changed (a lot) or not. So one does not know if the temperature
|
||||
has become invalid or not. Boolean logic would make it invalid, but troolean allows to state we
|
||||
just don't know. As long as there is no urgency ( a customer that needs a valid value)
|
||||
one does not need to resample yet.
|
||||
|
||||
See also https://en.wikipedia.org/wiki/Three-valued_logic
|
||||
|
||||
# Operation
|
||||
|
||||
See examples
|
||||
|
@ -1,17 +1,18 @@
|
||||
//
|
||||
// FILE: Troolean.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: class for troolean math (true false unknown)
|
||||
// URL:
|
||||
// VERSION: 0.1.3
|
||||
// PURPOSE: Arduino Library for a three state logic datatype supporting {true false unknown}
|
||||
// URL: https://github.com/RobTillaart/Troolean
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 initial version
|
||||
// 0.1.1 adjust (in)equality so that unknown == unknown
|
||||
// although there could be arguments that unknown != unknown
|
||||
// added isTrue(), isFalse(), isUnknown()
|
||||
// first public release
|
||||
//
|
||||
// 0.1.0 2018-01-10 initial version
|
||||
// 0.1.1 2018-01-28 adjust (in)equality so that unknown == unknown
|
||||
// although there could be arguments that unknown != unknown
|
||||
// added isTrue(), isFalse(), isUnknown()
|
||||
// first public release
|
||||
// 0.1.2 2020-06-07 small refactor; updated keywords.txt; metadata
|
||||
// 0.1.3 2020-06-19 fix library.json
|
||||
|
||||
#include "Troolean.h"
|
||||
|
||||
@ -37,7 +38,6 @@ Troolean::Troolean(const Troolean &t)
|
||||
_value = t._value;
|
||||
}
|
||||
|
||||
|
||||
// PRINTING
|
||||
size_t Troolean::printTo(Print& p) const
|
||||
{
|
||||
@ -99,7 +99,6 @@ Troolean::operator bool() const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// NEGATE
|
||||
// t -> f
|
||||
// f -> t
|
||||
@ -124,7 +123,6 @@ Troolean Troolean::operator && (const bool &b)
|
||||
if (_value == 0 || !b) return Troolean(0);
|
||||
if (_value == 1 && b) return Troolean(1);
|
||||
return Troolean(-1);
|
||||
|
||||
}
|
||||
|
||||
Troolean Troolean::operator || (const Troolean &t)
|
||||
@ -141,7 +139,4 @@ Troolean Troolean::operator || (const bool &b)
|
||||
return Troolean(-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -1,31 +1,29 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: Troolean.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: class for Troolean math
|
||||
// URL: https://en.wikipedia.org/wiki/Three-valued_logic
|
||||
// VERSION: 0.1.3
|
||||
// PURPOSE: Arduino Library for a three state logic datatype supporting {true false unknown}
|
||||
// URL: https://github.com/RobTillaart/Troolean
|
||||
// https://en.wikipedia.org/wiki/Three-valued_logic
|
||||
// Kleene and Priest logics
|
||||
//
|
||||
// HISTORY:
|
||||
// see Troolean.cpp file
|
||||
//
|
||||
|
||||
#ifndef TROOLEAN_H
|
||||
#define TROOLEAN_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Printable.h"
|
||||
|
||||
#define TROOLEAN_LIB_VERSION (F("0.1.1"))
|
||||
#define TROOLEAN_LIB_VERSION (F("0.1.3"))
|
||||
|
||||
// TODO:rvdt enum values in a separate type....
|
||||
#define unknown -1
|
||||
|
||||
class Troolean: public Printable
|
||||
{
|
||||
public:
|
||||
Troolean();
|
||||
Troolean(const int8_t);
|
||||
Troolean(const int8_t); // 0 = false, -1 = unknown anything else = true
|
||||
Troolean(const Troolean&);
|
||||
|
||||
size_t printTo(Print&) const;
|
||||
@ -52,9 +50,10 @@ public:
|
||||
inline bool isUnknown() { return _value == -1; };
|
||||
|
||||
// ideas
|
||||
// bool toBool(); // returns random true/false if unknown....
|
||||
// Troolean operator &&=
|
||||
// Troolean operator ||=
|
||||
//
|
||||
// bool toBool(); // returns random true/false if unknown....
|
||||
// extend with dontcare ? ==> four state logic ? Foolean?
|
||||
|
||||
private:
|
||||
@ -62,6 +61,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// END OF FILE
|
||||
// -- END OF FILE --
|
||||
|
@ -3,9 +3,7 @@
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: test for troolean (tri state) math library for Arduino
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
// URL: https://github.com/RobTillaart/Troolean
|
||||
//
|
||||
|
||||
#include "Troolean.h"
|
||||
|
@ -5,8 +5,6 @@
|
||||
// PURPOSE: test for troolean (tri state) math library for Arduino
|
||||
// URL:
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "Troolean.h"
|
||||
|
||||
|
@ -1,18 +1,12 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map for Troolean
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Troolean KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
isTrue KEYWORD2
|
||||
isFalse KEYWORD2
|
||||
isUnknown KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
unknown LITERAL1
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Troolean",
|
||||
"keywords": "Troolean,numbers",
|
||||
"description": "Library with Troolean math for Arduino.",
|
||||
"description": "Arduino Library for a three state logic datatype supporting {true false unknown}",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
@ -13,12 +13,9 @@
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Arduino.git"
|
||||
"url": "https://github.com/RobTillaart/Troolean.git"
|
||||
},
|
||||
"version":"0.1.1",
|
||||
"version":"0.1.3",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"export": {
|
||||
"include": "libraries/Troolean"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Troolean
|
||||
version=0.1.1
|
||||
version=0.1.3
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library with troolean math for Arduino.
|
||||
paragraph=
|
||||
sentence=Arduino Library for a three state logic datatype
|
||||
paragraph=supporting {true false unknown}
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/Troolean
|
||||
architectures=*
|
||||
includes=Troolean.h
|
||||
depends=
|
||||
|
1
libraries/VT100/replaced by ANSI library.txt
Normal file
1
libraries/VT100/replaced by ANSI library.txt
Normal file
@ -0,0 +1 @@
|
||||
https://github.com/RobTillaart/ANSI
|
@ -8,14 +8,13 @@ The XMLWriter class supports generating XML files and send these over a stream
|
||||
like Ethernet SD.File or Serial.
|
||||
|
||||
When instantiating an XMLWriter one can define the internal buffer size.
|
||||
This buffering makes the output faster, especially for Ethernet and SD.File.
|
||||
The buffer size should be at least 2 bytes.
|
||||
A bigger buffer is often faster but it also depends on the properties of the
|
||||
stream to see real performance gains.
|
||||
A bigger buffer will make the output faster, especially for Ethernet and SD.File.
|
||||
The buffer size should be at least 2 bytes and max 250.
|
||||
How much faster depends on the properties of the stream.
|
||||
E.g. the baudrate and internal buffer of Serial, packet behaviour of Ethernet,
|
||||
or paging of SD cards.
|
||||
So if performance is an issue one should do some testruns with different sizes
|
||||
for the buffer and choose one that is appropriate.
|
||||
If performance is low one should do testruns with different sizes for the buffer
|
||||
and choose one that is appropriate.
|
||||
|
||||
Indicative sizes based upon the examples.
|
||||
Run your tests to find your application optimum.
|
||||
@ -26,8 +25,87 @@ Run your tests to find your application optimum.
|
||||
| Serial | 5 |
|
||||
| SD File | 10-16 |
|
||||
|
||||
Important to know when usinig buffering is that your code should always include
|
||||
a call to **XML.flush()** at the end of the XML generation to flush the buffer.
|
||||
**Important** When using buffering you should always include a call to **XML.flush()**
|
||||
at the end of the XML generation. This will flush the last bytes in the internal buffer.
|
||||
|
||||
## Interface
|
||||
|
||||
Constructor
|
||||
- **XMLWriter(stream, bufsize);** Constructor defines the stream and the buffersize
|
||||
to optimize performance vs memory usage.
|
||||
|
||||
|
||||
Functions for manual layout control
|
||||
- **setIndentSize(size = 2);** preferred a multiple of 2;
|
||||
- **incrIndent()**
|
||||
- **decrIndent()**
|
||||
- **indent();**
|
||||
- **raw(str)** inject any string
|
||||
|
||||
General settings
|
||||
- **setConfig(cfg)** used to show/strip comment, indent, newLine.
|
||||
use **setConfig(0);** to minimize the output
|
||||
- **newLine(n)** add a number of newlines to the output, default = 1
|
||||
|
||||
----
|
||||
|
||||
Functions
|
||||
- **reset()** resets internal state, to be called before new XML is written
|
||||
- **Header()** injects standard XML header string, must be first line
|
||||
- **comment(text, multiline)** \<!-- text --\>
|
||||
if multiline == true it does not indent to allow bigger text blocks
|
||||
- **flush()** call flush() at the end of writing to empty the internal buffer. **!!**
|
||||
|
||||
Functions to create simple tags with named fields
|
||||
- **tagOpen(tag, newLine)** \<tag\>
|
||||
- **tagOpen(tag, name, newLine)** \<tag name="name"\>
|
||||
- **tagCLose()** \</tag\>
|
||||
|
||||
Functions to make up tags with multiple fields:
|
||||
- **tagStart(tag)** \<tag
|
||||
- **tagField(field, string);** field="string"
|
||||
- **tagField(field, T value, base = DEC);** standard math types
|
||||
- **tagEnd(newline = true, addSlash = true);** /\>
|
||||
|
||||
Functions to make a node
|
||||
- **writeNode(tag, value);** \<tag\>value\</tag\>
|
||||
- **writeNode(tag, T value, base = DEC);** standard math types
|
||||
|
||||
Helper
|
||||
- **escape(str)** expands the xml chars: \"\'\<\>\&
|
||||
|
||||
Metrics (to optimize buffersize in combination with timing)
|
||||
- **bufferIndex()** returns the size of the internal buffer
|
||||
- **bytesWritten()** idem, since reset().
|
||||
|
||||
## Print interface
|
||||
|
||||
XMLWriter 0.2.4 implements the Print interface, so at any moment one can use
|
||||
**print()** or **println()** to inject specific information.
|
||||
E.g. Note that **tagField()** and **writeNode()** do not support 64 bit integer
|
||||
types and large values of double.
|
||||
My **printHelpers library** helps to convert these to strings which can be printed.
|
||||
See example.
|
||||
|
||||
The Print interface can also be used to print objects that
|
||||
implement the **Printable** interface. See example.
|
||||
|
||||
With the support of the Print interface, **raw()** is becoming obsolete as it only
|
||||
can inject strings.
|
||||
|
||||
## Configuration flags
|
||||
|
||||
| Flag | Value | Meaning |
|
||||
|:----|:----|:----|
|
||||
|XMLWRITER_NONE | 0x00 | minimize output, smaller & faster |
|
||||
|XMLWRITER_COMMENT | 0x01 | allow comments |
|
||||
|XMLWRITER_INDENT | 0x02 | allow indentation |
|
||||
|XMLWRITER_NEWLINE | 0x04 | allow newlines |
|
||||
|
||||
- **setConfig(XMLWRITER_NONE);** to minimize the output in bytes.
|
||||
- **setConfig(XMLWRITER_NEWLINE);** to break an XML stream in lines.
|
||||
- **setConfig(XMLWRITER_NEWLINE | XMLWRITER_INDENT);** to see XML structure.
|
||||
- **setConfig(XMLWRITER_NEWLINE | XMLWRITER_INDENT | XMLWRITER_COMMENT);** to see XML structure + comments.
|
||||
|
||||
## Operation
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: XMLWriter.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.2
|
||||
// VERSION: 0.2.4
|
||||
// DATE: 2013-11-06
|
||||
// PURPOSE: Arduino library for creating XML
|
||||
//
|
||||
@ -19,7 +19,8 @@
|
||||
// 0.2.0 2020-04-24 refactor, added examples, #pragma, print as base class
|
||||
// 0.2.1 2020-04-26 performance optimized, setconfig() + newLine() added
|
||||
// 0.2.2 2020-04-29 dynamic buffer size in constructor
|
||||
//
|
||||
// 0.2.3 2020-06-19 fix library.json
|
||||
// 0.2.4 2020-07-07 fix #6 Print interface made public
|
||||
|
||||
#include <XMLWriter.h>
|
||||
|
||||
@ -51,6 +52,21 @@ void XMLWriter::header()
|
||||
print(F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"));
|
||||
}
|
||||
|
||||
// void XMLWriter::meta()
|
||||
// {
|
||||
// print(F("<!-- "));
|
||||
// print('\n');
|
||||
// print(F(" VERSION: "));
|
||||
// println(XMLWRITER_VERSION);
|
||||
// print(F("MAXLEVEL: "));
|
||||
// println(XMLWRITER_MAXLEVEL);
|
||||
// print(F(" TAGSIZE: "));
|
||||
// println(XMLWRITER_MAXTAGSIZE);
|
||||
// print(F(" CONFIG: "));
|
||||
// println(_config);
|
||||
// print(F(" -->\n"));
|
||||
// }
|
||||
|
||||
void XMLWriter::comment(const char* text, const bool multiLine)
|
||||
{
|
||||
if (_config & XMLWRITER_COMMENT)
|
||||
@ -82,13 +98,20 @@ void XMLWriter::tagOpen(const char* tag, const char* name, const bool newline)
|
||||
{
|
||||
if (_tidx > XMLWRITER_MAXLEVEL)
|
||||
{
|
||||
comment("XMLWRITER_MAXLEVEL exceeded.");
|
||||
comment("MAXLEVEL exceeded.");
|
||||
comment(tag);
|
||||
comment(name);
|
||||
flush();
|
||||
return;
|
||||
}
|
||||
// "unsafe" strcpy saves ~20 bytes
|
||||
strncpy(_tagStack[_tidx++], tag, XMLWRITER_MAXTAGSIZE);
|
||||
if (strlen(tag) > XMLWRITER_MAXTAGSIZE)
|
||||
{
|
||||
comment("MAXTAGSIZE exceeded.");
|
||||
comment(tag);
|
||||
flush();
|
||||
return;
|
||||
}
|
||||
strcpy(_tagStack[_tidx++], tag);
|
||||
tagStart(tag);
|
||||
if (name[0] != 0) tagField("name", name);
|
||||
tagEnd(newline, NOSLASH);
|
||||
@ -102,7 +125,6 @@ void XMLWriter::tagClose(const bool ind)
|
||||
print("</");
|
||||
print(_tagStack[--_tidx]);
|
||||
print(">\n");
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void XMLWriter::tagStart(const char *tag)
|
||||
|
@ -2,14 +2,14 @@
|
||||
//
|
||||
// FILE: XMLWriter.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.2
|
||||
// VERSION: 0.2.4
|
||||
// DATE: 2013-11-06
|
||||
// PURPOSE: Arduino library for creating XML
|
||||
//
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define XMLWRITER_VERSION "0.2.2"
|
||||
#define XMLWRITER_VERSION "0.2.3"
|
||||
|
||||
// for comment()
|
||||
#define NOMULTILINE false
|
||||
@ -38,16 +38,16 @@
|
||||
#define XMLWRITER_ESCAPE_SUPPORT
|
||||
|
||||
// configuration - setConfig
|
||||
#define XMLWRITER_NONE 0x00
|
||||
#define XMLWRITER_COMMENT 0x01
|
||||
#define XMLWRITER_INDENT 0x02
|
||||
#define XMLWRITER_NEWLINE 0x04
|
||||
#define XMLWRITER_NONE 0x00
|
||||
#define XMLWRITER_COMMENT 0x01
|
||||
#define XMLWRITER_INDENT 0x02
|
||||
#define XMLWRITER_NEWLINE 0x04
|
||||
|
||||
// uncomment next line to reduce ~30bytes RAM in escape() (AVR oonly)
|
||||
// #define __PROGMEM__
|
||||
|
||||
|
||||
class XMLWriter : Print
|
||||
class XMLWriter : public Print
|
||||
{
|
||||
public:
|
||||
// default = Serial
|
||||
@ -63,6 +63,8 @@ public:
|
||||
// standard XML header
|
||||
void header();
|
||||
|
||||
// void meta();
|
||||
|
||||
// if multiline == true it does not indent to allow bigger text blocks
|
||||
// <!-- text -->
|
||||
void comment(const char* text, const bool multiLine = false);
|
||||
|
@ -0,0 +1,58 @@
|
||||
//
|
||||
// FILE: XMLWriterPrint_1.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo Print interface
|
||||
// DATE: 2020-07-07
|
||||
// URL: https://github.com/RobTillaart/XMLWriter
|
||||
//
|
||||
|
||||
#include <XMLWriter.h>
|
||||
|
||||
XMLWriter XML(&Serial);
|
||||
|
||||
char buffer[24];
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
XML.newLine(0);
|
||||
XML.print("\n");
|
||||
XML.header();
|
||||
XML.comment("XMLWriter Print interface");
|
||||
XML.setConfig(0); // no indent, no (further) comments
|
||||
|
||||
// The {} are not mandatory shows the XML structure in the code...
|
||||
|
||||
XML.tagOpen("Order");
|
||||
{
|
||||
|
||||
XML.println();
|
||||
XML.tagOpen("Address stamp");
|
||||
{
|
||||
XML.println("Mr. D. Bowie\nSpiderstreet 42\n54321 Mars");
|
||||
}
|
||||
XML.tagClose();
|
||||
|
||||
XML.println();
|
||||
|
||||
XML.tagOpen("Actions");
|
||||
{
|
||||
XML.println("[ ] Two tickets for Central Park");
|
||||
XML.println("[ ] Diner at the Ritz");
|
||||
XML.println("[ ] Surprise Hotel");
|
||||
}
|
||||
XML.tagClose();
|
||||
XML.println();
|
||||
}
|
||||
XML.tagClose();
|
||||
XML.flush();
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user