Skip to content

Instantly share code, notes, and snippets.

@tprochazka
Created June 9, 2014 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tprochazka/d70f4385ee50c1e965a4 to your computer and use it in GitHub Desktop.
Save tprochazka/d70f4385ee50c1e965a4 to your computer and use it in GitHub Desktop.
Code for my Arduino Learning Kit project
/*
* 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