Merge branch 'master' into development
Conflicts: .gitignore libraries/MySensors/MyGateway.cpp libraries/MySensors/MyMQTT.cpp libraries/MySensors/MyMQTT.h libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino
This commit is contained in:
@@ -81,7 +81,8 @@ http://forum.mysensors.org/topic/303/mqtt-broker-gateway
|
||||
#define RADIO_SPI_SS_PIN 8 // radio SPI serial select
|
||||
#define RADIO_ERROR_LED_PIN A2 // Error led pin
|
||||
#define RADIO_RX_LED_PIN A1 // Receive led pin
|
||||
#define RADIO_TX_LED_PIN A0 // the PCB, on board LED*/
|
||||
#define RADIO_TX_LED_PIN A0 // the PCB, on board LED
|
||||
*/
|
||||
|
||||
// * Use this for default configured pro mini / nano etc :
|
||||
///*
|
||||
@@ -94,7 +95,7 @@ http://forum.mysensors.org/topic/303/mqtt-broker-gateway
|
||||
|
||||
#define TCP_PORT 1883 // Set your MQTT Broker Listening port.
|
||||
IPAddress TCP_IP ( 192, 168, 0, 234 ); // Configure your static ip-address here
|
||||
uint8_t TCP_MAC[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 }; // Mac-address - You should change this! see note *2 above!
|
||||
byte TCP_MAC[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 }; // Mac-address - You should change this! see note *2 above!
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -115,6 +116,7 @@ MySensor gw(transport, hw /*, signer*/);
|
||||
|
||||
|
||||
EthernetServer server = EthernetServer(TCP_PORT);
|
||||
EthernetClient *currentClient = NULL;
|
||||
MyMessage msg;
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
char broker[] PROGMEM = MQTT_BROKER_PREFIX;
|
||||
@@ -137,26 +139,44 @@ void writeEthernet(const char *writeBuffer, uint8_t *writeSize) {
|
||||
|
||||
|
||||
void processEthernetMessages() {
|
||||
char inputString[MQTT_MAX_PACKET_SIZE] = "";
|
||||
uint8_t inputSize = 0;
|
||||
EthernetClient client = server.available();
|
||||
if (client) {
|
||||
while (client.available()) {
|
||||
char inChar = client.read();
|
||||
inputString[inputSize] = inChar;
|
||||
inputSize++;
|
||||
}
|
||||
char inputString[MQTT_MAX_PACKET_SIZE] = "";
|
||||
byte inputSize = 0;
|
||||
byte readCnt = 0;
|
||||
byte length = 0;
|
||||
|
||||
EthernetClient client = server.available();
|
||||
if (client) {
|
||||
while (client.available()) {
|
||||
// Save the current client we are talking with
|
||||
currentClient = &client;
|
||||
byte inByte = client.read();
|
||||
readCnt++;
|
||||
|
||||
if (inputSize < MQTT_MAX_PACKET_SIZE) {
|
||||
inputString[inputSize] = (char)inByte;
|
||||
inputSize++;
|
||||
}
|
||||
|
||||
if (readCnt == 2) {
|
||||
length = (inByte & 127) * 1;
|
||||
}
|
||||
if (readCnt == (length+2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef TCPDUMP
|
||||
Serial.print("<<");
|
||||
char buf[4];
|
||||
for (uint8_t a=0; a<inputSize; a++) { sprintf(buf,"%02X ", (uint8_t)inputString[a]); Serial.print(buf); } Serial.println("");
|
||||
Serial.print("<<");
|
||||
char buf[4];
|
||||
for (byte a=0; a<inputSize; a++) { sprintf(buf, "%02X ", (byte)inputString[a]); Serial.print(buf); } Serial.println();
|
||||
#endif
|
||||
processMQTTMessage(inputString, inputSize);
|
||||
}
|
||||
processMQTTMessage(inputString, inputSize);
|
||||
currentClient = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void incomingMessage(const MyMessage &message) {
|
||||
rxBlink(1);
|
||||
sendMQTT(message);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Default sensor sketch for MySensor Micro module
|
||||
// Act as a temperature / humidity sensor by default.
|
||||
//
|
||||
// If A1 is held low while powering on, it will clear eeprom (and thereby the stored nodeid)
|
||||
// If A0 is held low while powering on, it will enter testmode, which verifies all on-board peripherals
|
||||
//
|
||||
// Battery voltage is repported as child sensorId 199, as well as battery percentage
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
#include <Wire.h>
|
||||
#include <SI7021.h>
|
||||
#include <SPI.h>
|
||||
#include <SPIFlash.h>
|
||||
#include <EEPROM.h>
|
||||
#include <sha204_lib_return_codes.h>
|
||||
#include <sha204_library.h>
|
||||
|
||||
// Define a static node address, remove if you want auto address assignment
|
||||
//#define NODE_ADDRESS 3
|
||||
@@ -20,13 +23,26 @@
|
||||
#define CHILD_ID_HUM 2
|
||||
#define CHILD_ID_BATT 199
|
||||
|
||||
//Pin definitions
|
||||
#define RESET_CFG_PIN A1
|
||||
#define LED_PIN A2
|
||||
|
||||
// How many milli seconds between each measurement
|
||||
#define MEASURE_INTERVAL 60000
|
||||
|
||||
// FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller
|
||||
#define FORCE_TRANSMIT_INTERVAL 30
|
||||
|
||||
// When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes.
|
||||
// Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement
|
||||
|
||||
//Pin definitions
|
||||
#define TEST_PIN A0
|
||||
#define LED_PIN A2
|
||||
#define ATSHA204_PIN 17 // A3
|
||||
|
||||
const int sha204Pin = ATSHA204_PIN;
|
||||
atsha204Class sha204(sha204Pin);
|
||||
|
||||
SI7021 humiditySensor;
|
||||
SPIFlash flash(8, 0x1F65);
|
||||
|
||||
MySensor gw;
|
||||
|
||||
// Sensor messages
|
||||
@@ -45,16 +61,17 @@ long lastBattery = -100;
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
// First check if we should boot into clear eeprom mode
|
||||
pinMode(RESET_CFG_PIN, INPUT);
|
||||
digitalWrite(RESET_CFG_PIN, HIGH); // Enable pullup
|
||||
if (!digitalRead(RESET_CFG_PIN)) resetEEP();
|
||||
digitalWrite(RESET_CFG_PIN, LOW);
|
||||
Serial.begin(115200);
|
||||
// First check if we should boot into test mode
|
||||
|
||||
pinMode(TEST_PIN,INPUT);
|
||||
digitalWrite(TEST_PIN, HIGH); // Enable pullup
|
||||
if (!digitalRead(TEST_PIN)) testMode();
|
||||
|
||||
digitalWrite(TEST_PIN,LOW);
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
|
||||
#ifdef NODE_ADDRESS
|
||||
@@ -67,12 +84,13 @@ void setup() {
|
||||
|
||||
humiditySensor.begin();
|
||||
|
||||
gw.sendSketchInfo("EnvironmentSensor", "1.0");
|
||||
gw.sendSketchInfo("MysensorMicro", "1.0");
|
||||
|
||||
gw.present(CHILD_ID_TEMP,S_TEMP);
|
||||
gw.present(CHILD_ID_HUM,S_HUM);
|
||||
|
||||
gw.present(CHILD_ID_BATT, S_POWER);
|
||||
switchClock(1<<CLKPS2); // Switch to 1Mhz for the reminder of the sketch, save power.
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +99,8 @@ void loop() {
|
||||
measureCount ++;
|
||||
bool forceTransmit = false;
|
||||
|
||||
if (measureCount > 30) {// Every 60th time we wake up, force a transmission on all sensors.
|
||||
if (measureCount > FORCE_TRANSMIT_INTERVAL
|
||||
) { // force a transmission
|
||||
forceTransmit = true;
|
||||
measureCount = 0;
|
||||
}
|
||||
@@ -106,23 +125,19 @@ void sendTempHumidityMeasurements(bool force)
|
||||
lastTemperature = -100;
|
||||
}
|
||||
|
||||
float temperature = humiditySensor.getCelsiusHundredths()/10;
|
||||
si7021_env data = humiditySensor.getHumidityAndTemperature();
|
||||
|
||||
temperature = temperature / 10;
|
||||
|
||||
int humidity = humiditySensor.getHumidityPercent();
|
||||
float temperature = data.celsiusHundredths/100;
|
||||
|
||||
int humidity = data.humidityPercent;
|
||||
|
||||
if (lastTemperature != temperature) {
|
||||
gw.send(msgTemp.set(temperature,1));
|
||||
lastTemperature = temperature;
|
||||
Serial.print("temperature ");
|
||||
Serial.println(temperature);
|
||||
}
|
||||
if (lastHumidity != humidity) {
|
||||
gw.send(msgHum.set(humidity));
|
||||
lastHumidity = humidity;
|
||||
Serial.print("Humidity ");
|
||||
Serial.println(humidity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +170,7 @@ long readVcc() {
|
||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0);
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
ADcdMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
|
||||
#endif
|
||||
@@ -173,19 +188,110 @@ long readVcc() {
|
||||
return result; // Vcc in millivolts
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resets eeprom to default value (while blinking LED_PIN)
|
||||
*/
|
||||
void resetEEP()
|
||||
void switchClock(unsigned char clk)
|
||||
{
|
||||
for (int i=0;i<512;i++) {
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
delay(100);
|
||||
EEPROM.write(i, 0xff);
|
||||
}
|
||||
cli();
|
||||
|
||||
CLKPR = 1<<CLKPCE; // Set CLKPCE to enable clk switching
|
||||
CLKPR = clk;
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
// Verify all peripherals, and signal via the LED if any problems.
|
||||
void testMode()
|
||||
{
|
||||
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
|
||||
uint8_t ret_code;
|
||||
byte tests = 0;
|
||||
|
||||
digitalWrite(LED_PIN, HIGH); // Turn on LED.
|
||||
|
||||
Serial.println(F("Testing peripherals!"));
|
||||
Serial.flush();
|
||||
Serial.print(F("-> SI7021 : "));
|
||||
Serial.flush();
|
||||
|
||||
if (humiditySensor.begin())
|
||||
{
|
||||
Serial.println(F("ok!"));
|
||||
tests ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("failed!"));
|
||||
}
|
||||
Serial.flush();
|
||||
|
||||
Serial.print(F("-> Flash : "));
|
||||
Serial.flush();
|
||||
if (flash.initialize())
|
||||
{
|
||||
Serial.println(F("ok!"));
|
||||
tests ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("failed!"));
|
||||
}
|
||||
Serial.flush();
|
||||
|
||||
|
||||
Serial.print(F("-> SHA204 : "));
|
||||
ret_code = sha204.sha204c_wakeup(rx_buffer);
|
||||
Serial.flush();
|
||||
if (ret_code != SHA204_SUCCESS)
|
||||
{
|
||||
Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
|
||||
}
|
||||
Serial.flush();
|
||||
if (ret_code == SHA204_SUCCESS)
|
||||
{
|
||||
ret_code = sha204.getSerialNumber(rx_buffer);
|
||||
if (ret_code != SHA204_SUCCESS)
|
||||
{
|
||||
Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("Ok (serial : "));
|
||||
for (int i=0; i<9; i++)
|
||||
{
|
||||
if (rx_buffer[i] < 0x10)
|
||||
{
|
||||
Serial.print('0'); // Because Serial.print does not 0-pad HEX
|
||||
}
|
||||
Serial.print(rx_buffer[i], HEX);
|
||||
}
|
||||
Serial.println(")");
|
||||
tests ++;
|
||||
}
|
||||
|
||||
}
|
||||
Serial.flush();
|
||||
|
||||
Serial.println(F("Test finished"));
|
||||
|
||||
if (tests == 3)
|
||||
{
|
||||
Serial.println(F("Selftest ok!"));
|
||||
while (1) // Blink OK pattern!
|
||||
{
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
delay(800);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
delay(200);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("----> Selftest failed!"));
|
||||
while (1) // Blink FAILED pattern! Rappidly blinking..
|
||||
{
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
/*
|
||||
Vera Arduino UVM-30A
|
||||
Arduino UVM-30A
|
||||
|
||||
connect the sensor as follows :
|
||||
|
||||
@@ -7,44 +9,55 @@
|
||||
- >>> GND
|
||||
out >>> A0
|
||||
|
||||
Contribution: epierre, bulldoglowell
|
||||
Converted to 1.4 by Henrik Ekblad
|
||||
Contribution: epierre, bulldoglowell, gizmocuz
|
||||
|
||||
Index table taken from: http://www.elecrow.com/sensors-c-111/environment-c-111_112/uv-sensor-moduleuvm30a-p-716.html
|
||||
Because this table is pretty lineair, we can calculate a UVI with one decimal
|
||||
|
||||
License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
|
||||
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define CHILD_ID_UV 0
|
||||
#define UV_SENSOR_ANALOG_PIN 0
|
||||
|
||||
#define CHILD_ID_UV 0
|
||||
|
||||
unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds)
|
||||
|
||||
MySensor gw;
|
||||
MyMessage uvMsg(CHILD_ID_UV, V_UV);
|
||||
int lastUV = -1;
|
||||
int uvIndexValue [13] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170, 3000};
|
||||
int uvIndex;
|
||||
|
||||
unsigned long lastSend =0;
|
||||
float uvIndex;
|
||||
float lastUV = -1;
|
||||
int uvIndexValue [12] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170};
|
||||
|
||||
void setup()
|
||||
{
|
||||
gw.begin();
|
||||
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("UV Sensor", "1.1");
|
||||
gw.sendSketchInfo("UV Sensor", "1.2");
|
||||
|
||||
// Register all sensors to gateway (they will be created as child devices)
|
||||
gw.present(CHILD_ID_UV, S_UV);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t uv = analogRead(0);// Get UV value
|
||||
Serial.print("Uv reading: ");
|
||||
Serial.println(uv);
|
||||
for (int i = 0; i < 13; i++)
|
||||
{
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
uint16_t uv = analogRead(UV_SENSOR_ANALOG_PIN);// Get UV value
|
||||
if (uv>1170)
|
||||
uv=1170;
|
||||
|
||||
//Serial.print("UV Analog reading: ");
|
||||
//Serial.println(uv);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
if (uv <= uvIndexValue[i])
|
||||
{
|
||||
@@ -52,11 +65,21 @@ void loop()
|
||||
break;
|
||||
}
|
||||
}
|
||||
Serial.print("Uv index: ");
|
||||
Serial.println(uvIndex);
|
||||
|
||||
//calculate 1 decimal if possible
|
||||
if (i>0) {
|
||||
float vRange=uvIndexValue[i]-uvIndexValue[i-1];
|
||||
float vCalc=uv-uvIndexValue[i-1];
|
||||
uvIndex+=(1.0/vRange)*vCalc-1.0;
|
||||
}
|
||||
|
||||
if (uvIndex != lastUV) {
|
||||
gw.send(uvMsg.set(uvIndex));
|
||||
//Serial.print("UVI: ");
|
||||
//Serial.println(uvIndex,2);
|
||||
|
||||
//Send value to gateway if changed, or at least every 5 minutes
|
||||
if ((uvIndex != lastUV)||(currentTime-lastSend >= 5*60*1000)) {
|
||||
lastSend=currentTime;
|
||||
gw.send(uvMsg.set(uvIndex,2));
|
||||
lastUV = uvIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,23 @@
|
||||
#include <MySensor.h>
|
||||
|
||||
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!)
|
||||
#define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
|
||||
|
||||
#define PULSE_FACTOR 1000 // Nummber of blinks per m3 of your meter (One rotation/liter)
|
||||
|
||||
#define SLEEP_MODE false // flowvalue can only be reported when sleep mode is false.
|
||||
#define MAX_FLOW 40 // Max flow (l/min) value to report. This filetrs outliers.
|
||||
#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
|
||||
#define CHILD_ID 5 // Id of the sensor child
|
||||
|
||||
#define MAX_FLOW 40 // Max flow (l/min) value to report. This filters outliers.
|
||||
|
||||
#define CHILD_ID 1 // Id of the sensor child
|
||||
|
||||
unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
|
||||
|
||||
MySensor gw;
|
||||
|
||||
MyMessage flowMsg(CHILD_ID,V_FLOW);
|
||||
MyMessage volumeMsg(CHILD_ID,V_VOLUME);
|
||||
MyMessage lastCounterMsg(CHILD_ID,V_VAR1);
|
||||
|
||||
double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter
|
||||
|
||||
volatile unsigned long pulseCount = 0;
|
||||
@@ -31,108 +39,119 @@ boolean pcReceived = false;
|
||||
unsigned long oldPulseCount = 0;
|
||||
unsigned long newBlink = 0;
|
||||
double oldflow = 0;
|
||||
double volume;
|
||||
double oldvolume;
|
||||
unsigned long lastSend;
|
||||
unsigned long lastPulse;
|
||||
unsigned long currentTime;
|
||||
boolean metric;
|
||||
MyMessage flowMsg(CHILD_ID,V_FLOW);
|
||||
MyMessage volumeMsg(CHILD_ID,V_VOLUME);
|
||||
MyMessage pcMsg(CHILD_ID,V_VAR1);
|
||||
|
||||
double volume =0;
|
||||
double oldvolume =0;
|
||||
unsigned long lastSend =0;
|
||||
unsigned long lastPulse =0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
gw.begin(incomingMessage);
|
||||
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Water Meter", "1.0");
|
||||
gw.sendSketchInfo("Water Meter", "1.2");
|
||||
|
||||
// Register this device as Waterflow sensor
|
||||
gw.present(CHILD_ID, S_WATER);
|
||||
|
||||
pulseCount = oldPulseCount = 0;
|
||||
|
||||
// Fetch last known pulse count value from gw
|
||||
gw.request(CHILD_ID, V_VAR1);
|
||||
|
||||
attachInterrupt(INTERRUPT, onPulse, RISING);
|
||||
lastSend = millis();
|
||||
lastSend = lastPulse = millis();
|
||||
|
||||
attachInterrupt(SENSOR_INTERRUPT, onPulse, RISING);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
gw.process();
|
||||
currentTime = millis();
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// Only send values at a maximum frequency or woken up from sleep
|
||||
bool sendTime = currentTime - lastSend > SEND_FREQUENCY;
|
||||
if (pcReceived && (SLEEP_MODE || sendTime)) {
|
||||
// New flow value has been calculated
|
||||
if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY))
|
||||
{
|
||||
lastSend=currentTime;
|
||||
|
||||
if (!pcReceived) {
|
||||
//Last Pulsecount not yet received from controller, request it again
|
||||
gw.request(CHILD_ID, V_VAR1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SLEEP_MODE && flow != oldflow) {
|
||||
oldflow = flow;
|
||||
|
||||
Serial.print("l/min:");
|
||||
Serial.println(flow);
|
||||
|
||||
// Check that we dont get unresonable large flow value.
|
||||
// could hapen when long wraps or false interrupt triggered
|
||||
if (flow<((unsigned long)MAX_FLOW)) {
|
||||
gw.send(flowMsg.set(flow, 2)); // Send flow value to gw
|
||||
}
|
||||
//Serial.print("l/min:");
|
||||
//Serial.println(flow);
|
||||
oldflow = flow;
|
||||
}
|
||||
|
||||
// No Pulse count in 2min
|
||||
// No Pulse count received in 2min
|
||||
if(currentTime - lastPulse > 120000){
|
||||
flow = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Pulse count has changed
|
||||
if (pulseCount != oldPulseCount) {
|
||||
gw.send(pcMsg.set(pulseCount)); // Send volumevalue to gw VAR1
|
||||
double volume = ((double)pulseCount/((double)PULSE_FACTOR));
|
||||
oldPulseCount = pulseCount;
|
||||
|
||||
Serial.print("pulsecount:");
|
||||
Serial.println(pulseCount);
|
||||
|
||||
gw.send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1
|
||||
|
||||
double volume = ((double)pulseCount/((double)PULSE_FACTOR));
|
||||
if (volume != oldvolume) {
|
||||
gw.send(volumeMsg.set(volume, 3)); // Send volume value to gw
|
||||
oldvolume = volume;
|
||||
|
||||
Serial.print("volume:");
|
||||
Serial.println(volume, 3);
|
||||
|
||||
gw.send(volumeMsg.set(volume, 3)); // Send volume value to gw
|
||||
}
|
||||
}
|
||||
lastSend = currentTime;
|
||||
} else if (sendTime && !pcReceived) {
|
||||
// No count received. Try requesting it again
|
||||
gw.request(CHILD_ID, V_VAR1);
|
||||
lastSend=currentTime;
|
||||
}
|
||||
|
||||
if (SLEEP_MODE) {
|
||||
gw.sleep(SEND_FREQUENCY);
|
||||
}
|
||||
}
|
||||
|
||||
void incomingMessage(const MyMessage &message) {
|
||||
if (message.type==V_VAR1) {
|
||||
pulseCount = oldPulseCount = message.getLong();
|
||||
if (message.type==V_VAR1) {
|
||||
unsigned long gwPulseCount=message.getULong();
|
||||
pulseCount += gwPulseCount;
|
||||
Serial.print("Received last pulse count from gw:");
|
||||
Serial.println(pulseCount);
|
||||
pcReceived = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void onPulse()
|
||||
{
|
||||
if (!SLEEP_MODE) {
|
||||
{
|
||||
if (!SLEEP_MODE)
|
||||
{
|
||||
unsigned long newBlink = micros();
|
||||
unsigned long interval = newBlink-lastBlink;
|
||||
lastPulse = millis();
|
||||
if (interval<500000L) {
|
||||
// Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min)
|
||||
return;
|
||||
|
||||
if (interval!=0)
|
||||
{
|
||||
lastPulse = millis();
|
||||
if (interval<500000L) {
|
||||
// Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min)
|
||||
return;
|
||||
}
|
||||
flow = (60000000.0 /interval) / ppl;
|
||||
}
|
||||
flow = (60000000.0 /interval) / ppl;
|
||||
lastBlink = newBlink;
|
||||
}
|
||||
pulseCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ void SI7021::setHeater(bool on) {
|
||||
// get humidity, then get temperature reading from humidity measurement
|
||||
struct si7021_env SI7021::getHumidityAndTemperature() {
|
||||
si7021_env ret = {0, 0, 0};
|
||||
ret.humidityBasisPoints = getHumidityBasisPoints();
|
||||
ret.humidityPercent = getHumidityPercent();
|
||||
ret.celsiusHundredths = _getCelsiusPostHumidity();
|
||||
ret.fahrenheitHundredths = (1.8 * ret.celsiusHundredths) + 3200;
|
||||
return ret;
|
||||
|
||||
@@ -23,7 +23,7 @@ This program is licensed under the GNU GPL v2
|
||||
typedef struct si7021_env {
|
||||
int celsiusHundredths;
|
||||
int fahrenheitHundredths;
|
||||
unsigned int humidityBasisPoints;
|
||||
unsigned int humidityPercent;
|
||||
} si7021_env;
|
||||
|
||||
class SI7021
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
* Minimal modifications should allow chips that have different page size but modifications
|
||||
* DEPENDS ON: Arduino SPI library
|
||||
*
|
||||
* Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
|
||||
* Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
@@ -32,15 +35,22 @@ SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) {
|
||||
|
||||
/// Select the flash chip
|
||||
void SPIFlash::select() {
|
||||
noInterrupts();
|
||||
//save current SPI settings
|
||||
#ifndef SPI_HAS_TRANSACTION
|
||||
_SREG = SREG;
|
||||
noInterrupts();
|
||||
#endif
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
//set FLASH chip SPI settings
|
||||
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
SPI.beginTransaction(_settings);
|
||||
#else
|
||||
// set FLASH SPI settings
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
SPI.begin();
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
#endif
|
||||
digitalWrite(_slaveSelectPin, LOW);
|
||||
}
|
||||
|
||||
@@ -48,9 +58,13 @@ void SPIFlash::select() {
|
||||
void SPIFlash::unselect() {
|
||||
digitalWrite(_slaveSelectPin, HIGH);
|
||||
//restore SPI settings to what they were before talking to the FLASH chip
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
SPI.endTransaction();
|
||||
#else
|
||||
SREG = _SREG; // restore interrupts IFF they were enabled
|
||||
#endif
|
||||
SPCR = _SPCR;
|
||||
SPSR = _SPSR;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
/// setup SPI, read device ID etc...
|
||||
@@ -58,7 +72,10 @@ boolean SPIFlash::initialize()
|
||||
{
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
digitalWrite(_slaveSelectPin, HIGH);
|
||||
pinMode(_slaveSelectPin, OUTPUT);
|
||||
SPI.begin();
|
||||
_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);
|
||||
unselect();
|
||||
wakeup();
|
||||
|
||||
@@ -185,22 +202,33 @@ void SPIFlash::writeByte(long addr, uint8_t byt) {
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// write 1-256 bytes to flash memory
|
||||
/// write multiple bytes to flash memory (up to 64K)
|
||||
/// WARNING: you can only write to previously erased memory locations (see datasheet)
|
||||
/// use the block erase commands to first clear memory (write 0xFFs)
|
||||
/// WARNING: if you write beyond a page boundary (or more than 256bytes),
|
||||
/// the bytes will wrap around and start overwriting at the beginning of that same page
|
||||
/// see datasheet for more details
|
||||
/// This version handles both page alignment and data blocks larger than 256 bytes.
|
||||
///
|
||||
void SPIFlash::writeBytes(long addr, const void* buf, uint16_t len) {
|
||||
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
for (uint16_t i = 0; i < len; i++)
|
||||
SPI.transfer(((byte*) buf)[i]);
|
||||
unselect();
|
||||
uint16_t n;
|
||||
uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page
|
||||
uint16_t offset = 0;
|
||||
while (len>0)
|
||||
{
|
||||
n = (len<=maxBytes) ? len : maxBytes;
|
||||
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
for (uint16_t i = 0; i < n; i++)
|
||||
SPI.transfer(((byte*) buf)[offset + i]);
|
||||
unselect();
|
||||
addr+=n; // adjust the addresses and remaining bytes by what we've just transferred.
|
||||
offset +=n;
|
||||
len -= n;
|
||||
maxBytes = 256; // now we can do up to 256 bytes per loop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// erase entire flash memory array
|
||||
/// may take several seconds depending on size, but is non blocking
|
||||
/// so you may wait for this to complete using busy() or continue doing
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2013 by Felix Rusu <felix@lowpowerlab.com>
|
||||
* SPI Flash memory library for arduino/moteino.
|
||||
* This works with 256byte/page SPI flash memory
|
||||
* For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes)
|
||||
* This works with 256uint8_t/page SPI flash memory
|
||||
* For instance a 4MBit (512Kuint8_t) flash chip will have 2048 pages: 256*2048 = 524288 uint8_ts (512Kuint8_ts)
|
||||
* Minimal modifications should allow chips that have different page size but modifications
|
||||
* DEPENDS ON: Arduino SPI library
|
||||
*
|
||||
* Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
@@ -56,34 +58,34 @@
|
||||
// but no actual need to wait for completion (instead need to check the status register BUSY bit)
|
||||
#define SPIFLASH_STATUSREAD 0x05 // read status register
|
||||
#define SPIFLASH_STATUSWRITE 0x01 // write status register
|
||||
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy byte after 3 address bytes)
|
||||
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy uint8_t after 3 address uint8_ts)
|
||||
#define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency)
|
||||
|
||||
#define SPIFLASH_SLEEP 0xB9 // deep power down
|
||||
#define SPIFLASH_WAKE 0xAB // deep power wake up
|
||||
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256bytes)
|
||||
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device)
|
||||
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256uint8_ts)
|
||||
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 uint8_ts, specific uint8_ts for each manufacturer and device)
|
||||
// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
|
||||
// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
|
||||
#define SPIFLASH_MACREAD 0x4B // read unique ID number (MAC)
|
||||
|
||||
class SPIFlash {
|
||||
public:
|
||||
static byte UNIQUEID[8];
|
||||
SPIFlash(byte slaveSelectPin, uint16_t jedecID=0);
|
||||
static uint8_t UNIQUEID[8];
|
||||
SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0);
|
||||
boolean initialize();
|
||||
void command(byte cmd, boolean isWrite=false);
|
||||
byte readStatus();
|
||||
byte readByte(long addr);
|
||||
void command(uint8_t cmd, boolean isWrite=false);
|
||||
uint8_t readStatus();
|
||||
uint8_t readByte(long addr);
|
||||
void readBytes(long addr, void* buf, word len);
|
||||
void writeByte(long addr, byte byt);
|
||||
void writeByte(long addr, uint8_t byt);
|
||||
void writeBytes(long addr, const void* buf, uint16_t len);
|
||||
boolean busy();
|
||||
void chipErase();
|
||||
void blockErase4K(long address);
|
||||
void blockErase32K(long address);
|
||||
word readDeviceId();
|
||||
byte* readUniqueId();
|
||||
uint8_t* readUniqueId();
|
||||
|
||||
void sleep();
|
||||
void wakeup();
|
||||
@@ -91,10 +93,16 @@ public:
|
||||
protected:
|
||||
void select();
|
||||
void unselect();
|
||||
byte _slaveSelectPin;
|
||||
uint8_t _slaveSelectPin;
|
||||
uint16_t _jedecID;
|
||||
byte _SPCR;
|
||||
byte _SPSR;
|
||||
uint8_t _SPCR;
|
||||
uint8_t _SPSR;
|
||||
uint8_t _SREG;
|
||||
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
SPISettings _settings;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user