Created
June 9, 2014 17:57
-
-
Save tprochazka/d70f4385ee50c1e965a4 to your computer and use it in GitHub Desktop.
Code for my Arduino Learning Kit project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2014 Tomas Prochazka | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
// Sorry for non english comments, I will be translate it when I will have time ;-) | |
// vložení knihoven z kterými budeme pracovat | |
#include <TM1638.h> // https://code.google.com/p/tm1638-library/ | |
#include <idDHT11.h> // https://github.com/niesteszeck/idDHT11 - využívající přerušení (neblokuje procesor) | |
#include <LCD5110_Basic.h> // http://www.henningkarlsen.com/electronics/library.php?id=44 | |
#include <Time.h> // http://www.pjrc.com/teensy/td_libs_Time.html | |
#include <TinyGPS.h> // http://arduiniana.org/libraries/TinyGPS/ | |
#include <Timer.h> // https://github.com/JChristensen/Timer | |
#include <DS1307RTC.h> // https://www.pjrc.com/teensy/td_libs_DS1307RTC.html | |
#include <Timezone.h> // https://github.com/JChristensen/Timezone | |
#include <Wire.h> | |
#include <SoftwareSerial.h> | |
// nastavení konstant | |
const int DHT_INTERVAL = 5000; // interval čtení teploty | |
const int COMFORT_TEMPERATURE = 24; // výchozí hodnota termostatu | |
const int TIMEZONE = 1; // časové pásmo: Central European Time | |
const int DHT_TEMP_CALIBRATION = -2; // kalibrace teploty | |
const int DHT_HUM_CALIBRATION = 10; // kalibrace vlhkosti | |
// konfigurace letního a zimního času | |
TimeChangeRule myDST = {"CEST", Last, Sun, Mar, 2, +60}; // letní | |
TimeChangeRule mySTD = {"CET", Last, Sun, Oct, 3, 0}; // zimní | |
Timezone myTZ(myDST, mySTD); | |
// konfigurace knihoven (nastavení správných PINů) | |
#define DHTPIN 2 // pin na kterém máme teplotní senzor | |
#define RELAY1PIN 14 // pin na relé 1 | |
#define RELAY2PIN 15 // pin na relé 2 | |
#define RELAY3PIN 16 // pin na relé 3 | |
#define LEDPIN 13 // pin na kterém je LED přímo na Arduinu | |
#define idDHT11intNumber 0 // číslo přerušení odpovídající portu 2 pro Arduino Uno | |
idDHT11 DHT11(DHTPIN,idDHT11intNumber,readDHTCallback); | |
LCD5110 myGLCD(8,9,10,11,12); // LCD PINs | |
extern uint8_t SmallFont[]; | |
extern uint8_t MediumNumbers[]; | |
extern uint8_t BigNumbers[]; | |
SoftwareSerial SerialGPS = SoftwareSerial(4, 3); | |
TinyGPS gps; | |
TM1638 tmModule(5, 6, 7); | |
unsigned long lmDHT = millis(); | |
unsigned int lmLCD = second(); | |
int humidity; | |
int temperature; | |
int targetTemperature = COMFORT_TEMPERATURE; | |
boolean allowGpsRead = false; | |
boolean demoRunning = false; | |
boolean clearLCD = true; | |
Timer t; | |
int tDemoSnake; | |
// toto se provede jednou při zapnutí (po resetu) | |
void setup() { | |
Serial.begin(115200); | |
Serial.println("Demo application by ATom"); | |
// Nastavení PINů pro relátka do režimu, kdy lze měnit jejich stav | |
pinMode(RELAY1PIN, OUTPUT); | |
pinMode(RELAY2PIN, OUTPUT); | |
pinMode(RELAY3PIN, OUTPUT); | |
pinMode(LEDPIN, OUTPUT); | |
digitalWrite(RELAY1PIN, HIGH); | |
digitalWrite(RELAY2PIN, HIGH); | |
digitalWrite(RELAY3PIN, HIGH); | |
myGLCD.InitLCD(); | |
// Nstavení rychlosti komunikace s GPS | |
SerialGPS.begin(9600); | |
tmModule.clearDisplay(); | |
readDHT((void*)0); | |
// nastavení zdroje aktuálního času a perioda jeho získání | |
setSyncProvider(RTC.get); | |
setSyncInterval(60 * 60); | |
updateLEDButtons(); | |
// rozblikáme LED na arduinu (port 13) | |
// t.oscillate(LEDPIN, 1000, LOW); | |
// každých 5 sekund načteme aktuální teplotu s DHT čipu (je hrozně pomalý) | |
t.every(DHT_INTERVAL, readDHT, (void*)0); | |
// aktivujeme hada, který bude postupně rozsvědcovat LED na TM1638 modulu | |
t.after(6000, demoEnd, (void*)0); | |
// Aktivujeme hada voláním pomoci přerušení, díky čemuž se nebude zasekávat když se čte s DHT senzoru. | |
demoRunning = true; | |
tDemoSnake = t.every(100, demoSnake, (void*)0); | |
// Nastavení textu na LED displej | |
tmModule.setDisplayToString("AhojPeto"); | |
byte b = tmModule.getButtons(); | |
} | |
// toto se opakuje neustále dokola | |
void loop() { | |
if (allowGpsRead) { | |
readGpsTime(); | |
} | |
// pokud máme k dispozici korekntí výsledky měření teploty | |
if (DHT11.getStatus() == IDDHTLIB_OK) { | |
humidity = DHT11.getHumidity() + DHT_HUM_CALIBRATION; | |
temperature = DHT11.getCelsius() + DHT_TEMP_CALIBRATION; | |
} | |
if (temperature > 0) { | |
if (temperature < targetTemperature) { | |
// zapnutí topení | |
digitalWrite(RELAY1PIN, LOW); | |
} | |
if (temperature > targetTemperature) { | |
// vypnutí topení | |
digitalWrite(RELAY1PIN, HIGH); | |
} | |
} | |
// pokud se změnil čas o 1s aktualizujeme displej | |
if (second() != lmLCD) { | |
printLCD(); | |
lmLCD = second(); | |
} | |
checkButtons(); | |
t.update(); | |
} | |
// nasledují funkce, které řeší komplexnější úkoly | |
void updateLEDButtons() { | |
if (!demoRunning) { | |
tmModule.setLED(digitalRead(RELAY2PIN) ? TM1638_COLOR_GREEN : TM1638_COLOR_RED, 0); | |
tmModule.setLED(digitalRead(RELAY3PIN) ? TM1638_COLOR_GREEN : TM1638_COLOR_RED, 1); | |
} | |
} | |
void checkButtons() { | |
// lokální proměnné jen pro tuto funkci | |
static byte lastState = 255; | |
byte state = tmModule.getButtons(); | |
if (lastState != state && lastState != 255) { | |
if (demoForceEnd()) { // ukončení dema pokud běží | |
lastState = state; | |
return; // po ukončení už stisk dále nezpracováváme | |
} | |
if (state & 0x1) { | |
// pokud je stisknuto tlačíko 1 | |
digitalWrite(RELAY2PIN, !digitalRead(RELAY2PIN)); | |
} | |
if (state & 0x2) { | |
// pokud je stisknuto tlačíko 2 | |
digitalWrite(RELAY3PIN, !digitalRead(RELAY3PIN)); | |
} | |
if (state & 0x4) { | |
// pokud je stisknuto tlačíko 3 | |
targetTemperature--; | |
tmModule.clearDisplay(); | |
tmModule.setDisplayToString("T:" + String(targetTemperature) + " C"); | |
} | |
if (state & 0x8) { | |
// pokud je stisknuto tlačíko 3 | |
targetTemperature++; | |
tmModule.clearDisplay(); | |
tmModule.setDisplayToString("T:" + String(targetTemperature) + " C"); | |
} | |
updateLEDButtons(); | |
} | |
lastState = state; | |
} | |
void readDHT(void *context) { | |
//if (!DHT11.acquiring()) { | |
DHT11.acquire(); | |
//} | |
} | |
void readDHTCallback() { | |
// toto se zavolá, jakmile teplotní senzor dokončí měření a začne posílat data | |
// což vyvolá přerušení, procesor ukončí svou současnou činnost, skočí sem | |
// načte teplotu a vlhkost a vrátí se k činnnosti s které byl vyrušen. | |
DHT11.isrCallback(); | |
} | |
// tisk informací na LCD display | |
void printLCD() { | |
if (clearLCD) { | |
myGLCD.clrScr(); | |
clearLCD = false; | |
} | |
if (timeStatus() > timeNotSet) { | |
myGLCD.setFont(SmallFont); | |
myGLCD.print(getHumanReadableTime(), LEFT, 0); | |
} | |
if (allowGpsRead) { | |
unsigned long chars = 0; | |
unsigned short sentences = 0, failed = 0; | |
gps.stats(&chars, &sentences, &failed); | |
myGLCD.setFont(SmallFont); | |
myGLCD.printNumI(failed, RIGHT, 0); | |
} | |
myGLCD.setFont(SmallFont); | |
myGLCD.print("Teplota", LEFT, 23); | |
myGLCD.setFont(MediumNumbers); | |
myGLCD.printNumI(temperature, RIGHT, 16); | |
myGLCD.setFont(SmallFont); | |
myGLCD.print("Vlhkost", LEFT, 40); | |
myGLCD.setFont(MediumNumbers); | |
myGLCD.printNumI(humidity, RIGHT, 35); | |
} | |
void readGpsTime() { | |
while (SerialGPS.available()) { | |
if (gps.encode(SerialGPS.read())) { // process gps messages | |
// when TinyGPS reports new data... | |
unsigned long age; | |
int Year; | |
byte Month, Day, Hour, Minute, Second; | |
gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, NULL, &age); | |
if (age < 500) { | |
// set the Time to the latest GPS reading | |
setSyncProvider(NULL); | |
setTime(Hour, Minute, Second, Day, Month, Year); | |
adjustTime(TIMEZONE * SECS_PER_HOUR); | |
RTC.set(now()); | |
setSyncProvider(RTC.get); | |
clearLCD = true; | |
allowGpsRead = false; | |
} | |
} | |
} | |
} | |
String getHumanReadableTime() { | |
time_t local = myTZ.toLocal(now()); | |
String time = ""; | |
time += getTimeDigit(hour(local)); | |
time += ":"; | |
time += getTimeDigit(minute(local)); | |
time += ":"; | |
time += getTimeDigit(second(local)); | |
return time; | |
} | |
String getTimeDigit(int digit) { | |
if (digit > 9) { | |
return String(digit); | |
} else { | |
String result = "0"; | |
result += digit; | |
return result; | |
} | |
} | |
void demoSnake(void *context) { | |
static word w1 = 0x1; | |
static word w2 = 0x8000; | |
tmModule.setLEDs(w1|w2); | |
w1 = w1 << 1; | |
w2 = w2 >> 1; | |
if (w1 >= 0x8000) { | |
w1 = 0x1; | |
w2 = 0x8000; | |
} | |
} | |
boolean demoForceEnd() { | |
if (!demoRunning) { | |
return false; | |
} | |
demoRunning = false; | |
t.stop(tDemoSnake); | |
tmModule.setLEDs(0); | |
tmModule.clearDisplay(); | |
updateLEDButtons(); | |
return true; | |
} | |
void demoEnd(void *context) { | |
if (!demoRunning) { | |
return; | |
} | |
t.stop(tDemoSnake); | |
tmModule.setLEDs(0); | |
tmModule.clearDisplay(); | |
delay(300); | |
tmModule.setDisplayToString("--------"); | |
delay(500); | |
tmModule.setDisplayToString("88888888"); | |
delay(500); | |
tmModule.setDisplayToString("88888888", 0xFF); | |
delay(500); | |
tmModule.setLEDs(0xFF); | |
delay(500); | |
tmModule.setLEDs(0xFF << 8); | |
for(int i=0; i < 100; i++) { | |
tmModule.setLEDs(0xFF); | |
delay(1); | |
tmModule.setLEDs(0xFF << 8); | |
delay(1); | |
} | |
delay(1000); | |
tmModule.clearDisplay(); | |
tmModule.setLEDs(0); | |
allowGpsRead = true; | |
demoRunning = false; | |
updateLEDButtons(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment