Browse Source

Init

master
Apostolos Fanakis 6 years ago
commit
37f9532826
  1. 36
      README.md
  2. 156
      dependencies/Adafruit_Sensor/Adafruit_Sensor.h
  3. 299
      dependencies/DHT/DHT.cpp
  4. 81
      dependencies/DHT/DHT.h
  5. 195
      dependencies/DHT/DHT_U.cpp
  6. 78
      dependencies/DHT/DHT_U.h
  7. 582
      dependencies/SevSeg/SevSeg.cpp
  8. 95
      dependencies/SevSeg/SevSeg.h
  9. 27
      tests/test_display/test_display.ino
  10. 97
      todoFindCoolNameForProject/todoFindCoolNameForProject.ino

36
README.md

@ -0,0 +1,36 @@
# Microprocessors and Peripherals semester assignment, 2019, AUTH
> Temperature and distance sensing and data sending over the internet
insertCoolProjectNameHere is an *experimental* application developed as part of the course "Microprocessors and Peripherals" assignment, that took place in the Department of Electrical & Computer Engineering at Aristotle University of Thessaloniki in 2019.
---
## Dependencies
In order to compile and execute this application the bellow referenced libraries and their dependencies are needed.
Libraries:
- SevSeg
- DHT
- Adafruit_Sensor (DHT.h dependency)
All the libraries' latest versions (as of the completion of the project) can be found in the `dependencies` directory of this repository. Instructions for installing them can be found in the links bellow:
- https://www.arduino.cc/en/Guide/Libraries#toc5
- https://www.arduino.cc/en/hacking/libraries
---
## Execution
To execute the code just open the `todoFindCoolNameForProject\todoFindCoolNameForProject.ino` file using the Arduino IDE and click the Verify and Upload buttons. All necessery peripherials need to be correctly connected to the Arduino board used, more information about the connections can be found inside the `todoFindCoolNameForProject.ino` file and the report.
---
## Support
Reach out to me:
- [apostolof's email](mailto:apotwohd@gmail.com "apotwohd@gmail.com")
- [anapt's email](mailto:ana.pachni.tsitiridou@gmail.com "ana.pachni.tsitiridou@gmail.com")
---

156
dependencies/Adafruit_Sensor/Adafruit_Sensor.h

@ -0,0 +1,156 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software< /span>
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
* extended sensor support to include color, voltage and current */
#ifndef _ADAFRUIT_SENSOR_H
#define _ADAFRUIT_SENSOR_H
#ifndef ARDUINO
#include <stdint.h>
#elif ARDUINO >= 100
#include "Arduino.h"
#include "Print.h"
#else
#include "WProgram.h"
#endif
/* Intentionally modeled after sensors.h in the Android API:
* https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */
/* Constants */
#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */
#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */
#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */
#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */
#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */
#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */
#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */
/** Sensor types */
typedef enum
{
SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */
SENSOR_TYPE_MAGNETIC_FIELD = (2),
SENSOR_TYPE_ORIENTATION = (3),
SENSOR_TYPE_GYROSCOPE = (4),
SENSOR_TYPE_LIGHT = (5),
SENSOR_TYPE_PRESSURE = (6),
SENSOR_TYPE_PROXIMITY = (8),
SENSOR_TYPE_GRAVITY = (9),
SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */
SENSOR_TYPE_ROTATION_VECTOR = (11),
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
SENSOR_TYPE_VOLTAGE = (15),
SENSOR_TYPE_CURRENT = (16),
SENSOR_TYPE_COLOR = (17)
} sensors_type_t;
/** struct sensors_vec_s is used to return a vector in a common format. */
typedef struct {
union {
float v[3];
struct {
float x;
float y;
float z;
};
/* Orientation sensors */
struct {
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */
float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */
};
};
int8_t status;
uint8_t reserved[3];
} sensors_vec_t;
/** struct sensors_color_s is used to return color data in a common format. */
typedef struct {
union {
float c[3];
/* RGB color space */
struct {
float r; /**< Red component */
float g; /**< Green component */
float b; /**< Blue component */
};
};
uint32_t rgba; /**< 24-bit RGBA value */
} sensors_color_t;
/* Sensor event (36 bytes) */
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
typedef struct
{
int32_t version; /**< must be sizeof(struct sensors_event_t) */
int32_t sensor_id; /**< unique sensor identifier */
int32_t type; /**< sensor type */
int32_t reserved0; /**< reserved */
int32_t timestamp; /**< time is in milliseconds */
union
{
float data[4];
sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */
sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */
sensors_vec_t orientation; /**< orientation values are in degrees */
sensors_vec_t gyro; /**< gyroscope values are in rad/s */
float temperature; /**< temperature is in degrees centigrade (Celsius) */
float distance; /**< distance in centimeters */
float light; /**< light in SI lux units */
float pressure; /**< pressure in hectopascal (hPa) */
float relative_humidity; /**< relative humidity in percent */
float current; /**< current in milliamps (mA) */
float voltage; /**< voltage in volts (V) */
sensors_color_t color; /**< color in RGB component values */
};
} sensors_event_t;
/* Sensor details (40 bytes) */
/** struct sensor_s is used to describe basic information about a specific sensor. */
typedef struct
{
char name[12]; /**< sensor name */
int32_t version; /**< version of the hardware + driver */
int32_t sensor_id; /**< unique sensor identifier */
int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */
float max_value; /**< maximum value of this sensor's value in SI units */
float min_value; /**< minimum value of this sensor's value in SI units */
float resolution; /**< smallest difference between two values reported by this sensor */
int32_t min_delay; /**< min delay in microseconds between events. zero = not a constant rate */
} sensor_t;
class Adafruit_Sensor {
public:
// Constructor(s)
Adafruit_Sensor() {}
virtual ~Adafruit_Sensor() {}
// These must be defined by the subclass
virtual void enableAutoRange(bool enabled) { (void)enabled; /* suppress unused warning */ };
virtual bool getEvent(sensors_event_t*) = 0;
virtual void getSensor(sensor_t*) = 0;
private:
bool _autoRange;
};
#endif

299
dependencies/DHT/DHT.cpp

@ -0,0 +1,299 @@
/* DHT library
MIT license
written by Adafruit Industries
*/
#include "DHT.h"
#define MIN_INTERVAL 2000
#define TIMEOUT -1
DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
_pin = pin;
_type = type;
#ifdef __AVR
_bit = digitalPinToBitMask(pin);
_port = digitalPinToPort(pin);
#endif
_maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for
// reading pulses from DHT sensor.
// Note that count is now ignored as the DHT reading algorithm adjusts itself
// based on the speed of the processor.
}
// Optionally pass pull-up time (in microseconds) before DHT reading starts.
// Default is 55 (see function declaration in DHT.h).
void DHT::begin(uint8_t usec) {
// set up the pins!
pinMode(_pin, INPUT_PULLUP);
// Using this value makes sure that millis() - lastreadtime will be
// >= MIN_INTERVAL right away. Note that this assignment wraps around,
// but so will the subtraction.
_lastreadtime = millis() - MIN_INTERVAL;
DEBUG_PRINT("DHT max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC);
pullTime = usec;
}
//boolean S == Scale. True == Fahrenheit; False == Celcius
float DHT::readTemperature(bool S, bool force) {
float f = NAN;
if (read(force)) {
switch (_type) {
case DHT11:
f = data[2];
if (data[3] & 0x80) {
f = -1 - f ;
}
f += (data[3] & 0x0f) * 0.1;
if(S) {
f = convertCtoF(f);
}
break;
case DHT12:
f = data[2];
f += (data[3] & 0x0f) * 0.1;
if (data[2] & 0x80) {
f *= -1;
}
if(S) {
f = convertCtoF(f);
}
break;
case DHT22:
case DHT21:
f = ((word)(data[2] & 0x7F)) << 8 | data[3];
f *= 0.1;
if (data[2] & 0x80) {
f *= -1;
}
if(S) {
f = convertCtoF(f);
}
break;
}
}
return f;
}
float DHT::convertCtoF(float c) {
return c * 1.8 + 32;
}
float DHT::convertFtoC(float f) {
return (f - 32) * 0.55555;
}
float DHT::readHumidity(bool force) {
float f = NAN;
if (read(force)) {
switch (_type) {
case DHT11:
case DHT12:
f = data[0] + data[1] * 0.1;
break;
case DHT22:
case DHT21:
f = ((word)data[0]) << 8 | data[1];
f *= 0.1;
break;
}
}
return f;
}
//boolean isFahrenheit: True == Fahrenheit; False == Celcius
float DHT::computeHeatIndex(bool isFahrenheit) {
float hi = computeHeatIndex(readTemperature(isFahrenheit), readHumidity(),
isFahrenheit);
return hi;
}
//boolean isFahrenheit: True == Fahrenheit; False == Celcius
float DHT::computeHeatIndex(float temperature, float percentHumidity,
bool isFahrenheit) {
// Using both Rothfusz and Steadman's equations
// http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
float hi;
if (!isFahrenheit)
temperature = convertCtoF(temperature);
hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094));
if (hi > 79) {
hi = -42.379 +
2.04901523 * temperature +
10.14333127 * percentHumidity +
-0.22475541 * temperature*percentHumidity +
-0.00683783 * pow(temperature, 2) +
-0.05481717 * pow(percentHumidity, 2) +
0.00122874 * pow(temperature, 2) * percentHumidity +
0.00085282 * temperature*pow(percentHumidity, 2) +
-0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2);
if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0))
hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882);
else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0))
hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2);
}
return isFahrenheit ? hi : convertFtoC(hi);
}
bool DHT::read(bool force) {
// Check if sensor was read less than two seconds ago and return early
// to use last reading.
uint32_t currenttime = millis();
if (!force && ((currenttime - _lastreadtime) < MIN_INTERVAL)) {
return _lastresult; // return last correct measurement
}
_lastreadtime = currenttime;
// Reset 40 bits of received data to zero.
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
#if defined(ESP8266)
yield(); // Handle WiFi / reset software watchdog
#endif
// Send start signal. See DHT datasheet for full signal diagram:
// http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
// Go into high impedence state to let pull-up raise data line level and
// start the reading process.
pinMode(_pin, INPUT_PULLUP);
delay(1);
// First set data line low for a period according to sensor type
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
switch(_type) {
case DHT22:
case DHT21:
delayMicroseconds(1100); // data sheet says "at least 1ms"
break;
case DHT11:
default:
delay(20); //data sheet says at least 18ms, 20ms just to be safe
break;
}
uint32_t cycles[80];
{
// End the start signal by setting data line high for 40 microseconds.
pinMode(_pin, INPUT_PULLUP);
// Delay a moment to let sensor pull data line low.
delayMicroseconds(pullTime);
// Now start reading the data line to get the value from the DHT sensor.
// Turn off interrupts temporarily because the next sections
// are timing critical and we don't want any interruptions.
InterruptLock lock;
// First expect a low signal for ~80 microseconds followed by a high signal
// for ~80 microseconds again.
if (expectPulse(LOW) == TIMEOUT) {
DEBUG_PRINTLN(F("DHT timeout waiting for start signal low pulse."));
_lastresult = false;
return _lastresult;
}
if (expectPulse(HIGH) == TIMEOUT) {
DEBUG_PRINTLN(F("DHT timeout waiting for start signal high pulse."));
_lastresult = false;
return _lastresult;
}
// Now read the 40 bits sent by the sensor. Each bit is sent as a 50
// microsecond low pulse followed by a variable length high pulse. If the
// high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds
// then it's a 1. We measure the cycle count of the initial 50us low pulse
// and use that to compare to the cycle count of the high pulse to determine
// if the bit is a 0 (high state cycle count < low state cycle count), or a
// 1 (high state cycle count > low state cycle count). Note that for speed all
// the pulses are read into a array and then examined in a later step.
for (int i=0; i<80; i+=2) {
cycles[i] = expectPulse(LOW);
cycles[i+1] = expectPulse(HIGH);
}
} // Timing critical code is now complete.
// Inspect pulses and determine which ones are 0 (high state cycle count < low
// state cycle count), or 1 (high state cycle count > low state cycle count).
for (int i=0; i<40; ++i) {
uint32_t lowCycles = cycles[2*i];
uint32_t highCycles = cycles[2*i+1];
if ((lowCycles == TIMEOUT) || (highCycles == TIMEOUT)) {
DEBUG_PRINTLN(F("DHT timeout waiting for pulse."));
_lastresult = false;
return _lastresult;
}
data[i/8] <<= 1;
// Now compare the low and high cycle times to see if the bit is a 0 or 1.
if (highCycles > lowCycles) {
// High cycles are greater than 50us low cycle count, must be a 1.
data[i/8] |= 1;
}
// Else high cycles are less than (or equal to, a weird case) the 50us low
// cycle count so this must be a zero. Nothing needs to be changed in the
// stored data.
}
DEBUG_PRINTLN(F("Received from DHT:"));
DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", "));
DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", "));
DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", "));
DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", "));
DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? "));
DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX);
// Check we read 40 bits and that the checksum matches.
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
_lastresult = true;
return _lastresult;
}
else {
DEBUG_PRINTLN(F("DHT checksum failure!"));
_lastresult = false;
return _lastresult;
}
}
// Expect the signal line to be at the specified level for a period of time and
// return a count of loop cycles spent at that level (this cycle count can be
// used to compare the relative time of two pulses). If more than a millisecond
// ellapses without the level changing then the call fails with a 0 response.
// This is adapted from Arduino's pulseInLong function (which is only available
// in the very latest IDE versions):
// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c
uint32_t DHT::expectPulse(bool level) {
#if (F_CPU > 16000000L)
uint32_t count = 0;
#else
uint16_t count = 0; // To work fast enough on slower AVR boards
#endif
// On AVR platforms use direct GPIO port access as it's much faster and better
// for catching pulses that are 10's of microseconds in length:
#ifdef __AVR
uint8_t portState = level ? _bit : 0;
while ((*portInputRegister(_port) & _bit) == portState) {
if (count++ >= _maxcycles) {
return TIMEOUT; // Exceeded timeout, fail.
}
}
// Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266
// right now, perhaps bugs in direct port access functions?).
#else
while (digitalRead(_pin) == level) {
if (count++ >= _maxcycles) {
return TIMEOUT; // Exceeded timeout, fail.
}
}
#endif
return count;
}

