mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
remove duplicates + minor
This commit is contained in:
parent
e5bc4a1d9a
commit
f9cf7e8124
@ -1,233 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.4
|
||||
// PURPOSE: library for BH1750FVI lux sensor Arduino
|
||||
// URL: https://github.com/RobTillaart/BH1750FVI
|
||||
//
|
||||
// 0.1.0 2020-02-02 initial version
|
||||
// 0.1.1 2020-03-28 refactor
|
||||
// 0.1.2 2020-03-29 unique name in repo, and new release tag.
|
||||
// 0.1.3 2020-06-05 fix library.json file
|
||||
// 0.1.4 2020-08-14 cleanup tabs/spaces;
|
||||
// 0.2.0 2020-08-18 implement logic for LOW & HIGH2;
|
||||
// implement correctionfactor; examples;
|
||||
// 0.2.1 2020-08-31 implement angle factor
|
||||
// 0.2.2 2020-09-04 implement temperature compensation
|
||||
// 0.2.3 2020-09-04 implement wavelength compensation
|
||||
// 0.2.4 2020-11-27 fix #10 rename _sensitivityFactor for ESP32
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
BH1750FVI::BH1750FVI(const uint8_t address, const uint8_t dataPin, const uint8_t clockPin)
|
||||
{
|
||||
_address = address;
|
||||
_data = 0;
|
||||
_error = BH1750FVI_OK;
|
||||
_sensitivityFactor = BH1750FVI_REFERENCE_TIME;
|
||||
_mode = BH1750FVI_MODE_HIGH;
|
||||
_wire = &Wire;
|
||||
|
||||
if ((dataPin < 255) && (clockPin < 255))
|
||||
{
|
||||
_wire->begin(dataPin, clockPin);
|
||||
} else {
|
||||
_wire->begin();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BH1750FVI::BH1750FVI(const uint8_t address, TwoWire *wire)
|
||||
{
|
||||
_address = address;
|
||||
_data = 0;
|
||||
_error = BH1750FVI_OK;
|
||||
_sensitivityFactor = BH1750FVI_REFERENCE_TIME; // P11
|
||||
_mode = BH1750FVI_MODE_HIGH;
|
||||
_wire = wire;
|
||||
_wire->begin();
|
||||
}
|
||||
|
||||
bool BH1750FVI::isReady()
|
||||
{
|
||||
// max times from datasheet P2 + P11;
|
||||
uint8_t timeout[3] = { 16, 120, 120 };
|
||||
if (_mode < 3)
|
||||
{
|
||||
float f = timeout[_mode] * _sensitivityFactor / BH1750FVI_REFERENCE_TIME;
|
||||
return (millis() - _requestTime) > f;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float BH1750FVI::getRaw(void)
|
||||
{
|
||||
return readData() * 0.833333333333f; // == 1 / 1.2;
|
||||
}
|
||||
|
||||
float BH1750FVI::getLux(void)
|
||||
{
|
||||
// lux without mode correction
|
||||
float lux = getRaw();
|
||||
|
||||
// sensitivity factor
|
||||
if (_sensitivityFactor != BH1750FVI_REFERENCE_TIME)
|
||||
{
|
||||
lux *= (1.0 * BH1750FVI_REFERENCE_TIME) / _sensitivityFactor;
|
||||
}
|
||||
// angle compensation
|
||||
if (_angle != 0)
|
||||
{
|
||||
lux *= _angleFactor;
|
||||
}
|
||||
// temperature compensation.
|
||||
if (_temp != 20)
|
||||
{
|
||||
float tempFactor = 1.0f - (_temp - 20.0f) / 2000.0f;
|
||||
lux *= tempFactor;
|
||||
}
|
||||
// wavelength compensation.
|
||||
if (_waveLength != 580)
|
||||
{
|
||||
lux *= _waveLengthFactor;
|
||||
}
|
||||
if (_mode == BH1750FVI_MODE_HIGH2)
|
||||
{
|
||||
lux *= 0.5f; // P11
|
||||
}
|
||||
|
||||
return lux;
|
||||
}
|
||||
|
||||
int BH1750FVI::getError()
|
||||
{
|
||||
int e = _error;
|
||||
_error = BH1750FVI_OK;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
//
|
||||
// operational mode
|
||||
//
|
||||
void BH1750FVI::setContHighRes()
|
||||
{
|
||||
_mode = BH1750FVI_MODE_HIGH;
|
||||
command(BH1750FVI_CONT_HIGH);
|
||||
_requestTime = millis();
|
||||
};
|
||||
|
||||
void BH1750FVI::setContHigh2Res()
|
||||
{
|
||||
_mode = BH1750FVI_MODE_HIGH2;
|
||||
command(BH1750FVI_CONT_HIGH2);
|
||||
_requestTime = millis();
|
||||
};
|
||||
|
||||
void BH1750FVI::setContLowRes()
|
||||
{
|
||||
_mode = BH1750FVI_MODE_LOW;
|
||||
command(BH1750FVI_CONT_LOW);
|
||||
_requestTime = millis();
|
||||
};
|
||||
|
||||
void BH1750FVI::setOnceHighRes()
|
||||
{
|
||||
_mode = BH1750FVI_MODE_HIGH;
|
||||
command(BH1750FVI_ONCE_HIGH);
|
||||
_requestTime = millis();
|
||||
};
|
||||
|
||||
void BH1750FVI::setOnceHigh2Res()
|
||||
{
|
||||
_mode = BH1750FVI_MODE_HIGH2;
|
||||
command(BH1750FVI_ONCE_HIGH2);
|
||||
_requestTime = millis();
|
||||
};
|
||||
|
||||
void BH1750FVI::setOnceLowRes()
|
||||
{
|
||||
_mode = BH1750FVI_MODE_LOW;
|
||||
command(BH1750FVI_ONCE_LOW);
|
||||
_requestTime = millis();
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
//
|
||||
// measurement timing
|
||||
//
|
||||
// P11 datasheet
|
||||
void BH1750FVI::changeTiming(uint8_t val)
|
||||
{
|
||||
val = constrain(val, 31, 254);
|
||||
_sensitivityFactor = val;
|
||||
// P5 instruction set table
|
||||
uint8_t Hbits = 0x40 | (val >> 5);
|
||||
uint8_t Lbits = 0x60 | (val & 0x1F);
|
||||
command(Hbits);
|
||||
command(Lbits);
|
||||
}
|
||||
|
||||
void BH1750FVI::setCorrectionFactor(float f)
|
||||
{
|
||||
// 31 .. 254 are range P11 - constrained in changeTIming call
|
||||
uint8_t timingValue = round(BH1750FVI_REFERENCE_TIME * f);
|
||||
changeTiming(timingValue);
|
||||
}
|
||||
|
||||
float BH1750FVI::getCorrectionFactor()
|
||||
{
|
||||
float f = 1.0f / BH1750FVI_REFERENCE_TIME;
|
||||
return _sensitivityFactor * f;
|
||||
}
|
||||
|
||||
void BH1750FVI::setAngle(int degrees)
|
||||
{
|
||||
_angle = constrain(degrees, -89, 89);
|
||||
// Lamberts Law.
|
||||
_angleFactor = 1.0f / cos(_angle * (PI / 180.0f));
|
||||
}
|
||||
|
||||
// interpolation tables uses more RAM (versus progmem)
|
||||
void BH1750FVI::setWaveLength(int waveLength)
|
||||
{
|
||||
_waveLength = constrain(waveLength, 400, 715);
|
||||
float tmp = 1.0f;
|
||||
if (_waveLength < 440) tmp = 0.01f + (_waveLength - 400) * 0.09f / 40.0f;
|
||||
else if (_waveLength < 510) tmp = 0.10f + (_waveLength - 440) * 0.80f / 70.0f;
|
||||
else if (_waveLength < 545) tmp = 0.90f - (_waveLength - 510) * 0.10f / 35.0f;
|
||||
else if (_waveLength < 580) tmp = 0.80f + (_waveLength - 545) * 0.20f / 35.0f;
|
||||
else if (_waveLength < 700) tmp = 1.00f - (_waveLength - 580) * 0.93f / 120.0f;
|
||||
else if (_waveLength < 715) tmp = 0.07f - (_waveLength - 700) * 0.07f / 15.0f;
|
||||
else if (_waveLength == 715) tmp = 0.01f;
|
||||
_waveLengthFactor = 1.0f / tmp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
//
|
||||
uint16_t BH1750FVI::readData()
|
||||
{
|
||||
if (_wire->requestFrom(_address, (uint8_t) 2) != 2)
|
||||
{
|
||||
_error = BH1750FVI_ERROR_WIRE_REQUEST;
|
||||
return _data; // last value
|
||||
}
|
||||
_data = _wire->read();
|
||||
_data <<= 8;
|
||||
_data += _wire->read();
|
||||
return _data;
|
||||
}
|
||||
|
||||
void BH1750FVI::command(uint8_t value)
|
||||
{
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(value);
|
||||
_error = _wire->endTransmission();
|
||||
}
|
||||
|
||||
// --- END OF FILE ---
|
@ -1,133 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: BH1750FVI_H.h
|
||||
// AUTHOR: Rob dot Tillaart at gmail dot com
|
||||
// VERSION: 0.2.4
|
||||
// PURPOSE: Arduino library for BH1750FVI (GY-30) lux sensor
|
||||
// HISTORY: See BH1750FVI.cpp
|
||||
//
|
||||
|
||||
|
||||
// breakout BH1750FVI / GY-30
|
||||
//
|
||||
// +-----------------------+
|
||||
// GND |o |
|
||||
// ADD |o |
|
||||
// SDA |o + | + = sensor
|
||||
// SCL |o |
|
||||
// VCC |o |
|
||||
// +-----------------------+
|
||||
//
|
||||
// ADD = ADDRESS:
|
||||
// 0 = 0x23
|
||||
// 1 = 0x5C
|
||||
//
|
||||
|
||||
#include "Wire.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#define BH1750FVI_LIB_VERSION "0.2.4"
|
||||
#define BH1750FVI_DEFAULT_ADDRESS 0x23
|
||||
#define BH1750FVI_ALT_ADDRESS 0x5C
|
||||
|
||||
// COMMANDS P5
|
||||
#define BH1750FVI_POWER_ON 0x00
|
||||
#define BH1750FVI_POWER_OFF 0x01
|
||||
#define BH1750FVI_RESET 0x07
|
||||
#define BH1750FVI_CONT_HIGH 0x10
|
||||
#define BH1750FVI_CONT_HIGH2 0x11
|
||||
#define BH1750FVI_CONT_LOW 0x13
|
||||
#define BH1750FVI_ONCE_HIGH 0x20
|
||||
#define BH1750FVI_ONCE_HIGH2 0x21
|
||||
#define BH1750FVI_ONCE_LOW 0x23
|
||||
|
||||
#define BH1750FVI_REFERENCE_TIME 0x45 // 69
|
||||
|
||||
#define BH1750FVI_MODE_LOW 0x00
|
||||
#define BH1750FVI_MODE_HIGH 0x01
|
||||
#define BH1750FVI_MODE_HIGH2 0x02
|
||||
|
||||
// ERROR CODES
|
||||
#define BH1750FVI_OK 0
|
||||
#define BH1750FVI_ERROR_WIRE_REQUEST -10
|
||||
|
||||
|
||||
class BH1750FVI
|
||||
{
|
||||
public:
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
// dataPin and clockPin can be used for ESP8266
|
||||
BH1750FVI(const uint8_t address , const uint8_t dataPin, const uint8_t clockPin);
|
||||
#endif
|
||||
|
||||
BH1750FVI(const uint8_t address, TwoWire *wire = &Wire);
|
||||
|
||||
float getRaw(); // no HIGH2 mode + no sensitivity factor.
|
||||
float getLux();
|
||||
int getError();
|
||||
|
||||
void powerOn() { command(BH1750FVI_POWER_ON); };
|
||||
void powerOff() { command(BH1750FVI_POWER_OFF); };
|
||||
void reset() { command(BH1750FVI_RESET); };
|
||||
|
||||
// MODE TIME RESOLUTION
|
||||
// 2 HIGH2 120 ms 0.5 lux // recommended max * 1.5 = 180 ms
|
||||
// 1 HIGH 120 ms 1.0 lux
|
||||
// 0 LOW 16 ms 4.0 lux
|
||||
uint8_t getMode() { return _mode; };
|
||||
|
||||
void setContHighRes();
|
||||
void setContHigh2Res();
|
||||
void setContLowRes();
|
||||
|
||||
void setOnceHighRes();
|
||||
void setOnceHigh2Res();
|
||||
void setOnceLowRes();
|
||||
bool isReady(); // only after setOnce...Res();
|
||||
|
||||
// read datasheet P11 about details of the correction or sensitivity factor
|
||||
// to be used for very high and very low brightness
|
||||
// or to correct for e.g. transparancy
|
||||
void changeTiming(uint8_t val); // 69 is default = BH1750FVI_REFERENCE_TIME
|
||||
void setCorrectionFactor(float f); // 0.45 .. 3.68
|
||||
float getCorrectionFactor();
|
||||
|
||||
// read datasheet P3 and check figure 4 and 5.
|
||||
// setAngle is constrained to -89..+89
|
||||
void setAngle(int degrees);
|
||||
int getAngle() { return _angle; };
|
||||
|
||||
// datasheet P3 figure 7
|
||||
// Effect of temperature is about 3% / 60°C ~~ 1% / 20°C
|
||||
// to be used if temp is really hot or cold.
|
||||
void setTemperature(int temp) { _temp = temp; };
|
||||
int getTemperature() { return _temp; };
|
||||
|
||||
|
||||
// datasheet Page 3 figure 1 (experimental correction)
|
||||
// Effect of wavelength can be substantial,
|
||||
// correctionfactor is calculated by multiple linear approximations.
|
||||
void setWaveLength(int waveLength);
|
||||
int getWaveLength() { return _waveLength; };
|
||||
|
||||
private:
|
||||
uint16_t readData();
|
||||
void command(uint8_t value);
|
||||
|
||||
uint8_t _address;
|
||||
uint16_t _data;
|
||||
int _error;
|
||||
uint8_t _sensitivityFactor;
|
||||
uint8_t _mode;
|
||||
uint32_t _requestTime = 0;
|
||||
float _angleFactor = 1;
|
||||
int _angle = 0;
|
||||
int _temp = 20;
|
||||
float _waveLengthFactor = 1;
|
||||
int _waveLength = 580;
|
||||
|
||||
TwoWire* _wire;
|
||||
};
|
||||
|
||||
// -- END OF FILE --
|
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 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,94 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_angle_measurement.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-08-31
|
||||
//
|
||||
|
||||
/*
|
||||
BH1750FVI_angle_measurement
|
||||
|
||||
Experimental application
|
||||
|
||||
first take a reference measurement for 5 seconds
|
||||
holding the sensor flat under a light source.
|
||||
|
||||
Then take a second reference for 5 seconds
|
||||
holding the sensor at 90 degrees.
|
||||
|
||||
Thereafter hold the sensor at any angle and the
|
||||
Arduino will estimate the angle based upon the
|
||||
Lux level compared to the references.
|
||||
|
||||
First trials are not not too bad, roughly within 15° accuracy
|
||||
|
||||
*/
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
float ref1 = 0;
|
||||
float ref2 = 0;
|
||||
|
||||
|
||||
float measure(int seconds, bool minimum = false)
|
||||
{
|
||||
float mn = 1e8;
|
||||
float mx = 0;
|
||||
uint32_t start = millis();
|
||||
while (millis() - start < (seconds * 1000UL))
|
||||
{
|
||||
float val = myLux.getLux();
|
||||
if (val > mx) mx = val;
|
||||
if (val < mn) mn = val;
|
||||
delay(200);
|
||||
}
|
||||
if (minimum) return mn;
|
||||
return mx;
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
|
||||
Serial.println("Reference 1");
|
||||
ref1 = measure(5, false);
|
||||
|
||||
Serial.println("Reference 2");
|
||||
ref2 = measure(5, true);
|
||||
Serial.println("Start");
|
||||
Serial.println(ref1);
|
||||
Serial.println(ref2);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
float val = measure(1, false);
|
||||
|
||||
val = map(val, ref2, ref1, 0, ref1); // does not constrain...
|
||||
|
||||
// prevent NAN
|
||||
float f = val / ref1; // map to 0..1
|
||||
if (f > 1) f = 1; // constrain upper
|
||||
if (f < -1) f = -1; // constrain lower
|
||||
|
||||
Serial.print(val, 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(f);
|
||||
Serial.print("\t");
|
||||
Serial.print(acos(f) * 180 / PI);
|
||||
Serial.print("\t");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
BH1750FVI_angle_measurement.ino
|
||||
|
||||
Experimental application
|
||||
|
||||
first take a reference measurement for 5 seconds
|
||||
holding the sensor flat under a light source.
|
||||
|
||||
Then take a second reference for 5 seconds
|
||||
holding the sensor at 90 degrees.
|
||||
|
||||
Thereafter hold the sensor at any angle and the
|
||||
Arduino will estimate the angle based upon the
|
||||
Lux level compared to the references.
|
||||
|
||||
First trials are not not too bad, roughly within 15° accuracy
|
||||
|
||||
*/
|
@ -1,65 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_async.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-08-20
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
float correctionFactor = 0.45; // min value see datasheet
|
||||
uint32_t count = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (myLux.isReady())
|
||||
{
|
||||
float val = myLux.getLux();
|
||||
|
||||
if (count % 20 == 0)
|
||||
{
|
||||
Serial.println("\nCNT \tLUX \tMODE \tFACTOR \tRAWLUX");
|
||||
}
|
||||
|
||||
Serial.print(count);
|
||||
Serial.print("\t");
|
||||
Serial.print(val, 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(myLux.getMode());
|
||||
Serial.print("\t");
|
||||
Serial.print(myLux.getCorrectionFactor(), 2);
|
||||
Serial.print("\t");
|
||||
Serial.println(val / myLux.getCorrectionFactor(), 1);
|
||||
|
||||
// note correctionfactor are steps of 1/69 internally, see datasheet
|
||||
correctionFactor += 0.05;
|
||||
if (correctionFactor > 3.68) // 0.45 - 3.68 = 45 steps of 0.05
|
||||
{
|
||||
correctionFactor = 0.45;
|
||||
Serial.println();
|
||||
}
|
||||
myLux.setCorrectionFactor(correctionFactor); // 0.45 .. 3.68
|
||||
|
||||
count++;
|
||||
}
|
||||
delay(1000);
|
||||
// do other things here
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,44 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_cont_high_res.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-02-02
|
||||
//
|
||||
// This is a minimal version, which can be optimized by
|
||||
// using mylux.getRaw() instead of myLux.getLux(); line38
|
||||
// gain on UNO: ~350 bytes smaller
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
uint32_t lastUpdate = 0;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t interval = 100;
|
||||
if (millis() - lastUpdate >= interval)
|
||||
{
|
||||
lastUpdate += interval;
|
||||
float val = myLux.getLux();
|
||||
Serial.println(val, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,43 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_cont_low_res.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-02-02
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
uint32_t lastUpdate = 0;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContLowRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t interval = 100;
|
||||
if (millis() - lastUpdate >= interval)
|
||||
{
|
||||
lastUpdate += interval;
|
||||
float val = myLux.getLux();
|
||||
Serial.println(val, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// END OF FILE
|
@ -1,43 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_setAngle.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-08-31
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for (int x = -90; x < 90; x += 1)
|
||||
{
|
||||
myLux.setAngle(x);
|
||||
float val = myLux.getLux();
|
||||
|
||||
Serial.print(val, 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(myLux.getAngle());
|
||||
Serial.print("\t");
|
||||
Serial.println();
|
||||
delay(20);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,55 +0,0 @@
|
||||
//
|
||||
// FILE: setCorrectionFactor.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-02-02
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
uint32_t lastUpdate = 0;
|
||||
|
||||
float correctionFactor = 0.45; // min value see datasheet
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t interval = 180; // max time see datasheet P2
|
||||
if (millis() - lastUpdate >= interval)
|
||||
{
|
||||
lastUpdate += interval;
|
||||
float val = myLux.getLux();
|
||||
|
||||
Serial.print(val, 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(myLux.getCorrectionFactor(), 3);
|
||||
Serial.print("\t");
|
||||
Serial.println(val / myLux.getCorrectionFactor(), 1);
|
||||
|
||||
// note correctionfactor are steps of 1/69 internally, see datasheet
|
||||
myLux.setCorrectionFactor(correctionFactor); // 0.45 .. 3.68
|
||||
correctionFactor += 0.05;
|
||||
if (correctionFactor > 3.68)
|
||||
{
|
||||
correctionFactor = 0.45;
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,44 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_setTemperature.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-09-04
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for (int t = -60; t < 100; t += 10)
|
||||
{
|
||||
myLux.setTemperature(t);
|
||||
float val = myLux.getLux();
|
||||
|
||||
Serial.print(val, 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(myLux.getTemperature());
|
||||
Serial.print("\t");
|
||||
Serial.println();
|
||||
delay(20);
|
||||
}
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,47 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_setWaveLength.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-09-04
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContHighRes();
|
||||
|
||||
for (int wl = 400; wl < 715; wl++)
|
||||
{
|
||||
myLux.setWaveLength(wl);
|
||||
float val = myLux.getLux();
|
||||
|
||||
Serial.print(val, 1);
|
||||
Serial.print("\t");
|
||||
Serial.print(myLux.getWaveLength());
|
||||
Serial.print("\t");
|
||||
Serial.println();
|
||||
delay(20);
|
||||
}
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,64 +0,0 @@
|
||||
//
|
||||
// FILE: BH1750FVI_single_shot_3_res.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo of BH1750FVI lux scanner library
|
||||
// DATE: 2020-08-20
|
||||
//
|
||||
|
||||
#include "BH1750FVI.h"
|
||||
|
||||
BH1750FVI myLux(0x23);
|
||||
|
||||
uint32_t lastUpdate = 0;
|
||||
float val;
|
||||
uint32_t count = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
myLux.powerOn();
|
||||
myLux.setContLowRes();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (count % 20 == 0)
|
||||
{
|
||||
Serial.println("\nLOW \tHIGH \tHIGH2 \tRAW");
|
||||
}
|
||||
count++;
|
||||
myLux.setOnceLowRes();
|
||||
delay(200);
|
||||
val = myLux.getLux();
|
||||
Serial.print(val, 1);
|
||||
Serial.print('\t');
|
||||
|
||||
myLux.setOnceHighRes();
|
||||
delay(200);
|
||||
val = myLux.getLux();
|
||||
Serial.print(val, 1);
|
||||
Serial.print('\t');
|
||||
|
||||
myLux.setOnceHigh2Res();
|
||||
delay(200);
|
||||
val = myLux.getLux();
|
||||
Serial.print(val, 1);
|
||||
Serial.print('\t');
|
||||
|
||||
myLux.setOnceHighRes();
|
||||
delay(200);
|
||||
val = myLux.getRaw();
|
||||
Serial.print(val, 1);
|
||||
Serial.print('\t');
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,37 +0,0 @@
|
||||
# Syntax Coloring Map For BH1750FVI
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
BH1750FVI KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
|
||||
getRaw KEYWORD2
|
||||
getLux KEYWORD2
|
||||
getError KEYWORD2
|
||||
|
||||
powerOn KEYWORD2
|
||||
powerOff KEYWORD2
|
||||
reset KEYWORD2
|
||||
|
||||
setContHighRes KEYWORD2
|
||||
setContHigh2Res KEYWORD2
|
||||
setContLowRes KEYWORD2
|
||||
setOnceHighRes KEYWORD2
|
||||
setOnceHigh2Res KEYWORD2
|
||||
setOnceLowRes KEYWORD2
|
||||
isReady KEYWORD2
|
||||
|
||||
changeTiming KEYWORD2
|
||||
setCorrectionFactor KEYWORD2
|
||||
getCorrectionFactor KEYWORD2
|
||||
|
||||
setAngle KEYWORD2
|
||||
getAngle KEYWORD2
|
||||
setTemperature KEYWORD2
|
||||
getTemperature KEYWORD2
|
||||
setWaveLength KEYWORD2
|
||||
getWaveLength KEYWORD2
|
||||
|
||||
# Instances (KEYWORD2)
|
||||
|
||||
# Constants (LITERAL1)
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "BH1750FVI_RT",
|
||||
"keywords": "BH1750FVI, BH1750, Lux, light, GY-30, GY30",
|
||||
"description": "Arduino library for BH1750FVI (GY-30) lux sensor. Includes compensation for angle, temperature and (experimental) wavelength.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/BH1750FVI_RT.git"
|
||||
},
|
||||
"version": "0.2.4",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
name=BH1750FVI_RT
|
||||
version=0.2.4
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for BH1750FVI (GY-30) lux sensor
|
||||
paragraph=Includes compensation for angle, temperature and (experimental) wavelength.
|
||||
category=Sensors
|
||||
url=https://github.com/RobTillaart/BH1750FVI_RT
|
||||
architectures=*
|
||||
includes=BH1750FVI.h
|
||||
depends=
|
@ -1,153 +0,0 @@
|
||||
# BH1750FVI_RT
|
||||
|
||||
Arduino library for BH1750FVI (GY-30) 16 bit I2C Lux sensor
|
||||
|
||||
## Description
|
||||
|
||||
The BH1750FVI is a 16 bit lux sensor with an I2C interface
|
||||
It is possible to detect a wide range from 0.11 - 100000 lux.
|
||||
|
||||
To be able to support this wide range, the sensor can operate in three modi.
|
||||
|
||||
| ID | Mode | Integration time | Resolution | Notes |
|
||||
|:----:|:----:|:----:|:----:|:----|
|
||||
| 0 | LOW | 16 ms | 4.0 Lux | to measure very bright light |
|
||||
| 1 | HIGH | 120 ms | 1.0 lux | default |
|
||||
| 2 | HIGH2 | 120 ms | 0.5 lux | to measure very dim light |
|
||||
|
||||
Furthermore one can set a correction factor to reduce / increase the
|
||||
integration time of the sensor.
|
||||
The factor should be between 0.45 - 3.68.
|
||||
It can be used to increase the working range like very bright or very low light conditions.
|
||||
Another aplication is to correct the transparancy of material, or the type of light used.
|
||||
|
||||
Note that the typical integration time will differ if the correction factor is changed.
|
||||
The **isReady()** an **getLux()** functions keep track of the adjustment needed.
|
||||
|
||||
## Interface hardware
|
||||
|
||||
Library was tested with a breakout board.
|
||||
|
||||
```
|
||||
// breakout BH1750FVI / GY-30
|
||||
//
|
||||
// +-----------------------+
|
||||
// GND |o |
|
||||
// ADD |o |
|
||||
// SDA |o + | + = sensor
|
||||
// SCL |o |
|
||||
// VCC |o |
|
||||
// +-----------------------+
|
||||
//
|
||||
// ADD = ADDRESS:
|
||||
// 0 = 0x23
|
||||
// 1 = 0x5C
|
||||
//
|
||||
```
|
||||
The sensor works on 2.4 - 3.6 volt so be careful not to connect directly to 5.0 volt.
|
||||
(Note: the breakout board was 5 volt tolerant)
|
||||
|
||||
## Interface API
|
||||
|
||||
- **BH1750FVI(address, dataPin, clockPin)** ESP constructor with I2C parameters
|
||||
- **BH1750FVI(address, TwoWire \*wire = &Wire)** constructor for other platforms
|
||||
- **getRaw()** reads the lux sensor,
|
||||
- **getLux()** reads the lux sensor and corrects for correctionFactor and for HIGH2 mode,
|
||||
- **getError()** get the latest error, mainly for debugging,
|
||||
- **powerOn()** wakes up the sensor,
|
||||
- **powerOff()** set sensor to sleep,
|
||||
- **reset()** resets the dataregister to 0, effectively removing last measurement.
|
||||
- **getMode()** gets the mode set by one of the set functions. See table above.
|
||||
- **setContHighRes()** continuous mode in HIGH resolution
|
||||
- **setContHigh2Res()** continuous mode in HIGH2 resolution
|
||||
- **setContLowRes()** continuous mode in LOW resolution
|
||||
- **setOnceHighRes()** single shot mode in HIGH resolution
|
||||
- **setOnceHigh2Res()** single shot mode in HIGH2 resolution
|
||||
- **setOnceLowRes()** single shot mode in LOW resolution
|
||||
- **isReady()** can be used to check if the sensor is ready.
|
||||
This is based on a calculated time, the sensor does not have a means to indicate ready directly.
|
||||
Needed only for the single shot modi.
|
||||
The function **isReady()** takes the correctionfactor into account.
|
||||
|
||||
**CorrectionFactor**
|
||||
|
||||
Please read datasheet P11 about details of the correction factor.
|
||||
- **changeTiming(uint8_t val)** 69 is default = BH1750FVI_REFERENCE_TIME
|
||||
- **setCorrectionFactor(float f)** prefered wrapper around changeTiming f = 0.45 .. 3.68
|
||||
- **getCorrectionFactor()** returns the correction factor.
|
||||
Note this can differ as it is stores as an integer internally.
|
||||
|
||||
**Angle sensitivity**
|
||||
|
||||
Note: experimental - use carefully
|
||||
|
||||
The lux sensor is really sensitive for the angle of the light.
|
||||
If one makes measurements outside, the position of the sun changes
|
||||
during the day. The **setAngle(degrees)** function provides a mean to correct that.
|
||||
|
||||
The angle adjustments is based upon the figure 4 and 5 (directional characteristics.)
|
||||
which describe **Lambert’s Cosine Law**. (details see wikipedia)
|
||||
So the correction factor is ```factor = 1.0 / cos(angle)```.
|
||||
At 90 degrees it would fail (divide by zero) so the input is constrained
|
||||
to angles between -89 - +89 degrees.
|
||||
|
||||
If the light is perpendicular on the sensor the angle to use is 0 degrees.
|
||||
Light coming from the side is 90 degrees.
|
||||
|
||||
- **setAngle(int degrees)** adjust the lux to incoming angle in dgrees
|
||||
- **getAngle()** returns set angle in degrees, 0 by default is perpendicular
|
||||
|
||||
**Temperature Compensation**
|
||||
|
||||
The reference temperature of the sensor = 20°C.
|
||||
The effect of temperature is small, about 3% per 60°C ==> 1% per 20°C
|
||||
so only on either a hot roof or on a icy cold day the effect is measurable.
|
||||
|
||||
- **setTemperature(int T)** see datasheet P3 fig7
|
||||
- **getTemperature()** returns temperature set, default = 20°C
|
||||
|
||||
|
||||
**Spectral Compensation ! EXPERIMENTAL !**
|
||||
|
||||
Spectral compensation is experimental and not tested. It is a compensation based upon the
|
||||
graph figure 1, page 3 of the datasheet. If one has light of a known wavelength one can
|
||||
compensate for it by setting the wavelength. It can also be used when using filters.
|
||||
As said it is not tested so use at your own risk, but I am interested in your experiences
|
||||
if you do real tests with it.
|
||||
|
||||
- **void setSpectral(int wavelength)** set wavelength,
|
||||
- **int getSpectral()** returns wavelength
|
||||
|
||||
As the graph (figure 1) is not lineair it is approximated by linear interpolation with the
|
||||
following six points.
|
||||
|
||||
| WaveLength | Perc % |
|
||||
|:----|:----:|
|
||||
| 400 | 1 |
|
||||
| 440 | 10 |
|
||||
| 510 | 90 |
|
||||
| 545 | 80 |
|
||||
| 580 | 100 |
|
||||
| 700 | 07 |
|
||||
| 725 | 1 |
|
||||
|
||||
Values outside the range will be mapped upon 400 or 715.
|
||||
Default wavelength will be 580 as that gives 100%
|
||||
|
||||
|
||||
## Ideas
|
||||
|
||||
**Intelligent isReady()**
|
||||
|
||||
After a **getLux()** call one can clean the dataregister explicitly with
|
||||
**reset()**. Then a call to **isReady()** fetches data and as long as
|
||||
data equals zero the sensor is not ready.
|
||||
|
||||
**DVI interface**
|
||||
|
||||
To investigate, sort of external reset?
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See samples...
|
@ -1,107 +0,0 @@
|
||||
|
||||
Complex numbers test for Arduino: 0.1.06
|
||||
|
||||
1. Print Complex, set, real, imag
|
||||
1.000 0.000i
|
||||
10.000 -2.000i
|
||||
3.000 0.000i
|
||||
-10.000 4.000i
|
||||
-5.000 -5.000i
|
||||
0.000 0.000i
|
||||
0.00
|
||||
0.00
|
||||
|
||||
2. == !=
|
||||
ok :)
|
||||
ok :)
|
||||
ok :)
|
||||
|
||||
3. negation -
|
||||
-10.000 2.000i
|
||||
10.000 -2.000i
|
||||
ok :)
|
||||
|
||||
4. + -
|
||||
13.000 -2.000i
|
||||
13.000 -2.000i
|
||||
7.000 -2.000i
|
||||
7.000 -2.000i
|
||||
|
||||
5. * /
|
||||
30.000 -6.000i
|
||||
90.000 -18.000i
|
||||
30.000 -6.000i
|
||||
10.000 -2.000i
|
||||
10.000 -2.000i
|
||||
10.000 -2.000i
|
||||
|
||||
6. assign += -= *= /=
|
||||
20.000 -4.000i
|
||||
23.000 -4.000i
|
||||
13.000 -2.000i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
288.000 -120.000i
|
||||
30.000 -6.000i
|
||||
10.000 -2.000i
|
||||
|
||||
7. phase modulus polar
|
||||
10.000 -2.000i
|
||||
10.20
|
||||
-0.20
|
||||
10.000 -2.000i
|
||||
|
||||
8. conjugate reciprocal
|
||||
10.000 2.000i
|
||||
10.000 -2.000i
|
||||
0.096 0.019i
|
||||
10.000 -2.000i
|
||||
|
||||
9. power: exp log pow sqrt sqr logn log10
|
||||
96.000 -40.000i
|
||||
-9166.239 -20028.597i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
880.000 -592.000i
|
||||
10.000 -2.000i
|
||||
0.534 0.542i
|
||||
10.000 -2.000i
|
||||
1.009 -0.086i
|
||||
|
||||
10. gonio: sin cos tan asin acos atan
|
||||
0.541 0.457i
|
||||
0.500 0.500i
|
||||
0.990 -0.250i
|
||||
0.500 0.500i
|
||||
0.404 0.564i
|
||||
0.500 0.500i
|
||||
|
||||
11. gonio csc sec cot acsc asec acot
|
||||
1.078 -0.912i
|
||||
0.500 0.500i
|
||||
0.950 0.240i
|
||||
0.500 0.500i
|
||||
0.839 -1.172i
|
||||
0.500 0.500i
|
||||
|
||||
12. gonio hyperbolicus I
|
||||
0.457 0.541i
|
||||
0.500 0.500i
|
||||
0.990 0.250i
|
||||
0.500 0.500i
|
||||
0.564 0.404i
|
||||
0.500 0.500i
|
||||
|
||||
13. gonio hyperbolicus II
|
||||
0.912 -1.078i
|
||||
0.500 0.500i
|
||||
0.950 -0.240i
|
||||
0.500 0.500i
|
||||
1.172 -0.839i
|
||||
0.500 0.500i
|
||||
|
||||
.. Complex done
|
||||
465072
|
||||
1.000 0.000i
|
@ -1,110 +0,0 @@
|
||||
Complex numbers test for Arduino: 0.1.11
|
||||
|
||||
1. Print Complex, set, real, imag
|
||||
1.000 0.000i
|
||||
10.000 -2.000i
|
||||
3.000 0.000i
|
||||
-10.000 4.000i
|
||||
-5.000 -5.000i
|
||||
0.000 0.000i
|
||||
0.00
|
||||
0.00
|
||||
|
||||
2. == !=
|
||||
ok :)
|
||||
ok :)
|
||||
ok :)
|
||||
|
||||
3. negation -
|
||||
-10.000 2.000i
|
||||
10.000 -2.000i
|
||||
ok :)
|
||||
|
||||
4. + -
|
||||
13.000 -2.000i
|
||||
13.000 -2.000i
|
||||
7.000 -2.000i
|
||||
7.000 -2.000i
|
||||
|
||||
5. * /
|
||||
30.000 -6.000i
|
||||
90.000 -18.000i
|
||||
30.000 -6.000i
|
||||
10.000 -2.000i
|
||||
10.000 -2.000i
|
||||
10.000 -2.000i
|
||||
|
||||
6. assign += -= *= /=
|
||||
20.000 -4.000i
|
||||
23.000 -4.000i
|
||||
13.000 -2.000i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
288.000 -120.000i
|
||||
30.000 -6.000i
|
||||
10.000 -2.000i
|
||||
|
||||
7. phase modulus polar
|
||||
10.000 -2.000i
|
||||
10.20
|
||||
-0.20
|
||||
10.000 -2.000i
|
||||
|
||||
8. conjugate reciprocal
|
||||
10.000 2.000i
|
||||
10.000 -2.000i
|
||||
0.096 0.019i
|
||||
10.000 -2.000i
|
||||
|
||||
9. power: exp log pow sqrt sqr logn log10
|
||||
96.000 -40.000i
|
||||
-9166.239 -20028.597i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
880.000 -592.000i
|
||||
10.000 -2.000i
|
||||
0.534 0.542i
|
||||
10.000 -2.000i
|
||||
1.009 -0.086i
|
||||
|
||||
10. gonio: sin cos tan asin acos atan
|
||||
0.541 0.457i
|
||||
0.500 0.500i
|
||||
0.990 -0.250i
|
||||
0.500 0.500i
|
||||
0.404 0.564i
|
||||
0.500 0.500i
|
||||
|
||||
11. gonio csc sec cot acsc asec acot
|
||||
1.078 -0.912i
|
||||
0.500 0.500i
|
||||
0.950 0.240i
|
||||
0.500 0.500i
|
||||
0.839 -1.172i
|
||||
0.500 0.500i
|
||||
|
||||
12. gonio hyperbolicus I
|
||||
0.457 0.541i
|
||||
0.500 0.500i
|
||||
0.990 0.250i
|
||||
0.500 0.500i
|
||||
0.564 0.404i
|
||||
0.500 0.500i
|
||||
|
||||
13. gonio hyperbolicus II
|
||||
0.912 -1.078i
|
||||
0.500 0.500i
|
||||
0.950 -0.240i
|
||||
0.500 0.500i
|
||||
1.172 -0.839i
|
||||
0.500 0.500i
|
||||
|
||||
14. gonio bug fix (minimal) test
|
||||
3.000 4.000i
|
||||
1.000 0.000i
|
||||
|
||||
.. Complex done
|
||||
520444
|
||||
1.000 0.000i
|
@ -1,110 +0,0 @@
|
||||
Complex numbers test for Arduino: 0.1.12
|
||||
|
||||
1. Print Complex, set, real, imag
|
||||
1.000 0.000i
|
||||
10.000 -2.000i
|
||||
3.000 0.000i
|
||||
-10.000 4.000i
|
||||
-5.000 -5.000i
|
||||
0.000 0.000i
|
||||
0.00
|
||||
0.00
|
||||
|
||||
2. == !=
|
||||
ok :)
|
||||
ok :)
|
||||
ok :)
|
||||
|
||||
3. negation -
|
||||
-10.000 2.000i
|
||||
10.000 -2.000i
|
||||
ok :)
|
||||
|
||||
4. + -
|
||||
13.000 -2.000i
|
||||
13.000 -2.000i
|
||||
7.000 -2.000i
|
||||
7.000 -2.000i
|
||||
|
||||
5. * /
|
||||
30.000 -6.000i
|
||||
90.000 -18.000i
|
||||
30.000 -6.000i
|
||||
10.000 -2.000i
|
||||
10.000 -2.000i
|
||||
10.000 -2.000i
|
||||
|
||||
6. assign += -= *= /=
|
||||
20.000 -4.000i
|
||||
23.000 -4.000i
|
||||
13.000 -2.000i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
288.000 -120.000i
|
||||
30.000 -6.000i
|
||||
10.000 -2.000i
|
||||
|
||||
7. phase modulus polar
|
||||
10.000 -2.000i
|
||||
10.20
|
||||
-0.20
|
||||
10.000 -2.000i
|
||||
|
||||
8. conjugate reciprocal
|
||||
10.000 2.000i
|
||||
10.000 -2.000i
|
||||
0.096 0.019i
|
||||
10.000 -2.000i
|
||||
|
||||
9. power: exp log pow sqrt sqr logn log10
|
||||
96.000 -40.000i
|
||||
-9166.239 -20028.597i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
10.000 -2.000i
|
||||
96.000 -40.000i
|
||||
880.000 -592.000i
|
||||
10.000 -2.000i
|
||||
0.534 0.542i
|
||||
10.000 -2.000i
|
||||
1.009 -0.086i
|
||||
|
||||
10. gonio: sin cos tan asin acos atan
|
||||
0.541 0.457i
|
||||
0.500 0.500i
|
||||
0.990 -0.250i
|
||||
0.500 0.500i
|
||||
0.404 0.564i
|
||||
0.500 0.500i
|
||||
|
||||
11. gonio csc sec cot acsc asec acot
|
||||
1.078 -0.912i
|
||||
0.500 0.500i
|
||||
0.950 0.240i
|
||||
0.500 0.500i
|
||||
0.839 -1.172i
|
||||
0.500 0.500i
|
||||
|
||||
12. gonio hyperbolicus I
|
||||
0.457 0.541i
|
||||
0.500 0.500i
|
||||
0.990 0.250i
|
||||
0.500 0.500i
|
||||
0.564 0.404i
|
||||
0.500 0.500i
|
||||
|
||||
13. gonio hyperbolicus II
|
||||
0.912 -1.078i
|
||||
0.500 0.500i
|
||||
0.950 -0.240i
|
||||
0.500 0.500i
|
||||
1.172 -0.839i
|
||||
0.500 0.500i
|
||||
|
||||
14. gonio bug fix (minimal) test
|
||||
3.000 4.000i
|
||||
1.000 0.000i
|
||||
|
||||
.. Complex done
|
||||
520444
|
||||
1.000 0.000i
|
@ -1,67 +0,0 @@
|
||||
|
||||
Complex numbers performance test for Arduino: 0.1.12
|
||||
|
||||
5 constructors 12
|
||||
set(0,0) 4
|
||||
c1 + 1 1588
|
||||
c1 + c2 1608
|
||||
+= c2 1616
|
||||
c5 = -c1 260
|
||||
c1 - 3 1012
|
||||
c1 - c2 1676
|
||||
c5 -= c2 1612
|
||||
c1 * 3 5720
|
||||
c1 * c2 5444
|
||||
c5 *= c2 4304
|
||||
c1 / 3 12188
|
||||
c1 / c2 12064
|
||||
c5 /= c2 6476
|
||||
|
||||
real() 4
|
||||
imag() 4
|
||||
modulus() 68
|
||||
phase 216
|
||||
polar() 260
|
||||
conjugate() 8
|
||||
reciprocal(); 8008
|
||||
|
||||
c_sqr() 4280
|
||||
c_exp() 41732
|
||||
c_log() 39484
|
||||
c_pow(2) 87740
|
||||
c_sqrt() 8464
|
||||
c_logn(c4) 72420
|
||||
c_pow(c5) 61004
|
||||
c_log10() 40080
|
||||
|
||||
c_sin() 57768
|
||||
c_asin() 74980
|
||||
c_cos() 57880
|
||||
c_acos() 73392
|
||||
c_tan() 128928
|
||||
c_atan() 66740
|
||||
|
||||
c_csc() 70168
|
||||
c_acsc() 85272
|
||||
c_sec() 70232
|
||||
c_asec() 86948
|
||||
c_cot() 141432
|
||||
c_acot() 74292
|
||||
|
||||
c_sinh() 57764
|
||||
c_asinh() 64392
|
||||
c_cosh() 57864
|
||||
c_acosh() 61956
|
||||
c_tanh() 128920
|
||||
c_atanh() 90900
|
||||
|
||||
c_csch() 70252
|
||||
c_acsch() 66284
|
||||
c_sech() 70220
|
||||
c_asech() 77312
|
||||
c_coth() 141352
|
||||
c_acoth() 98056
|
||||
|
||||
2317680
|
||||
|
||||
.. Complex done
|
@ -1,67 +0,0 @@
|
||||
|
||||
Complex numbers performance test for Arduino: 0.1.07
|
||||
|
||||
5 constructors 8
|
||||
set(0,0) 4
|
||||
c1 + 1 2580
|
||||
c1 + c2 2392
|
||||
+= c2 2104
|
||||
c5 = -c1 760
|
||||
c1 - 3 2464
|
||||
c1 - c2 2296
|
||||
c5 -= c2 1976
|
||||
c1 * 3 5700
|
||||
c1 * c2 5560
|
||||
c5 *= c2 5152
|
||||
c1 / 3 13864
|
||||
c1 / c2 13724
|
||||
c5 /= c2 12248
|
||||
|
||||
real() 4
|
||||
imag() 4
|
||||
modulus() 68
|
||||
phase 204
|
||||
polar() 24476
|
||||
conjugate() 4
|
||||
reciprocal(); 8572
|
||||
|
||||
c_sqr() 5092
|
||||
c_exp() 43100
|
||||
c_log() 40144
|
||||
c_pow(2) 89248
|
||||
c_sqrt() 8616
|
||||
c_logn(c4) 70780
|
||||
c_pow(c5) 62192
|
||||
c_log10() 38220
|
||||
|
||||
c_sin() 51772
|
||||
c_asin() 76844
|
||||
c_cos() 51860
|
||||
c_acos() 75248
|
||||
c_tan() 118520
|
||||
c_atan() 69332
|
||||
|
||||
c_csc() 66048
|
||||
c_acsc() 85060
|
||||
c_sec() 66292
|
||||
c_asec() 90756
|
||||
c_cot() 132736
|
||||
c_acot() 77304
|
||||
|
||||
c_sinh() 51764
|
||||
c_asinh() 66212
|
||||
c_cosh() 51860
|
||||
c_acosh() 64388
|
||||
c_tanh() 118524
|
||||
c_atanh() 92468
|
||||
|
||||
c_csch() 66140
|
||||
c_acsch() 70128
|
||||
c_sech() 66292
|
||||
c_asech() 81692
|
||||
c_coth() 132664
|
||||
c_acoth() 100032
|
||||
|
||||
2308648
|
||||
|
||||
.. Complex done
|
@ -1,67 +0,0 @@
|
||||
|
||||
Complex numbers performance test for Arduino: 0.1.11
|
||||
|
||||
5 constructors 12
|
||||
set(0,0) 4
|
||||
c1 + 1 1588
|
||||
c1 + c2 1608
|
||||
+= c2 1616
|
||||
c5 = -c1 260
|
||||
c1 - 3 1012
|
||||
c1 - c2 1676
|
||||
c5 -= c2 1612
|
||||
c1 * 3 5720
|
||||
c1 * c2 5444
|
||||
c5 *= c2 4304
|
||||
c1 / 3 12188
|
||||
c1 / c2 12064
|
||||
c5 /= c2 6476
|
||||
|
||||
real() 4
|
||||
imag() 4
|
||||
modulus() 68
|
||||
phase 216
|
||||
polar() 260
|
||||
conjugate() 8
|
||||
reciprocal(); 8008
|
||||
|
||||
c_sqr() 4280
|
||||
c_exp() 41732
|
||||
c_log() 39484
|
||||
c_pow(2) 87740
|
||||
c_sqrt() 8464
|
||||
c_logn(c4) 72420
|
||||
c_pow(c5) 61004
|
||||
c_log10() 40080
|
||||
|
||||
c_sin() 57768
|
||||
c_asin() 74980
|
||||
c_cos() 57880
|
||||
c_acos() 73392
|
||||
c_tan() 128928
|
||||
c_atan() 66740
|
||||
|
||||
c_csc() 70168
|
||||
c_acsc() 85272
|
||||
c_sec() 70232
|
||||
c_asec() 86948
|
||||
c_cot() 141432
|
||||
c_acot() 74292
|
||||
|
||||
c_sinh() 57764
|
||||
c_asinh() 64392
|
||||
c_cosh() 57864
|
||||
c_acosh() 61956
|
||||
c_tanh() 128920
|
||||
c_atanh() 90900
|
||||
|
||||
c_csch() 70252
|
||||
c_acsch() 66284
|
||||
c_sech() 70220
|
||||
c_asech() 77312
|
||||
c_coth() 141352
|
||||
c_acoth() 98056
|
||||
|
||||
2317680
|
||||
|
||||
.. Complex done
|
@ -1,39 +0,0 @@
|
||||
#include <cozir.h>
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial nss(3,2);
|
||||
#else
|
||||
#include <NewSoftSerial.h>
|
||||
NewSoftSerial nss(3,2);
|
||||
#endif
|
||||
|
||||
|
||||
COZIR czr(nss);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
Serial.println("Setup");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.println("Loop");
|
||||
float t = czr.Celsius();
|
||||
float f = czr.Fahrenheit();
|
||||
float h = czr.Humidity();
|
||||
uint16_t c = czr.CO2();
|
||||
|
||||
Serial.print("Celcius = ");
|
||||
Serial.println(t);
|
||||
Serial.print("Fahrenheit = ");
|
||||
Serial.println(f);
|
||||
Serial.print("Humidity = ");
|
||||
Serial.println(h);
|
||||
Serial.print("CO2 = ");
|
||||
Serial.println(c);
|
||||
|
||||
delay(3000);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// FILE: DAC8551.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Arduino library for DAC8551 SPI Digital Analog Convertor
|
||||
// VERSION: 0.2.1
|
||||
// VERSION: 0.2.2
|
||||
// URL: https://github.com/RobTillaart/DAC8551
|
||||
//
|
||||
// HISTORY
|
||||
@ -12,6 +12,7 @@
|
||||
// 0.1.3 2020-06-07 fix library.json
|
||||
// 0.2.0 2020-12-18 add slaveSelect to hardware SPI
|
||||
// 0.2.1 2020-12-18 add arduino-ci + unit tests
|
||||
// 0.2.2 2021-02-04 add DAC8550 DAC8501 DAC8501 derived class + minor refactor
|
||||
|
||||
|
||||
#include "DAC8551.h"
|
||||
@ -23,14 +24,16 @@ DAC8551::DAC8551(uint8_t slaveSelect)
|
||||
_slaveSelect = slaveSelect;
|
||||
}
|
||||
|
||||
|
||||
DAC8551::DAC8551(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)
|
||||
{
|
||||
_hwSPI = false;
|
||||
_hwSPI = false;
|
||||
_spiData = spiData;
|
||||
_spiClock = spiClock;
|
||||
_slaveSelect = slaveSelect;
|
||||
}
|
||||
|
||||
|
||||
// initializes the SPI
|
||||
// and sets internal state
|
||||
void DAC8551::begin()
|
||||
@ -62,47 +65,50 @@ void DAC8551::setValue(uint16_t value)
|
||||
updateDevice();
|
||||
}
|
||||
|
||||
|
||||
// returns 0..65535
|
||||
uint16_t DAC8551::getValue()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
void DAC8551::setPowerDown(uint8_t powerDownMode)
|
||||
{
|
||||
_register = powerDownMode;
|
||||
updateDevice();
|
||||
}
|
||||
|
||||
|
||||
uint8_t DAC8551::getPowerDownMode()
|
||||
{
|
||||
return _register & 0x03;
|
||||
}
|
||||
|
||||
|
||||
void DAC8551::updateDevice()
|
||||
{
|
||||
uint8_t configRegister = _register;
|
||||
|
||||
digitalWrite(_slaveSelect, LOW);
|
||||
if (_hwSPI)
|
||||
{
|
||||
SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE1));
|
||||
digitalWrite(_slaveSelect, LOW);
|
||||
SPI.transfer(configRegister);
|
||||
SPI.transfer(_value >> 8);
|
||||
SPI.transfer(_value & 0xFF);
|
||||
digitalWrite(_slaveSelect, HIGH);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
else // Software SPI
|
||||
{
|
||||
digitalWrite(_slaveSelect, LOW);
|
||||
swSPI_transfer(configRegister);
|
||||
swSPI_transfer(_value >> 8);
|
||||
swSPI_transfer(_value & 0xFF);
|
||||
digitalWrite(_slaveSelect, HIGH);
|
||||
}
|
||||
digitalWrite(_slaveSelect, LOW);
|
||||
}
|
||||
|
||||
|
||||
// simple one mode version
|
||||
void DAC8551::swSPI_transfer(uint8_t value)
|
||||
{
|
||||
@ -114,4 +120,39 @@ void DAC8551::swSPI_transfer(uint8_t value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// derive 8501, 8531 and 8550 from 8551
|
||||
//
|
||||
|
||||
DAC8501::DAC8501(uint8_t slaveSelect) : DAC8551(slaveSelect)
|
||||
{
|
||||
}
|
||||
|
||||
DAC8501::DAC8501(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)
|
||||
: DAC8551(spiData, spiClock, slaveSelect)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DAC8531::DAC8531(uint8_t slaveSelect) : DAC8551(slaveSelect)
|
||||
{
|
||||
}
|
||||
|
||||
DAC8531::DAC8531(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)
|
||||
: DAC8551(spiData, spiClock, slaveSelect)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DAC8550::DAC8550(uint8_t slaveSelect) : DAC8551(slaveSelect)
|
||||
{
|
||||
}
|
||||
|
||||
DAC8550::DAC8550(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)
|
||||
: DAC8551(spiData, spiClock, slaveSelect)
|
||||
{
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -4,7 +4,7 @@
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Arduino library for DAC8551 SPI Digital Analog Convertor
|
||||
// could work with DAC8550, not tested
|
||||
// VERSION: 0.2.1
|
||||
// VERSION: 0.2.2
|
||||
// HISTORY: See DAC8551.cpp
|
||||
// URL: https://github.com/RobTillaart/DAC8551
|
||||
//
|
||||
@ -13,7 +13,7 @@
|
||||
#include "SPI.h"
|
||||
|
||||
|
||||
#define DAC8551_LIB_VERSION (F("0.2.1"))
|
||||
#define DAC8551_LIB_VERSION (F("0.2.2"))
|
||||
|
||||
|
||||
#define DAC8551_POWERDOWN_NORMAL 0
|
||||
@ -36,7 +36,7 @@ public:
|
||||
void setPowerDown(uint8_t powerDownMode);
|
||||
uint8_t getPowerDownMode();
|
||||
|
||||
private:
|
||||
protected:
|
||||
uint8_t _spiData;
|
||||
uint8_t _spiClock;
|
||||
uint8_t _slaveSelect;
|
||||
@ -48,4 +48,58 @@ private:
|
||||
void swSPI_transfer(uint8_t value);
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// derive 8501, 8531 and 8550 from 8551
|
||||
//
|
||||
|
||||
#define DAC8501_POWERDOWN_NORMAL 0
|
||||
#define DAC8501_POWERDOWN_1K 1
|
||||
#define DAC8501_POWERDOWN_100K 2
|
||||
#define DAC8501_POWERDOWN_HIGH_IMP 3
|
||||
|
||||
|
||||
class DAC8501 : public DAC8551
|
||||
{
|
||||
public:
|
||||
DAC8501(uint8_t slaveSelect);
|
||||
DAC8501(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define DAC8531_POWERDOWN_NORMAL 0
|
||||
#define DAC8531_POWERDOWN_1K 1
|
||||
#define DAC8531_POWERDOWN_100K 2
|
||||
#define DAC8531_POWERDOWN_HIGH_IMP 3
|
||||
|
||||
|
||||
class DAC8531 : public DAC8551
|
||||
{
|
||||
public:
|
||||
DAC8531(uint8_t slaveSelect);
|
||||
DAC8531(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define DAC8550_POWERDOWN_NORMAL 0
|
||||
#define DAC8550_POWERDOWN_1K 1
|
||||
#define DAC8550_POWERDOWN_100K 2
|
||||
#define DAC8550_POWERDOWN_HIGH_IMP 3
|
||||
|
||||
|
||||
class DAC8550 : public DAC8551
|
||||
{
|
||||
public:
|
||||
DAC8550(uint8_t slaveSelect);
|
||||
DAC8550(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -5,13 +5,16 @@
|
||||
|
||||
# DAC8551
|
||||
|
||||
Arduino library for DAC8551 SPI Digital Analog Convertor
|
||||
Arduino library for DAC8501 DAC8531, DAC8550, DAC8551 SPI Digital Analog Convertor
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
The DAC8551 is a SPI based 16 bit DAC with one channel.
|
||||
|
||||
The DAC8501, DAC8531 and DAC8550 are drop in compatible
|
||||
They all have classed derived 1 to 1 from DAC8551.
|
||||
|
||||
**Warning** this library is not tested extensively
|
||||
|
||||
|
||||
@ -19,13 +22,20 @@ The DAC8551 is a SPI based 16 bit DAC with one channel.
|
||||
|
||||
### Core
|
||||
|
||||
- **DAC8551(uint8_t slaveSelect)** Constructor for hardware SPI,
|
||||
- **DAC8501(uint8_t slaveSelect)** Constructor for DAC8501 with hardware SPI,
|
||||
- **DAC8531(uint8_t slaveSelect)** Constructor for DAC8531 with hardware SPI,
|
||||
- **DAC8550(uint8_t slaveSelect)** Constructor for DAC8550 with hardware SPI,
|
||||
- **DAC8551(uint8_t slaveSelect)** Constructor for DAC8551 with hardware SPI,
|
||||
since 0.2.0 the slaveSelect pin needs to be defined.
|
||||
- **DAC8501(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)** Constructor for the software SPI
|
||||
- **DAC8531(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)** Constructor for the software SPI
|
||||
- **DAC8550(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)** Constructor for the software SPI
|
||||
- **DAC8551(uint8_t spiData, uint8_t spiClock, uint8_t slaveSelect)** Constructor for the software SPI
|
||||
- **void begin()** initializes all pins to default state
|
||||
- **void setValue(uint16_t value)** set the value of the channel to 0 - 65535
|
||||
- **uint16_t getValue()** returns the last value written.
|
||||
|
||||
|
||||
### Power down
|
||||
|
||||
check datasheet for details.
|
||||
@ -41,6 +51,15 @@ check datasheet for details.
|
||||
| DAC8551_POWERDOWN_HIGH_IMP | 3 |
|
||||
|
||||
|
||||
DAC8501, DAC8531 and DAC8550 uses the same constants.
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
- more testing
|
||||
- investigate differences between 8551 and 8550.
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
@ -56,6 +75,3 @@ See examples
|
||||
**demo_powerdown.ino**
|
||||
- idem
|
||||
|
||||
## TODO
|
||||
|
||||
more testing
|
||||
|
@ -1,6 +1,9 @@
|
||||
# Syntax Coloring Map For DAC8551
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
DAC8501 KEYWORD1
|
||||
DAC8531 KEYWORD1
|
||||
DAC8550 KEYWORD1
|
||||
DAC8551 KEYWORD1
|
||||
|
||||
|
||||
@ -14,6 +17,22 @@ getPowerDownMode KEYWORD2
|
||||
|
||||
# Constants (LITERAL1)
|
||||
DAC8551_LIB_VERSION LITERAL1
|
||||
|
||||
DAC8501_POWERDOWN_NORMAL LITERAL1
|
||||
DAC8501_POWERDOWN_1K LITERAL1
|
||||
DAC8501_POWERDOWN_100K LITERAL1
|
||||
DAC8501_POWERDOWN_HIGH_IMP LITERAL1
|
||||
|
||||
DAC8531_POWERDOWN_NORMAL LITERAL1
|
||||
DAC8531_POWERDOWN_1K LITERAL1
|
||||
DAC8531_POWERDOWN_100K LITERAL1
|
||||
DAC8531_POWERDOWN_HIGH_IMP LITERAL1
|
||||
|
||||
DAC8550_POWERDOWN_NORMAL LITERAL1
|
||||
DAC8550_POWERDOWN_1K LITERAL1
|
||||
DAC8550_POWERDOWN_100K LITERAL1
|
||||
DAC8550_POWERDOWN_HIGH_IMP LITERAL1
|
||||
|
||||
DAC8551_POWERDOWN_NORMAL LITERAL1
|
||||
DAC8551_POWERDOWN_1K LITERAL1
|
||||
DAC8551_POWERDOWN_100K LITERAL1
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "DAC8551",
|
||||
"keywords": "DAC8551, SPI, digital, analog, convertor",
|
||||
"description": "Arduino library for DAC8551 SPI Digital Analog Convertor",
|
||||
"keywords": "DAC8551, DAC8550, DAC8501, DAC8531, SPI, digital, analog, convertor",
|
||||
"description": "Arduino library for DAC8501, DAC8531, DAC8550 and DAC8551 SPI 16-bit Digital Analog Convertor",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/DAC8551"
|
||||
},
|
||||
"version":"0.2.1",
|
||||
"version":"0.2.2",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
name=DAC8551
|
||||
version=0.2.1
|
||||
version=0.2.2
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for DAC8551 SPI Digital Analog Convertor
|
||||
paragraph=could work with DAC8550 (not tested)
|
||||
sentence=Arduino library for DAC8501, DAC8531, DAC8550 and DAC8551 SPI 16-bit Digital Analog Convertor
|
||||
paragraph=
|
||||
category=Sensors
|
||||
url=https://github.com/RobTillaart/DAC8551
|
||||
architectures=*
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/DHTstable"
|
||||
},
|
||||
"version":"0.2.8",
|
||||
"version": "0.2.8",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelavr"
|
||||
}
|
||||
|
@ -1,149 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20.cpp
|
||||
// AUTHOR: Rob.Tillaart@gmail.com
|
||||
// VERSION: 0.1.6
|
||||
// DATE: 2017-07-25
|
||||
// PUPROSE: library for DS18B20 temperature sensor with minimal footprint
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2017-07-25 initial version
|
||||
// 0.1.1 2020-02-18 added getAddress()
|
||||
// 0.1.2 2020-04-11 #pragma once, refactor
|
||||
// 0.1.3 2020-04-22 #1 fix library.json file
|
||||
// 0.1.4 2020-04-23 #2 add retry in begin() to support Wemos
|
||||
// 0.1.5 2020-04-29 #4 added set/getConfig + DEVICE_CRC_ERROR + example
|
||||
// 0.1.6 2020-06-07 fix library.json
|
||||
|
||||
#include "DS18B20.h"
|
||||
|
||||
// OneWire commands
|
||||
#define STARTCONVO 0x44
|
||||
#define READSCRATCH 0xBE
|
||||
#define WRITESCRATCH 0x4E
|
||||
|
||||
// Scratchpad locations
|
||||
#define TEMP_LSB 0
|
||||
#define TEMP_MSB 1
|
||||
#define HIGH_ALARM_TEMP 2
|
||||
#define LOW_ALARM_TEMP 3
|
||||
#define CONFIGURATION 4
|
||||
#define INTERNAL_BYTE 5
|
||||
#define COUNT_REMAIN 6
|
||||
#define COUNT_PER_C 7
|
||||
#define SCRATCHPAD_CRC 8
|
||||
|
||||
// Device resolution
|
||||
#define TEMP_9_BIT 0x1F // 9 bit
|
||||
#define TEMP_10_BIT 0x3F // 10 bit
|
||||
#define TEMP_11_BIT 0x5F // 11 bit
|
||||
#define TEMP_12_BIT 0x7F // 12 bit
|
||||
|
||||
|
||||
DS18B20::DS18B20(OneWire* _oneWire)
|
||||
{
|
||||
_wire = _oneWire;
|
||||
_addresFound = false;
|
||||
_config = DS18B20_CLEAR;
|
||||
}
|
||||
|
||||
bool DS18B20::begin(void)
|
||||
{
|
||||
_config = DS18B20_CLEAR;
|
||||
_addresFound = false;
|
||||
for (uint8_t retries = 3; (retries > 0) && (_addresFound == false); retries--)
|
||||
{
|
||||
_wire->reset_search();
|
||||
_deviceAddress[0] = 0x00;
|
||||
_wire->search(_deviceAddress);
|
||||
_addresFound = _deviceAddress[0] != 0x00 &&
|
||||
_wire->crc8(_deviceAddress, 7) == _deviceAddress[7];
|
||||
}
|
||||
return _addresFound;
|
||||
}
|
||||
|
||||
void DS18B20::readScratchPad(uint8_t *scratchPad, uint8_t fields)
|
||||
{
|
||||
_wire->reset();
|
||||
_wire->select(_deviceAddress);
|
||||
_wire->write(READSCRATCH);
|
||||
|
||||
for (uint8_t i = 0; i < fields; i++)
|
||||
{
|
||||
scratchPad[i] = _wire->read();
|
||||
}
|
||||
_wire->reset();
|
||||
}
|
||||
|
||||
bool DS18B20::isConversionComplete(void)
|
||||
{
|
||||
return (_wire->read_bit() == 1);
|
||||
}
|
||||
|
||||
void DS18B20::requestTemperatures(void)
|
||||
{
|
||||
_wire->reset();
|
||||
_wire->skip();
|
||||
_wire->write(STARTCONVO, 0);
|
||||
}
|
||||
|
||||
float DS18B20::getTempC(void)
|
||||
{
|
||||
ScratchPad scratchPad;
|
||||
if (_config & DS18B20_CRC)
|
||||
{
|
||||
readScratchPad(scratchPad, 9);
|
||||
if (_wire->crc8(scratchPad, 8) != scratchPad[SCRATCHPAD_CRC])
|
||||
{
|
||||
return DEVICE_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
readScratchPad(scratchPad, 2);
|
||||
}
|
||||
int16_t rawTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 8) | scratchPad[TEMP_LSB];
|
||||
float temp = 0.0625 * rawTemperature;
|
||||
if (temp < -55) return DEVICE_DISCONNECTED;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void DS18B20::setResolution(uint8_t newResolution)
|
||||
{
|
||||
_wire->reset();
|
||||
_wire->select(_deviceAddress);
|
||||
_wire->write(WRITESCRATCH);
|
||||
// two dummy values for LOW & HIGH ALARM
|
||||
_wire->write(0);
|
||||
_wire->write(100);
|
||||
switch (newResolution)
|
||||
{
|
||||
case 12:
|
||||
_wire->write(TEMP_12_BIT);
|
||||
break;
|
||||
case 11:
|
||||
_wire->write(TEMP_11_BIT);
|
||||
break;
|
||||
case 10:
|
||||
_wire->write(TEMP_10_BIT);
|
||||
break;
|
||||
case 9:
|
||||
default:
|
||||
_wire->write(TEMP_9_BIT);
|
||||
break;
|
||||
}
|
||||
_wire->reset();
|
||||
}
|
||||
|
||||
bool DS18B20::getAddress(uint8_t* buf)
|
||||
{
|
||||
if (_addresFound)
|
||||
{
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
buf[i] = _deviceAddress[i];
|
||||
}
|
||||
}
|
||||
return _addresFound;
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,60 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: DS18B20.h
|
||||
// AUTHOR: Rob.Tillaart@gmail.com
|
||||
// VERSION: 0.1.6
|
||||
// DATE: 2017-07-25
|
||||
// PUPROSE: library for DS18B20 temperature sensor with minimal footprint
|
||||
//
|
||||
|
||||
//
|
||||
// BOTTOM VIEW
|
||||
//
|
||||
// PIN MEANING
|
||||
// /---+
|
||||
// / o | 1 GND
|
||||
// | o | 2 DATA
|
||||
// \ o | 3 VCC
|
||||
// \---+
|
||||
//
|
||||
|
||||
#define DS18B20_LIB_VERSION "0.1.6"
|
||||
|
||||
#include <OneWire.h>
|
||||
|
||||
// Error Code
|
||||
#define DEVICE_DISCONNECTED -127
|
||||
#define DEVICE_CRC_ERROR -128
|
||||
|
||||
// config codes
|
||||
#define DS18B20_CLEAR 0x00
|
||||
#define DS18B20_CRC 0x01
|
||||
|
||||
|
||||
typedef uint8_t DeviceAddress[8];
|
||||
typedef uint8_t ScratchPad[9];
|
||||
|
||||
|
||||
class DS18B20
|
||||
{
|
||||
public:
|
||||
explicit DS18B20(OneWire *);
|
||||
bool begin(void);
|
||||
void setResolution(uint8_t);
|
||||
void requestTemperatures(void);
|
||||
float getTempC(void);
|
||||
bool isConversionComplete(void);
|
||||
bool getAddress(uint8_t*);
|
||||
|
||||
void setConfig(uint8_t config) { _config = config; };
|
||||
uint8_t getConfig() { return _config; };
|
||||
|
||||
private:
|
||||
void readScratchPad(uint8_t *, uint8_t);
|
||||
DeviceAddress _deviceAddress;
|
||||
OneWire* _wire;
|
||||
bool _addresFound;
|
||||
uint8_t _config;
|
||||
};
|
||||
|
||||
// -- END OF FILE --
|
@ -1,21 +0,0 @@
|
||||
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.
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_diagnose.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: Minimal DS18B20 lib with async support.
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2020-04-23 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
if (sensor.begin() == false)
|
||||
{
|
||||
Serial.println("Error: Could not find sensor.");
|
||||
while (1);
|
||||
}
|
||||
sensor.setResolution(12);
|
||||
sensor.requestTemperatures();
|
||||
|
||||
start = millis();
|
||||
while (!sensor.isConversionComplete());
|
||||
stop = millis();
|
||||
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.println(sensor.getTempC(), 2);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
for (int res = 9; res < 13; res++)
|
||||
{
|
||||
sensor.setResolution(res);
|
||||
|
||||
start = millis();
|
||||
sensor.requestTemperatures();
|
||||
while (!sensor.isConversionComplete());
|
||||
float temperature = sensor.getTempC();
|
||||
stop = millis();
|
||||
|
||||
Serial.print(res);
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.println(temperature, 1); // 1 decimal makes perfect sense
|
||||
}
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,56 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_getAddress.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: DS18B20 lib getAddress demo
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2020-02-18 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
DeviceAddress da;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
Serial.print("\ngetAddress: ");
|
||||
Serial.println(sensor.getAddress(da));
|
||||
|
||||
sensor.begin();
|
||||
|
||||
Serial.print("\ngetAddress: ");
|
||||
Serial.println(sensor.getAddress(da));
|
||||
|
||||
if (!sensor.getAddress(da))
|
||||
{
|
||||
Serial.println("No address found!");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("Address: ");
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (da[i] < 0x10) Serial.print('0');
|
||||
Serial.print(da[i], HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// END OF FILE
|
@ -1,36 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_minimum.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: most minimal sketch
|
||||
//
|
||||
// WARNING: this sketch does not wait for isConversionComplete()
|
||||
// and therefor temperature read is probably incorrect
|
||||
// but it is fast and maybe accurate enough...
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2017-07-25 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
sensor.begin();
|
||||
}
|
||||
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
Serial.println(sensor.getTempC());
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_performance.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: show performance of DS18B20 lib
|
||||
// compared to datasheet times per resolution
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2017-07-25 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
sensor.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
float ti[4] = { 94, 188, 375, 750 };
|
||||
|
||||
Serial.println();
|
||||
Serial.println("Test takes about 30 seconds for 4 resolutions, 20 measurements");
|
||||
Serial.println("RES\tTIME\tACTUAL\tGAIN");
|
||||
for (int r = 9; r < 13; r++)
|
||||
{
|
||||
sensor.setResolution(r);
|
||||
|
||||
uint32_t duration = run(20);
|
||||
float avgDuration = duration / 20.0;
|
||||
|
||||
Serial.print(r);
|
||||
Serial.print("\t");
|
||||
Serial.print(ti[r - 9]);
|
||||
Serial.print("\t");
|
||||
Serial.print(avgDuration, 2);
|
||||
Serial.print("\t");
|
||||
Serial.print(avgDuration * 100 / ti[r - 9], 1);
|
||||
Serial.println("%");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
uint32_t run(int runs)
|
||||
{
|
||||
float t;
|
||||
start = millis();
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
while (!sensor.isConversionComplete());
|
||||
t = sensor.getTempC();
|
||||
}
|
||||
stop = millis();
|
||||
return stop - start;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_simple.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: equivalent of DallasTemperature library Simple
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2017-07-25 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
sensor.begin();
|
||||
}
|
||||
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
|
||||
while (!sensor.isConversionComplete()); // wait until sensor is ready
|
||||
|
||||
Serial.print("Temp: ");
|
||||
Serial.println(sensor.getTempC());
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: Minimal DS18B20 lib with async support.
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2017-07-25 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
sensor.begin();
|
||||
sensor.setResolution(12);
|
||||
sensor.requestTemperatures();
|
||||
|
||||
start = millis();
|
||||
int n = 0;
|
||||
// wait until sensor ready, do some counting for fun.
|
||||
while (!sensor.isConversionComplete()) n++;
|
||||
stop = millis();
|
||||
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(n);
|
||||
Serial.print("\t");
|
||||
Serial.println(sensor.getTempC(), 4); // 4 decimals is too much ...
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
float t;
|
||||
for (int r = 9; r < 13; r++)
|
||||
{
|
||||
sensor.setResolution(r);
|
||||
|
||||
int n = 0;
|
||||
start = millis();
|
||||
sensor.requestTemperatures();
|
||||
while (!sensor.isConversionComplete()) n++;
|
||||
t = sensor.getTempC();
|
||||
stop = millis();
|
||||
|
||||
Serial.print(r);
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.print(n);
|
||||
Serial.print("\t");
|
||||
Serial.println( t, 1); // 1 decimal makes perfect sense
|
||||
}
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_test_disconnect.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: Minimal DS18B20 lib with async support.
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2020-04-29 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
#define ONE_WIRE_BUS 2
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DS18B20 sensor(&oneWire);
|
||||
|
||||
uint32_t start, stop;
|
||||
uint8_t res = 12;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
// wait until address found
|
||||
if (sensor.begin() == false)
|
||||
{
|
||||
Serial.println("ERROR: No device found");
|
||||
while (!sensor.begin()); // wait until device comes available.
|
||||
}
|
||||
|
||||
sensor.setResolution(12);
|
||||
sensor.setConfig(DS18B20_CRC); // or 1
|
||||
sensor.requestTemperatures();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
start = millis();
|
||||
sensor.requestTemperatures();
|
||||
|
||||
// wait for data AND detect disconnect
|
||||
uint32_t timeout = millis();
|
||||
while (!sensor.isConversionComplete())
|
||||
{
|
||||
if (millis() - timeout >= 800) // check for timeout
|
||||
{
|
||||
Serial.println("ERROR: timeout or disconnect");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float t = sensor.getTempC();
|
||||
|
||||
if (t == DEVICE_CRC_ERROR)
|
||||
{
|
||||
Serial.println("ERROR: CRC error");
|
||||
}
|
||||
stop = millis();
|
||||
|
||||
Serial.print(res);
|
||||
Serial.print("\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.println( t, 1); // 1 decimal makes perfect sense
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,58 +0,0 @@
|
||||
//
|
||||
// FILE: DS18B20_two_sensors.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.0.1
|
||||
// PURPOSE: demo with two sensors (on two pins)
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.0.1 = 2017-07-25 initial version
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DS18B20.h>
|
||||
|
||||
// numbers chosen to match pin numbers..
|
||||
#define ONE_WIRE_BUS2 2
|
||||
#define ONE_WIRE_BUS3 3
|
||||
|
||||
OneWire oneWire2(ONE_WIRE_BUS2);
|
||||
OneWire oneWire3(ONE_WIRE_BUS3);
|
||||
|
||||
DS18B20 inside(&oneWire2);
|
||||
DS18B20 outside(&oneWire3);
|
||||
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("DS18B20 Library version: ");
|
||||
Serial.println(DS18B20_LIB_VERSION);
|
||||
|
||||
inside.begin();
|
||||
outside.begin();
|
||||
|
||||
// different resolution shows nicely the async behavior
|
||||
inside.setResolution(12);
|
||||
outside.setResolution(10);
|
||||
|
||||
inside.requestTemperatures();
|
||||
outside.requestTemperatures();
|
||||
}
|
||||
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// print the temperature when available and request a new reading
|
||||
if (inside.isConversionComplete())
|
||||
{
|
||||
Serial.print("inside:\t");
|
||||
Serial.println(inside.getTempC(),1);
|
||||
inside.requestTemperatures();
|
||||
}
|
||||
if (outside.isConversionComplete())
|
||||
{
|
||||
Serial.print("outside:\t\t");
|
||||
Serial.println(outside.getTempC(),1);
|
||||
outside.requestTemperatures();
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
//
|
||||
// FILE: oneWireSearch.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.02
|
||||
// PURPOSE: scan for 1-Wire devices + code snippet generator
|
||||
// DATE: 2015-june-30
|
||||
// URL: http://forum.arduino.cc/index.php?topic=333923
|
||||
//
|
||||
// inspired by http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
// 0.1.00 initial version
|
||||
// 0.1.01 first published version
|
||||
// 0.1.02 small output changes
|
||||
|
||||
#include <OneWire.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println("//\n// Start oneWireSearch.ino \n//");
|
||||
|
||||
for (uint8_t pin = 2; pin < 13; pin++)
|
||||
{
|
||||
findDevices(pin);
|
||||
}
|
||||
Serial.println("\n//\n// End oneWireSearch.ino \n//");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t findDevices(int pin)
|
||||
{
|
||||
OneWire ow(pin);
|
||||
|
||||
uint8_t address[8];
|
||||
uint8_t count = 0;
|
||||
|
||||
|
||||
if (ow.search(address))
|
||||
{
|
||||
Serial.print("\nuint8_t pin");
|
||||
Serial.print(pin, DEC);
|
||||
Serial.println("[][8] = {");
|
||||
do {
|
||||
count++;
|
||||
Serial.println(" {");
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
Serial.print("0x");
|
||||
if (address[i] < 0x10) Serial.print("0");
|
||||
Serial.print(address[i], HEX);
|
||||
if (i < 7) Serial.print(", ");
|
||||
}
|
||||
Serial.println(" },");
|
||||
} while (ow.search(address));
|
||||
|
||||
Serial.println("};");
|
||||
Serial.print("// nr devices found: ");
|
||||
Serial.println(count);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
# Syntax Coloring Map For DS18B20
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
DS18B20 KEYWORD1
|
||||
OneWire KEYWORD1
|
||||
DeviceAddress KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
begin KEYWORD2
|
||||
setResolution KEYWORD2
|
||||
getTempC KEYWORD2
|
||||
requestTemperatures KEYWORD2
|
||||
isConversionComplete KEYWORD2
|
||||
getAddress KEYWORD2
|
||||
setConfig KEYWORD2
|
||||
getConfig KEYWORD2
|
||||
|
||||
# Constants (LITERAL1)
|
||||
DS18B20_LIB_VERSION LITERAL1
|
||||
DEVICE_DISCONNECTED LITERAL1
|
||||
DEVICE_CRC_ERROR LITERAL1
|
||||
DS18B20_CLEAR LITERAL1
|
||||
DS18B20_CRC LITERAL1
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "DS18B20",
|
||||
"keywords": "DS18B20,Dallas,Semiconductor,Temperature,sensor,asynchronuous",
|
||||
"description": "Arduino library for the DS18B20 temperature sensor. Restricted to a single sensor per pin. Minimalistic version.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/DS18B20"
|
||||
},
|
||||
"version":"0.1.6",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
name=DS18B20_RT
|
||||
version=0.1.6
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for the DS18B20 temperature sensor.
|
||||
paragraph=Minimalistic version, restricted to one sensor per pin, asynchronuous mode only.
|
||||
category=Sensors
|
||||
url=https://github.com/RobTillaart/DS18B20
|
||||
architectures=*
|
||||
includes=OneWire.h,DS18B20.h
|
||||
depends=OneWire
|
@ -1,85 +0,0 @@
|
||||
# DS18B20
|
||||
|
||||
Arduino library for the DS18B20 sensor - restricted to one sensor per pin.
|
||||
|
||||
## Arduino Temperature Control Library (ATCL)
|
||||
|
||||
This DS18B20 library is not a full featured library for the DS18B20 family.
|
||||
This library supports only one DS18B20 per Arduino/ MCU pin.
|
||||
|
||||
If you need more functions or control over the DS18B20 family I refer to the library
|
||||
of Miles Burton - https://github.com/milesburton/Arduino-Temperature-Control-Library
|
||||
|
||||
## Description
|
||||
|
||||
I'm a great fan of the above library however some time ago I needed to strip it down
|
||||
to save a few dozen bytes. I reworked that minimalistic version into a library and I
|
||||
added a number of Arduino examples to help you get started.
|
||||
|
||||
The DS18B20 library supports only the DS18B20, only one sensor per pin, no parasite
|
||||
mode, no Fahrenheit and no alarm functions. The only feature the class supports is
|
||||
the asynchronous reading of the temperature by means of three core functions:
|
||||
|
||||
* void requestTemperatures()
|
||||
* bool isConversionComplete()
|
||||
* float readTempC()
|
||||
|
||||
The other main functions are
|
||||
* bool begin(void); *// returns true if the sensor is configured (available)*
|
||||
* void setResolution(uint8_t);
|
||||
* bool getAddress(uint8_t*) *// returns true if the sensor is configured (available)*
|
||||
|
||||
This allowed the class to be both minimal in size and non-blocking. In fact the class
|
||||
has no support for a synchronous read in one call. This choice will teach people
|
||||
how to work in a non-blocking way from the start.
|
||||
|
||||
Effort has been taken to keep the code, variables and function names compatible with
|
||||
ATCL library mentioned above. This way you can step over to that one with relatively
|
||||
few problems when you need more functionality like multiple sensors on one pin.
|
||||
|
||||
Finally this library will probably make it easier to use a DS18B20 with processing
|
||||
boards or IC's with small memory footprint.
|
||||
|
||||
## Operation
|
||||
|
||||
```
|
||||
// BOTTOM VIEW
|
||||
//
|
||||
// PIN MEANING
|
||||
// /---+
|
||||
// / o | 1 GND
|
||||
// | o | 2 DATA
|
||||
// \ o | 3 VCC
|
||||
// \---+
|
||||
```
|
||||
|
||||
This library supports only one DS18B20 per Arduino/ MCU pin.
|
||||
|
||||
Connect a pull-up resistor 4.7 KOhm between pin3 and pin2. When the wires are longer
|
||||
this resistor needs to be smaller.
|
||||
|
||||
### Pull up resistor
|
||||
|
||||
An **indicative** table for pull up resistors, (E12 series), to get started.
|
||||
|
||||
Note: thicker wires require smaller resistors (typically 1 step in E12 series)
|
||||
|
||||
|
||||
| Length | - 5.0 Volt | - 3.3 Volt |
|
||||
|--------------:|------------:|----------:|
|
||||
| 10cm (4") | 10K0 | 6K8 |
|
||||
| 20cm (8") | 8K2 | 4K7 |
|
||||
| 50cm (20") | 4K7 | 3K3 |
|
||||
| 100cm (3'4") | 3K3 | 2K2 |
|
||||
| 200cm (6'8") | 2K2 | 1K0 |
|
||||
| 500cm (16'8") | 1K0 | * |
|
||||
| longer | * | * |
|
||||
|
||||
\* = no info, smaller
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
Miles Burton who originally developed the Arduino Temperature Control Library.
|
||||
and all people who contributed to that lib.
|
||||
|
@ -1,203 +0,0 @@
|
||||
//
|
||||
// FILE: FRAM.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.1
|
||||
// DATE: 2018-01-24
|
||||
// PURPOSE: Arduino library for I2C FRAM
|
||||
// URL: https://github.com/RobTillaart/FRAM_I2C
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2018-01-24 initial version
|
||||
// 0.1.1 2019-07-31 added suppport for Fujitsu 64Kbit MB85RC64T (kudos ysoyipek)
|
||||
// 0.2.0 2020-04-30 refactor, add writeProtectPin code
|
||||
// 0.2.1 2020-06-10 fix library.json
|
||||
|
||||
#include "FRAM.h"
|
||||
|
||||
const uint8_t FRAM_SLAVE_ID_= 0x7C;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// PUBLIC
|
||||
//
|
||||
FRAM::FRAM()
|
||||
{}
|
||||
|
||||
int FRAM::begin(uint8_t address, int8_t writeProtectPin)
|
||||
{
|
||||
if (address < 0x50 || address > 0x57)
|
||||
{
|
||||
return FRAM_ERROR_ADDR;
|
||||
}
|
||||
|
||||
_address = address;
|
||||
Wire.begin();
|
||||
|
||||
if (writeProtectPin > -1)
|
||||
{
|
||||
_writeProtectPin = writeProtectPin;
|
||||
pinMode(_writeProtectPin, OUTPUT);
|
||||
}
|
||||
return FRAM_OK;
|
||||
}
|
||||
|
||||
void FRAM::write8(uint16_t memaddr, uint8_t value)
|
||||
{
|
||||
uint8_t val = value;
|
||||
writeBlock(memaddr, (uint8_t *)&val, 1);
|
||||
}
|
||||
|
||||
void FRAM::write16(uint16_t memaddr, uint16_t value)
|
||||
{
|
||||
uint16_t val = value;
|
||||
writeBlock(memaddr, (uint8_t *)&val, 2);
|
||||
}
|
||||
|
||||
void FRAM::write32(uint16_t memaddr, uint32_t value)
|
||||
{
|
||||
uint32_t val = value;
|
||||
writeBlock(memaddr, (uint8_t *)&val, 4);
|
||||
}
|
||||
|
||||
void FRAM::write(uint16_t memaddr, uint8_t * obj, uint16_t size)
|
||||
{
|
||||
const int blocksize = 24;
|
||||
uint8_t * p = obj;
|
||||
while (size >= blocksize)
|
||||
{
|
||||
writeBlock(memaddr, p, blocksize);
|
||||
memaddr += blocksize;
|
||||
p += blocksize;
|
||||
size -= blocksize;
|
||||
}
|
||||
// remaining
|
||||
if (size > 0)
|
||||
{
|
||||
writeBlock(memaddr, p, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t FRAM::read8(uint16_t memaddr)
|
||||
{
|
||||
uint8_t val;
|
||||
readBlock(memaddr, (uint8_t *)&val, 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t FRAM::read16(uint16_t memaddr)
|
||||
{
|
||||
uint16_t val;
|
||||
readBlock(memaddr, (uint8_t *)&val, 2);
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t FRAM::read32(uint16_t memaddr)
|
||||
{
|
||||
uint32_t val;
|
||||
readBlock(memaddr, (uint8_t *)&val, 4);
|
||||
return val;
|
||||
}
|
||||
|
||||
void FRAM::read(uint16_t memaddr, uint8_t * obj, uint16_t size)
|
||||
{
|
||||
const uint8_t blocksize = 24;
|
||||
uint8_t * p = obj;
|
||||
while (size >= blocksize)
|
||||
{
|
||||
readBlock(memaddr, p, blocksize);
|
||||
memaddr += blocksize;
|
||||
p += blocksize;
|
||||
size -= blocksize;
|
||||
}
|
||||
// remainder
|
||||
if (size > 0)
|
||||
{
|
||||
readBlock(memaddr, p, size);
|
||||
}
|
||||
}
|
||||
|
||||
bool FRAM::setWriteProtect(bool b)
|
||||
{
|
||||
if (_writeProtectPin == -1) return false;
|
||||
digitalWrite(_writeProtectPin, b ? HIGH : LOW);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t FRAM::getManufacturerID()
|
||||
{
|
||||
return getMetaData(0);
|
||||
}
|
||||
|
||||
uint16_t FRAM::getProductID()
|
||||
{
|
||||
return getMetaData(1);
|
||||
}
|
||||
|
||||
uint16_t FRAM::getSize()
|
||||
{
|
||||
uint16_t val = getMetaData(2); // density bits
|
||||
if (val > 0) return 1 << val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
//
|
||||
|
||||
// metadata is packed as [....MMMM][MMMMDDDD][PPPPPPPP]
|
||||
// M = manufacturerID
|
||||
// D = density => memsize = 2^D KB
|
||||
// P = product ID (together with D)
|
||||
uint16_t FRAM::getMetaData(uint8_t field)
|
||||
{
|
||||
if (field > 2) return 0;
|
||||
|
||||
Wire.beginTransmission(FRAM_SLAVE_ID_);
|
||||
Wire.write(_address << 1);
|
||||
Wire.endTransmission(false);
|
||||
int x = Wire.requestFrom(FRAM_SLAVE_ID_, (uint8_t)3);
|
||||
if (x != 3) return -1;
|
||||
|
||||
uint32_t value = 0;
|
||||
value = Wire.read();
|
||||
value |= Wire.read();
|
||||
value |= Wire.read();
|
||||
// MANUFACTURER
|
||||
if (field == 0) return (value >> 12) & 0xFF;
|
||||
// PRODUCT ID
|
||||
if (field == 1) return value & 0x0FFF;
|
||||
// DENSITY
|
||||
if (field == 2) return (value >> 8) & 0x0F;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FRAM::writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
|
||||
{
|
||||
// TODO constrain size < 30 ??
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(memaddr >> 8);
|
||||
Wire.write(memaddr & 0xFF);
|
||||
uint8_t * p = obj;
|
||||
for (uint8_t i = 0; i < size; i++)
|
||||
{
|
||||
Wire.write(*p++);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void FRAM::readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
|
||||
{
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(memaddr >> 8);
|
||||
Wire.write(memaddr & 0xFF);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(_address, size);
|
||||
uint8_t * p = obj;
|
||||
for (uint8_t i = 0; i < size; i++)
|
||||
{
|
||||
*p++ = Wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: FRAM.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.1
|
||||
// DATE: 2018-01-24
|
||||
// PURPOSE: Arduino library for I2C FRAM
|
||||
// URL: https://github.com/RobTillaart/FRAM_I2C
|
||||
//
|
||||
// HISTORY:
|
||||
// see FRAM.cpp file
|
||||
//
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
|
||||
#define FRAM_LIB_VERSION (F("0.2.1"))
|
||||
|
||||
#define FRAM_OK 0
|
||||
#define FRAM_ERROR_ADDR -10
|
||||
|
||||
class FRAM
|
||||
{
|
||||
public:
|
||||
FRAM();
|
||||
|
||||
// writeProtectPin is optional
|
||||
int begin(const uint8_t address = 0x50, int8_t writeProtectPin = -1);
|
||||
|
||||
void write8(uint16_t memaddr, uint8_t value);
|
||||
void write16(uint16_t memaddr, uint16_t value);
|
||||
void write32(uint16_t memaddr, uint32_t value);
|
||||
void write(uint16_t memaddr, uint8_t * obj, uint16_t size);
|
||||
|
||||
uint8_t read8(uint16_t memaddr);
|
||||
uint16_t read16(uint16_t memaddr);
|
||||
uint32_t read32(uint16_t memaddr);
|
||||
void read(uint16_t memaddr, uint8_t * obj, uint16_t size);
|
||||
|
||||
bool setWriteProtect(bool b);
|
||||
|
||||
uint16_t getManufacturerID();
|
||||
uint16_t getProductID();
|
||||
uint16_t getSize();
|
||||
|
||||
private:
|
||||
uint8_t _address;
|
||||
int8_t _writeProtectPin = -1; // default no pin ==> no write protect.
|
||||
|
||||
uint16_t getMetaData(uint8_t id);
|
||||
void writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
|
||||
void readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
|
||||
};
|
||||
|
||||
// -- END OF FILE --
|
@ -1,21 +0,0 @@
|
||||
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.
|
@ -1,23 +0,0 @@
|
||||
# FRAM_I2C
|
||||
|
||||
Arduino library for I2C FRAM
|
||||
|
||||
# Description
|
||||
|
||||
FRAM is a library to read and write (over I2C) to an FRAM module.
|
||||
FRAM is much faster than EEPROM and almost as fast as Arduino UNO RAM.
|
||||
Another imaportant feature is that FRAM keeps its content after a reboot (non-volatile)
|
||||
|
||||
Types of FRAM it should work with
|
||||
|
||||
| SIZE | TYPE |
|
||||
|:---:|:---:|
|
||||
| 8KB | MB85RC64T |
|
||||
| 32KB | MB85RC256V |
|
||||
| 64KB | MB85RC512T |
|
||||
| 128KB | MB85RC1MT |
|
||||
|
||||
|
||||
# Operational
|
||||
|
||||
See examples
|
@ -1,240 +0,0 @@
|
||||
//
|
||||
// FILE: testFRAM.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: test for FRAM library for Arduino
|
||||
// URL: https://github.com/RobTillaart/FRAM_I2C
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include "FRAM.h"
|
||||
|
||||
FRAM fram;
|
||||
|
||||
uint32_t start;
|
||||
uint32_t stop;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("FRAM_LIB_VERSION: ");
|
||||
Serial.println(FRAM_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
int rv = fram.begin(0x50);
|
||||
if (rv != 0)
|
||||
{
|
||||
Serial.println(rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
testID();
|
||||
testFRAMmemory();
|
||||
testReadWriteSmall();
|
||||
testReadWriteLarge();
|
||||
testWriteText();
|
||||
testReadText1();
|
||||
testReadText2();
|
||||
}
|
||||
Serial.println("done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void testID()
|
||||
{
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
Serial.println("takes ~32 seconds");
|
||||
|
||||
Serial.print("ManufacturerID: ");
|
||||
Serial.println(fram.getManufacturerID());
|
||||
Serial.print(" ProductID: ");
|
||||
Serial.println(fram.getProductID());
|
||||
Serial.print(" memory size: ");
|
||||
Serial.println(fram.getSize());
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void testFRAMmemory()
|
||||
{
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
Serial.println("takes ~32 seconds");
|
||||
|
||||
start = millis();
|
||||
uint8_t val = 0x55;
|
||||
for (uint16_t addr = 0; addr < 32768; addr++)
|
||||
{
|
||||
fram.write8(addr, val);
|
||||
if (fram.read8(addr) != 0x55)
|
||||
{
|
||||
Serial.print("FAIL: \t");
|
||||
Serial.println(addr);
|
||||
}
|
||||
if (addr % 1000 == 0)
|
||||
{
|
||||
Serial.print(".");
|
||||
}
|
||||
}
|
||||
stop = millis();
|
||||
Serial.println();
|
||||
Serial.print("TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void testReadWriteSmall()
|
||||
{
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
Serial.print("test8:\t");
|
||||
uint8_t t8 = 0xFE;
|
||||
fram.write8(1000, t8);
|
||||
if (fram.read8(1000) != 0xFE)
|
||||
{
|
||||
Serial.println("failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("ok.");
|
||||
}
|
||||
|
||||
Serial.print("test16:\t");
|
||||
uint16_t t16 = 0xFADE;
|
||||
fram.write16(1000, t16);
|
||||
if (fram.read16(1000) != 0xFADE)
|
||||
{
|
||||
Serial.println("failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("ok.");
|
||||
}
|
||||
|
||||
Serial.print("test32:\t");
|
||||
uint32_t t32 = 0xFADEFACE;
|
||||
fram.write32(1000, t32);
|
||||
if (fram.read32(1000) != 0xFADEFACE)
|
||||
{
|
||||
Serial.println("failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("ok.");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void testReadWriteLarge()
|
||||
{
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
uint8_t ar[100];
|
||||
for (int i = 0; i < 100; i++) ar[i] = i;
|
||||
|
||||
start = millis();
|
||||
fram.write(1000, ar, 100);
|
||||
stop = millis();
|
||||
Serial.print("WRITE 100 bytes TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
|
||||
for (int i = 0; i < 100; i++) ar[i] = 0;
|
||||
|
||||
start = millis();
|
||||
fram.read(1000, ar, 100);
|
||||
stop = millis();
|
||||
Serial.print("READ 100 bytes TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (ar[i] != i)
|
||||
{
|
||||
Serial.print("FAIL: \t");
|
||||
Serial.println(i);
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void testWriteText()
|
||||
{
|
||||
char str[10][20] =
|
||||
{
|
||||
"Hello world 0",
|
||||
"Hello world 1",
|
||||
"Hello world 2",
|
||||
"Hello world 3",
|
||||
"Hello world 4",
|
||||
"Hello world 5",
|
||||
"Hello world 6",
|
||||
"Hello world 7",
|
||||
"Hello world 8",
|
||||
"Hello world 9",
|
||||
};
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
start = millis();
|
||||
fram.write(2000, (uint8_t *)str, 200);
|
||||
stop = millis();
|
||||
Serial.print("WRITE 200 bytes TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
Serial.println();
|
||||
|
||||
}
|
||||
|
||||
void testReadText1()
|
||||
{
|
||||
char str[10][20];
|
||||
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
start = millis();
|
||||
fram.read(2000, (uint8_t *)str, 200);
|
||||
stop = millis();
|
||||
Serial.print("READ 200 bytes TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
Serial.println();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Serial.println(str[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void testReadText2()
|
||||
{
|
||||
char str[20];
|
||||
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
fram.read(2000 + 20 * i, (uint8_t *)str, 20);
|
||||
Serial.println(str);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
// END OF FILE
|
@ -1,89 +0,0 @@
|
||||
//
|
||||
// FILE: testFRAMPerformance.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: test for FRAM library for Arduino
|
||||
// URL: https://github.com/RobTillaart/FRAM_I2C
|
||||
//
|
||||
|
||||
#include "FRAM.h"
|
||||
|
||||
FRAM fram;
|
||||
|
||||
uint32_t start;
|
||||
uint32_t stop;
|
||||
|
||||
int ar[600];
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("FRAM_LIB_VERSION: ");
|
||||
Serial.println(FRAM_LIB_VERSION);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
int rv = fram.begin(0x50);
|
||||
if (rv != 0)
|
||||
{
|
||||
Serial.println(rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int s = 1; s < 9; s++) // test up to 800 KB
|
||||
{
|
||||
uint32_t speed = s * 100000UL;
|
||||
Serial.print("CLOCK: ");
|
||||
Serial.println(speed);
|
||||
Wire.setClock(speed);
|
||||
testReadWriteLarge();
|
||||
}
|
||||
Wire.setClock(100000);
|
||||
}
|
||||
Serial.println("done...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
void testReadWriteLarge()
|
||||
{
|
||||
Serial.println();
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
for (int i = 0; i < 600; i++) ar[i] = i;
|
||||
|
||||
start = millis();
|
||||
fram.write(1000, (uint8_t*)ar, 1200);
|
||||
stop = millis();
|
||||
Serial.print("WRITE 1200 bytes TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
|
||||
for (int i = 0; i < 600; i++) ar[i] = 0;
|
||||
|
||||
start = millis();
|
||||
fram.read(1000, (uint8_t*)ar, 1200);
|
||||
stop = millis();
|
||||
Serial.print("READ 1200 bytes TIME:\t");
|
||||
Serial.print(stop - start);
|
||||
Serial.println(" ms");
|
||||
|
||||
for (int i = 0; i < 600; i++)
|
||||
{
|
||||
if (ar[i] != i)
|
||||
{
|
||||
Serial.print("FAIL: \t");
|
||||
Serial.print(ar[i]);
|
||||
Serial.print('\t');
|
||||
Serial.println(i);
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// END OF FILE
|
@ -1,25 +0,0 @@
|
||||
# Syntax Coloring Map for FRAM
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
FRAM KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
begin KEYWORD2
|
||||
|
||||
write8 KEYWORD2
|
||||
write16 KEYWORD2
|
||||
write32 KEYWORD2
|
||||
write KEYWORD2
|
||||
|
||||
read8 KEYWORD2
|
||||
read16 KEYWORD2
|
||||
read32 KEYWORD2
|
||||
read KEYWORD2
|
||||
|
||||
getManufacturerID KEYWORD2
|
||||
getProductID KEYWORD2
|
||||
getSize KEYWORD2
|
||||
|
||||
# Constants (LITERAL1)
|
||||
FRAM_OK LITERAL1
|
||||
FRAM_ERROR_ADDR LITERAL1
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "FRAM_I2C",
|
||||
"keywords": "FRAM, storage",
|
||||
"description": "Library for FRAM for Arduino.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/FRAM_I2C.git"
|
||||
},
|
||||
"version":"0.2.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
name=FRAM_I2C
|
||||
version=0.2.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for I2C FRAM.
|
||||
paragraph=
|
||||
category=Data Storage
|
||||
url=https://github.com/RobTillaart/FRAM_I2C.git
|
||||
architectures=*
|
||||
includes=Wire.h,FRAM.h
|
||||
depends=Wire.h
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: FRAM.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.3.1
|
||||
// DATE: 2018-01-24
|
||||
// PURPOSE: Arduino library for I2C FRAM
|
||||
// URL: https://github.com/RobTillaart/FRAM_I2C
|
||||
@ -14,6 +14,7 @@
|
||||
// 0.2.2 2020-12-23 arduino-CI + unit test + getWriteProtect()
|
||||
// 0.2.3 2021-01-ii fix getMetaData (kudos to PraxisSoft
|
||||
// 0.3.0 2021-01-13 fix #2 ESP32 + WireN support
|
||||
// 0.3.1 2021-02-05 fix #7 typo in .cpp
|
||||
|
||||
|
||||
#include "FRAM.h"
|
||||
@ -34,7 +35,7 @@ FRAM::FRAM(TwoWire *wire)
|
||||
|
||||
|
||||
#if defined (ESP8266) || defined(ESP32)
|
||||
int PCF8574::begin(uint8_t sda, uint8_t scl, const uint8_t address = 0x50, int8_t writeProtectPin = -1);
|
||||
int FRAM::begin(uint8_t sda, uint8_t scl, const uint8_t address, int8_t writeProtectPin)
|
||||
{
|
||||
if (address < 0x50 || address > 0x57) return FRAM_ERROR_ADDR;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: FRAM.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.3.1
|
||||
// DATE: 2018-01-24
|
||||
// PURPOSE: Arduino library for I2C FRAM
|
||||
// URL: https://github.com/RobTillaart/FRAM_I2C
|
||||
@ -13,7 +13,7 @@
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#define FRAM_LIB_VERSION (F("0.3.0"))
|
||||
#define FRAM_LIB_VERSION (F("0.3.1"))
|
||||
|
||||
|
||||
#define FRAM_OK 0
|
||||
@ -29,7 +29,7 @@ public:
|
||||
|
||||
#if defined (ESP8266) || defined(ESP32)
|
||||
// address and writeProtectPin is optional
|
||||
int begin(uint8_t sda, uint8_t scl, const uint8_t address = 0x50, int8_t writeProtectPin = -1);
|
||||
int begin(uint8_t sda, uint8_t scl, const uint8_t address = 0x50, int8_t writeProtectPin = -1);
|
||||
#endif
|
||||
// address and writeProtectPin is optional
|
||||
int begin(const uint8_t address = 0x50, int8_t writeProtectPin = -1);
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/FRAM_I2C.git"
|
||||
},
|
||||
"version":"0.3.0",
|
||||
"version":"0.3.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=FRAM_I2C
|
||||
version=0.3.0
|
||||
version=0.3.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for I2C FRAM.
|
||||
|
@ -21,6 +21,26 @@ It has three examples
|
||||
- test sketch to test get / set values.
|
||||
|
||||
|
||||
## Breakout board
|
||||
|
||||
left to right
|
||||
|
||||
| pin | pinname | description |
|
||||
|:----:|:--------|:----------------|
|
||||
| 0 | VCC | +5V |
|
||||
| 1 | GND | ground |
|
||||
| 2 | SCL | I2C clock |
|
||||
| 3 | SDA | I2C data |
|
||||
| 4 | XDA | auxiliary data | see datasheet
|
||||
| 5 | XCL | auxiliary clock | see datasheet
|
||||
| 6 | AD0 | address |
|
||||
| 7 | INT | interrupt |
|
||||
|
||||
#### Address
|
||||
AD0 connected to GND => 0x68
|
||||
AD0 connected to VCC => 0x69
|
||||
|
||||
|
||||
## Calibration (short version for now)
|
||||
|
||||
1. load and run calibration example
|
||||
@ -31,7 +51,6 @@ It has three examples
|
||||
|
||||
## Interface
|
||||
|
||||
TODO
|
||||
|
||||
### Constructor
|
||||
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
Arduino library for HX711 24 bit ADC used for load cells and scales.
|
||||
|
||||
# Description
|
||||
|
||||
## Description
|
||||
|
||||
This HX711 library has an interface which is a superset of a library made by bogde.
|
||||
Some missing functions were added to get more info from the lib.
|
||||
@ -17,9 +18,10 @@ Another important difference is that this library uses floats. The 23 bits manti
|
||||
of the IEE754 float matches the 24 bit ADC very well. Furthermore it gave a smaller
|
||||
footprint.
|
||||
|
||||
### Main flow
|
||||
|
||||
First action is to call **begin(dataPin, clockPin)** to make connetion to the **HX711**.
|
||||
## Main flow
|
||||
|
||||
First action is to call **begin(dataPin, clockPin)** to make connection to the **HX711**.
|
||||
|
||||
Second step is callibration for which a number of functions exist.
|
||||
- **tare()** measures zero point
|
||||
@ -35,7 +37,7 @@ Steps to take for callibration
|
||||
1. save the offset and scale for later use e.g. EEPROM.
|
||||
|
||||
|
||||
### Pricing
|
||||
## Pricing
|
||||
|
||||
Some price functions were added to make it easy to use this library
|
||||
for pricing goods or for educational purposes. These functions are under discussion
|
||||
@ -44,8 +46,10 @@ the 0.2.0 release, it is on a todo list.
|
||||
|
||||
For weight conversion functions see https://github.com/RobTillaart/weight
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
### Scale values for loadcells
|
||||
|
||||
These scale values worked pretty well with a set of loadcells,
|
||||
@ -54,11 +58,13 @@ Use callibrate to find your values.
|
||||
- 5 KG loadcell scale.set_scale(420.52);
|
||||
- 20 KG loadcell scale.set_scale(127.15);
|
||||
|
||||
|
||||
### Connections HX711
|
||||
|
||||
- A+/A- uses gain of 128 or 64
|
||||
- B+/B- uses gain of 32
|
||||
|
||||
|
||||
### Connections
|
||||
|
||||
| HX711 Pin | Color |
|
||||
@ -80,6 +86,7 @@ Use callibrate to find your values.
|
||||
| B- | not connected |
|
||||
| B+ | not connected |
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
|
@ -56,9 +56,11 @@
|
||||
|
||||
// TWI buffer needs max 2 bytes for eeprom address
|
||||
// 1 byte for eeprom register address is available in txbuffer
|
||||
// NOTE this is typical on an UNO.
|
||||
// TODO investigate
|
||||
#define I2C_TWIBUFFERSIZE 30
|
||||
#if defined(ESP32) || defined(ESP8266)
|
||||
#define I2C_BUFFERSIZE 128
|
||||
#else
|
||||
#define I2C_BUFFERSIZE 30 // AVR, STM
|
||||
#endif
|
||||
|
||||
|
||||
I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress, TwoWire *wire)
|
||||
@ -120,8 +122,8 @@ int I2C_eeprom::writeByte(const uint16_t memoryAddress, const uint8_t data)
|
||||
|
||||
int I2C_eeprom::setBlock(const uint16_t memoryAddress, const uint8_t data, const uint16_t length)
|
||||
{
|
||||
uint8_t buffer[I2C_TWIBUFFERSIZE];
|
||||
for (uint8_t i = 0; i < I2C_TWIBUFFERSIZE; i++)
|
||||
uint8_t buffer[I2C_BUFFERSIZE];
|
||||
for (uint8_t i = 0; i < I2C_BUFFERSIZE; i++)
|
||||
{
|
||||
buffer[i] = data;
|
||||
}
|
||||
@ -152,7 +154,7 @@ uint16_t I2C_eeprom::readBlock(const uint16_t memoryAddress, uint8_t* buffer, co
|
||||
uint16_t rv = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
uint8_t cnt = I2C_TWIBUFFERSIZE;
|
||||
uint8_t cnt = I2C_BUFFERSIZE;
|
||||
if (cnt > len) cnt = len;
|
||||
rv += _ReadBlock(addr, buffer, cnt);
|
||||
addr += cnt;
|
||||
@ -177,8 +179,8 @@ int I2C_eeprom::updateBlock(const uint16_t memoryAddress, const uint8_t* buffer,
|
||||
uint16_t rv = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
uint8_t buf[I2C_TWIBUFFERSIZE];
|
||||
uint8_t cnt = I2C_TWIBUFFERSIZE;
|
||||
uint8_t buf[I2C_BUFFERSIZE];
|
||||
uint8_t cnt = I2C_BUFFERSIZE;
|
||||
|
||||
if (cnt > len) cnt = len;
|
||||
rv += _ReadBlock(addr, buf, cnt);
|
||||
@ -281,7 +283,7 @@ int I2C_eeprom::_pageBlock(const uint16_t memoryAddress, const uint8_t* buffer,
|
||||
{
|
||||
uint8_t bytesUntilPageBoundary = this->_pageSize - addr % this->_pageSize;
|
||||
|
||||
uint8_t cnt = I2C_TWIBUFFERSIZE;
|
||||
uint8_t cnt = I2C_BUFFERSIZE;
|
||||
if (cnt > len) cnt = len;
|
||||
if (cnt > bytesUntilPageBoundary) cnt = bytesUntilPageBoundary;
|
||||
|
||||
@ -316,7 +318,7 @@ void I2C_eeprom::_beginTransmission(const uint16_t memoryAddress)
|
||||
}
|
||||
|
||||
|
||||
// pre: length <= this->_pageSize && length <= I2C_TWIBUFFERSIZE;
|
||||
// pre: length <= this->_pageSize && length <= I2C_BUFFERSIZE;
|
||||
// returns 0 = OK otherwise error
|
||||
int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint8_t length)
|
||||
{
|
||||
|
@ -1,21 +0,0 @@
|
||||
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.
|
@ -1,184 +0,0 @@
|
||||
//
|
||||
// FILE: MAX31855.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.3
|
||||
// PURPOSE: Arduino library for MAX31855 chip for K type thermocouple
|
||||
// DATE: 2014-01-01
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
// HISTORY:
|
||||
//
|
||||
// 0.2.3 2020-08-30 fix #8 support hardware SPI + example
|
||||
// 0.2.2 2020-08-30 fix#9 + fix failing examples + minor refactor
|
||||
// 0.2.1 2020-08-26 read rawData and STATUS_NO_COMMUNICATION recognition (thanks to FabioBrondo)
|
||||
// 0.2.0 2020-06-20 #pragma once; major refactor; removed pre 1.0 support; fix offset
|
||||
// 0.1.10 2019-07-31 add 3 inline functions to test errors + demo sketch
|
||||
// 0.1.9 2017-07-27 reverted double -> float (issue33)
|
||||
// 0.1.08 2015-12-06 replaced all temperature calls with one TCfactor + update demos.
|
||||
// 0.1.07 2015-12-06 updated TC factors from the MAX31855 datasheet
|
||||
// 0.1.06 2015-12-05 added support for other types of TC's (experimental)
|
||||
// 0.1.05 2015-07-12 refactor robust constructor
|
||||
// 0.1.04 2015-03-09 replaced float -> double (ARM support)
|
||||
// 0.1.03 2014-01-24 fixed negative temperature
|
||||
// 0.1.02 2014-01-03 added offset
|
||||
// 0.1.01 2014-01-02 refactored speed/performance
|
||||
// 0.1.00 2014-01-02 initial version.
|
||||
//
|
||||
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
|
||||
MAX31855::MAX31855(const uint8_t cs)
|
||||
{
|
||||
_cs = cs;
|
||||
_hwSPI = true;
|
||||
|
||||
_offset = 0;
|
||||
_SC = K_TC;
|
||||
_status = STATUS_NOREAD;
|
||||
_temperature = -999;
|
||||
_internal = -999;
|
||||
}
|
||||
|
||||
MAX31855::MAX31855(const uint8_t sclk, const uint8_t cs, const uint8_t miso)
|
||||
{
|
||||
_sclk = sclk;
|
||||
_cs = cs;
|
||||
_miso = miso;
|
||||
_hwSPI = false;
|
||||
|
||||
_offset = 0;
|
||||
_SC = K_TC;
|
||||
_status = STATUS_NOREAD;
|
||||
_temperature = -999;
|
||||
_internal = -999;
|
||||
}
|
||||
|
||||
void MAX31855::begin()
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH);
|
||||
if (_hwSPI)
|
||||
{
|
||||
SPI.begin();
|
||||
delay(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
pinMode(_sclk, OUTPUT);
|
||||
pinMode(_miso, INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t MAX31855::read()
|
||||
{
|
||||
// return value of _read()
|
||||
// BITS DESCRIPTION
|
||||
// ----------------------
|
||||
// 00 - 02 STATUS
|
||||
// 03 RESERVED
|
||||
// 04 - 15 INTERNAL
|
||||
// 16 FAULT-BIT
|
||||
// 17 RESERVED
|
||||
// 18 - 30 TEMPERATURE (RAW)
|
||||
// 31 SIGN
|
||||
uint32_t value = _read();
|
||||
|
||||
if (value == 0xFFFFFFFF) // needs a pull up on miso pin to work properly!
|
||||
{
|
||||
// bit 3 and bit 17 should always be 0 - P10 datasheet
|
||||
_status = STATUS_NO_COMMUNICATION;
|
||||
return _status;
|
||||
}
|
||||
|
||||
_lastRead = millis();
|
||||
|
||||
// process status bit 0-2
|
||||
_status = value & 0x0007;
|
||||
if (_status != STATUS_OK)
|
||||
{
|
||||
return _status;
|
||||
}
|
||||
|
||||
value >>= 3;
|
||||
|
||||
// reserved bit 3, always 0
|
||||
value >>= 1;
|
||||
|
||||
// process internal bit 4-15
|
||||
_internal = (value & 0x07FF) * 0.0625;
|
||||
// negative flag set ?
|
||||
if (value & 0x0800)
|
||||
{
|
||||
_internal = -128 + _internal;
|
||||
}
|
||||
value >>= 12;
|
||||
|
||||
// Fault bit ignored as we have the 3 status bits
|
||||
// _fault = value & 0x01;
|
||||
value >>= 1;
|
||||
|
||||
// reserved bit 17, always 0
|
||||
value >>= 1;
|
||||
|
||||
// process temperature bit 18-30 + sign bit = 31
|
||||
_temperature = (value & 0x1FFF) * 0.25;
|
||||
// negative flag set ?
|
||||
if (value & 0x2000)
|
||||
{
|
||||
_temperature = -2048 + _temperature;
|
||||
}
|
||||
return _status;
|
||||
}
|
||||
|
||||
|
||||
uint32_t MAX31855::_read(void)
|
||||
{
|
||||
_rawData = 0;
|
||||
digitalWrite(_cs, LOW);
|
||||
if (_hwSPI)
|
||||
{
|
||||
SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
_rawData <<= 8;
|
||||
_rawData += SPI.transfer(0);
|
||||
}
|
||||
SPI.endTransaction();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int8_t i = 31; i >= 0; i--)
|
||||
{
|
||||
_rawData <<= 1;
|
||||
digitalWrite(_sclk, LOW);
|
||||
// delayMicroseconds(1); // DUE
|
||||
if ( digitalRead(_miso) ) _rawData++;
|
||||
digitalWrite(_sclk, HIGH);
|
||||
// delayMicroseconds(1); // DUE
|
||||
}
|
||||
}
|
||||
digitalWrite(_cs, HIGH);
|
||||
return _rawData;
|
||||
}
|
||||
|
||||
float MAX31855::getTemperature()
|
||||
{
|
||||
// offset needs to be added after multiplication TCfactor
|
||||
// not before otherwise offset will be larger / smaller
|
||||
// default behavior
|
||||
if (_SC == K_TC) return _temperature + _offset;
|
||||
|
||||
// EXPERIMENTAL OTHER THERMOCOUPLES
|
||||
// in practice this works also for K_TC but is way slower..
|
||||
// 1: reverse calculate the Voltage measured
|
||||
float Vout = K_TC * (_temperature - _internal); // PAGE 8 datasheet
|
||||
|
||||
// 2: from Voltage to corrected temperature using the Seebeck Coefficient
|
||||
float _temp = Vout / _SC + _internal;
|
||||
return _temp;
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,110 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: MAX31855.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.3
|
||||
// PURPOSE: Arduino library for MAX31855 chip for K type thermocouple
|
||||
// DATE: 2014-01-01
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
// http://forum.arduino.cc/index.php?topic=208061
|
||||
//
|
||||
// Bbreakout board
|
||||
//
|
||||
// +---------+
|
||||
// Vin | o |
|
||||
// 3Vo | o |
|
||||
// GND | o O | Thermocouple
|
||||
// D0 | o O | Thermocouple
|
||||
// CS | o |
|
||||
// CLK | o |
|
||||
// +---------+
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "SPI.h"
|
||||
|
||||
#define MAX31855_VERSION "0.2.3"
|
||||
|
||||
|
||||
// STATE constants returnd by read()
|
||||
#define STATUS_OK 0x00
|
||||
#define STATUS_OPEN_CIRCUIT 0x01
|
||||
#define STATUS_SHORT_TO_GND 0x02
|
||||
#define STATUS_SHORT_TO_VCC 0x04
|
||||
#define STATUS_ERROR 0x07
|
||||
#define STATUS_NOREAD 0x80
|
||||
#define STATUS_NO_COMMUNICATION 0x81
|
||||
|
||||
|
||||
// Thermocouples working is based upon Seebeck effect.
|
||||
// Different TC have a different Seebeck Coefficient (µV/°C)
|
||||
// See http://www.analog.com/library/analogDialogue/archives/44-10/thermocouple.html
|
||||
//
|
||||
// As the MAX31855 is designed for K type sensors, one can calculate
|
||||
// the factor needed to convert other sensors measurements.
|
||||
// NOTE: this is only a linear approximation.
|
||||
//
|
||||
// Seebeck Coefficients (sensitivity) from the MAX31855 datasheet page 8
|
||||
// to be used in setSeebeckCoefficient()
|
||||
//
|
||||
// TYPE COEFFICIENT
|
||||
#define E_TC 76.373
|
||||
#define J_TC 57.953
|
||||
#define K_TC 41.276
|
||||
#define N_TC 36.256
|
||||
#define R_TC 10.506
|
||||
#define S_TC 9.587
|
||||
#define T_TC 52.18
|
||||
|
||||
|
||||
class MAX31855
|
||||
{
|
||||
public:
|
||||
// HW SPI
|
||||
MAX31855(uint8_t CS);
|
||||
// SW SPI
|
||||
MAX31855(uint8_t SCLK, uint8_t CS, uint8_t MISO);
|
||||
void begin();
|
||||
|
||||
// returns state - bitfield: 0 = STATUS_OK
|
||||
uint8_t read();
|
||||
|
||||
float getInternal(void) const { return _internal; }
|
||||
float getTemperature(void);
|
||||
|
||||
uint8_t getStatus(void) const { return _status; };
|
||||
inline bool openCircuit() { return _status == STATUS_OPEN_CIRCUIT; };
|
||||
inline bool shortToGND() { return _status == STATUS_SHORT_TO_GND; };
|
||||
inline bool shortToVCC() { return _status == STATUS_SHORT_TO_VCC; };
|
||||
inline bool genericError() { return _status == STATUS_ERROR; };
|
||||
inline bool noRead() { return _status == STATUS_NOREAD; };
|
||||
inline bool noCommunication() { return _status == STATUS_NO_COMMUNICATION; };
|
||||
|
||||
// use offset to callibrate the TC.
|
||||
void setOffset(const float t) { _offset = t; };
|
||||
float getOffset() const { return _offset; };
|
||||
|
||||
// set the above E_TC (etc) Seebrecht Coefficients
|
||||
// one can also set your own optimized values.
|
||||
void setSeebeckCoefficient(const float SC) { _SC = SC; };
|
||||
float getSeebeckCoefficient() const { return _SC; };
|
||||
|
||||
uint32_t lastRead() { return _lastRead; };
|
||||
uint32_t getRawData() { return _rawData;};
|
||||
|
||||
private:
|
||||
uint32_t _read();
|
||||
uint8_t _status;
|
||||
float _internal;
|
||||
float _temperature;
|
||||
float _offset;
|
||||
float _SC;
|
||||
uint32_t _lastRead;
|
||||
uint32_t _rawData;
|
||||
bool _hwSPI;
|
||||
|
||||
uint8_t _sclk;
|
||||
uint8_t _miso;
|
||||
uint8_t _cs;
|
||||
};
|
||||
|
||||
// -- END OF FILE --
|
@ -1,46 +0,0 @@
|
||||
//
|
||||
// FILE: Demo_getRawData.ino
|
||||
// AUTHOR: FabioBrondo
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2020-08-24
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MAX31855.h>
|
||||
|
||||
#define MAXDO 7 // Defining the MISO pin
|
||||
#define MAXCS 6 // Defining the CS pin
|
||||
#define MAXCLK 5 // Defining the SCK pin
|
||||
|
||||
|
||||
MAX31855 thermocouple(MAXCLK, MAXCS, MAXDO);
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
delay(250);
|
||||
thermocouple.begin();
|
||||
}
|
||||
|
||||
|
||||
void loop ()
|
||||
{
|
||||
int status = thermocouple.read();
|
||||
if (status == STATUS_NO_COMMUNICATION)
|
||||
{
|
||||
Serial.println("NO COMMUNICATION");
|
||||
}
|
||||
|
||||
uint32_t value = thermocouple.getRawData(); // Read the raw Data value from the module
|
||||
Serial.print("RAW:\t");
|
||||
Serial.println(value, BIN); // Display the raw data value in BIN format
|
||||
|
||||
Serial.print("TMP:\t");
|
||||
Serial.println(thermocouple.getTemperature());
|
||||
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,69 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_array.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: demo of array of thermocouples
|
||||
// DATE: 2020-08-26
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
// kudos to FabioBrondo for the idea.
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
// note: pins are slightly different than other examples!
|
||||
const int dataPin = 7;
|
||||
const int clockPin = 6;
|
||||
|
||||
MAX31855 sensors[] =
|
||||
{
|
||||
MAX31855(clockPin, 5, dataPin),
|
||||
MAX31855(clockPin, 4, dataPin),
|
||||
MAX31855(clockPin, 3, dataPin)
|
||||
};
|
||||
|
||||
const uint8_t sensorCount = sizeof(sensors) / sizeof(MAX31855);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_array.ino : ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Serial.println(sensorCount);
|
||||
|
||||
for (int i = 0; i < sensorCount; i++)
|
||||
{
|
||||
sensors[i].begin();
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print("\tTime:\t");
|
||||
Serial.println(millis());
|
||||
|
||||
for (int i = 0; i < sensorCount; i++)
|
||||
{
|
||||
int status = sensors[i].read();
|
||||
if (status != STATUS_OK)
|
||||
{
|
||||
Serial.print(i);
|
||||
Serial.print("\tstatus:\t");
|
||||
Serial.println(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
float temp = sensors[i].getTemperature();
|
||||
Serial.print(i);
|
||||
Serial.print("\ttemp:\t");
|
||||
Serial.println(temp);
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,42 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo0.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.3
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2014-01-01
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo0: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
int status = tc.read();
|
||||
Serial.print("stat:\t\t");
|
||||
Serial.println(status);
|
||||
|
||||
float internal = tc.getInternal();
|
||||
Serial.print("internal:\t");
|
||||
Serial.println(internal);
|
||||
|
||||
float temp = tc.getTemperature();
|
||||
Serial.print("temperature:\t");
|
||||
Serial.println(temp);
|
||||
delay(1000);
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo1.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.4
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2014-01-02
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo1: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
int status = tc.read();
|
||||
if (status != 0)
|
||||
{
|
||||
Serial.print("stat:\t\t");
|
||||
Serial.println(status);
|
||||
}
|
||||
|
||||
float temp = tc.getTemperature();
|
||||
int m = temp * 10 - 200;
|
||||
|
||||
Serial.print(temp);
|
||||
Serial.print('\t');
|
||||
for (int i = 0; i < m; i++) Serial.write(']');
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,43 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo2.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.4
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2014-01-02
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
float t1, t2;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo2: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
tc.read();
|
||||
t1 = tc.getTemperature();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
tc.read();
|
||||
t2 = tc.getTemperature();
|
||||
Serial.print("delta:\t");
|
||||
Serial.println(t2 - t1, 2);
|
||||
t1 = t2;
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,76 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo3.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.4
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2014-01-02
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo3: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
|
||||
uint32_t start = micros();
|
||||
tc.read();
|
||||
uint32_t stop = micros();
|
||||
Serial.print("read:\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
start = micros();
|
||||
float t1 = tc.getTemperature();
|
||||
stop = micros();
|
||||
Serial.print("getTemperature:\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
start = micros();
|
||||
float t2 = tc.getInternal();
|
||||
stop = micros();
|
||||
Serial.print("getInternal:\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.println();
|
||||
Serial.println(t1, 2);
|
||||
Serial.println(t2, 2);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// this loop returns multiples of about 73mSec (counter multiples of ~143)
|
||||
// so the # measurements per second is about 14?
|
||||
uint32_t counter = 0;
|
||||
float t1 = tc.getTemperature();
|
||||
float t2 = t1;
|
||||
|
||||
uint32_t start = micros();
|
||||
while (t2 == t1)
|
||||
{
|
||||
tc.read();
|
||||
t1 = tc.getTemperature();
|
||||
counter++;
|
||||
}
|
||||
uint32_t stop = micros();
|
||||
|
||||
Serial.print("change:\t");
|
||||
Serial.println(stop - start);
|
||||
Serial.print("counter:\t");
|
||||
Serial.println(counter);
|
||||
Serial.println(t2, 2);
|
||||
Serial.println(t1, 2);
|
||||
Serial.println();
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo4.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.2
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2014-01-02
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo4: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
|
||||
uint32_t start = micros();
|
||||
for (int i = 0; i < 10; i++) tc.read();
|
||||
uint32_t stop = micros();
|
||||
Serial.print("10x read:\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
|
||||
start = micros();
|
||||
float t1 = tc.getTemperature();
|
||||
stop = micros();
|
||||
Serial.print("getTemperature:\t");
|
||||
Serial.println(stop - start);
|
||||
Serial.println(t1, 2);
|
||||
Serial.println();
|
||||
|
||||
start = micros();
|
||||
tc.setOffset(2.0);
|
||||
stop = micros();
|
||||
Serial.print("setOffset:\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
start = micros();
|
||||
tc.getOffset();
|
||||
stop = micros();
|
||||
Serial.print("getOffset:\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
tc.read();
|
||||
start = micros();
|
||||
t1 = tc.getTemperature();
|
||||
stop = micros();
|
||||
Serial.print("getTemperature:\t");
|
||||
Serial.println(stop - start);
|
||||
Serial.println(t1, 2);
|
||||
Serial.println();
|
||||
|
||||
|
||||
start = micros();
|
||||
float t2 = tc.getInternal();
|
||||
stop = micros();
|
||||
Serial.print("getInternal:\t");
|
||||
Serial.println(stop - start);
|
||||
Serial.println(t2, 4);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,55 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo5.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.4
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2014-01-02
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo5: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
tc.read();
|
||||
float t1 = tc.getTemperature();
|
||||
Serial.print(" temp before:\t");
|
||||
Serial.println(t1, 2);
|
||||
|
||||
float offset = tc.getOffset();
|
||||
Serial.print("offset before:\t");
|
||||
Serial.println(offset, 2);
|
||||
|
||||
tc.setOffset(3.14);
|
||||
offset = tc.getOffset();
|
||||
Serial.print(" offset after:\t");
|
||||
Serial.println(offset, 2);
|
||||
|
||||
tc.read();
|
||||
float t2 = tc.getTemperature();
|
||||
Serial.print(" temp after:\t");
|
||||
Serial.println(t2, 2);
|
||||
|
||||
Serial.print(" temp delta:\t");
|
||||
Serial.println(abs(t1 - t2), 2);
|
||||
|
||||
Serial.println("\ndone...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_demo6.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: thermocouple lib demo setSeebeckCoefficient()
|
||||
// DATE: 2015-12-06
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo6: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
tc.read();
|
||||
float t1 = tc.getTemperature();
|
||||
Serial.print(" temp before:\t");
|
||||
Serial.println(t1, 2);
|
||||
|
||||
float tcf = tc.getSeebeckCoefficient();
|
||||
Serial.print("SeebeckCoefficient before:\t");
|
||||
Serial.println(tcf, 4);
|
||||
|
||||
Serial.println("\nChange default K-type to J-type ThermoCouple");
|
||||
tc.setSeebeckCoefficient(J_TC);
|
||||
tcf = tc.getSeebeckCoefficient();
|
||||
Serial.print(" SeebeckCoefficient after:\t");
|
||||
Serial.println(tcf, 4);
|
||||
|
||||
tc.read();
|
||||
float t2 = tc.getTemperature();
|
||||
Serial.print(" temp after:\t");
|
||||
Serial.println(t2, 2);
|
||||
|
||||
Serial.print(" temp delta:\t");
|
||||
Serial.println(abs(t1 - t2), 2);
|
||||
|
||||
Serial.println("\ndone...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_hw_SPI.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: thermocouple lib demo application
|
||||
// DATE: 2020-08-30
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
//
|
||||
// | HW SPI | UNO | ESP32 |
|
||||
// |:---------|:-----:|:-------:|
|
||||
// | CLOCKPIN | 13 | 18 |
|
||||
// | MISO | 12 | 19 |
|
||||
// | MOSI | 11 | 23 |
|
||||
|
||||
// read() timing UNO
|
||||
// HWSPI 16000000 ~68 us
|
||||
// HWSPI 4000000 ~72 us
|
||||
// HWSPI 1000000 ~100 us
|
||||
// HWSPI 500000 ~128 us
|
||||
// SWSPI bitbang ~500 us
|
||||
|
||||
const int csPin = 6;
|
||||
|
||||
uint32_t start, stop;
|
||||
|
||||
MAX31855 tc(csPin);
|
||||
// MAX31855 tc(13, 6, 12); // sw SPI
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_demo0: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
start = micros();
|
||||
int status = tc.read();
|
||||
stop = micros();
|
||||
|
||||
Serial.println();
|
||||
Serial.print("time:\t\t");
|
||||
Serial.println(stop - start);
|
||||
|
||||
Serial.print("stat:\t\t");
|
||||
Serial.println(status);
|
||||
|
||||
uint32_t raw = tc.getRawData();
|
||||
Serial.print("raw:\t\t");
|
||||
Serial.println(raw, BIN);
|
||||
|
||||
float internal = tc.getInternal();
|
||||
Serial.print("internal:\t");
|
||||
Serial.println(internal);
|
||||
|
||||
float temp = tc.getTemperature();
|
||||
Serial.print("temperature:\t");
|
||||
Serial.println(temp);
|
||||
delay(1000);
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
//
|
||||
// FILE: max31855_test_error.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: thermocouple lib inline tests
|
||||
// DATE: 2019-07-31
|
||||
// URL: https://github.com/RobTillaart/MAX31855_RT
|
||||
//
|
||||
|
||||
#include "MAX31855.h"
|
||||
|
||||
const int doPin = 7;
|
||||
const int csPin = 6;
|
||||
const int clPin = 5;
|
||||
|
||||
MAX31855 tc(clPin, csPin, doPin);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start max31855_test_error: ");
|
||||
Serial.println(MAX31855_VERSION);
|
||||
Serial.println();
|
||||
|
||||
tc.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
int status = tc.read();
|
||||
Serial.print("stat:\t\t");
|
||||
Serial.println(status);
|
||||
|
||||
if (tc.getStatus())
|
||||
{
|
||||
Serial.print("error:\t\t");
|
||||
if (tc.shortToGND()) Serial.println("SHORT TO GROUND");
|
||||
if (tc.shortToVCC()) Serial.println("SHORT TO VCC");
|
||||
if (tc.openCircuit()) Serial.println("OPEN CIRCUIT");
|
||||
if (tc.genericError()) Serial.println("GENERIC ERROR");
|
||||
if (tc.noRead()) Serial.println("NO READ");
|
||||
if (tc.noCommunication()) Serial.println("NO COMMUNICATION");
|
||||
}
|
||||
|
||||
float internal = tc.getInternal();
|
||||
Serial.print("internal:\t");
|
||||
Serial.println(internal, 3);
|
||||
|
||||
float temp = tc.getTemperature();
|
||||
Serial.print("temperature:\t");
|
||||
Serial.println(temp, 2);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,49 +0,0 @@
|
||||
# Syntax Coloring Map For MAX31855
|
||||
|
||||
|
||||
# Datatypes (KEYWORD1)
|
||||
MAX31855 KEYWORD1
|
||||
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
begin KEYWORD2
|
||||
read KEYWORD2
|
||||
getInternal KEYWORD2
|
||||
getTemperature KEYWORD2
|
||||
|
||||
getStatus KEYWORD2
|
||||
shortToGND KEYWORD2
|
||||
shortToVCC KEYWORD2
|
||||
openCircuit KEYWORD2
|
||||
genericError KEYWORD2
|
||||
noRead KEYWORD2
|
||||
noCommunication KEYWORD2
|
||||
|
||||
setOffset KEYWORD2
|
||||
getOffset KEYWORD2
|
||||
setSeebeckCoefficient KEYWORD2
|
||||
getSeebeckCoefficient KEYWORD2
|
||||
|
||||
lastRead KEYWORD2
|
||||
getRawData KEYWORD2
|
||||
|
||||
|
||||
# Instances (KEYWORD2)
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
MAX31855_VERSION LITERAL1
|
||||
STATUS_OK LITERAL1
|
||||
STATUS_OPEN_CIRCUIT LITERAL1
|
||||
STATUS_SHORT_TO_GND LITERAL1
|
||||
STATUS_SHORT_TO_VCC LITERAL1
|
||||
STATUS_ERROR LITERAL1
|
||||
STATUS_NOREAD LITERAL1
|
||||
STATUS_NO_COMMUNICATION LITERAL1
|
||||
E_TC LITERAL1
|
||||
J_TC LITERAL1
|
||||
K_TC LITERAL1
|
||||
N_TC LITERAL1
|
||||
R_TC LITERAL1
|
||||
S_TC LITERAL1
|
||||
T_TC LITERAL1
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "MAX31855",
|
||||
"keywords": "MAX31855,Thermocouple,K type,temperature, offset, MAX31855K",
|
||||
"description": "Arduino library for MAX31855 chip for K type thermocouple. Has experimental support for other types of thermocouples.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MAX31855_RT"
|
||||
},
|
||||
"version":"0.2.3",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
name=MAX31855_RT
|
||||
version=0.2.3
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for MAX31855 chip for K type thermocouple.
|
||||
paragraph=Experimental support for "E, J, K, N, R, S, T" type TC.
|
||||
category=Sensors
|
||||
url=https://github.com/RobTillaart/MAX31855_RT
|
||||
architectures=*
|
||||
includes=MAX31855.h
|
||||
depends=
|
@ -1,219 +0,0 @@
|
||||
# MAX31855_RT
|
||||
|
||||
Arduino library for MAX31855 chip for K type thermocouple
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
The MAX38155 is a chip to convert the reading of a K-type thermocouple to a temperature.
|
||||
The working of thermocouples (TC) is based upon Seebeck effect.
|
||||
Different TC's have a different Seebeck Coefficient (SC) expressed in µV/°C.
|
||||
See http://www.analog.com/library/analogDialogue/archives/44-10/thermocouple.html
|
||||
|
||||
For every type of TC there exist an MAX31855 variant, this library is primary
|
||||
developed for the K-type sensor. However it has experimental support for all
|
||||
other types of TC's. See details below.
|
||||
|
||||
Library tested with breakout board
|
||||
|
||||
```
|
||||
+---------+
|
||||
Vin | o |
|
||||
3Vo | o |
|
||||
GND | o O | Thermocouple
|
||||
D0 | o O | Thermocouple
|
||||
CS | o |
|
||||
CLK | o |
|
||||
+---------+
|
||||
|
||||
```
|
||||
|
||||
## Hardware SPI vs software SPI
|
||||
|
||||
Default pin connections (ESP32 has more options)
|
||||
|
||||
| HW SPI | UNO | ESP32 |
|
||||
|:---------|:-----:|:-------:|
|
||||
| CLOCKPIN | 13 | 18 |
|
||||
| MISO | 12 | 19 |
|
||||
| MOSI | 11 | 23 |
|
||||
|
||||
Performance read() function, timing in us.
|
||||
|
||||
| mode | clock | timng UNO |
|
||||
|:----|----:|----:|
|
||||
| HWSPI | 16000000 | ~68 |
|
||||
| HWSPI | 4000000 | ~72 |
|
||||
| HWSPI | 1000000 | ~100 |
|
||||
| HWSPI | 500000 | ~128 |
|
||||
| SWSPI | bitbang | ~500 |
|
||||
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
To make a temperature reading call **tc.read()**.
|
||||
It returns the status of the read which is a value between 0..7
|
||||
The function **getStatus()** returns the same status value.
|
||||
|
||||
Table: values returned from **read()** and **getStatus()**
|
||||
|
||||
| value | Description | Action |
|
||||
|:----:|:----|:----|
|
||||
| 0 | OK | - |
|
||||
| 1 | Thermocouple open circuit | check wiring |
|
||||
| 2 | Thermocouple short to GND | check wiring |
|
||||
| 4 | Thermocouple short to VCC | check wiring |
|
||||
| 7 | Generic error | |
|
||||
| 128 | No read done yet | check wiring |
|
||||
| 129 | No communication | check wiring |
|
||||
|
||||
There are six functions to check the individual error conditions mentioned above.
|
||||
These make it easier to check them.
|
||||
|
||||
- **openCircuit()**
|
||||
- **shortToGND()**
|
||||
- **shortToVCC()**
|
||||
- **genericError()**
|
||||
- **noRead()**
|
||||
- **noCommunication()**
|
||||
|
||||
After a **tc.read()** you can get the temperature with **tc.getTemperature()**
|
||||
and **tc.getInternal()** for the interrnal temperature of the chip / board itself.
|
||||
|
||||
Repeated calls to **tc.getTemperature()** will give the same value until a new **tc.read()**.
|
||||
The latter fetches a new value from the sensor. Note that if the **tc.read()** fails
|
||||
the value of **tc.getTemperature()** can become incorrect.
|
||||
|
||||
The library supports a fixed offset to callibrate the thermocouple.
|
||||
For this the functions **tc.getOffset()** and **tc.setOffset(offset)** are available.
|
||||
This offset is included in the **tc.getTemperature()** function.
|
||||
|
||||
As the **tc** object holds its last known temperature it is easy to determine the delta
|
||||
with the last known temperature, e.g. for trend analysis.
|
||||
|
||||
```cpp
|
||||
float last = tc.getTemperature();
|
||||
int state = tc.read();
|
||||
if (state == STATUS_OK)
|
||||
{
|
||||
float new = tc.getTemperature();
|
||||
float delta = new - last;
|
||||
// process data
|
||||
}
|
||||
```
|
||||
|
||||
The **tc** object keeps track of the last time **tc.read()** is called in the function **tc.lastRead()**.
|
||||
The time is tracked in **millis()**. This makes it easy to read the sensor at certain intervals.
|
||||
|
||||
```cpp
|
||||
if (millis() - tc.lastRead() >= interval)
|
||||
{
|
||||
int state = tc.read();
|
||||
if (state == STATUS_OK)
|
||||
{
|
||||
float new = tc.getTemperature();
|
||||
// process read value.
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## GetRawData
|
||||
|
||||
The function **tc.getRawData()** allows you to get all the 32 bits raw data from the board,
|
||||
after the standard **tc.read()** call.
|
||||
|
||||
Example code can be found in the examples folder.
|
||||
|
||||
```cpp
|
||||
int state = thermocouple.read();
|
||||
uint32_t value = thermocouple.getRawData(); // Read the raw Data value from the module
|
||||
```
|
||||
|
||||
|
||||
## Pull Up Resistor
|
||||
|
||||
To have proper working of the MAX31855 board, you need to add a pull-up resistor
|
||||
(e.g. 4K7 - 1K depending on wirelength) between the MISO pin (from constructor call) and the
|
||||
VCC (5Volt). This improves the signal quality and will allow you to detect if there is
|
||||
proper communication with the board. WIthout pull-up one might get random noise that could
|
||||
look like real data.
|
||||
|
||||
**Note:** the MISO pin can be different from each board, please refer to your board datasheet.
|
||||
|
||||
If the MAX31855 board is not connected **tc.read()** will return **STATUS_NO_COMMUNICATION**.
|
||||
|
||||
You can verify this by **tc.getRawData()** which will give 32 HIGH bits or 0xFFFFFFFF).
|
||||
|
||||
You can use a simple code to detect connection error board:
|
||||
|
||||
```cpp
|
||||
uint8_t status = thermocouple.read();
|
||||
if (status == STATUS_NO_COMMUNICATION)
|
||||
{
|
||||
Serial.println("NO COMMUNICATION");
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```cpp
|
||||
uint8_t status = thermocouple.read();
|
||||
if (thermocouple.getRawData() == 0xFFFFFFFF)
|
||||
{
|
||||
Serial.println("NO COMMUNICATION");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
|
||||
|
||||
## Experimental part (to be tested)
|
||||
|
||||
**NOTE:**
|
||||
The support for other thermocouples is experimental **use at your own risk**.
|
||||
|
||||
|
||||
The MAX31855 is designed for K type sensors. It essentially measures a
|
||||
voltage difference and converts this voltage using the Seebeck Coefficient (SC)
|
||||
to the temperature. As the SC is lineair in its nature it is possible
|
||||
to replace the K-type TC with one of the other types of TC.
|
||||
|
||||
Datasheet Table 1, page 8
|
||||
|
||||
| Sensor type | Seebeck Coefficient (µV/°C) | Temp Range (°C) | Material |
|
||||
|:----:|:----|:----|:----|
|
||||
| E_TC | 76.373 | -270 to +1000 | Constantan Chromel |
|
||||
| J_TC | 57.953 | -210 to +1200 | Constantan Iron |
|
||||
| K_TC | 41.276 | -270 to +1372 | Alumel Chromel |
|
||||
| N_TC | 36.256 | -270 to +1300 | Nisil Nicrosil |
|
||||
| R_TC | 10.506 | -50 to +1768 | Platinum Platinum/Rhodium |
|
||||
| S_TC | 9.587 | +50 to +1768 | Platinum Platinum/Rhodium |
|
||||
| T_TC | 52.18 | -270 to +400 | Constantan Copper |
|
||||
|
||||
The core formula to calculate the temperature is (Datasheet page 8)
|
||||
```
|
||||
Vout = (41.276µV/°C) x (Temp_R - Temp_internal)
|
||||
```
|
||||
As we know the internal temperature and the returned temperature from the sensor
|
||||
the library can calculate the Vout measured (as the chip assumes that a K-type
|
||||
thermocouple is connected.
|
||||
Having that Vout we can redo the math for the actual thermocouple type and
|
||||
calculate the real temperature.
|
||||
|
||||
The library has two functions **tc.setSeebeckCoefficient(factor)** and
|
||||
**tc.getSeebeckCoefficient()**
|
||||
to get/set the Seebeck Coefficient (== thermocouple) to be used.
|
||||
One can adjust the values to improve the accuracy of the temperature read.
|
||||
|
||||
The **tc.getTemperature()** has implemented this algorithm, however as long
|
||||
as one does not set the Seebeck Coefficient it will use the K_TC as default.
|
||||
|
@ -1,21 +0,0 @@
|
||||
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.
|
@ -1,159 +0,0 @@
|
||||
//
|
||||
// FILE: MCP23017.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: Arduino library for I2C MCP23017 16 channel port expander
|
||||
// DATE: 2019-10-12
|
||||
// URL: https://github.com/RobTillaart/MCP23017_RT
|
||||
// LICENSE: MIT
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2019-10-12 initial version
|
||||
// 0.1.1 2020-06-19 refactor; #pragma once
|
||||
//
|
||||
// TODO:
|
||||
// interrupts
|
||||
// caching for performance?
|
||||
// INPUT_PULLUP
|
||||
//
|
||||
|
||||
#include "MCP23017.h"
|
||||
|
||||
#define MCP23017_DDR_A 0x00 // Data Direction Register
|
||||
#define MCP23017_DDR_B 0x01
|
||||
#define MCP23017_PUR_A 0x0C // Pull Up Resistors
|
||||
#define MCP23017_PUR_B 0x0D
|
||||
|
||||
#define MCP23017_IOCR 0x0A // IO control register
|
||||
|
||||
#define MCP23017_GPIOA 0x12
|
||||
#define MCP23017_GPIOB 0x13
|
||||
|
||||
|
||||
MCP23017::MCP23017(uint8_t addr)
|
||||
{
|
||||
_addr = addr;
|
||||
}
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
void MCP23017::begin(const uint8_t dataPin, const uint8_t clockPin)
|
||||
{
|
||||
Wire.begin(dataPin, clockPin);
|
||||
// Force INPUT_PULLUP
|
||||
writeReg(MCP23017_PUR_A, 0xFF);
|
||||
writeReg(MCP23017_PUR_B, 0xFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MCP23017::begin()
|
||||
{
|
||||
Wire.begin();
|
||||
// Force INPUT_PULLUP
|
||||
writeReg(MCP23017_IOCR, 0b00100000); // disable addres increment (datasheet)
|
||||
writeReg(MCP23017_PUR_A, 0xFF);
|
||||
writeReg(MCP23017_PUR_B, 0xFF);
|
||||
}
|
||||
|
||||
// single pin interface
|
||||
// pin 0..15
|
||||
// value INPUT, OUTPUT, INPUT_PULLUP
|
||||
// TODO: split INPUT_PULLUP and INPUT, for now they are the same
|
||||
void MCP23017::pinMode(uint8_t pin, uint8_t value)
|
||||
{
|
||||
if (pin > 15) return;
|
||||
if (value != INPUT && value != INPUT_PULLUP && value != OUTPUT) return;
|
||||
|
||||
uint8_t DDR = MCP23017_DDR_A; // Data Direction Register
|
||||
if (pin > 7)
|
||||
{
|
||||
DDR = MCP23017_DDR_B;
|
||||
pin -= 8;
|
||||
}
|
||||
uint8_t val = readReg(DDR);
|
||||
uint8_t mask = 1 << pin;
|
||||
// only work with valid
|
||||
if (value == INPUT || value == INPUT_PULLUP)
|
||||
{
|
||||
val |= mask;
|
||||
}
|
||||
else if (value == OUTPUT)
|
||||
{
|
||||
val &= ~mask;
|
||||
}
|
||||
// other values won't change val ....
|
||||
writeReg(DDR, val);
|
||||
}
|
||||
|
||||
void MCP23017::digitalWrite(uint8_t pin, uint8_t value) // pin = 0..15
|
||||
{
|
||||
if (pin > 15) return;
|
||||
uint8_t IOR = MCP23017_GPIOA;
|
||||
if (pin > 7)
|
||||
{
|
||||
IOR = MCP23017_GPIOB;
|
||||
pin -= 8;
|
||||
}
|
||||
uint8_t val = readReg(IOR);
|
||||
uint8_t mask = 1 << pin;
|
||||
if (value) val |= mask;
|
||||
else val &= ~mask;
|
||||
writeReg(IOR, val);
|
||||
}
|
||||
|
||||
uint8_t MCP23017::digitalRead(uint8_t pin)
|
||||
{
|
||||
if (pin > 15) return -100; // TODO magic number
|
||||
uint8_t IOR = MCP23017_GPIOA;
|
||||
if (pin > 7)
|
||||
{
|
||||
IOR = MCP23017_GPIOB;
|
||||
pin -= 8;
|
||||
}
|
||||
uint8_t val = readReg(IOR);
|
||||
uint8_t mask = 1 << pin;
|
||||
if (val & mask) return HIGH;
|
||||
return LOW;
|
||||
}
|
||||
|
||||
// 8 pins interface
|
||||
// whole register at once
|
||||
void MCP23017::pinMode8(uint8_t port, uint8_t value)
|
||||
{
|
||||
if (port == 0) writeReg(MCP23017_DDR_A, value);
|
||||
if (port == 1) writeReg(MCP23017_DDR_B, value);
|
||||
// explicitely ignore other values.
|
||||
}
|
||||
|
||||
void MCP23017::write8(uint8_t port, uint8_t value) // port = 0..1
|
||||
{
|
||||
if (port == 0) writeReg(MCP23017_GPIOA, value);
|
||||
if (port == 1) writeReg(MCP23017_GPIOB, value);
|
||||
// explicitely ignore other values.
|
||||
}
|
||||
|
||||
int MCP23017::read8(uint8_t port)
|
||||
{
|
||||
if (port == 0) return readReg(MCP23017_GPIOA);
|
||||
if (port == 1) return readReg(MCP23017_GPIOB);
|
||||
return -100; // TODO magic number
|
||||
}
|
||||
|
||||
|
||||
void MCP23017::writeReg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t MCP23017::readReg(uint8_t reg)
|
||||
{
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(_addr, (uint8_t)1);
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: MCP23017.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.1
|
||||
// PURPOSE: Arduino library for I2C MCP23017 16 channel port expander
|
||||
// DATE: 2019-10-12
|
||||
// URL: https://github.com/RobTillaart/MCP23017_RT
|
||||
// LICENSE: MIT
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
|
||||
#define MCP23017_LIB_VERSION "0.1.1"
|
||||
|
||||
class MCP23017
|
||||
{
|
||||
public:
|
||||
MCP23017(uint8_t addr);
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
void begin(const uint8_t dataPin, const uint8_t clockPin);
|
||||
#endif
|
||||
void begin();
|
||||
|
||||
// single pin interface
|
||||
void pinMode(uint8_t pin, uint8_t value);
|
||||
void digitalWrite(uint8_t pin, uint8_t value);
|
||||
uint8_t digitalRead(uint8_t pin);
|
||||
|
||||
// 8 pins interface
|
||||
void pinMode8(uint8_t port, uint8_t value);
|
||||
void write8(uint8_t port, uint8_t value);
|
||||
int read8(uint8_t port);
|
||||
|
||||
private:
|
||||
void writeReg(uint8_t reg, uint8_t value);
|
||||
uint8_t readReg(uint8_t reg);
|
||||
uint8_t _addr;
|
||||
};
|
||||
|
||||
// -- END OF FILE --
|
@ -1,26 +0,0 @@
|
||||
# MCP23017_RT
|
||||
|
||||
Arduino library for I2C MCP23017 16 channel port expander
|
||||
|
||||
## Description
|
||||
|
||||
Short discription of the interface
|
||||
|
||||
* **MCP23017(address)** constructor
|
||||
* **begin()**
|
||||
* **begin(sda, scl)** for ESP32
|
||||
|
||||
single pin interface
|
||||
* **pinMode(pin, value)** pin = 0..16 value = INPUT,OUTPUT
|
||||
* **digitalWrite(pin, value)** pin = 0..16 value = LOW(0) HIGH (!0)
|
||||
* **digitalRead(pin)** pin = 0..16
|
||||
|
||||
8 pins interface
|
||||
* **pinMode8(port, value)** port = 0, 1 value =
|
||||
* **write8(port, value)** port = 0, 1 value =
|
||||
* **read8(port)** port = 0, 1
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
|
@ -1,42 +0,0 @@
|
||||
//
|
||||
// FILE: MCP23017_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2019-10-14
|
||||
//
|
||||
// PUPROSE: test MCP23017 library
|
||||
//
|
||||
|
||||
#include "MCP23017.h"
|
||||
#include <Wire.h>
|
||||
|
||||
MCP23017 MCP(0x38);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(230400);
|
||||
Serial.print("MCP23017_test version: ");
|
||||
Serial.println(MCP23017_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
MCP.begin();
|
||||
|
||||
MCP.pinMode8(0, 0x00); // CHECK
|
||||
MCP.pinMode8(1, 0x00);
|
||||
|
||||
Serial.println("TEST digitalRead(pin)");
|
||||
for (int pin = 0; pin < 16; pin++)
|
||||
{
|
||||
int val = MCP.digitalRead(pin);
|
||||
Serial.print(val);
|
||||
Serial.print('\t');
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,65 +0,0 @@
|
||||
//
|
||||
// FILE: MCP23017_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2019-10-14
|
||||
//
|
||||
// PUPROSE: test MCP23017 library
|
||||
//
|
||||
|
||||
#include "MCP23017.h"
|
||||
#include <Wire.h>
|
||||
|
||||
MCP23017 MCP(0x27);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(230400);
|
||||
Serial.print("MCP23017_test version: ");
|
||||
Serial.println(MCP23017_LIB_VERSION);
|
||||
|
||||
Wire.begin();
|
||||
|
||||
MCP.begin();
|
||||
|
||||
MCP.pinMode8(0, 0x00); // 0 = output , 1 = input
|
||||
MCP.pinMode8(1, 0x00);
|
||||
Wire.setClock(50);
|
||||
|
||||
Serial.println("TEST digitalWrie(0)");
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
MCP.digitalWrite(0, i % 2); // alternating HIGH/LOW
|
||||
Serial.print(i % 2);
|
||||
Serial.print('\t');
|
||||
delay(250);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.println("TEST digitalWrie(pin)");
|
||||
for (int pin = 0; pin < 16; pin++)
|
||||
{
|
||||
MCP.digitalWrite(pin, 1 - pin % 2); // alternating HIGH/LOW
|
||||
Serial.print(1 - pin % 2);
|
||||
Serial.print('\t');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.println("TEST read back");
|
||||
|
||||
for (int pin = 0; pin < 16; pin++)
|
||||
{
|
||||
int val = MCP.digitalRead(pin);
|
||||
Serial.print(val);
|
||||
Serial.print('\t');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "MCP23017",
|
||||
"keywords": "MCP23017,I2C,16 I/O",
|
||||
"description": "Arduino library for I2C MCP23017 16 channel port expander",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MCP23017_RT.git"
|
||||
},
|
||||
"version":"0.1.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
name=MCP23017_RT
|
||||
version=0.1.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for I2C MCP23017 16 channel port expander 16 IO-lines
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=https://github.com/RobTillaart/MCP23017_RT
|
||||
architectures=*
|
||||
includes=MCP23017.h
|
||||
depends=
|
@ -1,20 +1,22 @@
|
||||
//
|
||||
// FILE: MCP_ADC.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.2
|
||||
// VERSION: 0.1.3
|
||||
// DATE: 2019-10-24
|
||||
// PURPOSE: Arduino library for MCP3002, MCP3004, MCP3008, MCP3202, MCP3204, MCP3208
|
||||
// URL: https://github.com/RobTillaart/MCP_ADC
|
||||
//
|
||||
|
||||
|
||||
#include "MCP_ADC.h"
|
||||
|
||||
|
||||
MCP_ADC::MCP_ADC(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
|
||||
{
|
||||
_dataIn = dataIn;
|
||||
_dataOut = dataOut;
|
||||
_clock = clock;
|
||||
_hwSPI = (dataIn == 255) && (dataOut == 255) && (clock == 255);
|
||||
_hwSPI = (dataIn == 255) || (dataOut == 255) || (clock == 255);
|
||||
if (_hwSPI == false)
|
||||
{
|
||||
pinMode(_dataIn, INPUT);
|
||||
@ -22,10 +24,14 @@ MCP_ADC::MCP_ADC(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
|
||||
pinMode(_clock, OUTPUT);
|
||||
digitalWrite(_dataOut, LOW);
|
||||
digitalWrite(_clock, LOW);
|
||||
// _SPIspeed = 0; TODO set to zero if SW SPI
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI.begin();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MCP_ADC::begin(uint8_t select)
|
||||
{
|
||||
_select = select;
|
||||
@ -33,18 +39,21 @@ void MCP_ADC::begin(uint8_t select)
|
||||
digitalWrite(_select, HIGH);
|
||||
}
|
||||
|
||||
|
||||
int16_t MCP_ADC::analogRead(uint8_t channel)
|
||||
{
|
||||
if (channel >= _channels) return 0;
|
||||
return readADC(channel, true);
|
||||
}
|
||||
|
||||
|
||||
int16_t MCP_ADC::differentialRead(uint8_t channel)
|
||||
{
|
||||
if (channel >= _channels) return 0;
|
||||
return readADC(channel, false);
|
||||
}
|
||||
|
||||
|
||||
int16_t MCP_ADC::deltaRead(uint8_t channel)
|
||||
{
|
||||
if (channel >= _channels) return 0;
|
||||
@ -58,16 +67,6 @@ int16_t MCP_ADC::deltaRead(uint8_t channel)
|
||||
return val0 - val1;
|
||||
}
|
||||
|
||||
void MCP_ADC::setSPIspeed(uint32_t speed)
|
||||
{
|
||||
_SPIspeed = speed;
|
||||
};
|
||||
|
||||
uint32_t MCP_ADC::getSPIspeed()
|
||||
{
|
||||
return _SPIspeed;
|
||||
};
|
||||
|
||||
|
||||
int16_t MCP_ADC::readADC(uint8_t channel, bool single)
|
||||
{
|
||||
@ -76,33 +75,31 @@ int16_t MCP_ADC::readADC(uint8_t channel, bool single)
|
||||
uint8_t data[3] = { 0,0,0 };
|
||||
uint8_t bytes = buildRequest(channel, single, data);
|
||||
|
||||
// TODO optimize _select handling
|
||||
digitalWrite(_select, LOW);
|
||||
if (_hwSPI)
|
||||
{
|
||||
SPI.beginTransaction(SPISettings(_SPIspeed, MSBFIRST, SPI_MODE0));
|
||||
digitalWrite(_select, LOW);
|
||||
for (uint8_t b = 0; b < bytes; b++)
|
||||
{
|
||||
data[b] = SPI.transfer(data[b]);
|
||||
}
|
||||
digitalWrite(_select, HIGH);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
else // Software SPI
|
||||
{
|
||||
digitalWrite(_select, LOW);
|
||||
for (uint8_t b = 0; b < bytes; b++)
|
||||
{
|
||||
data[b] = swSPI_transfer(data[b]);
|
||||
}
|
||||
digitalWrite(_select, HIGH);
|
||||
}
|
||||
digitalWrite(_select, HIGH);
|
||||
|
||||
if (bytes == 2) return ((256 * data[0] + data[1]) & _maxValue);
|
||||
// data[0]?
|
||||
return ((256 * data[1] + data[2]) & _maxValue);
|
||||
}
|
||||
|
||||
|
||||
// MSBFIRST
|
||||
uint8_t MCP_ADC::swSPI_transfer(uint8_t val)
|
||||
{
|
||||
|
@ -2,20 +2,24 @@
|
||||
//
|
||||
// FILE: MCP_ADC.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.2
|
||||
// VERSION: 0.1.3
|
||||
// DATE: 2019-10-24
|
||||
// PURPOSE: Arduino library for MCP_ADC
|
||||
// URL: https://github.com/RobTillaart/MCP_ADC
|
||||
//
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "SPI.h"
|
||||
|
||||
|
||||
#define MCP_ADC_LIB_VERSION (F("0.1.3"))
|
||||
|
||||
|
||||
class MCP_ADC
|
||||
{
|
||||
public:
|
||||
MCP_ADC(uint8_t dataIn = 255, uint8_t dataOut = 255, uint8_t clock = 255);
|
||||
// if only select is given ==> HW SPI
|
||||
void begin(uint8_t select);
|
||||
|
||||
uint8_t channels() { return _channels; };
|
||||
@ -23,9 +27,9 @@ public:
|
||||
int16_t analogRead(uint8_t channel);
|
||||
int16_t differentialRead(uint8_t channel);
|
||||
int16_t deltaRead(uint8_t channel);
|
||||
// speed in Hz
|
||||
void setSPIspeed(uint32_t speed);
|
||||
uint32_t getSPIspeed();
|
||||
// speed in Hz
|
||||
void setSPIspeed(uint32_t speed) { _SPIspeed = speed; };
|
||||
uint32_t getSPIspeed() { return _SPIspeed; };
|
||||
|
||||
protected:
|
||||
uint8_t _dataIn;
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
MCP3002 mcp2;
|
||||
MCP3004 mcp4;
|
||||
MCP3008 mcp8;
|
||||
// MCP3008 mcp8(11,12,13); // software spi
|
||||
MCP3008 mcp8; // hardware spi
|
||||
MCP3202 mcp22;
|
||||
MCP3204 mcp24;
|
||||
MCP3208 mcp28;
|
||||
@ -26,9 +27,9 @@ void setup()
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
|
||||
mcp2.begin(10);
|
||||
mcp2.begin(8);
|
||||
mcp4.begin(9);
|
||||
mcp8.begin(8);
|
||||
mcp8.begin(10);
|
||||
|
||||
Serial.println();
|
||||
|
||||
@ -71,11 +72,12 @@ void setup()
|
||||
test_2();
|
||||
test_3();
|
||||
|
||||
// on UNO there is no difference above 8MHz (half CPU clock)
|
||||
Serial.println("***************************************\n");
|
||||
for (int s = 1; s <= 16; s++)
|
||||
for (int s = 1; s <= 16; s *= 2)
|
||||
{
|
||||
Serial.println(s * 1000000);
|
||||
mcp8.setSPIspeed(s);
|
||||
Serial.println(s * 1000000UL);
|
||||
mcp8.setSPIspeed(s * 1000000UL);
|
||||
test_3();
|
||||
}
|
||||
|
||||
@ -163,7 +165,7 @@ void test_3()
|
||||
uint32_t val = 0;
|
||||
|
||||
start = micros();
|
||||
for (int channel = 0 ; channel < mcp8.channels(); channel++)
|
||||
for (int channel = 0; channel < mcp8.channels(); channel++)
|
||||
{
|
||||
val += mcp8.analogRead(channel);
|
||||
}
|
||||
@ -173,7 +175,7 @@ void test_3()
|
||||
delay(10);
|
||||
|
||||
start = micros();
|
||||
for (int channel = 0 ; channel < mcp8.channels(); channel++)
|
||||
for (int channel = 0; channel < mcp8.channels(); channel++)
|
||||
{
|
||||
val += mcp8.differentialRead(channel);
|
||||
}
|
||||
@ -183,7 +185,7 @@ void test_3()
|
||||
delay(10);
|
||||
|
||||
start = micros();
|
||||
for (int channel = 0 ; channel < mcp8.channels(); channel++)
|
||||
for (int channel = 0; channel < mcp8.channels(); channel++)
|
||||
{
|
||||
val += mcp8.deltaRead(channel);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MCP_ADC.git"
|
||||
},
|
||||
"version":"0.1.2",
|
||||
"version":"0.1.3",
|
||||
"frameworks": "*",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=MCP_ADC
|
||||
version=0.1.2
|
||||
version=0.1.3
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for MCP3002, MCP3004, MCP3008, MCP3202, MCP3204, MCP3208
|
||||
|
1
libraries/MCP_DAC
Submodule
1
libraries/MCP_DAC
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 781afba9a2c362b05401c9a894be53b565b56842
|
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-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,258 +0,0 @@
|
||||
//
|
||||
// FILE: PCA9685.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 24-apr-2016
|
||||
// VERSION: 0.3.0
|
||||
// PURPOSE: Arduino library for I2C PCA9685 16 channel PWM
|
||||
// URL: https://github.com/RobTillaart/PCA9685_RT
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2016-04-24 initial BETA version
|
||||
// 0.1.1 2019-01-30 testing && fixing
|
||||
// 0.2.0 2020-05-25 refactor; ESP32 begin(sda,scl)
|
||||
// 0.2.1 2020-06-19 fix library.json
|
||||
// 0.2.2 2020-09-21 fix #1 + add getFrequency()
|
||||
// 0.2.3 2020-11-21 fix digitalWrite (internal version only)
|
||||
// 0.3.0 2020-11-22 fix setting frequency
|
||||
|
||||
|
||||
#include "PCA9685.h"
|
||||
|
||||
|
||||
// REGISTERS CONFIGURATION - check datasheet for details
|
||||
#define PCA9685_MODE1 0x00
|
||||
#define PCA9685_MODE2 0x01
|
||||
|
||||
// MODE1 REGISTERS
|
||||
#define PCA9685_RESTART 0x80
|
||||
#define PCA9685_EXTCLK 0x40
|
||||
#define PCA9685_AUTOINCR 0x20
|
||||
#define PCA9685_SLEEP 0x10
|
||||
#define PCA9685_SUB1 0x08
|
||||
#define PCA9685_SUB2 0x04
|
||||
#define PCA9685_SUB3 0x02
|
||||
#define PCA9685_ALLCALL 0x01
|
||||
|
||||
// MODE2 REGISTERS (see datasheet)
|
||||
#define PCA9685_INVERT 0x10
|
||||
#define PCA9685_OCH 0x08
|
||||
#define PCA9685_OUTDRV 0x04
|
||||
#define PCA9685_OUTNE 0x03
|
||||
|
||||
// REGISTERS - CHANNELS
|
||||
#define PCA9685_CHANNEL_0 0x06 // 0x06 + 4*channel is base per channel
|
||||
|
||||
// REGISTERS - FREQUENCY
|
||||
#define PCA9685_PRE_SCALER 0xFE
|
||||
|
||||
// REGISTERS - Subaddressing I2C - not implemented
|
||||
#define PCA9685_SUBADR(x) (0x01+(x)) // x = 1..3
|
||||
#define PCA9685_ALLCALLADR 0x05
|
||||
|
||||
// REGISTERS - ALL_ON ALL_OFF - partly implemented
|
||||
#define PCA9685_ALL_ON_L 0xFA
|
||||
#define PCA9685_ALL_ON_H 0xFB
|
||||
#define PCA9685_ALL_OFF_L 0xFC
|
||||
#define PCA9685_ALL_OFF_H 0xFD // used for allOFF()
|
||||
|
||||
// NOT IMPLEMENTED YET
|
||||
#define PCA9685_TESTMODE 0xFF // do not be use. see datasheet.
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
PCA9685::PCA9685(const uint8_t deviceAddress)
|
||||
{
|
||||
_address = deviceAddress;
|
||||
_error = 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined (ESP8266) || defined(ESP32)
|
||||
void PCA9685::begin(uint8_t sda, uint8_t scl)
|
||||
{
|
||||
Wire.begin(sda, scl);
|
||||
reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
void PCA9685::begin()
|
||||
{
|
||||
Wire.begin();
|
||||
reset();
|
||||
}
|
||||
|
||||
void PCA9685::reset()
|
||||
{
|
||||
_error = 0;
|
||||
writeMode(PCA9685_MODE1, PCA9685_AUTOINCR | PCA9685_ALLCALL);
|
||||
writeMode(PCA9685_MODE2, PCA9685_OUTDRV);
|
||||
}
|
||||
|
||||
|
||||
void PCA9685::writeMode(uint8_t reg, uint8_t value)
|
||||
{
|
||||
if ((reg != PCA9685_MODE1) && (reg != PCA9685_MODE2))
|
||||
{
|
||||
_error = PCA9685_ERR_MODE;
|
||||
return;
|
||||
}
|
||||
writeReg(reg, value);
|
||||
}
|
||||
|
||||
|
||||
uint8_t PCA9685::readMode(uint8_t reg)
|
||||
{
|
||||
if ((reg != PCA9685_MODE1) && (reg != PCA9685_MODE2))
|
||||
{
|
||||
_error = PCA9685_ERR_MODE;
|
||||
return 0;
|
||||
}
|
||||
uint8_t value = readReg(reg);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// write value to single PWM channel
|
||||
void PCA9685::setPWM(uint8_t channel, uint16_t onTime, uint16_t offTime)
|
||||
{
|
||||
if (channel > 15)
|
||||
{
|
||||
_error = PCA9685_ERR_CHANNEL;
|
||||
return;
|
||||
}
|
||||
offTime &= 0x0FFFF; // non-doc feature - to easy set figure 8 P.17
|
||||
uint8_t reg = PCA9685_CHANNEL_0 + (channel << 2);
|
||||
writeReg2(reg, onTime, offTime);
|
||||
}
|
||||
|
||||
|
||||
// write value to single PWM channel
|
||||
void PCA9685::setPWM(uint8_t channel, uint16_t offTime)
|
||||
{
|
||||
setPWM(channel, 0, offTime);
|
||||
}
|
||||
|
||||
|
||||
// read value from single PWM channel
|
||||
void PCA9685::getPWM(uint8_t channel, uint16_t* onTime, uint16_t* offTime)
|
||||
{
|
||||
if (channel > 15)
|
||||
{
|
||||
_error = PCA9685_ERR_CHANNEL;
|
||||
return;
|
||||
}
|
||||
uint8_t reg = PCA9685_CHANNEL_0 + (channel << 2);
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(reg);
|
||||
_error = Wire.endTransmission();
|
||||
if (Wire.requestFrom(_address, (uint8_t)4) != 4)
|
||||
{
|
||||
_error = PCA9685_ERR_I2C;
|
||||
return;
|
||||
}
|
||||
uint16_t _data = Wire.read();
|
||||
*onTime = (Wire.read() * 256) + _data;
|
||||
_data = Wire.read();
|
||||
*offTime = (Wire.read() * 256) + _data;
|
||||
}
|
||||
|
||||
|
||||
// set update frequency for all channels
|
||||
void PCA9685::setFrequency(uint16_t freq, int offset)
|
||||
{
|
||||
_freq = freq;
|
||||
if (_freq < 24) _freq = 24; // page 25 datasheet
|
||||
if (_freq > 1526) _freq = 1526;
|
||||
// removed float operation for speed
|
||||
// faster but equal accurate
|
||||
// uint8_t scaler = round(25e6 / (_freq * 4096)) - 1;
|
||||
uint8_t scaler = 48828 / (_freq * 8) - 1;
|
||||
|
||||
uint8_t mode1 = readMode(PCA9685_MODE1);
|
||||
writeMode(PCA9685_MODE1, mode1 | PCA9685_SLEEP);
|
||||
scaler += offset;
|
||||
writeReg(PCA9685_PRE_SCALER, scaler);
|
||||
writeMode(PCA9685_MODE1, mode1);
|
||||
}
|
||||
|
||||
int PCA9685::getFrequency(bool cache)
|
||||
{
|
||||
if (cache) return _freq;
|
||||
uint8_t scaler = readReg(PCA9685_PRE_SCALER);
|
||||
scaler++;
|
||||
_freq = 48828 / scaler;
|
||||
_freq /= 8;
|
||||
return _freq;
|
||||
}
|
||||
|
||||
|
||||
// datasheet P.18 - fig. 9:
|
||||
// Note: bit[11-0] ON should NOT equal timer OFF in ON mode
|
||||
// in OFF mode it doesn't matter.
|
||||
void PCA9685::digitalWrite(uint8_t channel, uint8_t mode)
|
||||
{
|
||||
if (channel > 15)
|
||||
{
|
||||
_error = PCA9685_ERR_CHANNEL;
|
||||
return;
|
||||
}
|
||||
uint8_t reg = PCA9685_CHANNEL_0 + (channel << 2);
|
||||
if (mode != LOW) writeReg2(reg, 0x1000, 0x0000);
|
||||
else writeReg2(reg, 0x0000, 0x0000);
|
||||
}
|
||||
|
||||
void PCA9685::allOFF()
|
||||
{
|
||||
writeReg(PCA9685_ALL_OFF_H, 0x10);
|
||||
}
|
||||
|
||||
int PCA9685::lastError()
|
||||
{
|
||||
int e = _error;
|
||||
_error = 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
//
|
||||
void PCA9685::writeReg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
_error = Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
void PCA9685::writeReg2(uint8_t reg, uint16_t a, uint16_t b)
|
||||
{
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(reg);
|
||||
Wire.write(a & 0xFF);
|
||||
Wire.write((a >> 8) & 0x1F);
|
||||
Wire.write(b & 0xFF);
|
||||
Wire.write((b >> 8) & 0x1F);
|
||||
_error = Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
uint8_t PCA9685::readReg(uint8_t reg)
|
||||
{
|
||||
Wire.beginTransmission(_address);
|
||||
Wire.write(reg);
|
||||
_error = Wire.endTransmission();
|
||||
if (Wire.requestFrom(_address, (uint8_t)1) != 1)
|
||||
{
|
||||
_error = PCA9685_ERR_I2C;
|
||||
return 0;
|
||||
}
|
||||
uint8_t _data = Wire.read();
|
||||
return _data;
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -1,82 +0,0 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: PCA9685.H
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 24-apr-2016
|
||||
// VERSION: 0.3.0
|
||||
// PURPOSE: Arduino library for I2C PCA9685 16 channel PWM
|
||||
// URL: https://github.com/RobTillaart/PCA9685_RT
|
||||
//
|
||||
// HISTORY:
|
||||
// see PCA9685.cpp file
|
||||
//
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
|
||||
#define PCA9685_LIB_VERSION "0.3.0"
|
||||
|
||||
// ERROR CODES
|
||||
#define PCA9685_OK 0x00
|
||||
#define PCA9685_ERROR 0xFF
|
||||
#define PCA9685_ERR_CHANNEL 0xFE
|
||||
#define PCA9685_ERR_MODE 0xFD
|
||||
#define PCA9685_ERR_I2C 0xFC
|
||||
|
||||
|
||||
class PCA9685
|
||||
{
|
||||
public:
|
||||
explicit PCA9685(const uint8_t deviceAddress);
|
||||
|
||||
#if defined (ESP8266) || defined(ESP32)
|
||||
void begin(uint8_t sda, uint8_t scl);
|
||||
#endif
|
||||
void begin();
|
||||
void reset();
|
||||
|
||||
// reg = 1, 2 check datasheet for values
|
||||
void writeMode(uint8_t reg, uint8_t value);
|
||||
uint8_t readMode(uint8_t reg);
|
||||
|
||||
// single PWM setting, channel = 0..15,
|
||||
// onTime = 0..4095, offTime = 0..4095
|
||||
// allows shifted PWM's e.g. 2 servo's that do not start at same time.
|
||||
void setPWM(uint8_t channel, uint16_t onTime, uint16_t offTime);
|
||||
void getPWM(uint8_t channel, uint16_t* onTime, uint16_t* offTime);
|
||||
|
||||
// single PWM setting, channel = 0..15, offTime = 0..4095 (onTime = 0)
|
||||
void setPWM(uint8_t channel, uint16_t offTime);
|
||||
|
||||
// set update frequency for all channels
|
||||
// freq = 24 - 1526 Hz
|
||||
// note: as the frequency is converted to an 8 bit prescaler
|
||||
// the frequency set will seldom be exact, but best effort.
|
||||
void setFrequency(uint16_t freq, int offset = 0);
|
||||
int getFrequency(bool cache = true);
|
||||
|
||||
// set channel HIGH or LOW (effectively no PWM)
|
||||
void digitalWrite(uint8_t channel, uint8_t mode);
|
||||
|
||||
// for backwards compatibility; will be removed in future
|
||||
void setON(uint8_t channel) { digitalWrite(channel, HIGH); };
|
||||
void setOFF(uint8_t channel) { digitalWrite(channel, LOW); };
|
||||
|
||||
// experimental for 0.3.0
|
||||
void allOFF();
|
||||
|
||||
int lastError();
|
||||
|
||||
private:
|
||||
|
||||
// DIRECT CONTROL
|
||||
void writeReg(uint8_t reg, uint8_t value);
|
||||
void writeReg2(uint8_t reg, uint16_t a, uint16_t b);
|
||||
uint8_t readReg(uint8_t reg);
|
||||
|
||||
uint8_t _address;
|
||||
int _error;
|
||||
int _freq = 200; // default PWM frequency - P25 datasheet
|
||||
};
|
||||
|
||||
// -- END OF FILE --
|
@ -1,89 +0,0 @@
|
||||
# PCA9685_RT
|
||||
|
||||
Arduino library for I2C PCA9685 16 channel PWM extender
|
||||
|
||||
# Description
|
||||
|
||||
This library is to control the I2C PCA9685 PWM extender.
|
||||
The 16 channels are independently configurable in steps of 1/4096.
|
||||
This allows for better than 0.1% finetuning of the duty-cycle
|
||||
of the PWM signal.
|
||||
|
||||
The PWM's of the different channels have individual start and stop moments.
|
||||
This can be used to distribute the power more evenly over multiple servo's
|
||||
or give special effects when used in an RGB LED.
|
||||
|
||||
The frequency of the PWM can be set from 24 to 1526 according to the datasheet, however in practice not all frequencies are set accurate.
|
||||
Lower frequencies do better than higher frequencies.
|
||||
|
||||
|
||||
### interface
|
||||
|
||||
**begin()** initializes the library after startup. Mandatory.
|
||||
|
||||
**begin(sda, scl)** idem, ESP32 ESP8266 only. Library does not support
|
||||
multiple Wire instances (yet).
|
||||
|
||||
**reset()** resets the library to start up conditions.
|
||||
|
||||
**writeMode(reg, mode)** configuration of one of the two configuration registers.
|
||||
check datasheet for details.
|
||||
|
||||
**readMode(reg)** reads back the configured mode, useful to add or remove a
|
||||
single flag (bit masking)
|
||||
|
||||
**setPWM(channel, ontime, offtime)** The chip has 16 channels to do PWM.
|
||||
The signal is divided in 4096 steps, 0..4095.
|
||||
The pulse can begin =**ontime** on any step and it can stop on any step =**offtime**.
|
||||
This allows e.g. to distribute the power over the 16 channels, e.g. the
|
||||
channels do not need to start at the same moment with HIGH.
|
||||
|
||||
**setPWM(channel, offtime)** simple PWM that always start on **ontime = 0**
|
||||
|
||||
**getPWM(channel, ontime, offtime)** read back the configuration of the channel.
|
||||
|
||||
**setFrequency(freq, int offset = 0)** set the update speed of the channels.
|
||||
This value is set the same for all channels at once.
|
||||
The frequency is constrained to be between 24 and 1526 Hz.
|
||||
As the frequency is converted to an 8 bit **prescaler**,
|
||||
the frequency set will seldom be exact.
|
||||
After changing the frequency, one must set all channels (again),
|
||||
so one should set the frequency in **setup()**
|
||||
|
||||
The parameter offset can be used to tune the **prescaler** to get a frequency
|
||||
closer to the requested value. See **PCA9685_setFrequency_offset** example.
|
||||
Default the offset = 0. As the prescaler is smaller at higher frequencies
|
||||
higher frequencies are less accurate.
|
||||
Making offset too large can result in very incorrect frequencies.
|
||||
|
||||
When using offset, the **getFrequency(false)** will return the adjusted prescaler.
|
||||
|
||||
**getFrequency(cache = true)** get the current update frequency of the channels.
|
||||
This is same for all channels. If cache is false, the frequency is fetched and
|
||||
calculated from the **prescaler** register and will probably differ from the
|
||||
value set with **setFrequency()**.
|
||||
|
||||
**digitalWrite(channel, mode)** mode = HIGH or LOW, just use the PCA9685 as
|
||||
a digitalpin.
|
||||
This single function replaces the setON() and setOFF() that will become
|
||||
obsolete in the future.
|
||||
|
||||
**allOFF()** switches all PWM channels OFF. **Experimental** in 0.3.0
|
||||
To "undo" the allOFF one can call the **reset()** function and set all
|
||||
PWM channels again.
|
||||
|
||||
**lastError()** returns **PCA9685_OK = 0** if all is OK, and
|
||||
|
||||
| Error code | Value | Description |
|
||||
|:----|:----:|:----|
|
||||
| PCA9685_OK | 0x00 | Everything went well
|
||||
| PCA9685_ERROR | 0xFF | generic error
|
||||
| PCA9685_ERR_CHANNEL | 0xFE | Channel out of range
|
||||
| PCA9685_ERR_MODE | 0xFD | Invalid mode register chosen |
|
||||
| PCA9685_ERR_I2C | 0xFC | PCA9685 I2C communication error
|
||||
|
||||
|
||||
|
||||
# Operation
|
||||
|
||||
See examples
|
@ -1,53 +0,0 @@
|
||||
//
|
||||
// FILE: PCA9685_allOFF_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2020-11-22
|
||||
// VERSION: 0.1.0
|
||||
// PUPROSE: test PCA9685 library
|
||||
//
|
||||
|
||||
/*
|
||||
sets all channels to a PWM
|
||||
then switches them all off
|
||||
you can check it by testing all channels.
|
||||
*/
|
||||
|
||||
#include "PCA9685.h"
|
||||
|
||||
PCA9685 PCA(0x40);
|
||||
|
||||
const uint8_t PIN = 2;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Wire.begin();
|
||||
PCA.begin();
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.print("PCA9685 LIB version: ");
|
||||
Serial.println(PCA9685_LIB_VERSION);
|
||||
Serial.println();
|
||||
|
||||
pinMode(PIN, INPUT_PULLUP);
|
||||
for (int channel = 0; channel < 16; channel++)
|
||||
{
|
||||
PCA.setPWM(channel, 0, 1000);
|
||||
}
|
||||
delay(100); // to be sure they started.
|
||||
PCA.allOFF();
|
||||
|
||||
// delay(100);
|
||||
// PCA.reset(); // needed to reset the allOFF()
|
||||
// for (int channel = 0; channel < 16; channel++)
|
||||
// {
|
||||
// PCA.digitalWrite(channel, HIGH);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.println(digitalRead(PIN)); // you can measure all pins
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user