Az előző órának a programját módosítottam olyan értelemben, hogy az akkori egy digitenkénti kijelzés módosult azonos időben négy digitre. A program váza teljesen ugyan az, csak kiegészítettem a nyomógomb kezelésével, valamint switch-case szerkezettel a további adatok megjelenítéséhez az időn felül, mint például: év, hónap, nap és a jelenlegi hőmérséklet. Belekerült itt is a téli és nyári időszámítás automatikus beállítása.
Változók és könyvtárak deklarálása:
#include "Wire.h"
#include "DS3231.h"
#define DS3231 B1101000 // I2C address
const int pinPB = 6; // Pushbutton 1
int buttonState; // the current reading from the input pin
int lastButtonState = 0; // the previous reading from the input pin
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
const unsigned long debounceDelay = 100; // the debounce time; increase if the output flickers
int readingButton = 0;
int switchCase = 0;
Szegmensek bájtjainak deklarálása és mellettük a lábkiosztások és portok:
byte segment_digit1[] = {0, 1, 2, 3, 4, 5, 8};
byte segment_digit2[] = {9, 10, 11, 12, 13, 14, 15};
byte segment_digit3[] = {18, 19, 20, 21, 22, 23, 31};
byte segment_digit4[] = {30, 29, 28, 27, 26, 25, 24};
További változók a DS3231-es modulhoz kapcsolódóan, Binárisból decimálisba és decimálisból binárisba való átalakítások, hőmérsékletváltozó és kalibrált értékek hozzáadása:
byte second=0, minute=0, hour=0, weekday=0, day=0, month=0, year=0;
byte year_1000 = 2;
byte year_100 = 0;
byte DECTOBCD(byte val);
byte BCDTODEC(byte val);
byte Temperature = 0; // Temperature variable
int8_t MostSignificantBit = 0; // MSB will be the whole part of the temperature LSB - Fraction of the temperature - Not used
byte Calibration = 6; // Calibration flag
byte degree = 10; // To display degree symbol and C
Alprogramok meghívása:
void updateTime();
void printTime();
void print7Digit(byte number);
Téli és nyári időszámítás beállítása:
bool isDaylightSavingTime(int year, int month, int day, int weekday) {
// The Daylight saving time will starts at the last sunday of March
if (month == 3 && (day + 7 - weekday) > 31) {
return true;
}
// The daylight saving time will ends at the last sunday of October
if (month == 10 && (day + 7 - weekday) > 31) {
return false;
}
// From April to September it is always daylight saving time
if (month > 3 && month < 10) {
return true;
}
//The default is the winter time
return false;
}
A program következő része a void setup(), mely minden indítás után csak egyszer fut le. Itt törénik a szegmensek inicializálása, és az I2C kommunikáció inicializálása is:
void setup() {
byte init_segm; // Byte for the segments initialization (for for cycle)
Wire.begin(); // Begin I2C communication
// Initialize segments and pull them down
for (init_segm=0; init_segm pinMode(segment_digit1[init_segm], OUTPUT);
pinMode(segment_digit2[init_segm], OUTPUT);
pinMode(segment_digit3[init_segm], OUTPUT);
pinMode(segment_digit4[init_segm], OUTPUT);
pinMode(pinPB, INPUT);
digitalWrite(segment_digit1[init_segm], HIGH);
digitalWrite(segment_digit2[init_segm], HIGH);
digitalWrite(segment_digit3[init_segm], HIGH);
digitalWrite(segment_digit4[init_segm], HIGH);
}
}
Ezután következik a void loop(), mely minden alkalommal meghívja az alprogramokat, az updateSubroutine()-t és a printSubroutine()-t, mely updateSubroutine()-ban az idő frissítése történik valamint a printSubroutine()-ba a változók kiirása történik a kijelzőre:
updateSubroutine(); // Call updateTime subroutine - Updates and reads all the things which is needed for this project from the DS3231 each cycle
printSubroutine(); // Call printTime subroutine
checkButton(); // Call checkButton subroutine
Az updateSubroutine()-ban kezdődik meg a kommunikáció a DS3231 modullal, valamint itt történik a másodpercek, percek, órák, hét napjai, nap, hónap és év kiolvasása. Ha például március utolsó hétvégéje van, akkor itt állítja be az óra a nyári időszámítást úgy, hogy hozzáad az órához egyet, majd amikor éjfél lesz (24:00) akkor nullázza, ezért nem fog minden alkalommal csúszni az idő egy órát. Ebben a programban történik a hőmérséklet kiolvasása is (törtszámok nem kerülnek kijelzésre) valamint a nyomógomb figyelés is ebben a programban zajlik le.
void updateSubroutine() {
Wire.beginTransmission(DS3231);
Wire.write(0x00); // First register, seconds
Wire.endTransmission(); // End transmission of I2C
Wire.requestFrom(DS3231, 7);
second = BCDTODEC(Wire.read() & 0x7f);
minute = BCDTODEC(Wire.read());
hour = BCDTODEC(Wire.read() & 0x3f);
weekday = BCDTODEC(Wire.read());
day = BCDTODEC(Wire.read());
month = BCDTODEC(Wire.read() & 0x1f);
year = BCDTODEC(Wire.read() + 2000);
// Adjust daylight saving mode according to the actual date - On the last sunday of march it will be incremented by 1
if (isDaylightSavingTime(year, month, day, weekday)) {
hour +=1;
if (hour == 24) {
hour = 0;
}
}
// Reading the temperature from the DS3231
Wire.beginTransmission(DS3231);
Wire.write(0x11); // First byte of the temperature register
Wire.endTransmission();
Wire.requestFrom(DS3231, 2);
if(Wire.available() >= 2) {
MostSignificantBit = BCDTODEC(Wire.read());
}
Temperature = MostSignificantBit + Calibration;
A printSubroutine()-ban jelezzük ki az időt, évet, majd a hónapot és napot, valamint a hőmérsékletet. A kijelzésért egy switch-case szerkezet a felelős, mely a nyomógomb megnyomására változtatja a szerkezetét és ennek függvényében jelzi ki vagy az időt, az évet majd két másodperc múlva a hónapot és napot, vagy a hőmérsékletet.
void printSubroutine() {
byte printTimeVar; // Variable for pulling the segments down (to turn them off with a for cycle)
// Convert from 24 hour to 12 hour mode
byte temphour = hour % 24;
if (temphour == 0) {
// Not zero based, not one based, but 24 based.
temphour = 24;
}
switch (switchCase){
case 0:
print7Digit_Hours_1(temphour / 10);
print7Digit_Hours_2(temphour % 10);
print7Digit_Mins_1(minute/10);
print7Digit_Mins_2(minute%10);
break;
case 1:
// Reading the year
print7Digit_Hours_1(year_1000);
print7Digit_Hours_2(year_100);
print7Digit_Mins_1(year/10);
print7Digit_Mins_2(year%10);
delay(1000);
switchCase = 2;
break;
case 2:
// Display Month and Day
print7Digit_Hours_1(month / 10);
print7Digit_Hours_2(month % 10);
print7Digit_Mins_1(day/10);
print7Digit_Mins_2(day%10);
delay(1000);
switchCase = 3;
break;
case 3:
byte clear_segm;
for (clear_segm=0; clear_segm digitalWrite(segment_digit1[clear_segm], HIGH);
digitalWrite(segment_digit2[clear_segm], HIGH);
digitalWrite(segment_digit3[clear_segm], HIGH);
digitalWrite(segment_digit4[clear_segm], HIGH);
}
print7Digit_Mins_2(weekday%10);
delay(1000);
switchCase = 4;
break;
case 4:
// Display Temperature
print7Digit_Hours_1(Temperature / 10);
print7Digit_Hours_2(Temperature % 10);
print7Digit_Mins_1(degree);
print7Digit_Mins_2(degree);
delay(1000);
switchCase = 0;
}
}
A szegmenskijelzőkhöz tartozó bitmezők, melyek külön-külön deklarálják a számokat és a °C-hoz tartozó szimbólumot:
void print7Digit_Hours_1(byte number_Hours_1) {
// Bitfield for digits 0-9
const byte numtable_Hours_1[] = {
B11000000, // 0
B11111001, // 1
B00100100, // 2
B00110000, // 3
B10011001, // 4
B00010010, // 5
B10000010, // 6
B11111000, // 7
B10000000, // 8
B10010000, }; // 9
byte litpins_Hours_1 = numtable_Hours_1[number_Hours_1];
byte nums_Hours_1;
for (nums_Hours_1=0; nums_Hours_1 digitalWrite(segment_digit1[nums_Hours_1], (litpins_Hours_1>>nums_Hours_1) & 1);
}
}
// Display a single digit on the 7 segment for Hours 2/2
void print7Digit_Hours_2(byte number_Hours_2) {
// Bitfield for digits 0-9
const byte numtable_Hours_2[] = {
B11000000, // 0
B11111001, // 1
B00100100, // 2
B00110000, // 3
B10011001, // 4
B00010010, // 5
B10000010, // 6
B11111000, // 7
B10000000, // 8
B10010000, }; // 9
byte litpins_Hours_2 = numtable_Hours_2[number_Hours_2];
byte nums_Hours_2;
for (nums_Hours_2=0; nums_Hours_2 digitalWrite(segment_digit2[nums_Hours_2], (litpins_Hours_2>>nums_Hours_2) & 1);
}
}
// Display a single digit on the 7 segment for Minutes 1/2
void print7Digit_Mins_1(byte number_Mins_1) {
// Bitfield for digits 0-9
const byte numtable_Mins_1[] = {
B11000000, // 0
B11111001, // 1
B00100100, // 2
B00110000, // 3
B10011001, // 4
B00010010, // 5
B10000010, // 6
B11111000, // 7
B10000000, // 8
B10010000, // 9
B10011100, }; // Celsius degree
byte litpins_Mins_1 = numtable_Mins_1[number_Mins_1];
byte nums_Mins_1;
for (nums_Mins_1=0; nums_Mins_1 digitalWrite(segment_digit3[nums_Mins_1], (litpins_Mins_1>>nums_Mins_1) & 1);
}
}
// Display a single digit on the 7 segment for Minutes 2/2
void print7Digit_Mins_2(byte number_Mins_2) {
// Bitfield for digits 0-9
const byte numtable_Mins_2[] = {
B11000000, // 0
B11111001, // 1
B00100100, // 2
B00110000, // 3
B10011001, // 4
B00010010, // 5
B10000010, // 6
B11111000, // 7
B10000000, // 8
B10010000, // 9
B11000110,}; // Letter C
byte litpins_Mins_2 = numtable_Mins_2[number_Mins_2];
byte nums_Mins_2;
for (nums_Mins_2=0; nums_Mins_2 digitalWrite(segment_digit4[nums_Mins_2], (litpins_Mins_2>>nums_Mins_2) & 1);
}
}
A decimálisból binárisba, valamint binárisból decimálisba történő konverzió kapott helyet a program végén:
byte DECTOBCD(byte val) {
return ((val/10)<}
byte BCDTODEC(byte val) {
return (val>>4) * 10 + (val & 0xf);
}
A cikkem végén ismét közzé fogom tenni az .ino fájlt ha valaki tanulni szeretne belőle, vagy épp modosítani szeretné!
A cikk még nem ért véget, lapozz!