81
dependencies/DHT/DHT.h

@ -0,0 +1,81 @@
/* DHT library
MIT license
written by Adafruit Industries
*/
#ifndef DHT_H
#define DHT_H
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// Uncomment to enable printing out nice debug messages.
//#define DHT_DEBUG
// Define where debug output will be printed.
#define DEBUG_PRINTER Serial
// Setup debug printing macros.
#ifdef DHT_DEBUG
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
#else
#define DEBUG_PRINT(...) {}
#define DEBUG_PRINTLN(...) {}
#endif
// Define types of sensors.
#define DHT11 11
#define DHT12 12
#define DHT22 22
#define DHT21 21
#define AM2301 21
class DHT {
public:
DHT(uint8_t pin, uint8_t type, uint8_t count=6);
void begin(uint8_t usec=55);
float readTemperature(bool S=false, bool force=false);
float convertCtoF(float);
float convertFtoC(float);
float computeHeatIndex(bool isFahrenheit=true);
float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=true);
float readHumidity(bool force=false);
bool read(bool force=false);
private:
uint8_t data[5];
uint8_t _pin, _type;
#ifdef __AVR
// Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask
// for the digital pin connected to the DHT. Other platforms will use digitalRead.
uint8_t _bit, _port;
#endif
uint32_t _lastreadtime, _maxcycles;
bool _lastresult;
uint8_t pullTime; // Time (in usec) to pull up data line before reading
uint32_t expectPulse(bool level);
};
class InterruptLock {
public:
InterruptLock() {
#if !defined(ARDUINO_ARCH_NRF52)
noInterrupts();
#endif
}
~InterruptLock() {
#if !defined(ARDUINO_ARCH_NRF52)
interrupts();
#endif
}
};
#endif

