first commit
This commit is contained in:
493
ATMEGA_Oregon433_BUREAU_T_Sleep/ATMEGA_Oregon433_BUREAU_T_Sleep.ino
Executable file
493
ATMEGA_Oregon433_BUREAU_T_Sleep/ATMEGA_Oregon433_BUREAU_T_Sleep.ino
Executable file
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* connectingStuff, Oregon Scientific v2.1 Emitter
|
||||
* http://connectingstuff.net/blog/encodage-protocoles-oregon-scientific-sur-arduino
|
||||
* and
|
||||
* http://blog.idleman.fr/raspberry-pi-18-construire-une-sonde-de-temperature-radio-pour-7e/
|
||||
*
|
||||
* 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 2
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/power.h> // Power management
|
||||
#include <avr/wdt.h>
|
||||
|
||||
//#define THN132N
|
||||
const byte TEMPERATURE_1_PIN = 3; //A5;
|
||||
const byte LUMINOSITE_PIN=A1;
|
||||
const byte TRANSMITTER_PIN = 9;
|
||||
const byte LED_PIN = 13;
|
||||
|
||||
#define DEBUG TRUE
|
||||
|
||||
// On crée une instance de la classe oneWire pour communiquer avec le materiel on wire (dont le capteur ds18b20)
|
||||
OneWire oneWire(TEMPERATURE_1_PIN);
|
||||
|
||||
//On passe la reference onewire à la classe DallasTemperature qui vas nous permettre de relever la temperature simplement
|
||||
DallasTemperature sensors(&oneWire);
|
||||
|
||||
|
||||
const unsigned long TIME = 512;
|
||||
const unsigned long TWOTIME = TIME*2;
|
||||
|
||||
#define SEND_HIGH() digitalWrite(TRANSMITTER_PIN, HIGH)
|
||||
#define SEND_LOW() digitalWrite(TRANSMITTER_PIN, LOW)
|
||||
|
||||
// Buffer for Oregon message
|
||||
#ifdef THN132N
|
||||
byte OregonMessageBuffer[8];
|
||||
#else
|
||||
byte OregonMessageBuffer[9];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Send logical "0" over RF
|
||||
* \details azero bit be represented by an off-to-on transition
|
||||
* \ of the RF signal at the middle of a clock period.
|
||||
* \ Remenber, the Oregon v2.1 protocol add an inverted bit first
|
||||
*/
|
||||
inline void sendZero(void)
|
||||
{
|
||||
SEND_HIGH();
|
||||
delayMicroseconds(TIME);
|
||||
SEND_LOW();
|
||||
delayMicroseconds(TWOTIME);
|
||||
SEND_HIGH();
|
||||
delayMicroseconds(TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send logical "1" over RF
|
||||
* \details a one bit be represented by an on-to-off transition
|
||||
* \ of the RF signal at the middle of a clock period.
|
||||
* \ Remenber, the Oregon v2.1 protocol add an inverted bit first
|
||||
*/
|
||||
inline void sendOne(void)
|
||||
{
|
||||
SEND_LOW();
|
||||
delayMicroseconds(TIME);
|
||||
SEND_HIGH();
|
||||
delayMicroseconds(TWOTIME);
|
||||
SEND_LOW();
|
||||
delayMicroseconds(TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a bits quarter (4 bits = MSB from 8 bits value) over RF
|
||||
*
|
||||
* @param data Source data to process and sent
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Send a bits quarter (4 bits = MSB from 8 bits value) over RF
|
||||
* \param data Data to send
|
||||
*/
|
||||
inline void sendQuarterMSB(const byte data)
|
||||
{
|
||||
(bitRead(data, 4)) ? sendOne() : sendZero();
|
||||
(bitRead(data, 5)) ? sendOne() : sendZero();
|
||||
(bitRead(data, 6)) ? sendOne() : sendZero();
|
||||
(bitRead(data, 7)) ? sendOne() : sendZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send a bits quarter (4 bits = LSB from 8 bits value) over RF
|
||||
* \param data Data to send
|
||||
*/
|
||||
inline void sendQuarterLSB(const byte data)
|
||||
{
|
||||
(bitRead(data, 0)) ? sendOne() : sendZero();
|
||||
(bitRead(data, 1)) ? sendOne() : sendZero();
|
||||
(bitRead(data, 2)) ? sendOne() : sendZero();
|
||||
(bitRead(data, 3)) ? sendOne() : sendZero();
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
|
||||
/**
|
||||
* \brief Send a buffer over RF
|
||||
* \param data Data to send
|
||||
* \param size size of data to send
|
||||
*/
|
||||
void sendData(byte *data, byte size)
|
||||
{
|
||||
for(byte i = 0; i < size; ++i)
|
||||
{
|
||||
sendQuarterLSB(data[i]);
|
||||
sendQuarterMSB(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send an Oregon message
|
||||
* \param data The Oregon message
|
||||
*/
|
||||
void sendOregon(byte *data, byte size)
|
||||
{
|
||||
sendPreamble();
|
||||
//sendSync();
|
||||
sendData(data, size);
|
||||
sendPostamble();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send preamble
|
||||
* \details The preamble consists of 16 "1" bits
|
||||
*/
|
||||
inline void sendPreamble(void)
|
||||
{
|
||||
byte PREAMBLE[]={0xFF,0xFF};
|
||||
sendData(PREAMBLE, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send postamble
|
||||
* \details The postamble consists of 8 "0" bits
|
||||
*/
|
||||
inline void sendPostamble(void)
|
||||
{
|
||||
#ifdef THN132N
|
||||
sendQuarterLSB(0x00);
|
||||
#else
|
||||
byte POSTAMBLE[]={0x00};
|
||||
sendData(POSTAMBLE, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send sync nibble
|
||||
* \details The sync is 0xA. It is not use in this version since the sync nibble
|
||||
* \ is include in the Oregon message to send.
|
||||
*/
|
||||
inline void sendSync(void)
|
||||
{
|
||||
sendQuarterLSB(0xA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
|
||||
/**
|
||||
* \brief Set the sensor type
|
||||
* \param data Oregon message
|
||||
* \param type Sensor type
|
||||
*/
|
||||
inline void setType(byte *data, byte* type)
|
||||
{
|
||||
data[0] = type[0];
|
||||
data[1] = type[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the sensor channel
|
||||
* \param data Oregon message
|
||||
* \param channel Sensor channel (0x10, 0x20, 0x30)
|
||||
*/
|
||||
inline void setChannel(byte *data, byte channel)
|
||||
{
|
||||
data[2] = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the sensor ID
|
||||
* \param data Oregon message
|
||||
* \param ID Sensor unique ID
|
||||
*/
|
||||
inline void setId(byte *data, byte ID)
|
||||
{
|
||||
data[3] = ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the sensor battery level
|
||||
* \param data Oregon message
|
||||
* \param level Battery level (0 = low, 1 = high)
|
||||
*/
|
||||
void setBatteryLevel(byte *data, byte level)
|
||||
{
|
||||
if(!level) data[4] = 0x0C;
|
||||
else data[4] = 0x00;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the sensor temperature
|
||||
* \param data Oregon message
|
||||
* \param temp the temperature
|
||||
*/
|
||||
void setTemperature(byte *data, float temp)
|
||||
{
|
||||
// Set temperature sign
|
||||
if(temp < 0)
|
||||
{
|
||||
data[6] = 0x08;
|
||||
temp *= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data[6] = 0x00;
|
||||
}
|
||||
|
||||
// Determine decimal and float part
|
||||
int tempInt = (int)temp;
|
||||
int td = (int)(tempInt / 10);
|
||||
int tf = (int)round((float)((float)tempInt/10 - (float)td) * 10);
|
||||
|
||||
int tempFloat = (int)round((float)(temp - (float)tempInt) * 10);
|
||||
|
||||
// Set temperature decimal part
|
||||
data[5] = (td << 4);
|
||||
data[5] |= tf;
|
||||
|
||||
// Set temperature float part
|
||||
data[4] |= (tempFloat << 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the sensor humidity
|
||||
* \param data Oregon message
|
||||
* \param hum the humidity
|
||||
*/
|
||||
void setHumidity(byte* data, byte hum)
|
||||
{
|
||||
data[7] = (hum/10);
|
||||
data[6] |= (hum - data[7]*10) << 4;
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("Hum=" + hum);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sum data for checksum
|
||||
* \param count number of bit to sum
|
||||
* \param data Oregon message
|
||||
*/
|
||||
int Sum(byte count, const byte* data)
|
||||
{
|
||||
int s = 0;
|
||||
|
||||
for(byte i = 0; i<count;i++)
|
||||
{
|
||||
s += (data[i]&0xF0) >> 4;
|
||||
s += (data[i]&0xF);
|
||||
}
|
||||
|
||||
if(int(count) != count)
|
||||
s += (data[count]&0xF0) >> 4;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate checksum
|
||||
* \param data Oregon message
|
||||
*/
|
||||
void calculateAndSetChecksum(byte* data)
|
||||
{
|
||||
#ifdef THN132N
|
||||
int s = ((Sum(6, data) + (data[6]&0xF) - 0xa) & 0xff);
|
||||
|
||||
data[6] |= (s&0x0F) << 4; data[7] = (s&0xF0) >> 4;
|
||||
#else
|
||||
data[8] = ((Sum(8, data) - 0xa) & 0xFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(TRANSMITTER_PIN, OUTPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
Serial.println("\n[Oregon V2.1 encoder]");
|
||||
#endif
|
||||
|
||||
SEND_LOW();
|
||||
//On initialise le capteur de temperature
|
||||
sensors.begin();
|
||||
|
||||
|
||||
#ifdef THN132N
|
||||
// Create the Oregon message for a temperature only sensor (TNHN132N)
|
||||
byte ID[] = {0xEA,0x4C};
|
||||
#ifdef DEBUG
|
||||
Serial.println("Def THN132");
|
||||
#endif
|
||||
#else
|
||||
// Create the Oregon message for a temperature/humidity sensor (THGR2228N)
|
||||
byte ID[] = {0x1A,0x2D};
|
||||
#ifdef DEBUG
|
||||
Serial.println("UnDef THN132");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
setType(OregonMessageBuffer, ID);
|
||||
setChannel(OregonMessageBuffer, 0x20);
|
||||
// ATMEGA 1 = BC
|
||||
// TEST OREGON BB
|
||||
// TEST Luminosite BD
|
||||
setId(OregonMessageBuffer, 0xBD); // ID BB BC BD
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
// Read Vcc value
|
||||
long currentVcc = readVcc();
|
||||
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
if (currentVcc > 5000) {
|
||||
currentVcc = 5000;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
Serial.println(currentVcc);
|
||||
#endif
|
||||
|
||||
// Get Temperature, humidity and battery level from sensors
|
||||
// (ie: 1wire DS18B20 for température, ...)
|
||||
if (currentVcc < 3000) {
|
||||
setBatteryLevel(OregonMessageBuffer, 0); // 0 : low, 1 : high
|
||||
} else {
|
||||
setBatteryLevel(OregonMessageBuffer, 1); // 0 : low, 1 : high
|
||||
}
|
||||
// need addaptation here
|
||||
// Ajout perso
|
||||
|
||||
//Lancement de la commande de récuperation de la temperature
|
||||
sensors.requestTemperatures();
|
||||
|
||||
//Serial.println(sensors.getTempCByIndex(0));
|
||||
//if (LUMINOSITE_PIN != 0) {
|
||||
//setTemperature(OregonMessageBuffer,analogRead(LUMINOSITE_PIN));
|
||||
//} else {
|
||||
setTemperature(OregonMessageBuffer,15); //sensors.getTempCByIndex(0));
|
||||
//}
|
||||
|
||||
// setTemperature(OregonMessageBuffer, 11.2);
|
||||
|
||||
#ifndef THN132N
|
||||
// Set Humidity
|
||||
setHumidity(OregonMessageBuffer, 52);
|
||||
#endif
|
||||
|
||||
// Calculate the checksum
|
||||
calculateAndSetChecksum(OregonMessageBuffer);
|
||||
|
||||
// Show the Oregon Message
|
||||
#ifdef DEBUG
|
||||
for (byte i = 0; i < sizeof(OregonMessageBuffer); ++i) {
|
||||
Serial.print(OregonMessageBuffer[i] >> 4, HEX);
|
||||
Serial.print(OregonMessageBuffer[i] & 0x0F, HEX);
|
||||
|
||||
}
|
||||
Serial.println("");
|
||||
#endif
|
||||
|
||||
// Send the Message over RF
|
||||
sendOregon(OregonMessageBuffer, sizeof(OregonMessageBuffer));
|
||||
// Send a "pause"
|
||||
SEND_LOW();
|
||||
delayMicroseconds(TWOTIME*8);
|
||||
// Send a copie of the first message. The v2.1 protocol send the
|
||||
// message two time
|
||||
sendOregon(OregonMessageBuffer, sizeof(OregonMessageBuffer));
|
||||
|
||||
delay(1000);
|
||||
|
||||
// Wait for 30 seconds before send a new message
|
||||
SEND_LOW();
|
||||
//delay(3000);
|
||||
|
||||
// disable ADC
|
||||
//ADCSRA = 0;
|
||||
// sleep for a total of 64 seconds (8 x 8)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
myWatchdogEnable ();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Read current supply voltage
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
long readVcc() {
|
||||
bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC
|
||||
long result;
|
||||
// Read 1.1V reference against Vcc
|
||||
#if defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84
|
||||
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
ADMUX = _BV(MUX3) | _BV(MUX2);
|
||||
#else
|
||||
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328
|
||||
#endif
|
||||
delay(2); // Wait for Vref to settle
|
||||
ADCSRA |= _BV(ADSC); // Convert
|
||||
while (bit_is_set(ADCSRA,ADSC));
|
||||
result = ADCL;
|
||||
result |= ADCH<<8;
|
||||
result = 1126400L / result; // Back-calculate Vcc in mV
|
||||
ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
|
||||
return result; // Vcc in millivolts
|
||||
}
|
||||
|
||||
// watchdog interrupt
|
||||
ISR (WDT_vect)
|
||||
{
|
||||
wdt_disable(); // disable watchdog
|
||||
} // end of WDT_vect
|
||||
|
||||
void myWatchdogEnable()
|
||||
{
|
||||
// clear various "reset" flags
|
||||
MCUSR = 0;
|
||||
// allow changes, disable reset
|
||||
WDTCSR = bit (WDCE) | bit (WDE);
|
||||
// set interrupt mode and an interval
|
||||
WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay
|
||||
wdt_reset(); // pat the dog
|
||||
|
||||
byte old_ADCSRA = ADCSRA;
|
||||
// disable ADC to save power
|
||||
ADCSRA = 0;
|
||||
|
||||
// slow clock to divide by 256
|
||||
// clock_prescale_set (clock_div_256);
|
||||
|
||||
// ready to sleep
|
||||
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
|
||||
sleep_enable();
|
||||
|
||||
// turn off brown-out enable in software
|
||||
MCUCR = bit (BODS) | bit (BODSE);
|
||||
MCUCR = bit (BODS);
|
||||
sleep_cpu ();
|
||||
|
||||
// cancel sleep as a precaution
|
||||
sleep_disable();
|
||||
power_all_enable (); // enable modules again
|
||||
// reenable ADC
|
||||
ADCSRA = old_ADCSRA;
|
||||
}
|
||||
Reference in New Issue
Block a user