commit 63ff73a066fc4f1109b284646684f904c03fb6ae Author: IMback Date: Mon Nov 26 22:30:39 2018 +0100 inital commit working 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