195
dependencies/DHT/DHT_U.cpp

@ -0,0 +1,195 @@
// DHT Temperature & Humidity Unified Sensor Library
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include "DHT_U.h"
DHT_Unified::DHT_Unified(uint8_t pin, uint8_t type, uint8_t count, int32_t tempSensorId, int32_t humiditySensorId):
_dht(pin, type, count),
_type(type),
_temp(this, tempSensorId),
_humidity(this, humiditySensorId)
{}
void DHT_Unified::begin() {
_dht.begin();
}
void DHT_Unified::setName(sensor_t* sensor) {
switch(_type) {
case DHT11:
strncpy(sensor->name, "DHT11", sizeof(sensor->name) - 1);
break;
case DHT12:
strncpy(sensor->name, "DHT12", sizeof(sensor->name) - 1);
break;
case DHT21:
strncpy(sensor->name, "DHT21", sizeof(sensor->name) - 1);
break;
case DHT22:
strncpy(sensor->name, "DHT22", sizeof(sensor->name) - 1);
break;
default:
// TODO: Perhaps this should be an error? However main DHT library doesn't enforce
// restrictions on the sensor type value. Pick a generic name for now.
strncpy(sensor->name, "DHT?", sizeof(sensor->name) - 1);
break;
}
sensor->name[sizeof(sensor->name)- 1] = 0;
}
void DHT_Unified::setMinDelay(sensor_t* sensor) {
switch(_type) {
case DHT11:
sensor->min_delay = 1000000L; // 1 second (in microseconds)
break;
case DHT12:
sensor->min_delay = 2000000L; // 2 second (in microseconds)
break;
case DHT21:
sensor->min_delay = 2000000L; // 2 seconds (in microseconds)
break;
case DHT22:
sensor->min_delay = 2000000L; // 2 seconds (in microseconds)
break;
default:
// Default to slowest sample rate in case of unknown type.
sensor->min_delay = 2000000L; // 2 seconds (in microseconds)
break;
}
}
DHT_Unified::Temperature::Temperature(DHT_Unified* parent, int32_t id):
_parent(parent),
_id(id)
{}
bool DHT_Unified::Temperature::getEvent(sensors_event_t* event) {
// Clear event definition.
memset(event, 0, sizeof(sensors_event_t));
// Populate sensor reading values.
event->version = sizeof(sensors_event_t);
event->sensor_id = _id;
event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
event->timestamp = millis();
event->temperature = _parent->_dht.readTemperature();
return true;
}
void DHT_Unified::Temperature::getSensor(sensor_t* sensor) {
// Clear sensor definition.
memset(sensor, 0, sizeof(sensor_t));
// Set sensor name.
_parent->setName(sensor);
// Set version and ID
sensor->version = DHT_SENSOR_VERSION;
sensor->sensor_id = _id;
// Set type and characteristics.
sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
_parent->setMinDelay(sensor);
switch (_parent->_type) {
case DHT11:
sensor->max_value = 50.0F;
sensor->min_value = 0.0F;
sensor->resolution = 2.0F;
break;
case DHT12:
sensor->max_value = 60.0F;
sensor->min_value = -20.0F;
sensor->resolution = 0.5F;
break;
case DHT21:
sensor->max_value = 80.0F;
sensor->min_value = -40.0F;
sensor->resolution = 0.1F;
break;
case DHT22:
sensor->max_value = 125.0F;
sensor->min_value = -40.0F;
sensor->resolution = 0.1F;
break;
default:
// Unknown type, default to 0.
sensor->max_value = 0.0F;
sensor->min_value = 0.0F;
sensor->resolution = 0.0F;
break;
}
}
DHT_Unified::Humidity::Humidity(DHT_Unified* parent, int32_t id):
_parent(parent),
_id(id)
{}
bool DHT_Unified::Humidity::getEvent(sensors_event_t* event) {
// Clear event definition.
memset(event, 0, sizeof(sensors_event_t));
// Populate sensor reading values.
event->version = sizeof(sensors_event_t);
event->sensor_id = _id;
event->type = SENSOR_TYPE_RELATIVE_HUMIDITY;
event->timestamp = millis();
event->relative_humidity = _parent->_dht.readHumidity();
return true;
}
void DHT_Unified::Humidity::getSensor(sensor_t* sensor) {
// Clear sensor definition.
memset(sensor, 0, sizeof(sensor_t));
// Set sensor name.
_parent->setName(sensor);
// Set version and ID
sensor->version = DHT_SENSOR_VERSION;
sensor->sensor_id = _id;
// Set type and characteristics.
sensor->type = SENSOR_TYPE_RELATIVE_HUMIDITY;
_parent->setMinDelay(sensor);
switch (_parent->_type) {
case DHT11:
sensor->max_value = 80.0F;
sensor->min_value = 20.0F;
sensor->resolution = 5.0F;
break;
case DHT12:
sensor->max_value = 95.0F;
sensor->min_value = 20.0F;
sensor->resolution = 5.0F;
break;
case DHT21:
sensor->max_value = 100.0F;
sensor->min_value = 0.0F;
sensor->resolution = 0.1F;
break;
case DHT22:
sensor->max_value = 100.0F;
sensor->min_value = 0.0F;
sensor->resolution = 0.1F;
break;
default:
// Unknown type, default to 0.
sensor->max_value = 0.0F;
sensor->min_value = 0.0F;
sensor->resolution = 0.0F;
break;
}
}

