diff --git a/tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino b/tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino new file mode 100644 index 000000000..540733341 --- /dev/null +++ b/tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino @@ -0,0 +1,280 @@ +/****************************************************************************************************************************\ +* Arduino project "TheoTinySensor" Copyright 2013 Theo Arends +* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +****************************************************************************************************************************** + +/***************************************************************************************************************\ +* Purpose : Arduino Source code for Sensor based on Atmel ATTiny85, running on 8MHz +* Version : R109 - DS18B20 and BH1750 and Vcc test +* Date : 20140502 +* +* This code turns an Atmel ATTiny85 chip into a Sensor using the TheoV2 protocol. +* This code is not of any use without running a Unit within RF range to receive sensor data. +\***************************************************************************************************************/ + +#define SENSOR_TYPE 1 // 1 = DS18B20 and BH1750 sensor + +// Uncomment for test purpose +//#define THEO_TEST + +//***************************************************************************** + +#ifdef THEO_TEST + #define CHANNEL 0 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 2 // Send Delay in multiples of 4 seconds, so 2 = 2x4=8 seconds + #define VCC_LOOP 2 +#else + #define CHANNEL 1 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 30 // Send Delay in multiples of 4 seconds, so 70 = 70x4=280 seconds + #define VCC_LOOP 24 // Send Vcc once every hour +#endif + +#define VREF_35 10885 // Measured value for Vref at 3.5V Vcc * 10 (Chip dependent) +#define BATT_LOW 30 // 3.0V Battery low warning voltage * 10 (Functionality dependent) + +//***************************************************************************** + +#define DALLAS_PIN 1 // data to DS18B20, fysieke pin 6 on ATTiny85 +#define BH1750_ADDRESS 0x23 // i2c address BH1750 + +#define RF_TransmitDataPin 4 // data to RF Transmitter, fysieke pin 3 on ATTiny85 + +// ATMEL ATTINY85 +// AI=Analog Input +// o-\/-+ +// reset 1| |8 VCC +// Pin 3 (AI 3) PB3 2| |7 PB2 (AI 1) Pin 2 - SCL +// Pin 4 (AI 2) PB4 3| |6 PB1 PWM Pin 1 - PCINT1 +// GND 4| |5 PB0 PWM Pin 0 - SDA +// +----+ + +// Used by DS18B20 +#include // http://www.pjrc.com/teensy/arduino_libraries/OneWire.zip + +// Used by BH1750 +// Prepare library TinyWireM for 8MHz by editing the following files: +// 1) file USI_TWI_Master.cpp define F_CPU from 1000000UL to 8000000UL +// 2) file USI_TWI_Master.h define SYS_CLK from 1000.0 to 8000.0 +#include // http://playground.arduino.cc/Code/USIi2c + +byte VccTest; +byte Voltage; + +//***************************************************************************** +// Setup stuff +//***************************************************************************** +void setup() +{ + VccTest = VCC_LOOP; + + pinMode(RF_TransmitDataPin,OUTPUT); + + TinyWireM.begin(); + + Watchdog_setup(8); // Setup watchdog to notify us every 4 seconds +} + +//***************************************************************************** +// Main loop +//***************************************************************************** +void loop() +{ + int payload1 = 0; + int payload2 = 0; + + VccTest++; + + if (GetPayload(payload1, payload2) == 0) + SendData(payload1, payload2); + + Watchdog_sleep(SEND_DELAY + CHANNEL); // Go to deep sleep mode for some time +} + +//***************************************************************************** +// Sleep stuff +//***************************************************************************** +#include +#include + +void Watchdog_setup(int ii) +{ + // 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms, 6=1s, 7=2s, 8=4s, 9=8s + // The prescale value is held in bits 5,2,1,0 + // This block moves ii into these bits + byte bb; + if (ii > 9 ) ii=9; + bb=ii & 7; + if (ii > 7) bb|= (1<<5); + bb|= (1<= VCC_LOOP) // Do not run the Vcc test too often to save Battery power + { + VccTest = 0; + Voltage = ReadVcc(); + if (Voltage <= BATT_LOW) + Voltage |= 0x80; + } + DataBlock.Voltage = Voltage; + DataBlock.Payload1 = payload1; + DataBlock.Payload2 = payload2; + byte c = 0, *B = (byte*)&DataBlock; // bereken checksum: crc-8 uit bovenstaande bytes in de struct + for (byte x = 1; x < Size; x++) + c +=*(B+x); + DataBlock.Checksum = c; + + pinMode(RF_TransmitDataPin, OUTPUT); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + for (byte y = 0; y < TransmitRepeat; y++) // herhaal verzenden RF code + { + digitalWrite(RF_TransmitDataPin, HIGH); // 1 + delayMicroseconds(RF_PULSE_1 * 4); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + delayMicroseconds(RF_SPACE * 2); + for (byte x = 0; x < Size; x++) + { + for (byte Bit = 0; Bit <= 7; Bit++) + { + digitalWrite(RF_TransmitDataPin, HIGH); // 1 + if ((*(B + x) >> Bit) & 1) + delayMicroseconds(RF_PULSE_1); + else + delayMicroseconds(RF_PULSE_0); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + delayMicroseconds(RF_SPACE); + } + } + delayMicroseconds(RF_PULSE_1 * 10); + } +} + +//***************************************************************************** +// Measure battery voltage using internal bandgap voltage +//***************************************************************************** +byte ReadVcc() +{ + int result; + + bitSet(ADCSRA, ADEN); // switch Analog to Digital converter ON + ADMUX = 0x0C; // use VCC and internal bandgap (ATTiny85) + delayMicroseconds(250); // delay substantially improves accuracy + bitSet(ADCSRA, ADSC); // start conversion + while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC is clear + bitClear(ADCSRA, ADEN); // Switch Analog to Digital converter OFF + result = ADCW; + return result ? VREF_35 / result : 0; // 35 = 3.5V +} + +//***************************************************************************** +// DS18B20 Temperature Sensor and BH1750 light sensor support +//***************************************************************************** +byte GetPayload(int &temperature, int &light) +{ + if (GetDS18B20(temperature) != 0) return 1; + if (GetBH1750(light) != 0) return 1; + return 0; +} + +//***************************************************************************** +// DS18B20 Temperature +//***************************************************************************** +byte GetDS18B20(int &temperature) +{ + byte msb, lsb; + int temp; + + OneWire ds(DALLAS_PIN); // Setup a oneWire instance + ds.reset(); + ds.skip(); + ds.write(0x44); // Start conversion + Watchdog_delay(6); // Wait 750ms. Here 1 second + ds.reset(); // Read DS18B20 + ds.skip(); + ds.write(0xBE); // Read scratchpad + lsb = ds.read(); + msb = ds.read(); + ds.reset(); + temp = (msb<< 8) | lsb; + temperature = ((((6 * temp) + temp / 4) + 5) / 10) * 10; // multiply by (100 * 0.0625) or 6.25 and round to tenth + return 0; +} + +//***************************************************************************** +// BH1750 light +//***************************************************************************** +byte GetBH1750(int &light) +{ + byte msb, lsb; + unsigned int value; + + TinyWireM.beginTransmission(BH1750_ADDRESS); // Setup BH1750 + TinyWireM.send(0x20); // One time high resolution low power + TinyWireM.endTransmission(); + Watchdog_delay(4); // Wait 160-180ms. Here 250ms + TinyWireM.beginTransmission(BH1750_ADDRESS); // Read BH1750 + TinyWireM.requestFrom(BH1750_ADDRESS, 2); + msb = TinyWireM.receive(); + lsb = TinyWireM.receive(); + value = (msb<<8 | lsb) / 1.2; + if (value > 0x7fff) value = 0x7fff; + light = int(value); + return 0; +} diff --git a/tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino b/tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino new file mode 100644 index 000000000..1ab3ecc30 --- /dev/null +++ b/tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino @@ -0,0 +1,286 @@ +/****************************************************************************************************************************\ +* Arduino project "TheoTinySensor" Copyright 2013 Theo Arends +* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +****************************************************************************************************************************** + +**************************************************************************************************************** +* Purpose : Arduino Source code for Sensor based on Atmel ATTiny85, running on 8MHz +* Version : R201 - DHT11 or DHT22 and Vcc test +* Date : 20140414 +* 20140507 - R202 - Verwijdering VCC_LOOP +* +* This code turns an Atmel ATTiny85 chip into a Sensor using the TheoV2 protocol. +* This code is not of any use without running a Unit within RF range to receive sensor data. +\***************************************************************************************************************/ + +#define SENSOR_TYPE 2 // 2 = DHT22 or DHT11 sensor +#define DHT22 // DHT22 Temperatuur en luchtvochtigheid +//#define DHT11 // DHT11 Temperatuur en luchtvochtigheid + +// Uncomment for test purpose +//#define THEO_TEST + +//***************************************************************************** + +#ifdef THEO_TEST + #define CHANNEL 0 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 2 // Max Send Delay in multiples of 4.4 seconds, so 2 = 2x4.4=9 seconds +#else + #define CHANNEL 1 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 32 // Max Send Delay in multiples of 4.4 seconds, so 32 = 32x4.4=141 seconds +#endif + +#define VREF_35 10675 // Measured value for Vref at 3.5V Vcc * 10 (Chip dependent) +#define BATT_LOW 33 // 3.3V Battery low warning voltage * 10 (Functionality dependent) + +//***************************************************************************** + +#define DHT_PIN 1 // data to DHT11, fysieke pin 6 on ATTiny85 + +#define RF_TransmitDataPin 4 // data to RF Transmitter, fysieke pin 3 on ATTiny85 + +// ATMEL ATTINY85 +// AI=Analog Input +// o-\/-+ +// reset 1| |8 VCC +// Pin 3 (AI 3) PB3 2| |7 +// Pin 4 (AI 2) PB4 3| |6 PB1 PWM Pin 1 - PCINT1 +// GND 4| |5 +// +----+ + +byte VccTest; +byte Voltage; + +//***************************************************************************** +// Setup stuff +//***************************************************************************** +void setup() +{ + VccTest = 255; + + pinMode(RF_TransmitDataPin,OUTPUT); + + pinMode(DHT_PIN, OUTPUT); + digitalWrite(DHT_PIN, HIGH); // Pull high + delay(3000); + + Watchdog_setup(8); // Setup watchdog to notify us every 4.4 seconds +} + +//***************************************************************************** +// Main loop +//***************************************************************************** +void loop() +{ + int payload1 = 0; + int payload2 = 0; + + VccTest++; + if (VccTest == 0) // Do not run the Vcc test too often to save Battery power + { + Voltage = ReadVcc(); + if (Voltage <= BATT_LOW) + Voltage |= 0x80; + } + + if (GetPayload(payload1, payload2) == 0) + SendData(payload1, payload2); + +// Watchdog_sleep(SEND_DELAY + CHANNEL); // Go to deep sleep mode for some time + Watchdog_sleep(SEND_DELAY - SENSOR_TYPE - CHANNEL); // Go to deep sleep mode for some time but not longer than 150 sec +} + +//***************************************************************************** +// Sleep stuff +//***************************************************************************** +#include +#include + +void Watchdog_setup(int ii) +{ + // 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms, 6=1s, 7=2s, 8=4s, 9=8s + // The prescale value is held in bits 5,2,1,0 + // This block moves ii into these bits + byte bb; + if (ii > 9 ) ii=9; + bb=ii & 7; + if (ii > 7) bb|= (1<<5); + bb|= (1<> Bit) & 1) + delayMicroseconds(RF_PULSE_1); + else + delayMicroseconds(RF_PULSE_0); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + delayMicroseconds(RF_SPACE); + } + } + delayMicroseconds(RF_PULSE_1 * 10); + } +} + +//***************************************************************************** +// Measure battery voltage using internal bandgap voltage +//***************************************************************************** +byte ReadVcc() +{ + int result; + + bitSet(ADCSRA, ADEN); // switch Analog to Digital converter ON + ADMUX = 0x0C; // use VCC and internal bandgap (ATTiny85) + delayMicroseconds(250); // delay substantially improves accuracy + bitSet(ADCSRA, ADSC); // start conversion + while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC is clear + bitClear(ADCSRA, ADEN); // Switch Analog to Digital converter OFF + result = ADCW; + return result ? VREF_35 / result : 0; // 35 = 3.5V +} + +//***************************************************************************** +// DHT11 or DHT22 Temperature and humidity sensor support +//***************************************************************************** +byte GetPayload(int &temperature, int &humidity) +{ + return GetDHT(temperature, humidity); +} + +//***************************************************************************** +// DHT11 or DHT22 Temperature and humidity +// http://forums.adafruit.com/viewtopic.php?f=25&t=43933 +// https://github.com/markruys/arduino-DHT +//***************************************************************************** +byte GetDHT(int &temperature, int &humidity) +{ + unsigned long startTime = millis(); + word rawHumidity; + word rawTemperature; + word data; + + digitalWrite(DHT_PIN, LOW); // Send start signal + pinMode(DHT_PIN, OUTPUT); +#ifdef DHT22 + delayMicroseconds(800); +#else + delay(18); +#endif + pinMode(DHT_PIN, INPUT); + digitalWrite(DHT_PIN, HIGH); // Switch bus to receive data + // We're going to read 83 edges: + // - First a FALLING, RISING, and FALLING edge for the start bit + // - Then 40 bits: RISING and then a FALLING edge per bit + // To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long + for (int8_t i = -3 ; i < 2 * 40; i++) + { + byte age; + + startTime = micros(); + do + { + age = (unsigned long)(micros() - startTime); + if (age > 90) return 1; + } + while (digitalRead(DHT_PIN) == (i & 1) ? HIGH : LOW); + if (i >= 0 && (i & 1)) + { + data <<= 1; // Now we are being fed our 40 bits + if (age > 30) data |= 1; // A zero max 30 usecs, a one at least 68 usecs. We got a one + } + switch (i) + { + case 31: + rawHumidity = data; + break; + case 63: + rawTemperature = data; + data = 0; + break; + } + } + // Verify checksum + if ((byte)(((byte)rawHumidity) + (rawHumidity >> 8) + ((byte)rawTemperature) + (rawTemperature >> 8)) != data) + return 2; +#ifdef DHT22 + int t = (rawTemperature & 0x7fff) * 10; + temperature = rawTemperature & 0x8000 ? - t : t; +// humidity = (rawHumidity / 10) * 100; // round to whole + humidity = rawHumidity * 10; +#else + humidity = (rawHumidity >> 8) * 100; + temperature = (rawTemperature >> 8) * 100; +#endif + return 0; +} + \ No newline at end of file diff --git a/tools/theov2_attiny85/info.txt b/tools/theov2_attiny85/info.txt new file mode 100644 index 000000000..fc93b2057 --- /dev/null +++ b/tools/theov2_attiny85/info.txt @@ -0,0 +1,15 @@ +These files provide Arduino code for ATTiny85 battery powered sensor hardware. + +Tasmota can receive and decode them when defines USE_RF_SENSOR and USE_THEO_V2 are enabled + + +TheoV2Sensor1 - Light and Temperature +Uses BH1750 and DS18B20 +Uses 1 x 3.6V Lithium battery lasting at least 3 years +See https://sidweb.nl/cms3/en/projects/mcs51/attiny85-lichtsensor + + +TheoV2Sensor2 - Temperature and Humidity +Uses DHT22 +Uses 3 x AAA battery lasting at least 3 years +See https://sidweb.nl/cms3/en/projects/mcs51/vocht-en-tempsensor \ No newline at end of file