/* * 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 #include #include #include #define LED_PIN (13) #define DEBUG TRUE #define SEND_MESSAGE_DELAY 30000 // Ne pas dépasser 32000 !! Delay in ms between each value's extraction #define SEND_433_PAUSE 160 // 16 multiple const byte TRANSMITTER_PIN = 9; // Init RCSwitch RCSwitch mySwitch = RCSwitch(); // float temperature = 0.0; float pressure = 0.0; float pression = 0.0; float presiune = 0.0; // ################# Barometre #### Adafruit_BMP085 bmp; // ##################### ///////////////// OREGON ////////////////////////////////////// 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; } /** * \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> 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 } /******************************************************************/ /******************************************************************/ /******************************************************************/ //////////////// FIN OREGON ///////////////////////////////// // ============================================================= void setup() { mySwitch.enableTransmit(TRANSMITTER_PIN); Serial.begin(9600); // Sleep /* Don't forget to configure the pin! */ pinMode(LED_PIN, OUTPUT); // TEST SONDE BAROMETRE //byte ID[] = {0x5A,0x5D}; #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 // Barometre BE setId(OregonMessageBuffer, 0xBE); // ID BB BC BE } void loop() { digitalWrite(13, HIGH); // Read Vcc value long currentVcc = 5000; //readVcc(); barometre(); digitalWrite(13, LOW); if (currentVcc > 5000) { currentVcc = 5000; } #ifdef DEBUG Serial.println(currentVcc); #endif byte ID[] = {0x1A,0x2D}; sendMyOregon( ID, 0x20, 0xBE, temperature, 58, currentVcc); //sendMyOregon( ID, 0x20, 0xBC,temperature, 52); // // // Get Temperature, humidity and battery level from sensors // // (ie: 1wire DS18B20 for température, ...) // if (currentVcc < 3800) { // setBatteryLevel(OregonMessageBuffer, 0); // 0 : low, 1 : high // } else { // setBatteryLevel(OregonMessageBuffer, 1); // 0 : low, 1 : high // } // // need addaptation here //// Ajout perso // // setTemperature(OregonMessageBuffer,temperature); // // //// 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)); // // Narcoleptic.delay(SEND_433_PAUSE); // // // Wait for 30 seconds before send a new message // SEND_LOW(); // //delay(3000); Narcoleptic.delay(SEND_MESSAGE_DELAY); Narcoleptic.delay(SEND_MESSAGE_DELAY); } void barometre() { /* See Example: TypeA_WithDIPSwitches */ // mySwitch.switchOn("00001", "10000"); // delay(1000); // BMP if (bmp.begin()) { temperature = bmp.readTemperature(); pressure= bmp.readPressure() / 100.0; pression = pressure / 101.325; pression = pression * 0.760 * 100; // http://en.wikipedia.org/wiki/Atmospheric_pressure#Mean_sea_level_pressure // Serial.print("Presiure la nivelul marii (calculata) = "); presiune = bmp.readSealevelPressure(19) / 101.325; presiune = presiune * 0.760; #ifdef DEBUG Serial.print("Temperature="); Serial.println(temperature); Serial.print("pressure="); Serial.println(pressure); Serial.print("presiune="); Serial.println(presiune); #endif } } ////-------------------------------------------------------------------------------------------------- //// 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 //} void sendMyOregon(byte messageID[], byte channel, byte id, float temp, byte hum, int currentVcc) { byte OregonMessageBuffer[9]; // Messages gérés par Domoticz // 0xEA4C taille 8 bytes température et niveau de batterie //0x1A2D taille 9 bytes température humidité et niveau de batterie (0 / 1) //0xF824 3 températures 2 humidité //0x1984 0x1994 Vent ? //0x2914 Pluie setType(OregonMessageBuffer, messageID); setChannel(OregonMessageBuffer, channel); // ATMEGA 1 = BC // TEST OREGON BB // TEST Luminosite BD // Barometre BF setId(OregonMessageBuffer, id); // ID BB BC BF setBatteryLevel(OregonMessageBuffer, 1); // 0 : low, 1 : high if (currentVcc < 3800) { setBatteryLevel(OregonMessageBuffer, 0); // 0 : low, 1 : high } else { setBatteryLevel(OregonMessageBuffer, 1); // 0 : low, 1 : high } setTemperature(OregonMessageBuffer,temp); setHumidity(OregonMessageBuffer, hum); // Calculate the checksum calculateAndSetChecksum(OregonMessageBuffer); // 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)); }