78
dependencies/DHT/DHT_U.h

@ -0,0 +1,78 @@
// DHT Temperature & Humidity Unified Sensor Library
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#ifndef DHT_U_H
#define DHT_U_H
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHT_SENSOR_VERSION 1
class DHT_Unified {
public:
DHT_Unified(uint8_t pin, uint8_t type, uint8_t count=6, int32_t tempSensorId=-1, int32_t humiditySensorId=-1);
void begin();
class Temperature : public Adafruit_Sensor {
public:
Temperature(DHT_Unified* parent, int32_t id);
bool getEvent(sensors_event_t* event);
void getSensor(sensor_t* sensor);
private:
DHT_Unified* _parent;
int32_t _id;
};
class Humidity : public Adafruit_Sensor {
public:
Humidity(DHT_Unified* parent, int32_t id);
bool getEvent(sensors_event_t* event);
void getSensor(sensor_t* sensor);
private:
DHT_Unified* _parent;
int32_t _id;
};
Temperature temperature() {
return _temp;
}
Humidity humidity() {
return _humidity;
}
private:
DHT _dht;
uint8_t _type;
Temperature _temp;
Humidity _humidity;
void setName(sensor_t* sensor);
void setMinDelay(sensor_t* sensor);
};
#endif

582
dependencies/SevSeg/SevSeg.cpp

