This post will cover the doors and windows notifier
Previous posts:
Pi IoT - Simone - Introduction
Pi IoT - Simone - #1 - Light Controller
Pi IoT - Simone - #2 - Main System
For this part of the project I initially wanted to use the EnOcean Hall Sensor since it seamed the easiest and most non intrusive way to do it but unfortunately the sensor is on a different frequency so it does not connect to the receiver. Instead I used the I2C connection protocol from the light controller for this.
The system has three components:
1. The hall sensor with the ATTiny controller that feeds the data through I2C to the main system.
2. The main system that receives the data and calculates if the door is opened or closed
3. A magnet that will be glued on the door.
1.
The sensor component should be positioned on the door frame is such a way that it would be possible for the magnet on the door to get close to it when the door is closed. (You can place it inside the door frame if you carve a hole in it and because it is a magnetic sensor you can actually cover it up afterwards so you do not see it)
I used for this an AT Tiny 84 SSU and and as a hall sensor I used an SS495A HONEYWELL . This is not really a very exact sensor but it serves it's purpose for this project, it actually makes the difference between tiny movements of the magnet that is close to it.
2.
The controller for the sensor should only read the data and send it to the Main Server on the Raspberry PI when it is requested. The calculation behind this is made from the raspberry.
To calibrate the system a logic can be inserted into the application that would require you to close the door so it can see what is the value it receives when the magnet is positioned closest to the sensor. Then the application will take that value as a default closed values and any other input will be considered opened.
3.
The magnet should be positioned on the door so when it is closed the magnetic field would reach the hall sensor sending data to the main system.
NOTE:
As I said, initially I wanted to use the EnOcean sensor for this. As I described in the main system there can be more than one Raspberry PIs and one I used to make the connections to the EnOcean devices, then connect to the main system as a client and feed data to it. This would have solved some issues and the biggest one is that no more wires would have been needed.
The code for the micro controller:
//#define _DEBUG #ifdef _DEBUG #include <Wire.h> #else #include "TinyWireS.h" #endif #include "I2CTypes.h" #define SLAVE_ADDRESS 0x10 const int analogInPin = A0; static const String c_identification = "2#10#1#Usa Balcon#0"; int m_freeMemory = 0; uint8_t m_i2cMessageData[32]; int m_i2cMessageDataLength; int m_messageCounter; uint8_t m_dataArray[32]; int freeRam() { extern int __heap_start, *__brkval; int v; return ((int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval)) / 4; } void setup() { pinMode(1, OUTPUT); // initialize i2c as slave and define callbacks for i2c communication #ifdef _DEBUG Wire.begin(SLAVE_ADDRESS); Wire.onReceive(receiveData); Wire.onRequest(sendData); #else TinyWireS.begin(SLAVE_ADDRESS); TinyWireS.onReceive(receiveData); TinyWireS.onRequest(sendData); #endif m_i2cMessageDataLength = 0; m_i2cMessageData[0] = 0xFE; #ifdef _DEBUG Serial.begin(9600); #endif } void loop() { #ifdef _DEBUG m_freeMemory = freeRam(); Serial.println(analogRead(A0) * (5.0 / 1023.0)); delay(1000); //Serial.print("Memory: "); //Serial.println(m_freeMemory); #else TinyWireS_stop_check(); #endif } void sendData() { uint8_t byteToWrite = 0x05; byteToWrite = m_i2cMessageData[m_messageCounter]; m_messageCounter++; if (m_messageCounter >= m_i2cMessageDataLength) { m_messageCounter = 0; } #ifdef _DEBUG Wire.write(byteToWrite); #else TinyWireS.send(byteToWrite); #endif } // callback for received data #ifdef _DEBUG void receiveData(int byteCount) { #else void receiveData(uint8_t byteCount) { #endif uint8_t index = 0; #ifdef _DEBUG while (Wire.available()) { m_dataArray[index] = Wire.read(); index++; } #else while (TinyWireS.available()) { m_dataArray[index] = TinyWireS.receive(); index++; } #endif processMessage(); } void processMessage() { m_i2cMessageData[1] = m_dataArray[0]; switch (m_dataArray[0]) { case SW_Ping: m_i2cMessageDataLength = 4; m_i2cMessageData[2] = 0; m_messageCounter = 0; break; case SW_Identify: int length; length = c_identification.length(); m_i2cMessageDataLength = 3 + length; for (int i = 0; i < length; i++) { m_i2cMessageData[2 + i] = c_identification[i]; } m_messageCounter = 0; break; case SW_Restart: break; case SW_Get: int sensorValue = analogRead(analogInPin); m_i2cMessageDataLength = 3; m_i2cMessageData[2] = sensorValue; m_messageCounter = 0; break; default: m_i2cMessageDataLength = 4; m_i2cMessageData[2] = 0; m_messageCounter = 0; break; } } m_i2cMessageData[m_i2cMessageDataLength - 1] = 0xFF; }