Код: Выделить всё
char old_char[2]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
char new_char[2]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function
двоечку заменить на троечку
Код: Выделить всё
char old_char[3]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
char new_char[3]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function
Примерная схема соединения:
Весь код:
Код: Выделить всё
//matrix clock 32x8_pro_mini_v1.2 (align data & fix slow DHT22)
//include libraries:
#include "LedControl.h"
#include "FontLEDClock.h" // Font library
#include "Wire.h"
#include "RTClib.h" // DS1307 clock
#include "Button.h" // Button library by Alexander Brevig
#include "DHT.h" // DHT22
#include "EEPROM.h"
#define DS3231_I2C_ADDRESS 0x68
#define DHTPIN 7
#define DHTTYPE DHT22
// DS3231
// SCL pin -> Arduino A5
// SDA pin -> Arduino A4
// VCC pin -> Arduino +5v
// GND pin -> Arduino gnd
// Setup LED Matrix
// pin 6 is connected to the DataIn on the display
// pin 5 is connected to the CLK on the display
// pin 4 is connected to LOAD on the display (CS)
const int numDevices = 3; // number of MAX7219s used
LedControl lc = LedControl(6,4,5,numDevices); //sets the 3 pins and numDevices
//global variables
byte intensity = EEPROM.read(0); // value intensity from EEPROM (0-11)
byte clock_mode = 0; // Default clock mode. Default = 0 (basic_mode)
byte old_mode = clock_mode; // Stores the previous clock mode, so if we go to date or whatever, we know what mode to go back to after.
byte change_mode_time = 0; // Holds hour when clock mode will next change if in random mode.
unsigned long delaytime = 500; // We always wait a bit between updates of the display
int rtc[7]; // Holds real time clock output
float temp3231;
byte tMSB, tLSB;
DHT dht(DHTPIN, DHTTYPE);
// "Sunday", "Monday", "Tuesday", "Wed", "Thursday", "Friday", "Saturday"
char days[7][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
//define constants
#define NUM_DISPLAY_MODES 1 // Number display modes (conting zero as the first mode)
#define NUM_SETTINGS_MODES 1 // Number settings modes = 1 (conting zero as the first mode)
#define SLIDE_DELAY 20 // The time in milliseconds for the slide effect per character in slide mode. Make this higher for a slower effect
#define cls clear_display // Clear display
RTC_DS1307 ds1307; // Create RTC object
Button buttonA = Button(2, BUTTON_PULLUP); // Setup button A (using button library)
Button buttonB = Button(3, BUTTON_PULLUP); // Setup button B (using button library)
//--------------------------------------------------------------------------------
void setup() {
//EEPROM.write(0, 0); // ??? Only first run
digitalWrite(2, HIGH); // turn on pullup resistor for button on pin 2
digitalWrite(3, HIGH); // turn on pullup resistor for button on pin 3
digitalWrite(4, HIGH); // turn on pullup resistor for button on pin 4
//initialize the matrix panels
for (int address = 0; address < numDevices; address++) /*The MAX72XX is in power-saving mode on startup*/
{
lc.shutdown(address, false); /* Set the brightness to a medium values */
lc.setIntensity(address, intensity); /* and clear the display */
lc.clearDisplay(address);
}
//Setup DS1307 RTC
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino
#endif
ds1307.begin(); //start RTC Clock
dht.begin(); //start DHT 22 (AM2302)
//Show software hello message
printhello();
}
//--------------------------------------------------------------------------------
void loop() {
//run the clock with whatever mode is set by clock_mode - the default is set at top of code.
switch (clock_mode){
case 0:
slide();
break;
case 1:
setup_menu();
break;
case 2:
//Exit
break;
}
}
//--------------------------------------------------------------------------------
//plot a point on the display
void plot (byte x, byte y, byte val) {
//select which matrix depending on the x coord
byte address;
if (x >= 0 && x <= 7) {
address = 2;
}
if (x >= 8 && x <= 15) {
address = 1;
x = x - 8;
}
if (x >= 16 && x <= 23) {
address = 0;
x = x - 16;
}
if (val == 1) {
lc.setLed(address, y, x, true);
} else {
lc.setLed(address, y, x, false);
}
}
//--------------------------------------------------------------------------------
//clear screen
void clear_display() {
for (byte address = 0; address < numDevices; address++) {
lc.clearDisplay(address);
}
}
//--------------------------------------------------------------------------------
//fade screen down
void fade_down() {
//fade from global intensity to 1
for (byte i = intensity; i > 0; i--) {
for (byte address = 0; address < numDevices; address++) {
lc.setIntensity(address, i);
}
delay(30); //change this to change fade down speed
}
clear_display(); //clear display completely (off)
//reset intentsity to global val
for (byte address = 0; address < numDevices; address++) {
lc.setIntensity(address, intensity);
}
}
//--------------------------------------------------------------------------------
//power up led test & display hello
void printhello() {
byte i = 0;
char ver_a[6] = "SLIDE";
char ver_b[6] = "CLOCK";
char ver_c[6] = "ver.3";
//test all leds.
for (byte x = 0; x <= 23; x++) {
for (byte y = 0; y <= 7; y++) {
plot(x, y, 1);
}
}
delay(700);
fade_down();
while (ver_a[i]) {
puttinychar((i * 4), 1, ver_a[i]);
delay(35);
i++;
}
delay(700);
fade_down();
i = 0;
while (ver_b[i]) {
puttinychar((i * 4), 1, ver_b[i]);
delay(35);
i++;
}
delay(700);
fade_down();
i = 0;
while (ver_c[i]) {
puttinychar((i * 4), 1, ver_c[i]);
delay(35);
i++;
}
delay(700);
fade_down();
}
//--------------------------------------------------------------------------------
// Copy a 3x5 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate
// This is unoptimized and simply uses plot() to draw each dot.
void puttinychar(byte x, byte y, char c)
{
byte dots;
if (c >= 'A' && c <= 'Z' || (c >= 'a' && c <= 'z') ) {
c &= 0x1F; // A-Z maps to 1-26
}
else if (c >= '0' && c <= '9') {
c = (c - '0') + 32;
}
else if (c == ' ') {
c = 0; // space
}
else if (c == '.') {
c = 27; // full stop
}
else if (c == ':') {
c = 28; // colon
}
else if (c == '\'') {
c = 29; // single quote mark
}
else if (c == '!') {
c = 30; // single quote mark
}
else if (c == '%') {
c = 31; // single quote mark
}
for (byte col = 0; col < 3; col++) {
dots = pgm_read_byte_near(&mytinyfont[c][col]);
for (char row = 0; row < 5; row++) {
if (dots & (16 >> row))
plot(x + col, y + row, 1);
else
plot(x + col, y + row, 0);
}
}
}
//--------------------------------------------------------------------------------
void slide() {
byte digits_old[4] = {99, 99, 99, 99}; //old values we store time in. Set to somthing that will never match the time initially so all digits get draw when the mode starts
byte digits_new[4]; //new digits time will slide to reveal
//byte digits_x_pos[4] = {25, 19, 7, 1}; //x pos for which to draw each digit at
byte digits_x_pos[4] = {19, 13, 6, 0}; //x pos for which to draw each digit at
char old_char[3]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
char new_char[3]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function
cls();
byte old_secs = rtc[0]; //store seconds in old_secs. We compare secs and old secs. WHen they are different we redraw the display
//run clock main loop as long as run_mode returns true
while (1) {
get_time();
//check for button press
if (buttonA.uniquePress()) {
switch_mode();
return;
}
if (buttonB.uniquePress()) {
dht.readTemperature();
dht.readHumidity();
display_date();
return;
}
//if secs have changed then update the display
if (rtc[0] != old_secs) {
old_secs = rtc[0];
byte hours = rtc[2];
digits_new[0] = (rtc[1] % 10); //2 - mins ones
digits_new[1] = ((rtc[1] / 10) % 10); //3 - mins tens
digits_new[2] = (hours % 10); //4 - hour ones
digits_new[3] = ((hours / 10) % 10); //5 - hour tens
//compare digits 0 to 3 (mins and hours)
for (byte i = 0; i <= 3; i++) {
//see if digit has changed...
if (digits_old[i] != digits_new[i]) {
//run 9 step animation sequence for each in turn
for (byte seq = 0; seq <= 9 ; seq++) {
//convert digit to string
itoa(digits_old[i], old_char, 10);
itoa(digits_new[i], new_char, 10);
//draw the animation frame for each digit
slideanim(digits_x_pos[i], 0, seq, old_char[0], new_char[0]);
delay(SLIDE_DELAY);
}
}
}
//save digita array tol old for comparison next loop
for (byte i = 0; i <= 3; i++) {
digits_old[i] = digits_new[i];
}
}//secs/oldsecs
}//while loop
fade_down();
}
//--------------------------------------------------------------------------------
//this draws the animation of one char sliding on and the other sliding off. There are 8 steps in the animation, we call the function to draw one of the steps from 0-7
//inputs are are char x and y, animation frame sequence (0-7) and the current and new chars being drawn.
void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) {
//if sequence number is below 7, we need to draw the current char
if (sequence < 7) {
byte dots;
if (current_c >= 'A' && current_c <= 'Z' ) {
current_c &= 0x1F; // A-Z maps to 1-26
}
else if (current_c >= 'a' && current_c <= 'z') {
current_c = (current_c - 'a') + 41; // A-Z maps to 41-67
}
else if (current_c >= '0' && current_c <= '9') {
current_c = (current_c - '0') + 31;
}
else if (current_c == ' ') {
current_c = 0; // space
}
else if (current_c == '.') {
current_c = 27; // full stop
}
else if (current_c == '\'') {
current_c = 28; // single quote mark
}
else if (current_c == ':') {
current_c = 29; //colon
}
else if (current_c == '>') {
current_c = 30; // clock_mode selector arrow
}
byte curr_char_row_max = 8 - sequence; //the maximum number of rows to draw is 6 - sequence number
byte start_y = sequence; //y position to start at - is same as sequence number. We inc this each loop
//plot each row up to row maximum (calculated from sequence number)
for (byte curr_char_row = 0; curr_char_row <= curr_char_row_max; curr_char_row++) {
for (byte col = 0; col < 5; col++) {
dots = pgm_read_byte_near(&myfont[current_c][col]);
if (dots & (128 >> curr_char_row)) //8 row
plot(x + col, y + start_y, 1); //plot led on
else
plot(x + col, y + start_y, 0); //else plot led off
}
start_y++;//add one to y so we draw next row one down
}
}
//draw a blank line between the characters if sequence is between 1 and 7. If we don't do this we get the remnants of the current chars last position left on the display
if (sequence >= 1 && sequence <= 9) {
for (byte col = 0; col < 5; col++) {
plot(x + col, y + (sequence - 1), 0); //the y position to draw the line is equivalent to the sequence number - 1
}
}
//if sequence is above 2, we also need to start drawing the new char
if (sequence >= 2) {
//work out char
byte dots;
//if (new_c >= 'A' && new_c <= 'Z' || (new_c >= 'a' && new_c <= 'z') ) {
// new_c &= 0x1F; // A-Z maps to 1-26
//}
if (new_c >= 'A' && new_c <= 'Z' ) {
new_c &= 0x1F; // A-Z maps to 1-26
}
else if (new_c >= 'a' && new_c <= 'z') {
new_c = (new_c - 'a') + 41; // A-Z maps to 41-67
}
else if (new_c >= '0' && new_c <= '9') {
new_c = (new_c - '0') + 31;
}
else if (new_c == ' ') {
new_c = 0; // space
}
else if (new_c == '.') {
new_c = 27; // full stop
}
else if (new_c == '\'') {
new_c = 28; // single quote mark
}
else if (new_c == ':') {
new_c = 29; // clock_mode selector arrow
}
else if (new_c == '>') {
new_c = 30; // clock_mode selector arrow
}
byte newcharrowmin = 7 - (sequence - 2); //minimumm row num to draw for new char - this generates an output of 6 to 0 when fed sequence numbers 2-8. This is the minimum row to draw for the new char
byte start_y = 0; //y position to start at - is same as sequence number. we inc it each row
//plot each row up from row minimum (calculated by sequence number) up to 6
for (byte newcharrow = newcharrowmin; newcharrow <= 7; newcharrow++) {
for (byte col = 0; col < 5; col++) {
dots = pgm_read_byte_near(&myfont[new_c][col]);
if (dots & (128 >> newcharrow)) //8*5 font
plot(x + col, y + start_y, 1); //plot led on
else
plot(x + col, y + start_y, 0); //else plot led off
}
start_y++;//add one to y so we draw next row one down
}
}
}
//--------------------------------------------------------------------------------
//display_date - print the day of week, date and month with a flashing cursor effect
void display_date()
{
cls();
int t = dht.readTemperature();
int h = dht.readHumidity();
//read the date from the DS1307
byte dow = rtc[3]; // day of week 0 = Sunday
byte date = rtc[4];
byte month = rtc[5];
int i = 0;
//print the day name
i = 0;
while(days[dow][i])
{
puttinychar((i*4+6), 1, days[dow][i]);
delay(40);
i++;
}
delay(1000);
fade_down();
cls();
//print the date & month
String str_date;
if (date < 10){str_date+="0";}
str_date+=date;
str_date+=".";
if (month < 10){str_date+="0";}
str_date+=month;
i = 0;
while(str_date[i])
{
puttinychar((i*4+3), 1, str_date[i]);
delay(40);
i++;
}
delay(1000);
fade_down();
cls();
//print temp from DHT 22 (AM2302)
t = dht.readTemperature();
h = dht.readHumidity();
String str_temp = "";
String str_humi = "";
str_temp += "t:";
str_temp += String(t);
str_temp += "'";
str_humi += "h:";
str_humi += String(h);
str_humi += "%";
i = 0;
while (str_temp[i]) {
puttinychar((i*4+3), 1, str_temp[i]);
delay(40);
i++;
}
delay(1500);
fade_down();
cls();
i = 0;
while (str_humi[i]) {
puttinychar((i*4+2), 1, str_humi[i]);
delay(40);
i++;
}
delay(1500);
fade_down();
cls();
}
//--------------------------------------------------------------------------------
//dislpay menu to change the clock mode
void switch_mode() {
//remember mode we are in. We use this value if we go into settings mode, so we can change back from settings mode (6) to whatever mode we were in.
old_mode = clock_mode;
char* modes[] = {
"Clock", "Setup"
};
byte next_clock_mode;
byte firstrun = 1;
//loop waiting for button (timeout after 35 loops to return to mode X)
for (int count = 0; count < 35 ; count++) {
//if user hits button, change the clock_mode
if (buttonA.uniquePress() || firstrun == 1) {
count = 0;
cls();
if (firstrun == 0) {
clock_mode++;
}
if (clock_mode > NUM_DISPLAY_MODES) {
clock_mode = 0;
}
//print arrown and current clock_mode name on line one and print next clock_mode name on line two
char str_top[9];
//strcpy (str_top, "-");
strcpy (str_top, modes[clock_mode]);
next_clock_mode = clock_mode + 1;
if (next_clock_mode > NUM_DISPLAY_MODES) {
next_clock_mode = 0;
}
byte i = 0;
while (str_top[i]) {
puttinychar(i * 4, 1, str_top[i]);
i++;
}
firstrun = 0;
}
delay(50);
}
}
//--------------------------------------------------------------------------------
//dislpay menu to change the clock settings
void setup_menu() {
char* set_modes[] = {
"Set", "Bright", "Exit"};
//if (ampm == 0) {
// set_modes[1] = ("12 Hr");
//}
byte setting_mode = 0;
byte next_setting_mode;
byte firstrun = 1;
//loop waiting for button (timeout after 35 loops to return to mode X)
for(int count=0; count < 35 ; count++) {
//if user hits button, change the clock_mode
if(buttonA.uniquePress() || firstrun == 1){
count = 0;
cls();
if (firstrun == 0) {
setting_mode++;
}
if (setting_mode > NUM_SETTINGS_MODES) {
setting_mode = 0;
}
//print arrown and current clock_mode name on line one and print next clock_mode name on line two
char str_top[9];
strcpy (str_top, set_modes[setting_mode]);
next_setting_mode = setting_mode + 1;
if (next_setting_mode > NUM_SETTINGS_MODES) {
next_setting_mode = 0;
}
byte i = 0;
while(str_top[i]) {
puttinychar(i*4, 1, str_top[i]);
i++;
}
firstrun = 0;
}
delay(50);
}
//pick the mode
switch(setting_mode){
case 0:
set_time();
break;
case 1:
set_intensity();
break;
case 2:
//exit menu
break;
}
//change the clock from mode 6 (settings) back to the one it was in before
clock_mode=old_mode;
}
//--------------------------------------------------------------------------------
//change screen intensity
void set_intensity() {
cls();
byte i = 0;
char text[7] = "Bright";
while(text[i]) {
puttinychar((i*4), 0, text[i]);
i++;
}
//wait for button input
while (!buttonA.uniquePress()) {
levelbar (0,6,(intensity*2),2); //display the intensity level as a bar
while (buttonB.isPressed()) {
if(intensity == 11) {
intensity = 0;
cls ();
}
else {
intensity++;
}
//print the new value
i = 0;
while(text[i]) {
puttinychar((i*4), 0, text[i]);
i++;
}
//display the intensity level as a bar
levelbar (0,6,(intensity*2)+2,2);
//change the brightness setting on the displays
for (byte address = 0; address < numDevices; address++) {
lc.setIntensity(address, intensity);
}
delay(150);
}
}
EEPROM.write(0, intensity);
}
//--------------------------------------------------------------------------------
// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybar
void levelbar (byte xpos, byte ypos, byte xbar, byte ybar) {
for (byte x = 0; x < xbar; x++) {
for (byte y = 0; y <= ybar; y++) {
plot(x+xpos, y+ypos, 1);
}
}
}
//--------------------------------------------------------------------------------
//set time and date routine
void set_time() {
cls();
//fill settings with current clock values read from clock
get_time();
byte set_min = rtc[1];
byte set_hr = rtc[2];
byte set_date = rtc[4];
byte set_mnth = rtc[5];
int set_yr = rtc[6];
//Set function - we pass in: which 'set' message to show at top, current value, reset value, and rollover limit.
set_date = set_value(2, set_date, 1, 31);
set_mnth = set_value(3, set_mnth, 1, 12);
set_yr = set_value(4, set_yr, 2013, 2099);
set_hr = set_value(1, set_hr, 0, 23);
set_min = set_value(0, set_min, 0, 59);
ds1307.adjust(DateTime(set_yr, set_mnth, set_date, set_hr, set_min));
cls();
}
//--------------------------------------------------------------------------------
//used to set min, hr, date, month, year values. pass
//message = which 'set' message to print,
//current value = current value of property we are setting
//reset_value = what to reset value to if to rolls over. E.g. mins roll from 60 to 0, months from 12 to 1
//rollover limit = when value rolls over
int set_value(byte message, int current_value, int reset_value, int rollover_limit){
cls();
char messages[6][17] = {
"Min", "Hour", "Day", "Month", "Year"};
//Print "set xyz" top line
byte i = 0;
while(messages[message][i])
{
puttinychar(i*4 , 1, messages[message][i]);
i++;
}
delay(2000);
cls();
//print digits bottom line
char buffer[5] = " ";
itoa(current_value,buffer,10);
puttinychar(0 , 1, buffer[0]);
puttinychar(4 , 1, buffer[1]);
puttinychar(8 , 1, buffer[2]);
puttinychar(12, 1, buffer[3]);
delay(300);
//wait for button input
while (!buttonA.uniquePress()) {
while (buttonB.isPressed()){
if(current_value < rollover_limit) {
current_value++;
}
else {
current_value = reset_value;
}
//print the new value
itoa(current_value, buffer ,10);
puttinychar(0 , 1, buffer[0]);
puttinychar(4 , 1, buffer[1]);
puttinychar(8 , 1, buffer[2]);
puttinychar(12, 1, buffer[3]);
delay(150);
}
}
return current_value;
}
//--------------------------------------------------------------------------------
void get_time()
{
//get time
DateTime now = ds1307.now();
//save time to arrayhumidity
rtc[6] = now.year();
rtc[5] = now.month();
rtc[4] = now.day();
rtc[3] = now.dayOfWeek(); //returns 0-6 where 0 = Sunday
rtc[2] = now.hour();
rtc[1] = now.minute();
rtc[0] = now.second();
//flash arduino led on pin 13 every second
if ( (rtc[0] % 2) == 0) {
digitalWrite(13, HIGH);
}
else {
digitalWrite(13, LOW);
}
}
И библиотеки для часов на трех матрицах 8x8 MAX7219
Собрал на коленке схему для проверки работоспособности.
phpBB [media]