산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

미니 LED 매트릭스 시계

구성품 및 소모품

Arduino Nano R3
× 1
Maxim 통합 DS3231M - ±5ppm, I2C 실시간 클록
× 1
푸시버튼 스위치, 순간
× 2
LED 매트릭스 모듈 32x8
× 1

필요한 도구 및 기계

납땜 인두(일반)

앱 및 온라인 서비스

Arduino IDE

이 프로젝트 정보

"Nick의 LED 프로젝트" 페이지에서 시계 프로젝트 마녀가 8x8 LED가 있는 4개의 매트릭스에 시간을 표시하는 것을 발견했습니다. 그는 매트릭스 모듈 패널 DIY 키트를 판매하는 "ICStation" 매장의 매트릭스로 시계를 만들었습니다.

코드를 최소한으로 변경하여 완전히 접혀 있고 훨씬 저렴한 MAX7219 도트 매트릭스 모듈 icrocontroller 4-in-1 디스플레이로 시계를 만들었습니다. 알리익스프레스에서 구매했습니다.

시계에는 많은 기능이 있습니다.

- 큰 숫자의 기본 모드

- 숫자가 화면을 켜고 끄는 슬라이드 모드

- 초 모드가 있는 작은 숫자

- 단어로 쓰여진 시간, 예. "12시 10분"

- 날짜 표시

- 12/24시간 옵션

- 밝기 옵션

- 몇 시간마다 디스플레이 모드를 변경하는 임의의 시계 모드 옵션.

- 설정 및 디스플레이 선택을 위한 푸시 버튼 방식 메뉴.

회로에서 볼 수 있듯이 매트릭스를 제외하고 arduino 보드, 실시간 클럭 모듈 및 설정을 위한 두 개의 푸시 버튼이 필요합니다. 아래 링크에서 라이브러리 및 수정된 코드를 다운로드할 수 있습니다.

<섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

코드