@ -0,0 +1,582 @@
/* SevSeg Library
*
* Copyright 2017 Dean Reading
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* This library allows an Arduino to easily display numbers and letters on a
* 7-segment display without a separate 7-segment display controller.
*
* Direct any questions or suggestions to deanreading@hotmail.com
* See the included readme for instructions.
* https://github.com/DeanIsMe/SevSeg
*/
#include "SevSeg.h"
#define BLANK_IDX 36 // Must match with 'digitCodeMap'
#define DASH_IDX 37
#define PERIOD_IDX 38
#define ASTERISK_IDX 39
static const long powersOf10[] = {
1, // 10^0
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
}; // 10^9
static const long powersOf16[] = {
0x1, // 16^0
0x10,
0x100,
0x1000,
0x10000,
0x100000,
0x1000000,
0x10000000
}; // 16^7
// digitCodeMap indicate which segments must be illuminated to display
// each number.
static const byte digitCodeMap[] = {
// GFEDCBA Segments 7-segment map:
B00111111, // 0 "0" AAA
B00000110, // 1 "1" F B
B01011011, // 2 "2" F B
B01001111, // 3 "3" GGG
B01100110, // 4 "4" E C
B01101101, // 5 "5" E C
B01111101, // 6 "6" DDD
B00000111, // 7 "7"
B01111111, // 8 "8"
B01101111, // 9 "9"
B01110111, // 65 'A'
B01111100, // 66 'b'
B00111001, // 67 'C'
B01011110, // 68 'd'
B01111001, // 69 'E'
B01110001, // 70 'F'
B00111101, // 71 'G'
B01110110, // 72 'H'
B00000110, // 73 'I'
B00001110, // 74 'J'
B01110110, // 75 'K' Same as 'H'
B00111000, // 76 'L'
B00000000, // 77 'M' NO DISPLAY
B01010100, // 78 'n'
B00111111, // 79 'O'
B01110011, // 80 'P'
B01100111, // 81 'q'
B01010000, // 82 'r'
B01101101, // 83 'S'
B01111000, // 84 't'
B00111110, // 85 'U'
B00111110, // 86 'V' Same as 'U'
B00000000, // 87 'W' NO DISPLAY
B01110110, // 88 'X' Same as 'H'
B01101110, // 89 'y'
B01011011, // 90 'Z' Same as '2'
B00000000, // 32 ' ' BLANK
B01000000, // 45 '-' DASH
B10000000, // 46 '.' PERIOD
B01100011, // 42 '*' DEGREE ..
};
// Constant pointers to constant data
const byte * const numeralCodes = digitCodeMap;
const byte * const alphaCodes = digitCodeMap + 10;
// SevSeg Constructor
/******************************************************************************/
SevSeg::SevSeg() {
// Initial value
ledOnTime = 2000; // Corresponds to a brightness of 100
waitOffTime = 0;
waitOffActive = false;
numDigits = 0;
prevUpdateIdx = 0;
prevUpdateTime = 0;
resOnSegments = 0;
updateWithDelays = 0;
}
// begin
/******************************************************************************/
// Saves the input pin numbers to the class and sets up the pins to be used.
// If you use current-limiting resistors on your segment pins instead of the
// digit pins, then set resOnSegments as true.
// Set updateWithDelays to true if you want to use the 'pre-2017' update method
// In that case, the processor is occupied with delay functions while refreshing
// leadingZerosIn indicates whether leading zeros should be displayed
// disableDecPoint is true when the decimal point segment is not connected, in
// which case there are only 7 segments.
void SevSeg::begin(byte hardwareConfig, byte numDigitsIn, byte digitPinsIn[],
byte segmentPinsIn[], bool resOnSegmentsIn,
bool updateWithDelaysIn, bool leadingZerosIn, bool disableDecPoint) {
resOnSegments = resOnSegmentsIn;
updateWithDelays = updateWithDelaysIn;
leadingZeros = leadingZerosIn;
numDigits = numDigitsIn;
numSegments = disableDecPoint ? 7 : 8; // Ternary 'if' statement
//Limit the max number of digits to prevent overflowing
if (numDigits > MAXNUMDIGITS) numDigits = MAXNUMDIGITS;
switch (hardwareConfig) {
case 0: // Common cathode
digitOnVal = LOW;
segmentOnVal = HIGH;
break;
case 1: // Common anode
digitOnVal = HIGH;
segmentOnVal = LOW;
break;
case 2: // With active-high, low-side switches (most commonly N-type FETs)
digitOnVal = HIGH;
segmentOnVal = HIGH;
break;
case 3: // With active low, high side switches (most commonly P-type FETs)
digitOnVal = LOW;
segmentOnVal = LOW;
break;
}
digitOffVal = !digitOnVal;
segmentOffVal = !segmentOnVal;
// Save the input pin numbers to library variables
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
segmentPins[segmentNum] = segmentPinsIn[segmentNum];
}
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitPins[digitNum] = digitPinsIn[digitNum];
}
// Set the pins as outputs, and turn them off
for (byte digit = 0 ; digit < numDigits ; digit++) {
pinMode(digitPins[digit], OUTPUT);
digitalWrite(digitPins[digit], digitOffVal);
}
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
pinMode(segmentPins[segmentNum], OUTPUT);
digitalWrite(segmentPins[segmentNum], segmentOffVal);
}
blank(); // Initialise the display
}
// refreshDisplay
/******************************************************************************/
// Turns on the segments specified in 'digitCodes[]'
// There are 4 versions of this function, with the choice depending on the
// location of the current-limiting resistors, and whether or not you wish to
// use 'update delays' (the standard method until 2017).
// For resistors on *digits* we will cycle through all 8 segments (7 + period),
// turning on the *digits* as appropriate for a given segment, before moving on
// to the next segment.
// For resistors on *segments* we will cycle through all __ # of digits,
// turning on the *segments* as appropriate for a given digit, before moving on
// to the next digit.
// If using update delays, refreshDisplay has a delay between each digit/segment
// as it cycles through. It exits with all LEDs off.
// If not using updateDelays, refreshDisplay exits with a single digit/segment
// on. It will move to the next digit/segment after being called again (if
// enough time has passed).
void SevSeg::refreshDisplay() {
if (!updateWithDelays) {
unsigned long us = micros();
// Exit if it's not time for the next display change
if (waitOffActive) {
if (us - prevUpdateTime < waitOffTime) return;
}
else {
if (us - prevUpdateTime < ledOnTime) return;
}
prevUpdateTime = us;
if (!resOnSegments) {
/**********************************************/
// RESISTORS ON DIGITS, UPDATE WITHOUT DELAYS
if (waitOffActive) {
waitOffActive = false;
}
else {
// Turn all lights off for the previous segment
segmentOff(prevUpdateIdx);
if (waitOffTime) {
// Wait a delay with all lights off
waitOffActive = true;
return;
}
}
prevUpdateIdx++;
if (prevUpdateIdx >= numSegments) prevUpdateIdx = 0;
// Illuminate the required digits for the new segment
segmentOn(prevUpdateIdx);
}
else {
/**********************************************/
// RESISTORS ON SEGMENTS, UPDATE WITHOUT DELAYS
if (waitOffActive) {
waitOffActive = false;
}
else {
// Turn all lights off for the previous digit
digitOff(prevUpdateIdx);
if (waitOffTime) {
// Wait a delay with all lights off
waitOffActive = true;
return;
}
}
prevUpdateIdx++;
if (prevUpdateIdx >= numDigits) prevUpdateIdx = 0;
// Illuminate the required segments for the new digit
digitOn(prevUpdateIdx);
}
}
else {
if (!resOnSegments) {
/**********************************************/
// RESISTORS ON DIGITS, UPDATE WITH DELAYS
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
// Illuminate the required digits for this segment
segmentOn(segmentNum);
// Wait with lights on (to increase brightness)
delayMicroseconds(ledOnTime);
// Turn all lights off
segmentOff(segmentNum);
// Wait with all lights off if required
if (waitOffTime) delayMicroseconds(waitOffTime);
}
}
else {
/**********************************************/
// RESISTORS ON SEGMENTS, UPDATE WITH DELAYS
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
// Illuminate the required segments for this digit
digitOn(digitNum);
// Wait with lights on (to increase brightness)
delayMicroseconds(ledOnTime);
// Turn all lights off
digitOff(digitNum);
// Wait with all lights off if required
if (waitOffTime) delayMicroseconds(waitOffTime);
}
}
}
}
// segmentOn
/******************************************************************************/
// Turns a segment on, as well as all corresponding digit pins
// (according to digitCodes[])
void SevSeg::segmentOn(byte segmentNum) {
digitalWrite(segmentPins[segmentNum], segmentOnVal);
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit
digitalWrite(digitPins[digitNum], digitOnVal);
}
}
}
// segmentOff
/******************************************************************************/
// Turns a segment off, as well as all digit pins
void SevSeg::segmentOff(byte segmentNum) {
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitalWrite(digitPins[digitNum], digitOffVal);
}
digitalWrite(segmentPins[segmentNum], segmentOffVal);
}
// digitOn
/******************************************************************************/
// Turns a digit on, as well as all corresponding segment pins
// (according to digitCodes[])
void SevSeg::digitOn(byte digitNum) {
digitalWrite(digitPins[digitNum], digitOnVal);
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit
digitalWrite(segmentPins[segmentNum], segmentOnVal);
}
}
}
// digitOff
/******************************************************************************/
// Turns a digit off, as well as all segment pins
void SevSeg::digitOff(byte digitNum) {
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
digitalWrite(segmentPins[segmentNum], segmentOffVal);
}
digitalWrite(digitPins[digitNum], digitOffVal);
}
// setBrightness
/******************************************************************************/
// Sets ledOnTime according to the brightness given. Standard brightness range
// is 0 to 100. Flickering is more likely at brightness > 100, and < -100.
// A positive brightness introduces a delay while the LEDs are on, and a
// negative brightness introduces a delay while the LEDs are off.
void SevSeg::setBrightness(int brightness) {
brightness = constrain(brightness, -200, 200);
if (brightness > 0) {
ledOnTime = map(brightness, 0, 100, 1, 2000);
waitOffTime = 0;
waitOffActive = false;
}
else {
ledOnTime = 0;
waitOffTime = map(brightness, 0, -100, 1, 2000);
}
}
// setNumber
/******************************************************************************/
// This function only receives the input and passes it to 'setNewNum'.
// It is overloaded for all number data types, so that floats can be handled
// correctly.
void SevSeg::setNumber(long numToShow, char decPlaces, bool hex) { //long
setNewNum(numToShow, decPlaces, hex);
}
void SevSeg::setNumber(unsigned long numToShow, char decPlaces, bool hex) { //unsigned long
setNewNum(numToShow, decPlaces, hex);
}
void SevSeg::setNumber(int numToShow, char decPlaces, bool hex) { //int
setNewNum(numToShow, decPlaces, hex);
}
void SevSeg::setNumber(unsigned int numToShow, char decPlaces, bool hex) { //unsigned int
setNewNum(numToShow, decPlaces, hex);
}
void SevSeg::setNumber(char numToShow, char decPlaces, bool hex) { //char
setNewNum(numToShow, decPlaces, hex);
}
void SevSeg::setNumber(byte numToShow, char decPlaces, bool hex) { //byte
setNewNum(numToShow, decPlaces, hex);
}
void SevSeg::setNumber(float numToShow, char decPlaces, bool hex) { //float
char decPlacesPos = constrain(decPlaces, 0, MAXNUMDIGITS);
if (hex) {
numToShow = numToShow * powersOf16[decPlacesPos];
}
else {
numToShow = numToShow * powersOf10[decPlacesPos];
}
// Modify the number so that it is rounded to an integer correctly
numToShow += (numToShow >= 0) ? 0.5f : -0.5f;
setNewNum(numToShow, decPlaces, hex);
}
// setNewNum
/******************************************************************************/
// Changes the number that will be displayed.
void SevSeg::setNewNum(long numToShow, char decPlaces, bool hex) {
byte digits[numDigits];
findDigits(numToShow, decPlaces, hex, digits);
setDigitCodes(digits, decPlaces);
}
// setSegments
/******************************************************************************/
// Sets the 'digitCodes' that are required to display the desired segments.
// Using this function, one can display any arbitrary set of segments (like
// letters, symbols or animated cursors). See setDigitCodes() for common
// numeric examples.
//
// Bit-segment mapping: 0bHGFEDCBA
// Visual mapping:
// AAAA 0000
// F B 5 1
// F B 5 1
// GGGG 6666
// E C 4 2
// E C 4 2 (Segment H is often called
// DDDD H 3333 7 DP, for Decimal Point)
void SevSeg::setSegments(byte segs[]) {
for (byte digit = 0; digit < numDigits; digit++) {
digitCodes[digit] = segs[digit];
}
}
// setChars
/******************************************************************************/
// Displays the string on the display, as best as possible.
// Only alphanumeric characters plus '-' and ' ' are supported
void SevSeg::setChars(char str[]) {
for (byte digit = 0; digit < numDigits; digit++) {
digitCodes[digit] = 0;
}
byte strIdx = 0; // Current position within str[]
for (byte digitNum = 0; digitNum < numDigits; digitNum++) {
char ch = str[strIdx];
if (ch == '\0') break; // NULL string terminator
if (ch >= '0' && ch <= '9') { // Numerical
digitCodes[digitNum] = numeralCodes[ch - '0'];
}
else if (ch >= 'A' && ch <= 'Z') {
digitCodes[digitNum] = alphaCodes[ch - 'A'];
}
else if (ch >= 'a' && ch <= 'z') {
digitCodes[digitNum] = alphaCodes[ch - 'a'];
}
else if (ch == ' ') {
digitCodes[digitNum] = digitCodeMap[BLANK_IDX];
}
else if (ch == '.') {
digitCodes[digitNum] = digitCodeMap[PERIOD_IDX];
}
else if (ch == '*') {
digitCodes[digitNum] = digitCodeMap[ASTERISK_IDX];
}
else {
// Every unknown character is shown as a dash
digitCodes[digitNum] = digitCodeMap[DASH_IDX];
}
strIdx++;
// Peek at next character. It it's a period, add it to this digit
if (str[strIdx] == '.') {
digitCodes[digitNum] |= digitCodeMap[PERIOD_IDX];
strIdx++;
}
}
}
// blank
/******************************************************************************/
void SevSeg::blank(void) {
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitCodes[digitNum] = digitCodeMap[BLANK_IDX];
}
segmentOff(0);
digitOff(0);
}
// findDigits
/******************************************************************************/
// Decides what each digit will display.
// Enforces the upper and lower limits on the number to be displayed.
void SevSeg::findDigits(long numToShow, char decPlaces, bool hex, byte digits[]) {
const long * powersOfBase = hex ? powersOf16 : powersOf10;
const long maxNum = powersOfBase[numDigits] - 1;
const long minNum = -(powersOfBase[numDigits - 1] - 1);
// If the number is out of range, just display dashes
if (numToShow > maxNum || numToShow < minNum) {
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digits[digitNum] = DASH_IDX;
}
}
else {
byte digitNum = 0;
// Convert all number to positive values
if (numToShow < 0) {
digits[0] = DASH_IDX;
digitNum = 1; // Skip the first iteration
numToShow = -numToShow;
}
// Find all digits for base's representation, starting with the most
// significant digit
for ( ; digitNum < numDigits ; digitNum++) {
long factor = powersOfBase[numDigits - 1 - digitNum];
digits[digitNum] = numToShow / factor;
numToShow -= digits[digitNum] * factor;
}
// Find unnnecessary leading zeros and set them to BLANK
if (decPlaces < 0) decPlaces = 0;
if (!leadingZeros) {
for (digitNum = 0 ; digitNum < (numDigits - 1 - decPlaces) ; digitNum++) {
if (digits[digitNum] == 0) {
digits[digitNum] = BLANK_IDX;
}
// Exit once the first non-zero number is encountered
else if (digits[digitNum] <= 9) {
break;
}
}
}
}
}
// setDigitCodes
/******************************************************************************/
// Sets the 'digitCodes' that are required to display the input numbers
void SevSeg::setDigitCodes(byte digits[], char decPlaces) {
// Set the digitCode for each digit in the display
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitCodes[digitNum] = digitCodeMap[digits[digitNum]];
// Set the decimal point segment
if (decPlaces >= 0) {
if (digitNum == numDigits - 1 - decPlaces) {
digitCodes[digitNum] |= digitCodeMap[PERIOD_IDX];
}
}
}
}
/// END ///

