From 63ff73a066fc4f1109b284646684f904c03fb6ae Mon Sep 17 00:00:00 2001 From: IMback Date: Mon, 26 Nov 2018 22:30:39 +0100 Subject: [PATCH] inital commit working --- BMP280.cpp | 90 ++++++++++++++++++++++++++++++++++ BMP280.h | 68 ++++++++++++++++++++++++++ W433DataTransmitter.cpp | 97 +++++++++++++++++++++++++++++++++++++ W433DataTransmitter.h | 31 ++++++++++++ dht11.cpp | 79 ++++++++++++++++++++++++++++++ dht11.h | 23 +++++++++ main.cpp | 104 ++++++++++++++++++++++++++++++++++++++++ power.h | 0 softspim.cpp | 56 ++++++++++++++++++++++ softspim.h | 30 ++++++++++++ watchdog.h | 33 +++++++++++++ writepin.cpp | 19 ++++++++ writepin.h | 14 ++++++ 13 files changed, 644 insertions(+) create mode 100644 BMP280.cpp create mode 100644 BMP280.h create mode 100644 W433DataTransmitter.cpp create mode 100644 W433DataTransmitter.h create mode 100644 dht11.cpp create mode 100644 dht11.h create mode 100644 main.cpp create mode 100644 power.h create mode 100644 softspim.cpp create mode 100644 softspim.h create mode 100644 watchdog.h create mode 100644 writepin.cpp create mode 100644 writepin.h diff --git a/BMP280.cpp b/BMP280.cpp new file mode 100644 index 0000000..f080fc3 --- /dev/null +++ b/BMP280.cpp @@ -0,0 +1,90 @@ +#include "BMP280.h" +#include "writepin.h" +#include + +BMP280::BMP280(SpiMaster* spi, volatile uint8_t *port, const uint8_t pin): _port(port), _pin(pin), _spi(spi) +{ + writePin(_port, _pin, true); +} + +void BMP280::write(const uint8_t address, const uint8_t data) +{ + writePin(_port, _pin, false); + _spi->write(address & ~(1<<7)); + _spi->write(data); + writePin(_port, _pin, true); +} + +uint16_t BMP280::read16b(const uint8_t address) +{ + writePin(_port, _pin, false); + _spi->write(address); + uint16_t out = static_cast(_spi->read()) << 8; + out |= _spi->read(); + writePin(_port, _pin, false); + return out; +} + +uint8_t BMP280::read8b(const uint8_t address) +{ + writePin(_port, _pin, false); + _spi->write(address); + return _spi->read(); +} + +uint16_t BMP280::getPressure() +{ + write(CTRL_REG, 0b11100101); + _delay_ms(10); + uint16_t out = read16b(PRESS_REG_HIGH); + _delay_ms(10); + write(CTRL_REG, 0b11100100); + return compensatePressure(out); +} + +#ifndef PRECOMP_COMPENSATION +uint32_t BMP280::compensatePressure(const int32_t adc_P) +{ + int32_t var1, var2; + uint32_t p; + var1 = (((int32_t)t_fine)>>1) - (int32_t)64000; + var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((int32_t)read16b(DIG_P6)); + var2 = var2 + ((var1*((int32_t)read16b(DIG_P5)))<<1); + var2 = (var2>>2)+(((int32_t)read16b(DIG_P4))<<16); + var1 = ((((read16b(DIG_P3) * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((int32_t)read16b(DIG_P2)) * var1)>>1))>>18); + var1 =((((32768+var1))*((int32_t)read16b(DIG_P1)))>>15); + if (var1 == 0) return 0; + p = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125; + if (p < 0x80000000) + { + p = (p << 1) / ((uint32_t)var1); + } + else + { + p = (p / (uint32_t)var1) * 2; + } + var1 = (((int32_t)read16b(DIG_P9)) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12; + var2 = (((int32_t)(p>>2)) * ((int32_t)read16b(DIG_P8)))>>13; + p = (uint32_t)((int32_t)p + ((var1 + var2 + (int16_t)read16b(DIG_P7)) >> 4)); + return p; +} + +#else +uint32_t BMP280::compensatePressure(const int32_t adc_P) +{ + if constexpr(var1StepB == 0) return 0; + uint32_t p = (((uint32_t)(((int32_t)1048576)-adc_P)-var2StepB))*3125; + if (p < 0x80000000) + { + p = (p << 1) / var1StepB; + } + else + { + p = (p / var1StepB) * 2; + } + int16_t var1 = (((int32_t)digP9value) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12; + int16_t var2 = (((int32_t)(p>>2)) * ((int32_t)digP8value))>>13; + p = (uint32_t)((int32_t)p + ((var1 + var2 + (int16_t)digP7value) >> 4)); + return p; +} +#endif diff --git a/BMP280.h b/BMP280.h new file mode 100644 index 0000000..f6a2949 --- /dev/null +++ b/BMP280.h @@ -0,0 +1,68 @@ +#pragma once +#include + +#include "softspim.h" + +#define PRECOMP_COMPENSATION + +class BMP280 +{ +private: + + static constexpr uint8_t TEMP_REG_LOW = 0xFB; + static constexpr uint8_t TEMP_REG_HIGH = 0xFA; + static constexpr uint8_t PRESS_REG_LOW = 0xF8; + static constexpr uint8_t PRESS_REG_HIGH = 0xF7; + static constexpr uint8_t CONFIG_REG = 0xF5; + static constexpr uint8_t CTRL_REG = 0xF4; + static constexpr uint8_t ID_REG = 0xD0; + + static constexpr uint8_t DIG_T1 = 0x88; + static constexpr uint8_t DIG_T2 = 0x8A; + static constexpr uint8_t DIG_T3 = 0x8C; + static constexpr uint8_t DIG_P1 = 0x8E; + static constexpr uint8_t DIG_P2 = 0x90; + static constexpr uint8_t DIG_P3 = 0x92; + static constexpr uint8_t DIG_P4 = 0x94; + static constexpr uint8_t DIG_P5 = 0x96; + static constexpr uint8_t DIG_P6 = 0x98; + static constexpr uint8_t DIG_P7 = 0x9A; + static constexpr uint8_t DIG_P8 = 0x9C; + static constexpr uint8_t DIG_P9 = 0x9E; + + static constexpr int32_t t_fine = 102400; + +#ifdef PRECOMP_COMPENSATION + static constexpr uint16_t digP1value = 42; + static constexpr int16_t digP2value = 48; + static constexpr int16_t digP3value = 49; + static constexpr int16_t digP4value = 30; + static constexpr int16_t digP5value = -32; + static constexpr int16_t digP6value = 58; + static constexpr int16_t digP7value = 7; + static constexpr int16_t digP8value = 3; + static constexpr int16_t digP9value = 58; + static constexpr int32_t var1StepA = ((((int32_t)t_fine)>>1) - (int32_t)64000); + static constexpr int32_t var1StepB = ((((32768+((((digP3value * + (((var1StepA>>2) * (var1StepA>>2)) >> 13 )) >> 3) + ((((int32_t)digP2value) * var1StepA)>>1))>>18)))* + ((int32_t)digP1value))>>15); + static constexpr int32_t var2StepA = ((((var1StepA>>2) * (var1StepA>>2)) >> 11 ) * ((int32_t)digP6value)) + ((var1StepA*((int32_t)digP5value))<<1); + static constexpr int16_t var2StepB = ((var2StepA>>2)+(((int32_t)digP4value)<<16))>>12; + static constexpr int32_t var3 = 52; +#endif + + volatile uint8_t *_port; + const uint8_t _pin; + + SpiMaster *_spi; + + void write(const uint8_t address, const uint8_t data); + uint16_t read16b(const uint8_t address); + uint8_t read8b(const uint8_t address); + uint32_t compensatePressure(const int32_t adc_P); + +public: + + BMP280(SpiMaster* spi, volatile uint8_t *port, const uint8_t pin); + uint16_t getPressure(); +}; diff --git a/W433DataTransmitter.cpp b/W433DataTransmitter.cpp new file mode 100644 index 0000000..ececa05 --- /dev/null +++ b/W433DataTransmitter.cpp @@ -0,0 +1,97 @@ +#include "W433DataTransmitter.h" +#include "writepin.h" + +W433DataTransmitter::W433DataTransmitter(volatile unsigned char *port, unsigned char pin): _port(port), _pin(pin) +{ +} + +void W433DataTransmitter::sendBit(const bool bit) +{ + switch(bit) + { + case true: + writePin(_port,_pin,true); + _delay_us(SMALL_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + writePin(_port,_pin,true); + _delay_us(SMALL_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + break; + + case false: + writePin(_port,_pin,true); + _delay_us(LARGE_TIME); + writePin(_port,_pin,false); + _delay_us(SMALL_TIME); + writePin(_port,_pin,true); + _delay_us(SMALL_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + break; + } +} + +void W433DataTransmitter::sendSyncpulse() +{ + for(uint8_t i = 0; i < 25; ++i) + { + writePin(_port,_pin,true); + _delay_us(SYNC_TIME); + writePin(_port,_pin,false); + _delay_us(SYNC_TIME); + } +} + +void W433DataTransmitter::sendEndPulse() +{ + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + writePin(_port,_pin,true); + _delay_us(LARGE_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME*10); +} + +void W433DataTransmitter::sendRawData(const uint8_t data) +{ + for(uint8_t i = 0; i < 8; i++) sendBit(data & ( 1 << (7 - i))); +} + +void W433DataTransmitter::sendPacket(const uint32_t data) +{ + sendSyncpulse(); + _delay_us(LARGE_TIME); + sendRawData(signature); + uint8_t checksum = 0; + for(uint8_t i = 0; i < 4; ++i) + { + uint8_t dataOctet = (data & (0xFF000000 >> i*8 )) >> (24 - 8*i); + for(uint8_t i = 0; i < 8; i++) checksum = checksum + (dataOctet & ( 1 << (8 - i))); + sendRawData( dataOctet ); + + } + sendRawData( checksum ); + sendEndPulse(); +} + +void W433DataTransmitter::send(const uint8_t* const data, uint16_t length) +{ + uint16_t packets = length/4; + if(length % 4 != 0) ++packets; + for(uint8_t j = 0; j < packets; j++) + { + uint32_t paketData = 0; + uint8_t* paketDataPointer = reinterpret_cast(&paketData); + for(uint8_t i = 0; i < 4 && j*4+i < length; i++) paketDataPointer[3-i] = data[j*4+i]; + sendPacket(paketData); + } +} + +void W433DataTransmitter::send(const uint8_t data) +{ + sendPacket(data); +} + + diff --git a/W433DataTransmitter.h b/W433DataTransmitter.h new file mode 100644 index 0000000..8d3304e --- /dev/null +++ b/W433DataTransmitter.h @@ -0,0 +1,31 @@ +#pragma once +#include + +#include + + +class W433DataTransmitter +{ +private: + + static constexpr uint16_t SYNC_TIME = 800; + static constexpr uint16_t LARGE_TIME = 2000; + static constexpr uint16_t SMALL_TIME = 500; + + static constexpr uint8_t signature = 0xA5; + volatile unsigned char * const _port; + unsigned char _pin; + + void sendBit(const bool bit); + void sendSyncpulse(); + void sendRawData(const uint8_t data); + void sendEndPulse(); + +public: + + W433DataTransmitter(volatile unsigned char * const port, unsigned char pin); + void send(const uint8_t* const data, uint16_t length); + void send(const uint8_t data); + void sendPacket(const uint32_t data); + +}; diff --git a/dht11.cpp b/dht11.cpp new file mode 100644 index 0000000..f1c2dc3 --- /dev/null +++ b/dht11.cpp @@ -0,0 +1,79 @@ +#include "dht11.h" + +Dht11::Dht11(volatile unsigned char *port, volatile unsigned char *inPort, volatile unsigned char *port_ctl, const unsigned char pin): _port(port), _inPort(inPort), _port_ctl(port_ctl), _pin(pin) +{} + +uint8_t Dht11::read() +{ + // BUFFER TO RECEIVE + uint8_t bits[5]; + uint8_t cnt = 7; + uint8_t idx = 0; + + // EMPTY BUFFER + for (uint8_t i=0; i< 5; i++) bits[i] = 0; + + // REQUEST SAMPLE + setDirection(_port_ctl, _pin, true); + writePin(_port, _pin, false); + _delay_ms(2); + writePin(_port, _pin, true); + setDirection(_port_ctl, _pin, false); + _delay_us(42); + + + // ACKNOWLEDGE or TIMEOUT + unsigned int loopCnt = LOOP_TIMEOUT_COUNT; + while(!readPin(_inPort, _pin)) + if (loopCnt-- == 0) return 1; + + loopCnt = LOOP_TIMEOUT_COUNT; + while(readPin(_inPort, _pin) ) + if (loopCnt-- == 0) return 2; + + // READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT + for (uint8_t i=0; i<40; i++) + { + loopCnt = LOOP_TIMEOUT_COUNT; + while(!readPin(_inPort, _pin)) + if (loopCnt-- == 0) return 3; + + loopCnt = 0; + while(readPin(_inPort, _pin)) + { + _delay_us(10); + if (loopCnt++ > LOOP_TIMEOUT_SMALL_COUNT) return 4; + } + + if( loopCnt > BIT_COUNT )bits[idx] |= (1 << cnt); + if (cnt == 0) // next byte? + { + cnt = 7; // restart at MSB + idx++; // next byte! + } + else cnt--; + } + + // WRITE TO RIGHT VARS + // as bits[1] and bits[3] are allways zero they are omitted in formulas. + uint8_t sum; + if constexpr(DHT22) sum= bits[0] + bits[1] + bits[2] + bits[3]; + else sum = bits[1] + bits[3]; + + if(bits[4] == sum && sum != 0) + { + if constexpr(DHT22) + { + humidity = (static_cast(bits[0]) << 8) + bits[1]; + temperature = (static_cast((bits[2] & 0b01111111) << 8) + bits[3]); + if(bits[2] & 0b10000000) temperature=temperature*-1; + } + else + { + humidity = bits[1]; + temperature = bits[3]*10; + } + return 0; + } + else return 5; +} diff --git a/dht11.h b/dht11.h new file mode 100644 index 0000000..fbd0973 --- /dev/null +++ b/dht11.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include +#include "writepin.h" + +class Dht11 +{ + static constexpr uint16_t LOOP_TIMEOUT_COUNT = (10000.0 / 16000000.0)*F_CPU; + static constexpr uint8_t LOOP_TIMEOUT_SMALL_COUNT = (100.0 / 16000000.0)*F_CPU; + static constexpr uint8_t BIT_COUNT = 6;//(8.0 / 16000000.0)*F_CPU; + static constexpr bool DHT22 = true; + + volatile unsigned char * const _port; + volatile unsigned char * const _port_ctl; + volatile unsigned char * const _inPort; + const unsigned char _pin; + +public: + Dht11(volatile unsigned char *port, volatile unsigned char *inPort, volatile unsigned char *port_ctl, const unsigned char pin); + uint8_t read(); + int16_t humidity = 0; + uint16_t temperature = 0; +}; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..179c685 --- /dev/null +++ b/main.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include "dht11.h" +#include "W433DataTransmitter.h" +#include "watchdog.h" +#include "softspim.h" +#include "BMP280.h" + +#define TEMP_SENSOR_DATA PB4 +#define TRANSMITTER_DATA PD0 +#define DOOR_PIN PD2 +#define POWER_PIN PD5 +#define LED_PIN PD1 + +EMPTY_INTERRUPT( WDT_OVERFLOW_vect); + +static constexpr uint8_t id = 1; +static constexpr bool WATCH_DOOR = false; + + +static void power(const bool power) +{ + if(power) + { + PORTD |= 1 << POWER_PIN | 1 << LED_PIN; + DDRD = 1 << POWER_PIN | 1 << LED_PIN | 1 << TRANSMITTER_DATA; + DDRB = 1 << PB0 | 1 << PB1 | 1 << PB3; + } + else + { + PORTD &= ~(1 << POWER_PIN | 1 << LED_PIN | 1 << TRANSMITTER_DATA); + //DDRD &= ~(1 << TRANSMITTER_DATA); + DDRB = 0; + } +} + +int main() +{ + + Dht11 tempSensor(&PORTB, &PINB, &DDRB, TEMP_SENSOR_DATA); + + //pressure sensor + SpiMaster spi; + BMP280 pressSensor(&spi, &PORTB, PB1); + + //Transmitter and transmiter power + W433DataTransmitter transmiter(&PORTD, TRANSMITTER_DATA); + + sei(); + + wdt_set(WDTO_8S); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + + uint8_t couter = 50; + + while(true) + { + if(++couter > 1) + { + couter = 0; + + power(true); + _delay_ms(2000); + + //temperature sensor + tempSensor.read(); + uint8_t paket[4]; + paket[0] = 1; + paket[1] = id; + paket[2] = tempSensor.temperature >> 8; + paket[3] = tempSensor.temperature; + transmiter.send(paket, 4); + + //humidity sensor + paket[0] = 2; + paket[2] = tempSensor.humidity >> 8; + paket[3] = tempSensor.humidity; + transmiter.send(paket, 4); + + //presure sensor + uint16_t pressure = pressSensor.getPressure(); + paket[0] = 3; + paket[2] = pressure >> 8; + paket[3] = pressure; + transmiter.send(paket, 4); + + //door + if constexpr(WATCH_DOOR) + { + paket[0] = 0; + paket[1] = 2; + paket[2] = 0; + paket[3] = readPin(&PIND, DOOR_PIN); + transmiter.send(paket, 4); + } + power(false); + } + sleep_mode(); + } +} + diff --git a/power.h b/power.h new file mode 100644 index 0000000..e69de29 diff --git a/softspim.cpp b/softspim.cpp new file mode 100644 index 0000000..bffaad5 --- /dev/null +++ b/softspim.cpp @@ -0,0 +1,56 @@ +#include "softspim.h" +#include "writepin.h" +#include + +SpiMaster::SpiMaster() +{ + +} + +uint8_t SpiMaster::readWrite(uint8_t in) +{ + _delay_us(DELAY_TIME_US); + uint8_t recByte = 0; + for(uint8_t i = 0; i < 8; ++i) + { + if constexpr (BIT_ORDER == 0) writePin(_port, _pinOut, in & (1 << i)); + else writePin(_port, _pinOut, in & (1 << (7-i))); + if constexpr (CLOCK_PHASE == 0) _delay_us(DELAY_TIME_US); + writePin(_port, _pinClock, !CLOCK_POLARITY); + if constexpr (CLOCK_PHASE == 1) _delay_us(DELAY_TIME_US); + if constexpr (BIT_ORDER == 0) recByte |= readPin(_pinReg, _pinIn) << i; + else recByte |= readPin(_pinReg, _pinIn) << (7-i); + if constexpr (CLOCK_PHASE == 0) _delay_us(DELAY_TIME_US); + writePin(_port, _pinClock, CLOCK_POLARITY); + if constexpr (CLOCK_PHASE == 1) _delay_us(DELAY_TIME_US); + } + return recByte; +} + +void SpiMaster::readWrite(uint8_t length, uint8_t* bufferIn, uint8_t* bufferOut) +{ + for(uint8_t i = 0; i < length; ++i) + { + uint8_t outByte = 0; + if(bufferOut) outByte = bufferOut[i]; + uint8_t inByte = readWrite(outByte); + if(bufferIn) bufferIn[i] = inByte; + } +} + + +void SpiMaster::prepare() +{ + writePin(_port, _pinClock, CLOCK_POLARITY); +} + + +void SpiMaster::write(uint8_t in) +{ + readWrite(in); +} + +uint8_t SpiMaster::read() +{ + return readWrite(); +} diff --git a/softspim.h b/softspim.h new file mode 100644 index 0000000..bb31f1c --- /dev/null +++ b/softspim.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +class SpiMaster +{ +private: + + static constexpr uint8_t CLOCK_POLARITY = 1; + static constexpr uint8_t CLOCK_PHASE = 1; + static constexpr uint8_t BIT_ORDER = 1; + + volatile uint8_t *_port = &PORTB; + volatile uint8_t *_pinReg = &PINB; + static constexpr uint8_t _pinIn = PB2; + static constexpr uint8_t _pinOut = PB0; + static constexpr uint8_t _pinClock = PB3; + + static constexpr uint8_t DELAY_TIME_US = 10; + + +public: + + SpiMaster(); + void readWrite(uint8_t length, uint8_t* bufferIn, uint8_t* bufferOut); + uint8_t readWrite(uint8_t in = 0); + void prepare(); + uint8_t read(); + void write(uint8_t in); +}; diff --git a/watchdog.h b/watchdog.h new file mode 100644 index 0000000..de49320 --- /dev/null +++ b/watchdog.h @@ -0,0 +1,33 @@ +#pragma once +#include + +#define wdt_set(value) \ + __asm__ __volatile__ ( \ + "in __tmp_reg__,__SREG__" "\n\t" \ + "cli" "\n\t" \ + "wdr" "\n\t" \ + "sts %0,%1" "\n\t" \ + "out __SREG__,__tmp_reg__" "\n\t" \ + "sts %0,%2" \ + : /* no outputs */ \ + : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \ + "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \ + "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \ + _BV(WDIE) | (value & 0x07)) ) \ + : "r0" \ + ) + + +#define wdt_off(x) \ + __asm__ __volatile__ ( \ + "in __tmp_reg__,__SREG__" "\n\t" \ + "cli" "\n\t" \ + "wdr" "\n\t" \ + "sts %0,%1" "\n\t" \ + "sts %0,%2" \ + : /* no outputs */ \ + : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \ + "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \ + "r" ((uint8_t) (0x00)) \ + : "r0" \ + ) diff --git a/writepin.cpp b/writepin.cpp new file mode 100644 index 0000000..744a47d --- /dev/null +++ b/writepin.cpp @@ -0,0 +1,19 @@ +#include "writepin.h" + +void writePin(volatile unsigned char *port, const unsigned char pin, const bool state) //waste 2 cycles +{ + if(!state) *port &= ~(1 << pin); + else *port |= (1 << pin); +} + +void setBit( volatile unsigned char *reg, const unsigned char bit, bool value ) +{ + writePin(reg, bit, value); +} + +void setDirection( volatile unsigned char *portDirReg, const unsigned char pin, bool makeOutput ) +{ + writePin(portDirReg, pin, makeOutput); +} + +bool readPin( volatile unsigned char *inPort, const unsigned char pin){ return (bool) (*inPort & (1 << pin));} diff --git a/writepin.h b/writepin.h new file mode 100644 index 0000000..616d4c5 --- /dev/null +++ b/writepin.h @@ -0,0 +1,14 @@ +#ifndef WRITEPIN_H +#define WRITEPIN_H +#include + + +void writePin(volatile unsigned char *port, const unsigned char pin, const bool state); + +void setBit( volatile unsigned char *reg, const unsigned char bit, bool value ); + +void setDirection( volatile unsigned char *portDirReg, const unsigned char pin, bool makeOutput ); + +bool readPin( volatile unsigned char *inPort, const unsigned char pin); + +#endif