<울>
  • 코드
  • 도서관
  • 코드Arduino
    <사전>/************************************************ *************************Mini Clock v1.0, 2014년 7월 Nick Hall작성 GPL 조건에 따라 배포. 빌드 방법에 대한 도움말 시계 내 블로그 참조:http://123led.wordpress.com/IDE v1.6.5에서 테스트됨 ***************************** ******************************************///라이브러리 포함:#포함 "LedControl.h#include // 글꼴 라이브러리#include // DS1307 clock#include "RTClib.h" // DS1307 clock#include // 버튼 라이브러리 by Alexander Brevig// LED Matrix 설정// 핀 12는 디스플레이의 DataIn에 연결// 핀 11은 디스플레이의 CLK에 연결// 핀 10은 디스플레이의 LOAD에 연결LedControl lc =LedControl(12, 11, 10, 4); // 3개의 핀을 12, 11 및 10으로 설정한 다음 4개의 디스플레이를 설정합니다(최대 8개의 디스플레이)//전역 변수byte intensity =7; // 기본 강도/밝기(0-15)byte clock_mode =0; // 기본 시계 모드. 기본값 =0(basic_mode)bool random_mode =0; // 무작위 모드 정의 - 몇 시간마다 표시 유형을 변경합니다. 기본값 =0(오프)바이트 old_mode =clock_mode; // 이전 시계 모드를 저장하므로 날짜 등으로 이동하면 after.bool ampm =0으로 돌아갈 모드를 알 수 있습니다. // 12시간 또는 24시간을 정의합니다. 0 =24시간. 1 =12시간 바이트 change_mode_time =0; // 무작위 모드인 경우 시계 모드가 다음에 변경될 때 시간을 유지합니다. unsigned long delaytime =500; // 항상 displayint rtc[7]; // 실시간 시계 유지 outputchar days[7][4] ={ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; //요일 배열 - 슬라이드, basic_mode 및 jumble 모드에서 사용됨(DS1307은 요일에 대해 1-7 값을 출력함)char daysfull[7][9] ={ "Sunday", "Monday", "Tuesday", "Wed ", "목요일", "금요일", "토요일"};문자 접미사[4][3] ={ "st", "nd", "rd", "th"}; // 슬라이드, basic_mode 및 jumble 모드에서 사용되는 날짜 접미사 배열. e,g, 1st 2nd ...//define constants#define NUM_DISPLAY_MODES 3 // 숫자 표시 모드(첫 번째 모드로 0 계속)#define NUM_SETTINGS_MODES 4 // 숫자 설정 모드 =6(첫 번째 모드로 0 계속)# define SLIDE_DELAY 20 // 슬라이드 모드에서 문자당 슬라이드 효과에 대한 시간(밀리초)입니다. 더 느린 효과를 위해 이 값을 높이십시오.#define cls clear_display // Clear displayRTC_DS1307 ds1307; // RTC objectButton 생성 buttonA =Button(2, BUTTON_PULLUP); // 버튼 A 설정(버튼 라이브러리 사용)Button buttonB =Button(3, BUTTON_PULLUP); // 버튼 B 설정(버튼 라이브러리 사용)void setup() { digitalWrite(2, HIGH); // 핀 2의 버튼에 대한 풀업 저항을 켭니다. digitalWrite(3, HIGH); // 핀 3의 버튼에 대한 풀업 저항을 켭니다. digitalWrite(4, HIGH); // 4번 핀의 버튼에 대한 풀업 저항을 켭니다. Serial.begin(9600); //start serial //4개의 매트릭스 패널 초기화 //LedControl을 생성할 때 이미 장치 수를 설정했습니다. int devices =lc.getDeviceCount(); //루프에서 모든 장치를 초기화해야 합니다. for (int address =0; address =0 &&x <=7) { 주소 =3; } if (x>=8 &&x <=15) { 주소 =2; x =x - 8; } if (x>=16 &&x <=23) { 주소 =1; x =x - 16; } if (x>=24 &&x <=31) { 주소 =0; x =x - 24; } if (val ==1) { lc.setLed(주소, y, x, 참); } else { lc.setLed(주소, y, x, 거짓); }}//clear screenvoid clear_display() { for (byte address =0; address <4; address++) { lc.clearDisplay(address); }}//화면 페이드 downvoid fade_down() { //전역 강도에서 1로 페이드 for (byte i =intensity; i> 0; i--) { for (byte address =0; address <4; address++) { lc .setIntensity(주소, i); } 지연(30); //페이드 다운 속도를 변경하려면 이것을 변경하십시오. } clear_display(); //디스플레이를 완전히 지우기(off) // 의도를 전역 val로 재설정 for (byte address =0; address <4; address++) { lc.setIntensity(address, intensity); }}//LED 테스트 및 디스플레이 소프트웨어 버전의 전원을 켭니다. numbervoid printver() { byte i =0; char ver_a[9] ="버전 1.0"; char ver_b[9] =" 안녕하세요! "; // 모든 LED를 테스트합니다. for (byte x =0; x <=31; x++) { for (byte y =0; y <=7; y++) { plot(x, y, 1); } } 지연(500); 페이드다운(); 동안 (ver_a[i]) { puttinychar((i * 4), 1, ver_a[i]); 지연(35); 나는 ++; } 지연(700); 페이드다운(); 나는 =0; 동안 (ver_b[i]) { puttinychar((i * 4), 1, ver_b[i]); 지연(35); 나는 ++; } 지연(700); fade_down();}// puttinychar// myfont 데이터 구조에서 메모리를 표시하기 위해 3x5 문자 상형 문자를 복사합니다. 왼쪽 상단은 주어진 좌표에 있습니다. // 이것은 최적화되지 않았으며 단순히 plot()을 사용하여 각 점을 그립니다.void puttinychar (바이트 x, 바이트 y, char c){ 바이트 점; if (c>='A' &&c <='Z' || (c>='a' &&c <='z') ) { c &=0x1F; // A-Z는 1-26에 매핑 } else if (c>='0' &&c <='9') { c =(c - '0') + 32; } else if (c ==' ') { c =0; // 공백 } else if (c =='.') { c =27; // 마침표 } else if (c ==':') { c =28; // 콜론 } else if (c =='\'') { c =29; // 작은따옴표 } else if (c =='!') { c =30; // 작은따옴표 } else if (c =='?') { c =31; // 작은따옴표 } 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); 그렇지 않으면 플롯(x + 열, y + 행, 0); } }}void putnormalchar(바이트 x, 바이트 y, char c){ 바이트 점; // if (c>='A' &&c <='Z' || (c>='a' &&c <='z') ) { // c &=0x1F; // A-Z는 1-26에 매핑됩니다. // } if (c>='A' &&c <='Z' ) { c &=0x1F; // A-Z는 1-26에 매핑 } else if (c>='a' &&c <='z') { c =(c - 'a') + 41; // A-Z는 41-67에 매핑 } else if (c>='0' &&c <='9') { c =(c - '0') + 31; } else if (c ==' ') { c =0; // 공백 } else if (c =='.') { c =27; // 마침표 } else if (c =='\'') { c =28; // 작은따옴표 } else if (c ==':') { c =29; // clock_mode 선택 화살표 } else if (c =='>') { c =30; // clock_mode 선택 화살표 } else if (c>=-80 &&c <=-67) { c *=-1; } for (char col =0; col <5; col++) { 점 =pgm_read_byte_near(&myfont[c][col]); for (char row =0; row <7; row++) { //플로팅을 시도하기 전에 화면에 좌표가 있는지 확인 //if ((x>=0) &&(x <=31) &&(y>=0) &&(y <=7)){ if (dots &(64>> row)) { // 7행만. 플롯(x + 열, y + 행, 1); } else { 플롯(x + 열, y + 행, 0); } //} } }}//small_mode//초 단위로 작은 3x5 문자로 시간 표시 displayvoid small_mode() { char textchar[8]; // 디스플레이의 16자 바이트 mins =100; //분 바이트 초 =rtc[0]; //초 바이트 old_secs =secs; //오래된 초 값 유지 - 초가 마지막으로 업데이트된 시간 표시 - 초가 변경되었는지 확인하는 데 사용 cls(); // run_mode가 true를 반환하는 한 시계 메인 루프를 실행합니다. while (run_mode()) { get_time(); //버튼 누름 확인 if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); 반품; } //초가 변경되면 디스플레이에서 업데이트합니다. secs =rtc[0]; if (secs !=old_secs) { //초 char 버퍼[3]; itoa(초, 버퍼, 10); //수정 - 그렇지 않으면 num에 선행 0이 있는 경우와 같이, 예를 들어 "03"초, ito는 이것을 공백 "3"이 있는 문자로 변환합니다. if (초 <10) { 버퍼[1] =버퍼[0]; 버퍼[0] ='0'; } 퍼티니 문자(20, 1, ':'); //초 콜론 puttinychar( 24, 1, buffer[0]); //초 puttinychar( 28, 1, 버퍼[1]); //초 old_secs =초; } //분이 변경되면 시간이 변경됩니다. if (mins !=rtc[1]) { //다음 번 비교를 위해 재설정 mins =rtc[1]; 바이트 시간 =rtc[2]; if (시간> 12) { 시간 =시간 - ampm * 12; } if (시간 <1) { 시간 =시간 + ampm * 12; } //바이트 다우 =rtc[3]; // DS1307은 0 - 6을 출력합니다. 여기서 0은 Sunday0 - 6이고 0은 Sunday입니다. //바이트 날짜 =rtc[4]; //문자 설정 char buffer[3]; itoa(시간, 버퍼, 10); //수정 - 그렇지 않으면 num에 선행 0이 있는 경우와 같이, 예를 들어 "03"시간, ito는 이것을 공백 "3"이 있는 문자로 덮습니다. if (시간 <10) { 버퍼[1] =버퍼[0]; // 12시간 모드인 경우 선행 0을 비워둡니다. if (ampm) { 버퍼[0] =' '; } else { 버퍼[0] ='0'; } } //시간 설정 문자 textchar[0] =buffer[0]; textchar[1] =버퍼[1]; 텍스트 문자[2] =':'; itoa(분, 버퍼, 10); if (분 <10) { 버퍼[1] =버퍼[0]; 버퍼[0] ='0'; } //최소 문자 설정 textchar[3] =buffer[0]; textchar[4] =버퍼[1]; //초 수행 textchar[5] =':'; 버퍼[3]; 초 =rtc[0]; itoa(초, 버퍼, 10); //수정 - 그렇지 않으면 num에 선행 0이 있는 경우와 같이, 예를 들어 "03"초, ito는 이것을 공백 "3"이 있는 문자로 변환합니다. if (초 <10) { 버퍼[1] =버퍼[0]; 버퍼[0] ='0'; } //초 설정 textchar[6] =buffer[0]; textchar[7] =버퍼[1]; 바이트 x =0; 바이트 y =0; //각 문자 출력 for (byte x =0; x <6; x++) { puttinychar( x * 4, 1, textchar[x]); } } 지연(50); } fade_down();}// basic_mode()// 5x7 문자로 시간 표시void basic_mode(){ cls(); 문자 버퍼[3]; // rtc 값을 char로 변환하기 위해 int에서 char로 변환하려면 화면에 인쇄할 수 있습니다. byte offset =0; // 12시간 모드에 있고 시계가 3자리만 표시할 때 숫자의 x 위치를 오프셋하고 디스플레이 중앙에 표시하는 데 사용됩니다. 예를 들어 3:21 바이트 x, y; // 12시간 모드에서 12:59 -> 1:00am을 굴릴 때 디스플레이의 왼쪽 "1" 위에 투명한 상자를 그리는 데 사용됩니다. // ampm이 1바이트로 설정된 경우 12/24시간 변환 수행 시간 =rtc[2]; if (시간> 12) { 시간 =시간 - ampm * 12; } if (시간 <1) { 시간 =시간 + ampm * 12; } // 오프셋 변환 수행 if (ampm &&hours <10) { offset =2; } //다음 분을 설정합니다. //set_next_date()에 날짜를 표시합니다. // 처음에 mins를 값 100으로 설정 - 시계의 첫 번째 루프에서 rtc[1]과 같지 않을 것입니다. 즉, 함수 byte secs =100을 입력할 때 시계 표시를 그립니다. 최소 바이트 =100; 정수 개수 =0; //run_mode가 true를 반환하는 한 클럭 메인 루프를 실행합니다. while (run_mode()) { //클럭 칩에서 시간을 가져옵니다. get_time(); //버튼 누름 확인 if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); 반품; } //자동으로 날짜를 표시할 시간인지 확인 //check_show_date(); // 깜박임을 그립니다. 초가 변경된 경우 켜짐으로 표시됩니다. if (secs !=rtc[0]) { //초를 새로운 값으로 업데이트 secs =rtc[0]; // 그리기 :플롯(15 - 오프셋, 2, 1); //최고점 플롯(15 - 오프셋, 5, 1); //하위 포인트 수 =400; } //카운트가 다 떨어지면 :를 끕니다. if (count ==0) { plot (15 - offset, 2, 0); //최고점 플롯(15 - 오프셋, 5, 0); //하점 } else { count--; } // 버튼이 눌렸거나 mins !=rtc[1]인 경우 디스플레이를 다시 그립니다. 즉, 시간이 분 단위로 저장한 것에서 변경된 경우(분이 100일 때 함수를 처음 입력할 때도 트리거됨) if (mins !=rtc[1]) { //분과 시간을 새로운 값으로 업데이트 mins =rtc[1]; 시간 =rtc[2]; // 12시간 모드로 설정된 ampm 시간 조정 if (hours> 12) { hours =hours - ampm * 12; } if (시간 <1) { 시간 =시간 + ampm * 12; } itoa(시간, 버퍼, 10); //시간 <10인 경우 숫자 예. "3"시간, ito는 이것을 공백 "3"이 있는 문자로 변환합니다. 이는 우리가 원하지 않는 if (hours <10) { buffer[1] =buffer[0]; 버퍼[0] ='0'; } //시간 인쇄 // 12시간 모드이고 시간 <10이면 선행 0을 인쇄하지 않고 오프셋을 설정하여 디스플레이 중앙에 3자리 숫자를 표시합니다. if (ampm &&시간 <10) { 오프셋 =2; //시간이 오전 1시이면 오프셋이 변경되므로 전체 디스플레이를 지우고 이전 12:59를 비워야 합니다. if ((hours ==1 &&mins ==0) ) { cls(); } } else { // 그렇지 않으면 오프셋이 없고 인쇄 시간 10자리 오프셋 =0; //시간이 오전 10시이면 오프셋이 변경되므로 전체 디스플레이를 지우고 이전 9:59를 비워야 합니다. if (hours ==10 &&mins ==0) { cls(); } putnormalchar(1, 0, 버퍼[0]); } //시간 1자리 출력 putnormalchar(7 - offset, 0, buffer[1]); //print mins //mins <10인 경우 앞에 0을 추가 itoa (mins, buffer, 10); if (분 <10) { 버퍼[1] =버퍼[0]; 버퍼[0] ='0'; } //최소 10과 1의 숫자를 출력합니다. putnormalchar(19 - offset, 0, buffer[0]); putnormalchar(25 - 오프셋, 0, 버퍼[1]); } } fade_down();}//basic_mode와 비슷하지만 슬라이드 효과가 있습니다. //시간을 저장하는 오래된 값. 모드가 시작될 때 모든 숫자가 그려지도록 처음에는 시간과 절대 일치하지 않는 것으로 설정합니다. byte numeric_new[4]; //새로운 숫자 시간은 바이트를 나타내기 위해 슬라이드할 것입니다.digits_x_pos[4] ={25, 19, 7, 1}; // 각 숫자를 그릴 위치 x char old_char[2]; // itoa를 사용하여 현재 숫자(바이트 유형)를 애니메이션 함수에 전달할 char로 전치할 때 사용 char new_char[2]; // itoa를 사용하여 새 숫자(바이트 유형)를 char로 변환하여 애니메이션 함수에 전달할 때 사용 //old_chars - 디스플레이에 5일 및 날짜 접미사 문자를 저장합니다. 예를 들어 "월"과 "성". 이러한 문자가 업데이트될 때 현재 문자로 슬라이드 애니메이션에 이러한 문자를 제공합니다. //처음에 A로 보냈는데, 이것은 clocl이 모드에 들어가고 마지막 문자가 저장되지 않았을 때 사용됩니다. //char old_chars[6] ="AAAAAA"; //디스플레이에 시계 콜론을 표시합니다. cls(); putnormalchar( 13, 0, ':'); 바이트 old_secs =rtc[0]; //old_secs에 초를 저장합니다. 초와 이전 초를 비교합니다. 그것들이 다를 때 우리는 디스플레이를 다시 그립니다. // run_mode가 true를 반환하는 한 시계 메인 루프를 실행합니다. while (run_mode()) { get_time(); //버튼 누름 확인 if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); 반품; } //초가 변경된 경우 디스플레이를 업데이트합니다. if (rtc[0] !=old_secs) { old_secs =rtc[0]; // ampm이 1바이트로 설정된 경우 12/24시간 변환 수행 시간 =rtc[2]; if (시간> 12) { 시간 =시간 - ampm * 12; } if (시간 <1) { 시간 =시간 + ampm * 12; } //모든 날짜와 시간을 개별 숫자로 분할 - Digits_new 배열에 고정 //rtc[0] =secs //저장된 위치 및 숫자 배열 //digits_new[0] =(rtc[0]%10); //0 - 1초 //digits_new[1] =((rtc[0]/10)%10); //1 - 초 십 //rtc[1] =mins 자리수_new[0] =(rtc[1] % 10); //2 - 분 1 숫자_new[1] =((rtc[1] / 10) % 10); //3 - 분 십 //rtc[2] =시간 숫자_new[2] =(시간 % 10); //4 - 시 1 숫자_new[3] =((시 / 10) % 10); //5 - 시간 십 //rtc[4] =날짜 //digits_new[6] =(rtc[4]%10); //6 - 날짜 1 //digits_new[7] =((rtc[4]/10)%10); //7 - 날짜 10 // 모든 문자의 초기 화면을 그립니다. 그런 다음 변경 사항을 그립니다. //숫자 0에서 3(분 및 시간)을 비교 for (byte i =0; i <=3; i++) { //숫자가 변경되었는지 확인... if (digits_old[i] !=digits_new[i]) { //각각에 대해 9단계 애니메이션 시퀀스를 차례로 실행 for (byte seq =0; seq <=8; seq++) { //숫자를 문자열로 변환 itoa(digits_old[i], old_char, 10); itoa(digits_new[i], new_char, 10); // 12시간 모드로 설정되고 숫자 2(시간 10 모드)에 있는 경우 이것이 0인지 확인합니다. 그렇다면 대신 비워 두어 오후 2시가 아닌 오후 2시를 얻습니다. if (ampm &&i ==3) { if (digits_new[3] ==0) { new_char[0] =' '; } if (digits_old[3] ==0) { old_char[0] =' '; } } //각 자릿수에 대한 애니메이션 프레임을 그립니다. slideanim(digits_x_pos[i], 0, seq, old_char[0], new_char[0]); 지연(SLIDE_DELAY); } } } /* //날짜 숫자 6(일)과 (7) 십을 비교합니다. 둘 중 하나라도 변경되면 날짜 행을 업데이트해야 합니다. 1월 31일 -> 2월 1일부터 날짜 10을 비교하면 1의 숫자는 변경되지 않습니다. //표시되는 요일을 변경합니다. 아래 루프는 3개의 문자 각각을 차례로 통과합니다. "MON" for (byte day_char =0; day_char <=2; day_char++){ //각 문자에 대한 애니메이션 시퀀스 실행 for (byte seq =0; seq <=8; seq++){ //요일(0 - 6 ) 이 숫자를 days char 배열로 읽습니다. 배열 0-2의 초 숫자는 요일 이름의 3개 문자를 가져옵니다. 슬라이드애님(6*day_char,8,seq,old_chars[day_char],days[rtc[3]][day_char]); //6 x day_char는 char delay(SLIDE_DELAY)에 대한 x 위치를 제공합니다. } //오래된 날짜 문자를 배열 pos 0-2의 old_chars 배열에 저장합니다. 다음에 요일을 변경하고 애니메이션에 현재 문자로 공급할 때 이것을 사용합니다. 업데이트된 문자가 새 문자로 제공됩니다. old_chars[day_char] =일[rtc[3]][day_char]; } // 날짜의 10자리(필요한 경우)와 1자리를 변경합니다. (날짜의 1자리 숫자는 항상 변경되지만 이것을 'if' 루프에 넣으면 코드가 좀 더 깔끔해집니다.) for (byte i =7; i>=6; i--){ if (digits_old[i] !=digits_new[i]) { for (byte seq =0; seq <=8; seq++){ itoa(digits_old[i],old_char,10); itoa(digits_new[i],new_char,10); 슬라이드애님(digits_x_pos[i],8,seq,old_char[0],new_char[0]); 지연(SLIDE_DELAY); } } } //일 접미사 "nd" "rd" "th" 등을 인쇄합니다. 먼저 날짜를 계산합니다. 2자 접미사 - 예:st, nd, rd, th 바이트 s =3; //접미사 배열을 읽을 위치. 바이트 날짜 =rtc[4]; if(날짜 ==1 || 날짜 ==21 || 날짜 ==31) { s =0; } else if (날짜 ==2 || 날짜 ==22) { s =1; } else if (날짜 ==3 || 날짜 ==23) { s =2; } for (byte suffix_char =0; suffix_char <=1; suffix_char++){ for (byte seq =0; seq <=8; seq++){ slideanim((suffix_char*6)+36,8,seq,old_chars[suffix_char+3 ],접미사[s][접미사_문자]); // old_char 배열 char를 현재 char로, 접미사 배열을 new char delay(SLIDE_DELAY)로 전달합니다. } // 배열 pos 3과 5에 있는 이전 chars 배열의 suffic char를 저장합니다. 다음에 이 chars를 사용하여 접미사를 변경하고 애니메이션에 현재 char로 제공합니다. 업데이트된 문자가 새 문자로 제공됩니다. old_chars[suffix_char+3] =접미사[s][suffix_char]; } }//end do date line */ //비교를 위해 이전 디지털 배열을 저장합니다. } }//secs/oldsecs }//while 루프 fade_down();}//slide에 의해 호출//이것은 한 문자가 슬라이딩되고 다른 문자가 슬라이딩하는 애니메이션을 그립니다. 애니메이션에는 8단계가 있습니다. 0-7 단계 중 하나를 그리는 함수를 호출합니다. // 입력은 char x 및 y, 애니메이션 프레임 시퀀스(0-7), 현재 및 새 문자가 그려집니다.void Slideanim(byte x, byte y, byte sequence, char current_c, char new_c) { // 하나의 문자를 끄고 다른 문자를 켜려면 순서대로 9개의 단계 또는 프레임이 필요합니다... // seq# 0123456 <-디스플레이의 행 // | ||||||| // seq0 0123456 START - 디스플레이 0-6의 모든 행은 현재 문자 행 0-6을 표시합니다. // seq1 012345 현재 문자는 디스플레이에서 한 행 아래로 이동합니다. 0-5행만 볼 수 있습니다. 표시 위치 1-6에 있습니다. 맨 위에 빈 행이 삽입되었습니다. // seq2 6 01234 현재 문자가 2행 아래로 이동합니다. 이제 디스플레이의 디스플레이 행 2-6에서 행 0-4만 표시됩니다. 디스플레이의 행 1은 비어 있습니다. 0행은 새로운 char의 6행을 보여줍니다. // seq3 56 0123 // seq4 456 012 half old / half new char // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 012346 show all rows char //위에서 우리는 볼 수 있습니다... //currentchar는 0-6, 0-5, 0-4를 실행하여 0까지 계속합니다. 시작 Y 위치는 매번 1 행씩 증가합니다. //new char는 6, 5-6, 4-6, 3-6을 차례로 실행합니다. 시작 Y 위치는 매번 1행씩 증가합니다. // 시퀀스 번호가 7보다 작으면 현재 char를 그려야 합니다. if (sequence <7) { byte dots; // if (current_c>='A' &&|| (current_c>='a' &¤t_c <='z') ) { // current_c &=0x1F; // A-Z는 1-26에 매핑됩니다. // } if (current_c>='A' &¤t_c <='Z' ) { current_c &=0x1F; // A-Z는 1-26에 매핑 } else if (current_c>='a' &¤t_c <='z') { current_c =(current_c - 'a') + 41; // A-Z는 41-67에 매핑됩니다. } else if (current_c>='0' &¤t_c <='9') { current_c =(current_c - '0') + 31; } else if (current_c ==' ') { current_c =0; // 공백 } else if (current_c =='.') { current_c =27; // 마침표 } else if (current_c =='\'') { current_c =28; // 작은따옴표 } else if (current_c ==':') { current_c =29; //콜론 } else if (current_c =='>') { current_c =30; // clock_mode 선택 화살표 } byte curr_char_row_max =7 - sequence; // 그릴 최대 행 수는 6입니다. - 시퀀스 번호 바이트 start_y =sequence; // 시작하는 y 위치 -는 시퀀스 번호와 동일합니다. 이 각 루프를 추가합니다. // 각 행을 최대 행(순서 번호에서 계산)까지 플로팅합니다. 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 (점 &(64>> curr_char_row)) plot(x + col, y + start_y, 1); // else에서 주도하는 플롯 plot(x + col, y + start_y, 0); //else plot led off } start_y++;//y에 1을 추가하여 다음 행을 하나 아래로 그립니다. } } // 시퀀스가 ​​1과 7 사이이면 문자 사이에 빈 줄을 그립니다. 이렇게 하지 않으면 다음을 얻습니다. 현재 문자의 나머지 부분은 디스플레이에 남은 마지막 위치입니다. if (sequence>=1 &&sequence <=8) { for (byte col =0; col <5; col++) { plot(x + col, y + (sequence - 1), 0); //선을 그릴 y 위치는 시퀀스 번호와 동일합니다. - 1 } } // 시퀀스가 ​​2보다 크면 새 문자 그리기도 시작해야 합니다. if (sequence>=2) { //문자 바이트를 계산합니다. 점; //if (new_c>='A' &&new_c <='Z' || (new_c>='a' &&new_c <='z') ) { // new_c &=0x1F; // A-Z는 1-26에 매핑 //} if (new_c>='A' &&new_c <='Z' ) { new_c &=0x1F; // A-Z는 1-26에 매핑됩니다. } else if (new_c>='a' &&new_c <='z') { new_c =(new_c - 'a') + 41; // A-Z는 41-67에 매핑 } else if (new_c>='0' &&new_c <='9') { new_c =(new_c - '0') + 31; } else if (new_c ==' ') { new_c =0; // 공백 } else if (new_c =='.') { new_c =27; // 마침표 } else if (new_c =='\'') { new_c =28; // 작은따옴표 } else if (new_c ==':') { new_c =29; // clock_mode 선택 화살표 } else if (new_c =='>') { new_c =30; // clock_mode 선택 화살표 } byte newcharrowmin =6 - (시퀀스 - 2); //새 문자에 대해 그릴 최소 행 번호 - 시퀀스 번호 2-8을 입력할 때 6에서 0의 출력을 생성합니다. 이것은 새로운 char 바이트 start_y =0에 대해 그릴 최소 행입니다. // 시작하는 y 위치 -는 시퀀스 번호와 동일합니다. 우리는 각 행을 증가시킵니다. // 행 최소값(순서 번호로 계산)에서 최대 6까지 각 행을 플로팅 ) { 점 =pgm_read_byte_near(&myfont[new_c][col]); if (점 &(64>> newcharrow)) plot(x + col, y + start_y, 1); // else에서 주도하는 플롯 plot(x + col, y + start_y, 0); //else plot led off } start_y++;//y에 1을 추가하여 다음 행을 하나 아래로 그립니다. } }}//숫자 대신 단어를 사용하여 시계를 인쇄합니다.void word_clock() { cls(); char 숫자[19][10] ={ "하나", "둘", "셋", "넷", "다섯", "여섯", "일곱", "여덟", "아홉", "열", "열한", "열둘", "열셋", "열넷", "열다섯", "열여섯", "열일곱", "열여덟", "열아홉" }; char numbertens[5][7] ={ "10", "20", "30", "40", "50" }; //잠재적으로 3줄 표시 char str_a[8]; 문자 str_b[8]; 문자 str_c[8]; //바이트 hour_y, mins_y; //시와 분 행의 위치와 시, 분 byte hours =rtc[2]; if (시간> 12) { 시간 =시간 - ampm * 12; } if (시간 <1) { 시간 =시간 + ampm * 12; } get_time(); // 클럭 칩에서 시간 가져오기 바이트 old_mins =100; // old_mins에 min을 저장합니다. min과 old min을 비교하고 다르면 디스플레이를 다시 그립니다. 모드가 시작될 때 디스플레이가 그려지도록 초기에 100으로 설정합니다. 바이트 분; //run_mode가 true를 반환하는 한 시계 메인 루프를 실행합니다. while (run_mode()) { //버튼 누름을 확인합니다. if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); } get_time(); //클럭 칩에서 시간 가져오기 mins =rtc[1]; //get mins //mins가 old_mins와 다른 경우 - 디스플레이 다시 그리기 if (mins !=old_mins) { //old_mins를 현재 mins 값으로 업데이트 old_mins =mins; // 다음에 비교를 위해 재설정 mins =rtc[1]; 시간 =rtc[2]; //시를 12시간 형식으로 만듭니다. if (hours> 12) { hours =hours - 12; } if (시간 ==0) { 시간 =12; } // mins 값을 두 개의 개별 숫자로 나눕니다. int minsdigit =rtc[1] % 10; 바이트 minsdigitten =(rtc[1] / 10) % 10; //mins <=10 이면 맨 윗줄은 "minsdigti past"를 읽어야 하고 맨 아래줄은 시간을 읽어야 합니다. if (mins <10) { strcpy (str_a, numbers[minsdigit - 1]); strcpy(str_b, "과거"); strcpy(str_c, 숫자[시간 - 1]); } //mins =10이면 위와 같이 minsdigit을 사용할 수 없으므로 /n 시간 이후에 10을 인쇄하는 경우가 많습니다. if (분 ==10) { strcpy (str_a, 숫자[9]); strcpy(str_b, "과거"); strcpy(str_c, 숫자[시간 - 1]); } //시간이 시간이 아닌 경우 - 즉, 두 분 숫자가 모두 0이 아닌 경우 //첫 번째 줄을 "시간"으로, 두 번째 및 세 번째 줄을 "minstens" "mins"로 읽습니다. "세 /n 스물 /n 하나" else if (minsdigitten !=0 &&minsdigit !=0 ) { strcpy (str_a, 숫자[시간 - 1]); //mins가 10대인 경우 두 번째 줄에 숫자 배열의 10대를 사용합니다(예:"fifteen" //if (mins>=11 &&mins <=19) { if (mins <=19) { strcpy (str_b, 숫자[mins - 1]); } else { strcpy (str_b, numbertens[minsdigitten - 1]); strcpy(str_c, 숫자[minsdigit - 1]); } } // 최소 숫자가 0이면 인쇄하지 않습니다. 읽기 "시간" "minstens" 예:"3 /n 20" else if (minsdigitten !=0 &&minsdigit ==0 ) { strcpy (str_a, 숫자[시간 - 1]); strcpy (str_b, 숫자tens[minsdigitten - 1]); strcpy(str_c, ""); } // 두 분이 모두 0이면, 즉 시간에 있으면 맨 위 줄은 "시간"을 읽고 맨 아래 줄은 "시"를 읽습니다. else if (minsdigitten ==0 &&minsdigit ==0 ) { strcpy (str_a, 숫자[시간 - 1]); strcpy(str_b, "O'CLOCK"); strcpy(str_c, ""); } }//작업 종료 시간 // 루프에서 실행 // "12" 바이트 인쇄 라인 len =0; 동안 (str_a[len]) { len++; }; //메시지 바이트 길이 가져오기 offset_top =(31 - ((len - 1) * 4)) / 2; // // 플롯 시간 라인 바이트 i =0; 동안 (str_a[i]) { puttinychar((i * 4) + offset_top, 1, str_a[i]); 나는 ++; } //디스플레이를 유지하지만 버튼이 눌렸는지 확인합니다. int counter =1000; while (counter> 0){ //버튼 누름 확인 if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); } 지연(1); 카운터--; } 페이드다운(); //b 라인 인쇄 len =0; 동안 (str_b[len]) { len++; }; //메시지 길이 가져오기 offset_top =(31 - ((len - 1) * 4)) / 2; 나는 =0; 동안 (str_b[i]) { puttinychar((i * 4) + offset_top, 1, str_b[i]); 나는 ++; } //표시를 유지하지만 버튼 누름 확인 counter =1000; while (카운터> 0){ if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); } 지연(1); 카운터--; } 페이드다운(); //있는 경우 라인 c를 인쇄합니다. 렌 =0; 동안 (str_c[len]) { len++; }; //메시지 길이 가져오기 offset_top =(31 - ((len - 1) * 4)) / 2; 나는 =0; 동안 (str_c[i]) { puttinychar((i * 4) + offset_top, 1, str_c[i]); 나는 ++; } 카운터 =1000; while (counter> 0){ //버튼 누름 확인 if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); } 지연(1); 카운터--; } 페이드다운(); //디스플레이를 공백으로 유지하지만 다시 시작하기 전에 버튼이 눌렸는지 확인합니다. 카운터 =1000; while (counter> 0){ //버튼 누름 확인 if (buttonA.uniquePress()) { switch_mode(); 반품; } if (buttonB.uniquePress()) { display_date(); } 지연(1); 카운터--; } } fade_down();}/// 스크롤 메시지 - 현재 사용되지 않음 - too slow.void scroll() { char message[] ={"Hello There "}; cls(); 바이트 p =6; //문자열 바이트의 현재 위치 chara[] ={0, 1, 2, 3, 4, 5}; //문자열 int x[] ={0, 6, 12, 18, 24, 30}; //각 char 바이트에 대한 xpos y =0; //y 위치 // clear_buffer(); while (message[p] !='\0') { // 6개 문자 모두 그리기 for (byte c =0; c <6; c++) { putnormalchar(x[c],y,message[ chara[c] ] ); // 각 문자 뒤에 꺼진 픽셀 라인을 그립니다. 그렇지 않으면 문자 사이의 간격에 이전 문자의 픽셀이 남습니다. for (byte yy =0; yy <8; yy ++) { plot(x[c] + 5, yy, 0); } //각 문자에서 하나씩 제거 위치 x[c] =x[c] - 1; } // 문자가 화면을 벗어나면 재설정 for (byte i =0; i <=5; i++) { if (x[i] <-5 ) { x[i] =31; 문자[i] =피; p++; } } }}//display_date - 깜박이는 커서로 요일, 날짜 및 월을 인쇄합니다. effectvoid display_date(){ cls(); //DS1307 바이트에서 날짜 읽기 dow =rtc[3]; // 요일 0 =일요일 바이트 날짜 =rtc[4]; 바이트 월 =rtc[5] - 1; //디스플레이에 출력할 월 이름의 배열. char monthnames[12][9] ={ "January", "February", "March", "April", "May", "June", "July"로 플레이할 수 있는 문자가 8자뿐이므로 일부는 단축되었습니다. , "8월", "9월", "10월", "11월", "12월" }; //요일 이름을 출력합니다. //텍스트의 길이를 픽셀 단위로 얻습니다. 그러면 나머지 픽셀 b2를 구분하고 오프셋 바이트로 사용하여 디스플레이 중앙에 텍스트를 표시할 수 있습니다. len =0; 동안(일 전체[다우][렌]) { 렌++; }; 바이트 오프셋 =(31 - ((len-1)*4)) / 2; //our offset to centre up the text //print the name int i =0; while(daysfull[dow][i]) { puttinychar((i*4) + offset , 1, daysfull[dow][i]); 나는 ++; } 지연(1000); fade_down(); cls(); // print date numerals char buffer[3]; itoa(date,buffer,10); offset =10; //offset to centre text if 3 chars - e.g. 3rd // first work out date 2 letter suffix - eg st, nd, rd, th etc // char suffix[4][3]={"st", "nd", "rd", "th" }; is defined at top of code byte s =3; if(date ==1 || date ==21 || date ==31) { s =0; } else if (date ==2 || date ==22) { s =1; } else if (date ==3 || date ==23) { s =2; } //print the 1st date number puttinychar(0+offset, 1, buffer[0]); //if date is under 10 - then we only have 1 digit so set positions of sufix etc one character nearer byte suffixposx =4; //if date over 9 then print second number and set xpos of suffix to be 1 char further away if (date> 9){ suffixposx =8; puttinychar(4+offset, 1, buffer[1]); offset =8; //offset to centre text if 4 chars } //print the 2 suffix characters puttinychar(suffixposx+offset, 1, suffix[s][0]); puttinychar(suffixposx+4+offset, 1, suffix[s][1]); 지연(1000); fade_down(); //print the month name //get length of text in pixels, that way we can centre it on the display by divindin the remaining pixels b2 and using that as an offset len =0; while(monthnames[month][len]) { len++; }; offset =(31 - ((len-1)*4)) / 2; //our offset to centre up the text i =0; while(monthnames[month][i]) { puttinychar((i*4) +offset, 1, monthnames[month][i]); 나는 ++; } 지연(1000); fade_down();}//dislpay menu to change the clock modevoid 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[] ={ "Basic", "Small", "Slide", "Words", "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 + 1 ) { 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 + 1 ) { next_clock_mode =0; } byte i =0; while (str_top[i]) { putnormalchar(i * 6, 0, str_top[i]); 나는 ++; } firstrun =0; } delay(50); }}//run clock main loop as long as run_mode returns truebyte run_mode() { //if random mode is on... check the hour when we change mode. if (random_mode) { //if hour value in change mode time =hours. then reurn false =i.e. exit mode. if (change_mode_time ==rtc[2]) { //set the next random clock mode and time to change it set_next_random(); //exit the current mode. 반환 0; } } //else return 1 - keep running in this mode return 1;}//set the next hour the clock will change mode when random mode is onvoid set_next_random() { //set the next hour the clock mode will change - current time plus 1 - 4 hours get_time(); change_mode_time =rtc[2] + random (1, 5); //if change_mode_time now happens to be over 23, then set it to between 1 and 3am if (change_mode_time> 23) { change_mode_time =random (1, 4); } //set the new clock mode clock_mode =random(0, NUM_DISPLAY_MODES + 1); //pick new random clock mode}//dislpay menu to change the clock settingsvoid setup_menu() { char* set_modes[] ={ "Rndom", "24 Hr","Set", "Brght", "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]) { putnormalchar(i*6, 0, str_top[i]); 나는 ++; } firstrun =0; } delay(50); } //pick the mode switch(setting_mode){ case 0:set_random(); 부서지다; case 1:set_ampm(); 부서지다; case 2:set_time(); 부서지다; case 3:set_intensity(); 부서지다; case 4://exit menu break; } //change the clock from mode 6 (settings) back to the one it was in before clock_mode=old_mode;}//toggle random mode - pick a different clock mode every few hoursvoid set_random(){ cls(); char text_a[9] ="Off"; char text_b[9] ="On"; byte i =0; //if random mode is on, turn it off if (random_mode){ //turn random mode off random_mode =0; //print a message on the display while(text_a[i]) { putnormalchar((i*6), 0, text_a[i]); 나는 ++; } } else { //turn randome mode on. random_mode =1; //set hour mode will change set_next_random(); //print a message on the display while(text_b[i]) { putnormalchar((i*6), 0, text_b[i]); 나는 ++; } } delay(1500); //leave the message up for a second or so}//set 12 or 24 hour clockvoid set_ampm() { // AM/PM or 24 hour clock mode - flip the bit (makes 0 into 1, or 1 into 0 for ampm mode) ampm =(ampm ^ 1); cls();}//change screen intensityintensityvoid set_intensity() { cls(); byte i =0; char text[7] ="Bright"; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); 나는 ++; } //wait for button input while (!buttonA.uniquePress()) { levelbar (0,6,(intensity*2)+2,2); //display the intensity level as a bar while (buttonB.isPressed()) { if(intensity ==15) { intensity =0; cls (); } else { intensity++; } //print the new value i =0; while(text[i]) { puttinychar((i*4)+4, 0, text[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 <4; address++) { lc.setIntensity(address, intensity); } delay(150); } }}// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybarvoid levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x =0; x
    LibrariesArduino
    미리보기 없음(다운로드만 가능).

    회로도


    제조공정

    1. LED 시퀀서
    2. 뻐꾸기 시계
    3. MATLAB - 행렬
    4. 미니 보스 전투
    5. 마스터 시계
    6. 베를린 시계
    7. 아날로그 스타일 LED POV 시계
    8. LED 매트릭스 + 모션 센서 도어 디스플레이 [Arduino Holiday]
    9. 사운드에 의한 8x LED 조명
    10. Arduino Quadruped