95
dependencies/SevSeg/SevSeg.h

@ -0,0 +1,95 @@
/* SevSeg Library
*
* Copyright 2017 Dean Reading
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* This library allows an Arduino to easily display numbers and letters on a
* 7-segment display without a separate 7-segment display controller.
*
* Direct any questions or suggestions to deanreading@hotmail.com
* See the included readme for instructions.
* https://github.com/DeanIsMe/SevSeg
*/
#ifndef MAXNUMDIGITS
#define MAXNUMDIGITS 8 // Can be increased, but the max number is 2^31
#endif
#ifndef SevSeg_h
#define SevSeg_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// Use defines to link the hardware configurations to the correct numbers
#define COMMON_CATHODE 0
#define COMMON_ANODE 1
#define N_TRANSISTORS 2
#define P_TRANSISTORS 3
#define NP_COMMON_CATHODE 1
#define NP_COMMON_ANODE 0
class SevSeg
{
public:
SevSeg();
void refreshDisplay();
void begin(byte hardwareConfig, byte numDigitsIn, byte digitPinsIn[],
byte segmentPinsIn[], bool resOnSegmentsIn=0,
bool updateWithDelaysIn=0, bool leadingZerosIn=0,
bool disableDecPoint=0);
void setBrightness(int brightnessIn); // A number from 0..100
void setNumber(long numToShow, char decPlaces=-1, bool hex=0);
void setNumber(unsigned long numToShow, char decPlaces=-1, bool hex=0);
void setNumber(int numToShow, char decPlaces=-1, bool hex=0);
void setNumber(unsigned int numToShow, char decPlaces=-1, bool hex=0);
void setNumber(char numToShow, char decPlaces=-1, bool hex=0);
void setNumber(byte numToShow, char decPlaces=-1, bool hex=0);
void setNumber(float numToShow, char decPlaces=-1, bool hex=0);
void setSegments(byte segs[]);
void setChars(char str[]);
void blank(void);
private:
void setNewNum(long numToShow, char decPlaces, bool hex=0);
void findDigits(long numToShow, char decPlaces, bool hex, byte digits[]);
void setDigitCodes(byte nums[], char decPlaces);
void segmentOn(byte segmentNum);
void segmentOff(byte segmentNum);
void digitOn(byte digitNum);
void digitOff(byte digitNum);
bool digitOnVal,digitOffVal,segmentOnVal,segmentOffVal;
bool resOnSegments, updateWithDelays, leadingZeros;
byte digitPins[MAXNUMDIGITS];
byte segmentPins[8];
byte numDigits;
byte numSegments;
byte prevUpdateIdx; // The previously updated segment or digit
byte digitCodes[MAXNUMDIGITS]; // The active setting of each segment of each digit
unsigned long prevUpdateTime; // The time (millis()) when the display was last updated
int ledOnTime; // The time (us) to wait with LEDs on
int waitOffTime; // The time (us) to wait with LEDs off
bool waitOffActive; // Whether the program is waiting with LEDs off
};
#endif //SevSeg_h
/// END ///

