297 lines
11 KiB
Arduino
297 lines
11 KiB
Arduino
/*************************************
|
|
* LDR-schakelaar isr0
|
|
* Author: Michel Bats
|
|
* Website: www.batssoft.nl
|
|
* Version: 1.2.0
|
|
* Revision: 20150207
|
|
*
|
|
* Used libraries:
|
|
* Adafruit_SSD1306\Adafruit_SSD1306 by adafruit
|
|
* https://github.com/adafruit/Adafruit_SSD1306
|
|
* Adafruit-GFX-Library\Adafruit_GFX by adafruit
|
|
* https://github.com/adafruit/Adafruit-GFX-Library
|
|
* NewRemoteSwitch\NewRemoteTransmitter by fuzzillogic
|
|
* https://bitbucket.org/fuzzillogic/433mhzforarduino/wiki/Home
|
|
*************************************/
|
|
|
|
// Bibliotheken
|
|
#include <SPI.h>
|
|
#include <Wire.h>
|
|
#include <NewRemoteTransmitter.h>
|
|
#include <Adafruit_GFX.h>
|
|
#include <Adafruit_SSD1306.h>
|
|
|
|
// Bepalingen
|
|
#define ledPin 13 // Debug-LED (13 is standaard on-board)
|
|
#define sensorLdr A0 // Input van LDR
|
|
#define potSwitch A1 // Input van potmeter voor schakelpunt
|
|
#define potThreshold A2 // Input van potmeter voor hysteresis
|
|
#define potDim A3 // Input van potmeter voor dim-niveau
|
|
// Bepalingen Klik Aan Klik Uit (KAKU/kaku)
|
|
#define kakuAddr 10911174
|
|
#define kakuUnit 14 // 14 is 4-3 op de afstandsbediening
|
|
// Bepalingen Display
|
|
#define OLED_ADDR 60 // 60 = 0x3C / 61 = 0x3D
|
|
#define OLED_RESET 4
|
|
// Interupts
|
|
#define displaySwitch 0 // ISR adres van de drukknop om het scherm te activeren. (ISR0 = Pin2)
|
|
|
|
// Initialisatie NewRemoteTransmitter
|
|
NewRemoteTransmitter transmitter(kakuAddr, 11, 260, 4);
|
|
// Initialisatie Adafruit_SSD1306
|
|
Adafruit_SSD1306 display(OLED_RESET);
|
|
|
|
// Aanmaken benodigde variabelen
|
|
int sensorLdrValue;
|
|
int currentSensorLdrValue;
|
|
int potSwitchValue;
|
|
int potThresholdValue;
|
|
int potDimValue;
|
|
int switchValueHigh;
|
|
int switchValueLow;
|
|
int switchValueHighDispPos;
|
|
int switchValueLowDispPos;
|
|
int sensorLdrValueDispPos;
|
|
int dimLevel;
|
|
int dimLevelPercent;
|
|
int currentState;
|
|
int displayOn = 60;
|
|
int currentDimLevel = -1;
|
|
|
|
// 32x32 icoon voor licht aan.
|
|
#define BULB32_ON_HEIGHT 32
|
|
#define BULB32_ON_WIDTH 32
|
|
static const unsigned char PROGMEM bulb32_on_bmp[] =
|
|
{
|
|
B00000000, B00000010, B01000000, B00000000, // 1
|
|
B00000000, B01000010, B01000010, B00000000, // 2
|
|
B00000000, B01000010, B01000010, B00000000, // 3
|
|
B00000100, B00100000, B00000100, B00100000, // 4
|
|
B00000010, B00000111, B11100000, B01000000, // 5
|
|
B00000001, B00011111, B11111000, B10000000, // 6
|
|
B00000000, B00111111, B11111100, B00000000, // 7
|
|
B00111000, B01111111, B11111110, B00011100, // 8
|
|
B00000100, B11111111, B11111111, B00100000, // 9
|
|
B00000001, B11111111, B11111111, B10000000, // 10
|
|
B00000001, B11111111, B11111111, B10000000, // 11
|
|
B00000011, B11111111, B11111111, B11000000, // 12
|
|
B00111011, B11111111, B11111111, B11011100, // 13
|
|
B00000011, B11111111, B11111111, B11000000, // 14
|
|
B00000011, B11111111, B11111111, B11000000, // 15
|
|
B00000011, B11111111, B11111111, B11000000, // 16
|
|
B01110011, B11111111, B11111111, B11011100, // 17
|
|
B00000011, B11111111, B11111111, B11000000, // 18
|
|
B00000001, B11111111, B11111111, B10000000, // 19
|
|
B00000001, B11111111, B11111111, B10000000, // 20
|
|
B00000100, B11111111, B11111111, B00100000, // 21
|
|
B00011000, B01111111, B11111110, B00011000, // 22
|
|
B00000000, B00111111, B11111100, B00000000, // 23
|
|
B00000001, B00011111, B11111000, B10000000, // 24
|
|
B00000010, B00001111, B11110000, B01000000, // 25
|
|
B00000100, B00001111, B11110000, B00100000, // 26
|
|
B00000000, B00001111, B11110000, B00000000, // 27
|
|
B00000000, B00000000, B00000000, B00000000, // 28
|
|
B00000000, B00001111, B11110000, B00000000, // 29
|
|
B00000000, B00000000, B00000000, B00000000, // 30
|
|
B00000000, B00001111, B11110000, B00000000, // 31
|
|
B00000000, B00000111, B11100000, B00000000 // 32
|
|
};
|
|
// 32x32 icoon voor licht uit.
|
|
#define BULB32_OFF_HEIGHT 32
|
|
#define BULB32_OFF_WIDTH 32
|
|
static const unsigned char PROGMEM bulb32_off_bmp[] =
|
|
{
|
|
B00000000, B00000000, B00000000, B00000000, // 1
|
|
B00000000, B00000000, B00000000, B00000000, // 2
|
|
B00000000, B00000000, B00000000, B00000000, // 3
|
|
B00000000, B00000000, B00000000, B00000000, // 4
|
|
B00000000, B00000111, B11100000, B00000000, // 5
|
|
B00000000, B00011100, B00111000, B00000000, // 6
|
|
B00000000, B00110000, B00001100, B00000000, // 7
|
|
B00000000, B01100000, B00000110, B00000000, // 8
|
|
B00000000, B11000000, B00000011, B00000000, // 9
|
|
B00000001, B10000000, B00000001, B10000000, // 10
|
|
B00000001, B00000000, B00000000, B10000000, // 11
|
|
B00000011, B00000000, B00000000, B11000000, // 12
|
|
B00000010, B00000000, B00000000, B01000000, // 13
|
|
B00000010, B00000000, B00000000, B01000000, // 14
|
|
B00000010, B00000000, B00000000, B01000000, // 15
|
|
B00000010, B00000000, B00000000, B01000000, // 16
|
|
B00000010, B00000000, B00000000, B01000000, // 17
|
|
B00000011, B00000000, B00000000, B11000000, // 18
|
|
B00000001, B00000000, B00000000, B10000000, // 19
|
|
B00000001, B10000000, B00000001, B10000000, // 20
|
|
B00000000, B11000000, B00000011, B00000000, // 21
|
|
B00000000, B01100000, B00000110, B00000000, // 22
|
|
B00000000, B00110000, B00001100, B00000000, // 23
|
|
B00000000, B00011000, B00011000, B00000000, // 24
|
|
B00000000, B00001000, B00010000, B00000000, // 25
|
|
B00000000, B00001000, B00010000, B00000000, // 26
|
|
B00000000, B00001111, B11110000, B00000000, // 27
|
|
B00000000, B00000000, B00000000, B00000000, // 28
|
|
B00000000, B00001111, B11110000, B00000000, // 29
|
|
B00000000, B00000000, B00000000, B00000000, // 30
|
|
B00000000, B00001111, B11110000, B00000000, // 31
|
|
B00000000, B00000111, B11100000, B00000000 // 32
|
|
};
|
|
|
|
void setup() {
|
|
// Start Display
|
|
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR, HEX);
|
|
display.clearDisplay();
|
|
|
|
// Start debug-led
|
|
pinMode(ledPin, OUTPUT);
|
|
|
|
// Opstartscherm
|
|
// Lamp laten knipperen op het opstartscherm en op de daadwerkelijke schakelaar/dimmer.
|
|
display.setTextSize(1);
|
|
display.setTextColor(WHITE);
|
|
display.setCursor(0, 0);
|
|
display.println("VERLICHTING");
|
|
display.println("");
|
|
display.println("v1.2.1 (20150207)");
|
|
display.println("v1.2.0 (20141211)");
|
|
display.println("v1.1.3 (20141202)");
|
|
display.println("v1.1.2 (20141118)");
|
|
//display.println("v1.1.1 (20141117)");
|
|
//display.println("v1.1.0 (20141116)");
|
|
display.println("|");
|
|
display.println("v1.0.0 (20141116)");
|
|
digitalWrite(ledPin, LOW);
|
|
transmitter.sendUnit(kakuUnit, false);
|
|
currentState = 0;
|
|
display.drawBitmap(97, 0, bulb32_off_bmp, 32, 32, 1);
|
|
display.display();
|
|
delay(1000);
|
|
digitalWrite(ledPin, HIGH);
|
|
transmitter.sendUnit(kakuUnit, true);
|
|
currentState = 1;
|
|
display.drawBitmap(97, 0, bulb32_on_bmp, 32, 32, 1);
|
|
display.display();
|
|
delay(1000);
|
|
display.display();
|
|
display.clearDisplay();
|
|
|
|
// initieel ophalen van LDR-waarde
|
|
currentSensorLdrValue = analogRead(sensorLdr);
|
|
|
|
// Aanmaken interupt
|
|
attachInterrupt(0, isr0, RISING);
|
|
}
|
|
|
|
void loop() {
|
|
// Ophalen analoge waarden
|
|
sensorLdrValue = analogRead(sensorLdr); // LDR
|
|
potSwitchValue = analogRead(potSwitch); // De potmeter voor het schakelpunt
|
|
potThresholdValue = analogRead(potThreshold); // De potmeter voor de hysteresis
|
|
potDimValue = analogRead(potDim); // De potmeter voor het dim-niveau
|
|
|
|
// In geval van abrupte wijziging in LDR waarde dit opvangen door niet meer als 1 waarde afwijken van vorige meting
|
|
if (sensorLdrValue > currentSensorLdrValue) {
|
|
currentSensorLdrValue++;
|
|
sensorLdrValue = currentSensorLdrValue;
|
|
}
|
|
else if (sensorLdrValue < currentSensorLdrValue) {
|
|
currentSensorLdrValue--;
|
|
sensorLdrValue = currentSensorLdrValue;
|
|
}
|
|
|
|
// Huidige LDR-waarde opslaan voor de volgende ronde.
|
|
currentSensorLdrValue = sensorLdrValue;
|
|
|
|
// Berekenen van de hysteresis en de waarde niet onder/boven de min/max LDR-waarde uit laten komen.
|
|
switchValueHigh = potSwitchValue + (potThresholdValue / 2);
|
|
if (switchValueHigh > 1022) { // Door 1022 te gebruiken kán er nog geschakeld worden. Bij 1023 valt de LDR bij max altijd in de hysteresis.
|
|
switchValueHigh = 1022;
|
|
}
|
|
switchValueLow = potSwitchValue - (potThresholdValue / 2);
|
|
if (switchValueLow < 1) { // Door 1 te gebruiken kán er nog geschakeld worden. Bij 0 valt de LDR bij min altijd in de hysteresis.
|
|
switchValueLow = 1;
|
|
}
|
|
|
|
// Dim-niveau volgens potmeter omzetten in waarden voor de KAKU-dimmer
|
|
// 1023 is 1020 geworden. Potmeters komen nooit helemaal op maximaal (niet stabiel althans) daarrom iets onder de maximaal-waarde.
|
|
dimLevel = map(potDimValue, 0, 1020, 0, 15); // 0 t/m 1020 omzetten naar 0 t/m 15.
|
|
// Dim-niveau volgens potmeter omzetten in procenten voor weergave op het scherm
|
|
dimLevelPercent = map(potDimValue, 0, 1020, 0, 100); // 0 t/m 1020 omzetten naar 0 t/m 100.
|
|
|
|
// Aanschakelen KAKU-dimmer als deze (volgens het programma) uit zou zijn mits aan de voorwaarden wordt voldaan.
|
|
if (sensorLdrValue <= switchValueLow && currentDimLevel != dimLevel) {
|
|
digitalWrite(ledPin, HIGH);
|
|
// Controleren of de huidige staat uit is. Zo ja, eerst een signaal versturen dat de unit aan moet.
|
|
// Dit is bij Dimmers niet nodig maar als er zich een schakelaar op dit kanaal bevindt dan wordt deze ook geschakeld.
|
|
if (currentState == 0) {
|
|
transmitter.sendUnit(kakuUnit, true);
|
|
}
|
|
transmitter.sendDim(kakuUnit, dimLevel);
|
|
currentDimLevel = dimLevel;
|
|
currentState = 1;
|
|
}
|
|
// Uitschakelen KAKU-dimmer als deze (volgens het programma) aan zou zijn mits aan de voorwaarden wordt voldaan.
|
|
else if (sensorLdrValue >= switchValueHigh && currentState == 1) {
|
|
digitalWrite(ledPin, LOW);
|
|
transmitter.sendUnit(kakuUnit, false);
|
|
currentDimLevel = -1;
|
|
currentState = 0;
|
|
}
|
|
|
|
if (displayOn > 1) {
|
|
// displayOn in mindering brengen
|
|
displayOn--;
|
|
|
|
// Gegevens voor het display.
|
|
// Potmeter-waarden omzetten naar scherm-posities.
|
|
switchValueLowDispPos = map(switchValueLow, 0, 1023, 0, 127);
|
|
switchValueHighDispPos = map(switchValueHigh, 0, 1023, 0, 127);
|
|
sensorLdrValueDispPos = map(sensorLdrValue, 0, 1023, 0, 127);
|
|
|
|
// Tekst weergeven op het scherm
|
|
display.setTextSize(1);
|
|
display.setTextColor(WHITE);
|
|
display.setCursor(0, 0);
|
|
display.println("VERLICHTING");
|
|
display.println("");
|
|
display.println("Dimmer-niveau:");
|
|
display.print(" ");
|
|
display.print(dimLevel);
|
|
display.print(" (");
|
|
display.print(dimLevelPercent);
|
|
display.println("%)");
|
|
|
|
// Lamp-icoon
|
|
// Icoon voor licht aan weergeven als het licht (volgens het programma) aan is.
|
|
if (currentState == 1 ) {
|
|
display.drawBitmap(97, 0, bulb32_on_bmp, 32, 32, 1);
|
|
}
|
|
// Icoon voor licht uit weergeven als het licht (volgens het programma) uit is.
|
|
else {
|
|
display.drawBitmap(97, 0, bulb32_off_bmp, 32, 32, 1);
|
|
}
|
|
|
|
// Lijnen tekenen voor visuele weergave (op het scherm) van de gegevens
|
|
display.drawLine(0, 40, 127, 40, WHITE);
|
|
display.drawLine(0, 52, 127, 52, WHITE);
|
|
display.drawLine(0, 63, 127, 63, WHITE);
|
|
display.fillRect(switchValueLowDispPos, 48, switchValueHighDispPos - switchValueLowDispPos + 1, 9, WHITE);
|
|
display.drawLine(sensorLdrValueDispPos, 40, sensorLdrValueDispPos, 63, WHITE);
|
|
}
|
|
|
|
// Display uitvoer zolang er data is.
|
|
if (displayOn > 0) {
|
|
// Uitvoer naar display en display-buffer leegmaken.
|
|
display.display();
|
|
display.clearDisplay();
|
|
}
|
|
|
|
// 1000ms (1sec) wachten voor het starten van de volgende ronde.
|
|
// Wordt vooral gebruikt om het abrupt wijzigen van de LDR tegen te gaan.
|
|
delay(1000);
|
|
}
|
|
|
|
void isr0() //interrupt service routine
|
|
{
|
|
displayOn = 120;
|
|
}
|
|
|