27
tests/test_display/test_display.ino

@ -0,0 +1,27 @@
/*
* Simple code to test the display function and electrical connections.
*/
#include <SevSeg.h>
//Instantiates a seven segment object
SevSeg sevseg;
void setup() {
byte numDigits = 4;
byte digitPins[] = {14, 17, 18, 12};
byte segmentPins[] = {15, 19, 7, 9, 6, 16, 8};
bool resistorsOnSegments = false;
byte hardwareConfig = COMMON_CATHODE;
bool updateWithDelays = false;
bool leadingZeros = false;
bool disableDecPoint = true;
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
updateWithDelays, leadingZeros, disableDecPoint);
}
void loop() {
sevseg.setNumber(555,0); // Displays '3.141'
sevseg.refreshDisplay();
sevseg.setBrightness(100);
}

97
todoFindCoolNameForProject/todoFindCoolNameForProject.ino

@ -0,0 +1,97 @@
/*
* TODO: write something here
*/
#include <SevSeg.h>
#include "DHT.h"
// Digital pin connected to the DHT sensor
#define DHTPIN 2
#define DHTTYPE DHT11 // DHT 11
#define BUFFER_SIZE 24
#define LOW_TEMP_LED_PIN 3
#define HIGH_TEMP_LED_PIN 4
#define RELAY_PIN 5
#define LOW_TEMP 28
#define HIGH_TEMP 28
// Initializes DHT sensor.
DHT dht(DHTPIN, DHTTYPE);
int temperatureReadingsCounter;
float temperatures[BUFFER_SIZE];
void setup() {
Serial.begin(9600);
Serial.println("Running setup function");
dht.begin();
temperatureReadingsCounter = 0;
pinMode(LOW_TEMP_LED_PIN, OUTPUT);
pinMode(HIGH_TEMP_LED_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
}
void loop() {
float lastTemperature = getNewTemp();
if (lastTemperature >= HIGH_TEMP) {
// Turns red led and relay on
digitalWrite(HIGH_TEMP_LED_PIN, HIGH);
digitalWrite(RELAY_PIN, HIGH);
// Turns blue led off
digitalWrite(LOW_TEMP_LED_PIN, LOW);
} else if (lastTemperature < LOW_TEMP) {
// Turns blue led on
digitalWrite(LOW_TEMP_LED_PIN, HIGH);
// Turns red led off
digitalWrite(HIGH_TEMP_LED_PIN, LOW);
digitalWrite(RELAY_PIN, LOW);
} else {
// Turns red led off
digitalWrite(LOW_TEMP_LED_PIN, LOW);
// Turns blue led off
digitalWrite(HIGH_TEMP_LED_PIN, LOW);
digitalWrite(RELAY_PIN, LOW);
}
if (temperatureReadingsCounter == BUFFER_SIZE) {
float avgTemp = calcAverageTempAndReset(temperatures);
Serial.println(avgTemp);
temperatureReadingsCounter = 0;
}
// Wait a few seconds between measurements.
Serial.println(temperatureReadingsCounter);
delay(1000);
}
float getNewTemp(){
// Reads temperature as Celsius (the default)
float t = dht.readTemperature();
// Checks if the read failed and handles the failure
if (isnan(t)) {
Serial.print(F("Failed to read from DHT sensor!"));
return;
}
for (int i = BUFFER_SIZE - 1; i>0; i--) {
temperatures[i] = temperatures[i-1];
}
temperatures[0] = t;
++temperatureReadingsCounter;
Serial.print(F("Temperature: "));
Serial.print(t);
Serial.println(F("°C "));
return t;
}
float calcAverageTempAndReset(float *array) {
float sum = 0 ; // sum will be larger than an item, float for safety.
for (int i = 0; i<BUFFER_SIZE; i++){
sum += array[i];
}
return sum / BUFFER_SIZE ; // average will be fractional
}
Loading…
Cancel
Save