Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Relógio de matriz de 7 segmentos

Componentes e suprimentos

SparkFun Arduino Pro Mini 328 - 5 V / 16 MHz
× 1
Relógio em tempo real (RTC)
Compre um "Módulo de relógio em tempo real DS1302 para Arduino" e desfaça a solda do soquete ic e do cristal.
× 1
Bateria CR1220 e suporte
Pesquise "5pcs, Black Housing CR1220 CR1225 Button Cell Socket Holder BS-1220-1"
× 1
Capacitor 0.1uf 1206 SMD
× 1
Capacitor 10uF 1206 SMD Ceramic
× 1
Interruptor tátil, acionado pela parte superior
variante de 12 mm com botões no topo
× 4
Módulo conversor redutor 3A Mini DC-DC
× 1
Visor de catodo comum de 4 dígitos 7 de 0,28 pol.
× 36
MAX7219 DIP IC
× 18
Buzzer
× 1
Cabeçalho da máquina
Você precisa de cabeçalhos masculinos e femininos - geralmente vêm em tiras de 40, então você terá 8 tiras de masculino pinos usinados e 8 tiras de soquetes femininos usinados
× 1
Soquete de alimentação DC
Pesquise "12 V DC Power Supply Jack Socket Female Panel Mount Conector 5.5 x 2.ODZ2"
× 1

Ferramentas e máquinas necessárias

Ferro de soldar (genérico)
Impressora 3D (genérica)

Aplicativos e serviços online

Arduino IDE

Sobre este projeto


Enquanto navegava no Hackaday.io, encontrei um lindo relógio feito com uma série de telas de 7 segmentos da Frugha. Eu realmente queria construir isso, mas a versão de Frugha é bem grande devido a ele usar telas de 7 segmentos de 0,56 ". Meu projeto usa telas de 7 segmentos de 0,28", tornando-o apenas um quarto do tamanho.

O software foi reescrito para incorporar um despertador e uma tela de configuração para definir a hora, data e alarme.





Vídeo





Tela de configuração


O relógio é controlado por quatro botões. O botão SELECIONAR (na parte superior) mostrará a tela de configuração. A seleção atual piscará. Pressionar o botão SELECIONAR novamente irá percorrer as diferentes seções de configuração (ou seja, hora, data, alarme, sintonia, brilho, formato de data e relógio).

Pressionar o botão ENTER (2 ° para baixo a partir do topo) enquanto um dos itens do menu é selecionado permitirá que você altere suas configurações. Onde houver mais de uma configuração para um item de menu, o botão ENTER alternará entre elas. A configuração ativa piscará.

Quando uma configuração estiver piscando, os botões PARA CIMA e PARA BAIXO (os dois botões inferiores) irão alterar a configuração.





Tela de data


Pressionar o botão ENTER (2 ° de cima para baixo) enquanto o relógio é exibido mostrará a tela de data por cinco segundos.

A seção Formato de data na tela de configuração permite definir o formato de data (DD-MM ou MM-DD) e a fonte usada.





Considerações de design


Para simplificar o design da placa, minha versão usa visores de 4 dígitos em vez dos visores de um único dígito usados ​​na versão original. Como as telas de 0,28 "são pequenas, tive que colocar os chips MAX7219 em uma placa separada. Para simplesmente fazer a fiação, conectores de pino macho e fêmea usinados são usados ​​para conectar as placas,

Os arquivos Eagle foram incluídos, caso você deseje que as placas sejam feitas comercialmente ou faça como eu fiz e faça você mesmo. Usei o método do toner para fazer o meu.





Os quadros de coluna


Devem ser feitos seis painéis de coluna que acomodam todos os displays. Ao soldar os cabeçotes machos da máquina, comece com o conjunto do meio e trabalhe até a borda externa. Use um palito de fósforo ou algo semelhante para levantar o soquete o suficiente para que você possa soldar os pinos facilmente. Use um pequeno ferro de soldar com ponta fina e solda de 0,5 mm.

Depois de criar os módulos de coluna, recomendo que você pinte a borda da tela com tinta preta fosca. Isso interromperá a exibição das bordas brancas se uma tela não estiver perfeitamente alinhada com sua vizinha. Também usando um marcador, numere cada módulo de coluna. Isso ajuda quando eles são inseridos na placa-mãe MAX7219.





A placa-mãe MAX7219


Ao projetar a placa-mãe e as placas das colunas, não mapeei os segmentos ou dígitos corretos do MAX7219 para seus pinos de exibição correspondentes. Eu queria manter o layout do PCB o mais simples possível e ajustar para qualquer diferença no software.

Eu recomendo quando se trata de soquetes usinados fêmeas que você os coloque nos pinos machos das placas de coluna primeiro e depois solde o conjunto no lugar enquanto eles estão conectados. Isso significa que os pinos da coluna se alinharão exatamente com seus soquetes correspondentes. Se você precisar removê-los, ter os módulos de coluna numerados garantirá que eles voltem para a mesma posição.





A placa MPU


A placa do microprocessador contém todos os outros componentes. Os quatro botões e dois capacitores SMD são montados na parte traseira da placa e todos os outros componentes são montados na parte frontal da placa. Para manter um perfil baixo, o conector de pino FTDI que geralmente é soldado ao Arduino Pro Mini agora está soldado diretamente ao PCB. Dois fios vão dos pinos DTR e VCC diretamente para o PCB.





Defendendo o caso


Os arquivos STL para a frente e o verso foram incluídos. Ambos foram impressos usando uma altura de camada de 0,2 e uma aba. A frente também possui suportes habilitados que tocam apenas a placa de impressão.

A placa-mãe MAX7219 com seus módulos de coluna desliza pela frente. Se você achar que está um pouco solto, use uma camada ou duas de fita adesiva como embalagem.

A placa MPU é colada a quente na parte traseira.





Software


O software requer que a biblioteca MD_MAX72XX tenha sido instalada em seu Arduino IDE. Forneci meu esboço Hardware_Test_V1 para teste. Ele iluminará todos os segmentos para que você possa verificar se há curtos ou fiação quebrada. Assim que a exibição funcionar, carregue o esboço Clock_V4.

Código

  • Clock_V4.ino
  • Digits.h
  • Tunes.h
  • Button.h
  • Button.cpp
  • Hardware_Test_V1.zip
Clock_V4.ino C / C ++
 / * --------------------------------------------- ------ * 7 Segment array clock * * Baseado no clock de Frugha (https://hackaday.io/project/169632-7-segment-display-array-clock) * * Modificações por John Bradnam (jbrad2089 @ gmail.com) * - Hardware alterado para usar telas de 7 segmentos de 0,28 ". * - Dispositivo MAX7219, ordem de dígitos e segmentos foi alterado para simplesmente um * roteamento de placa PCB complexo. * - Hardware usa Arduino Mini Pro, DS1302 RTC e 4 botões * - Função de alarme adicionada com uso de alarme selecionável * - Configuração de brilho adicionada * - Tela de configuração adicionada para definir hora, data, alarme, música e brilho * - Tela de data adicionada (é exibida por dois segundos quando o botão ENTER é pressionado * Atualização 2020 -06-16 * - Adicionada opção de formato de data na tela de configuração * - Aumento do tempo limite da tela de data de 2 para 5 segundos * - Adicionada uma escolha configurável de fonte para exibição de data * -------------- ------------------------------------ * / #include  #include  #include  # include  #include  #include "button.h" #include "Tunes.h" #include "Digits.h" #define HARDWARE_TYPE MD_MAX72XX ::GENERIC_HW # define MAX_DEVICES 18 # define LED_CLK 13 / / ou SCK (WHI) #define LED_DATA 11 // ou MOSI (BRN) #define LED_CS 10 // ou SS (YEL) #define SPEAKER 2 # define SW_UP 3 # define SW_DOWN 4 # define RTC_CLK 5 # define RTC_IO 6 # define SW_ENTER 7 # define RTC_CE 8 # define SW_SELECT 9DS1302RTC rtc (RTC_CE, RTC_IO, RTC_CLK); // interface de hardware SPIMD_MAX72XX mx =MD_MAX72XX (HARDWARE_TYPE, LED_CS, MAX_DEVICES); // Interface de hardware SPIMD_MAX72XX mx =MD_MAX72XX (HARDWARE_TYPE, LED_CS, MAX_DEVICES); // MxD_TAD_MAX72XX; LED_CLK, LED_CS, MAX_DEVICES); // Manipulação de EEPROM # define EEPROM_ADDRESS 0 # define EEPROM_MAGIC 0x0BAD0DADtypedef struct {uint32_t magic; alarme bool; uint8_t minutos; uint8_t horas; bool format12hr; brilho uint8_t; uint8_t tune; bool formatDmy; bool squareFont;} EEPROM_DATA; EEPROM_DATA EepromData; // As configurações atuais da EEPROM evitam clockButtonPressed (void); void enterButtonPressed (void); void downButtonPressed (void); void upButtonPressed (void); Botão * clockButton; Botão * enterButton; Botão * downButton; Botão * upButton; false; #define SETUP_FLASH_RATE 200; configuração longa não assinadaTimeout; bool setupDisplayState =false; enum ClockButtonModesEnum {CLOCK, TIME_SET, DATE_SET, ALARM_SET, TUNE_SET, BRIGHT_SET, FORMAT_SET}; TIME_METHOSetModesEnum_Time_Time_Enum_Time_Enu; timeSetMode =TIME_HOUR; enum DateSetMenuEnum {DATE_YEAR, DATE_MONTH, DATE_DAY}; DateSetMenuEnum dateSetMode =DATE_YEAR; enum AlarmSetMenuEnum {ALARM_HOUR, ALARM_MIN, ALARM_STATE}; AlarmSetMenuEnum alarmSetMode =ALARM_HOUR; enum FormatSetMenuEnum {DAY_MONTH, FONT_STYLE}; FormatSetMenuEnum formatSetMode =DAY_MONTH; int lastSeconds =-1; bool alarmRinging =falso; // verdadeiro quando o alarme está onbool alarmCancelled =false; // alarme cancelado por userbool musicPlaying =false; // verdadeiro se estiver reproduzindo um songbool clockColon =false; // mostrar / ocultar cólonint8_t dom [] ={31,28,31,30,31,30,31,31,30,31,30,31}; tmElements_t newTime; // Usado para armazenar novo timevoid setup () {Serial.begin (115200); // Eprom readEepromData (); // Inicializar os botões clockButton =new Button (SW_SELECT); enterButton =novo botão (SW_ENTER); downButton =novo botão (SW_DOWN); downButton-> Repetir (downButtonPressed); botão ascendente =novo botão (SW_UP); upButton-> Repetir (upButtonPressed); // Inicializar pinMode de som (SPEAKER, OUTPUT); mx.begin (); mx.control (MD_MAX72XX ::INTENSITY, EepromData.brightness); //0..MAX_INTENSITY mx.update (MD_MAX72XX ::OFF); // Sem atualização automática setSyncProvider (rtc.get); // a função para obter a hora do RTC if (timeStatus ()! =timeSet) {Serial.println ("RTC Sync Bad"); newTime.Year =CalendarYrToTm (2020); newTime.Month =5; newTime.Day =30; newTime.Hour =14; newTime.Minute =53; newTime.Second =0; time_t t =makeTime (newTime); setTime (t); rtc.set (t); if (rtc.set (t)! =0) {Serial.println ("Falha ao definir hora"); }} newTime.Year =CalendarYrToTm (ano ()); newTime.Month =month (); newTime.Day =day (); newTime.Hour =hora (); newTime.Minute =minuto (); newTime.Second =second (); Serial.println ("Time:" + String (newTime.Hour) + ":" + String (newTime.Minute) + ":" + String (newTime.Second)); Serial.println ("Data:" + String (newTime.Day) + "/" + String (newTime.Month) + "/" + String (tmYearToCalendar (newTime.Year))); clockMode =CLOCK; showTime (true);} void loop () {testButtons (); if (clockMode ==CLOCK) {showTime (false); if (EepromData.alarm &&EepromData.hours ==hora () &&EepromData.minutes ==minuto ()) {if (! alarmCancelled) {alarmRinging =true; playSong (melodias [EepromData.tune]); }} else {alarmCancelled =false; alarmRinging =false; }} else {showSetup (false); } delay (100);} // ----------------------------------------- ---------------------- // Testa se algum botão foi pressionadovoid testButtons () {// Pressione os botões uma vez se (clockButton-> Pressed ()) { clockButtonPressed (); } if (enterButton-> Pressed ()) {enterButtonPressed (); } // Não é necessário verificar o resultado de pressionado, pois o manipulador do botão invocará sua função de repetição upButton-> Pressed (); downButton-> Pressed ();} // ---------------------------------------- ----------------------- // Manipula CLOCK bttonvoid clockButtonPressed () {if (cancelAlarm ()) return; inSubMenu =false; clockMode =(clockMode ==FORMAT_SET)? CLOCK:(ClockButtonModesEnum) ((int) clockMode + 1); if (clockMode ==CLOCK) {Serial.println ("Saving Time:" + String (newTime.Hour) + ":" + String (newTime.Minute)); Serial.println ("De:" + String (hora ()) + ":" + String (minuto ())); if (newTime.Year! =CalendarYrToTm (ano ()) || newTime.Month! =mês () || newTime.Day! =dia () || newTime.Hour! =hora () || newTime.Minute! =minuto ()) {// Atualizar hora Serial.println ("Atualizando RTC"); newTime.Second =second (); time_t t =makeTime (newTime); setTime (t); rtc.set (t); if (rtc.set (t)! =0) {Serial.println ("Falha ao definir hora"); }} writeEepromData (); showTime (true); } else {if (clockMode ==TIME_SET) {newTime.Year =CalendarYrToTm (ano ()); newTime.Month =month (); newTime.Day =day (); newTime.Hour =hora (); newTime.Minute =minuto (); newTime.Second =second (); Serial.println ("Tempo de carregamento:" + String (hora ()) + ":" + String (minuto ())); } showSetup (true); }} // ---------------------------------------------- ----------------- // Manipula ENTER bttonvoid enterButtonPressed () {if (cancelAlarm ()) return; if (clockMode! =CLOCK) {if (! inSubMenu) {timeSetMode =TIME_HOUR; dateSetMode =DATE_YEAR; alarmSetMode =ALARM_HOUR; formatSetMode =DAY_MONTH; inSubMenu =true; } else {switch (clockMode) {case TIME_SET:timeSetMode =(timeSetMode ==TIME_FORMAT)? TIME_HOUR:(TimeSetMenuEnum) ((int) timeSetMode + 1); pausa; case DATE_SET:dateSetMode =(dateSetMode ==DATE_DAY)? DATE_YEAR:(DateSetMenuEnum) ((int) dateSetMode + 1); pausa; case ALARM_SET:alarmSetMode =(alarmSetMode ==ALARM_STATE)? ALARM_HOUR:(AlarmSetMenuEnum) ((int) alarmSetMode + 1); pausa; case FORMAT_SET:formatSetMode =(formatSetMode ==FONT_STYLE)? DAY_MONTH:(FormatSetMenuEnum) ((int) formatSetMode + 1); pausa; }} showSetup (true); } else {showDate (day (), month (), year ()); atraso (5000); }} // ---------------------------------------------- ----------------- // Handle DOWN bttonvoid downButtonPressed () {if (cancelAlarm ()) return; switch (clockMode) {case TIME_SET:if (inSubMenu) {switch (timeSetMode) {case TIME_HOUR:newTime.Hour =(newTime.Hour + 24 - 1)% 24; pausa; caso TIME_MIN:newTime.Minute =(newTime.Minute + 60 - 1)% 60; pausa; case TIME_FORMAT:EepromData.format12hr =! EepromData.format12hr; pausa; } showSetup (true); } pausa; case DATE_SET:if (inSubMenu) {switch (dateSetMode) {case DATE_YEAR:newTime.Year =((newTime.Year - 30 + 100) - 1)% 100 + 30; pausa; caso DATE_MONTH:newTime.Month =((newTime.Month - 1 + 12) - 1)% 12 + 1; pausa; case DATE_DAY:uint8_t md =daysInMonth (newTime.Year, newTime.Month); newTime.Day =((newTime.Day - 1 + md) - 1)% md + 1; pausa; } showSetup (true); } pausa; case ALARM_SET:if (inSubMenu) {switch (alarmSetMode) {case ALARM_HOUR:EepromData.hours =(EepromData.hours + 24 - 1)% 24; pausa; case ALARM_MIN:EepromData.minutes =(EepromData.minutes + 60 - 1)% 60; pausa; case ALARM_STATE:EepromData.alarm =! EepromData.alarm; pausa; } showSetup (true); } pausa; case TUNE_SET:EepromData.tune =(EepromData.tune + NUM_OF_MELODIES - 1)% NUM_OF_MELODIES; showSetup (true); pausa; case BRIGHT_SET:EepromData.brightness =(EepromData.brightness + MAX_INTENSITY - 1)% MAX_INTENSITY; mx.control (MD_MAX72XX ::INTENSITY, EepromData.brightness); //0..MAX_INTENSITY showSetup (true); pausa; case FORMAT_SET:if (inSubMenu) {switch (formatSetMode) {case DAY_MONTH:EepromData.formatDmy =! EepromData.formatDmy; pausa; case FONT_STYLE:EepromData.squareFont =! EepromData.squareFont; pausa; }} showSetup (true); pausa; }} // ---------------------------------------------- ----------------- // Manipula UP bttonvoid upButtonPressed () {if (cancelAlarm ()) return; switch (clockMode) {case TIME_SET:if (inSubMenu) {switch (timeSetMode) {case TIME_HOUR:newTime.Hour =(newTime.Hour + 1)% 24; pausa; caso TIME_MIN:newTime.Minute =(newTime.Minute + 1)% 60; pausa; case TIME_FORMAT:EepromData.format12hr =! EepromData.format12hr; pausa; } showSetup (true); } pausa; case DATE_SET:if (inSubMenu) {switch (dateSetMode) {case DATE_YEAR:newTime.Year =((newTime.Year - 30) + 1)% 100 + 30; pausa; caso DATE_MONTH:newTime.Month =((newTime.Month - 1) + 1)% 12 + 1; pausa; case DATE_DAY:uint8_t md =daysInMonth (newTime.Year, newTime.Month); newTime.Day =(newTime.Day% md) + 1; pausa; } showSetup (true); } pausa; case ALARM_SET:if (inSubMenu) {switch (alarmSetMode) {case ALARM_HOUR:EepromData.hours =(EepromData.hours + 1)% 24; pausa; case ALARM_MIN:EepromData.minutes =(EepromData.minutes + 1)% 60; pausa; case ALARM_STATE:EepromData.alarm =! EepromData.alarm; pausa; } showSetup (true); } pausa; case TUNE_SET:EepromData.tune =(EepromData.tune + 1)% NUM_OF_MELODIES; showSetup (true); pausa; case BRIGHT_SET:EepromData.brightness =(EepromData.brightness + 1)% MAX_INTENSITY; mx.control (MD_MAX72XX ::INTENSITY, EepromData.brightness); //0..MAX_INTENSITY showSetup (true); pausa; case FORMAT_SET:if (inSubMenu) {switch (formatSetMode) {case DAY_MONTH:EepromData.formatDmy =! EepromData.formatDmy; pausa; case FONT_STYLE:EepromData.squareFont =! EepromData.squareFont; pausa; }} showSetup (true); pausa; }} // ---------------------------------------------- ----------------- // Desativa o alarme se estiver tocando um tunebool cancelAlarm () {if (musicPlaying) {musicPlaying =false; alarmCancelled =alarmRinging; return true; } colheita(); retorna falso;}//-------------------------------------------- ------------------- // Mostra o menu de configuração e exibe o item atual selecionado para evitar showSetup (bool force) {setupDisplayState =setupDisplayState | força; força =força || (millis ()> setupTimeout); if (forçar) {setupTimeout =millis () + SETUP_FLASH_RATE; bool on =setupDisplayState; setupDisplayState =! setupDisplayState; mx.clear (); if (on ||! (clockMode ==TIME_SET &&! inSubMenu)) displayString (0,7, "TINE"); if (on ||! (clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_HOUR)) displayNumber (0,13, newTime.Hour, 2, true); if (on ||! (clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_MIN)) displayNumber (0,16, newTime.Minute, 2, true); if (on ||! (clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_FORMAT)) displayString (0,19, (EepromData.format12hr)? "12HR":"24HR"); if (on ||! (clockMode ==DATE_SET &&! inSubMenu)) displayString (1,7, "DATE"); if (on ||! (clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_YEAR)) displayNumber (1,13, tmYearToCalendar (newTime.Year), 4, true); if (on ||! (clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_MONTH)) displayNumber (1,18, newTime.Month, 2, true); if (on ||! (clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_DAY)) displayNumber (1,21, newTime.Day, 2, true); if (on ||! (clockMode ==ALARM_SET &&! inSubMenu)) displayString (2,6, "ALARN"); if (on ||! (clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_HOUR)) displayNumber (2,13, EepromData.hours, 2, true); if (on ||! (clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_MIN)) displayNumber (2,16, EepromData.minutes, 2, true); if (on ||! (clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_STATE)) displayString (2,19, (EepromData.alarm)? "ON":"OFF"); if (on ||! (clockMode ==TUNE_SET &&! inSubMenu)) displayString (3,7, "TUNE"); if (on ||! (clockMode ==TUNE_SET &&inSubMenu)) {switch (EepromData.tune) {case 0:displayString (3,13, "ELISE"); pausa; caso 1:displayString (3,13, "RANGE"); pausa; caso 2:displayString (3,13, "SUNSHINE"); pausa; }} if (on ||! (clockMode ==BRIGHT_SET &&! inSubMenu)) displayString (4,1, "BRIGHTNESS"); if (on ||! (clockMode ==BRIGHT_SET &&inSubMenu)) displayNumber (4,13, EepromData.brightness, 0, false); if (on ||! (clockMode ==FORMAT_SET &&! inSubMenu)) displayString (5,0, "DATE ​​FORNAT"); if (on ||! (clockMode ==FORMAT_SET &&inSubMenu &&formatSetMode ==DAY_MONTH)) displayString (5,13, ​​(EepromData.formatDmy)? "DD-NN":"NN-DD"); if (on ||! (clockMode ==FORMAT_SET &&inSubMenu &&formatSetMode ==FONT_STYLE)) displayString (5,19, (EepromData.squareFont)? "FONT1":"FONT2"); mx.update (); }} // ---------------------------------------------- ----------------- // Exibe a hora atual no visor se alterado // forçar - sempre mostra a hora, mesmo se não for alterado, evite showTime (bool force) {force =force || (últimos segundos! =segundo ()); if (forçar) {lastSeconds =second (); showTime (hora (), minuto (), verdadeiro, verdadeiro, (segundo () &0x01), (clockMode! =CLOCK ||! EepromData.format12hr)); }} // ---------------------------------------------- ----------------- // Exibir a hora no visor // h - hora // m - minuto // he - hora habilitar // me - minuto habilitar // ce - dois pontos permitem void showTime (int h, int m, bool he, bool me, bool ce, bool f24) {mx.clear (); if (he) {if (! f24 &&h> 12) {h =h - 12; } if (h> 9 || f24) {displayLargeDigit (0, h / 10); } displayLargeDigit (5, h% 10); } if (me) {displayLargeDigit (13, m / 10); displayLargeDigit (18, m% 10); } if (ce) {displayLargeDigit (11, 10); } mx.update ();} // ---------------------------------------- ----------------------- void showDate (int d, int m, int y) {#define XOFS 3 mx.clear (); if (EepromData.formatDmy) {displayDateDigit (XOFS + 0, d / 10); displayDateDigit (XOFS + 4, d% 10); displayDateDigit (XOFS + 8, 10); // dois pontos displayDateDigit (XOFS + 12, m / 10); displayDateDigit (XOFS + 16, m% 10); } else {displayDateDigit (XOFS + 0, m / 10); displayDateDigit (XOFS + 4, m% 10); displayDateDigit (XOFS + 8, 10); // dois pontos displayDateDigit (XOFS + 12, d / 10); displayDateDigit (XOFS + 16, d% 10); } displayNumber (5, 10, y, 0, falso); mx.update ();} // ----------------------------------------- ---------------------- // Escreva um quadrado ou dígito pequeno com base na definição de configuração // x =0 a 23 // v =dígito grande ou quadrado para display (0..10) void displayDateDigit (uint8_t x, uint8_t v) {if (EepromData.squareFont) {displaySquareDigit (x, v); } else {displaySmallDigit (x, v); }} // ---------------------------------------------- ----------------- // Escreva uma máscara de bit de segmento // x =0 a 23 // v =dígito grande para exibir (0..10) void displayLargeDigit (uint8_t x , uint8_t v) {if (x <24 &&v <11) {for (uint8_t row =0; row <6; row ++) {for (uint8_t col =0; col <6; col ++) {writePhysicalDigit (row, col + x, pgm_read_byte (&largeDigits [v] [linha] [col]), falso); }}}} // -------------------------------------------- ------------------- // Escreva uma máscara de bit de segmento // x =0 a 23 // v =dígito grande para exibir (0..10) void displaySmallDigit ( uint8_t x, uint8_t v) {if (x <24 &&v <11) {for (uint8_t row =0; row <5; row ++) {for (uint8_t col =0; col <3; col ++) {writePhysicalDigit (row, col + x, pgm_read_byte (&smallDigits [v] [linha] [col]), falso); }}}} // -------------------------------------------- ------------------- // Escreva uma máscara de bit de segmento // x =0 a 23 // v =dígito grande para exibir (0..10) void displaySquareDigit ( uint8_t col, uint8_t v) {// Ordem do segmento defbca _ g uint8_t mask =ascii [v]; if (mask ==B00000000) {// Hyphen mask =B00000001; } if (mask &B00000100) {// seg A writePhysicalDigit (0, col + 0, 0xff, false); writePhysicalDigit (0, col + 1, 0xff, false); writePhysicalDigit (0, col + 2, 0xff, false); } if (mask &B00010000) {// seg B writePhysicalDigit (0, col + 2, 0xff, false); writePhysicalDigit (1, col + 2, 0xff, false); writePhysicalDigit (2, col + 2, 0xff, false); } if (máscara &B00001000) {// seg C writePhysicalDigit (2, col + 2, 0xff, false); writePhysicalDigit (3, col + 2, 0xff, false); writePhysicalDigit (4, col + 2, 0xff, false); } if (mask &B10000000) {// seg D writePhysicalDigit (4, col + 0, 0xff, false); writePhysicalDigit (4, col + 1, 0xff, false); writePhysicalDigit (4, col + 2, 0xff, false); } if (mask &B01000000) {// seg C writePhysicalDigit (2, col, 0xff, false); writePhysicalDigit (3, col, 0xff, false); writePhysicalDigit (4, col, 0xff, false); } if (mask &B00100000) {// seg E writePhysicalDigit (0, col, 0xff, false); writePhysicalDigit (1, col, 0xff, false); writePhysicalDigit (2, col, 0xff, false); } if (mask &B00000001) {// seg D writePhysicalDigit (2, col + 0, 0xff, false); writePhysicalDigit (2, col + 1, 0xff, false); writePhysicalDigit (2, col + 2, 0xff, false); }} // ---------------------------------------------- ----------------- // Grava a string de caracteresuint8_t displayString (uint8_t linha, uint8_t col, String s) {for (int i =0; i  0x5F) {c =0x3F; // Usado como um caractere de espaço} c =c - 0x30; writePhysicalDigit (linha, col, ascii [c], verdadeiro); col =col + 1; }} // ---------------------------------------------- ----------------- // Escreva um numberuint8_t displayNumber (uint8_t row, uint8_t col, int number, int padding, bool leaderZeros) {if (padding ==0) {padding =(número> 0)? floor (log10 (número)) + 1:1; } col =col + preenchimento; bool primeiro =verdadeiro; para (int i =0; i > 2) * 3 + (linha>> 1); uint16_t c =((uint16_t) dev <<3) | digitMap [dig]; if (! apagar) {v =v | mx.getColumn (c); } mx.setColumn (c, v); }} // ---------------------------------------------- ----------------- // Retorna os dias em um determinado ano e mês // Fev tem 28, a menos que seja um ano bissexto ou a virada de um séculouint8_t daysInMonth (int y, int m) {return dom [m - 1] + ((m ==2 &&(y% 4) ==0 &&(y% 100)! =0)? 1:0);} // ------- -------------------------------------------------- ------ // Grave a estrutura EepromData em EEPROMvoid writeEepromData () {// Esta função usa EEPROM.update () para realizar a gravação, portanto, não reescreve o valor se ele não mudou. EEPROM.put (EEPROM_ADDRESS, EepromData);} // -------------------------------------- ------------------------- // Ler a estrutura EepromData de EEPROM, inicializar se necessário evite readEepromData () {// Eprom EEPROM.get (EEPROM_ADDRESS, EepromData); //Serial.println("magic:"+ String (EepromData.magic, 16) +", alarme:"+ String (EepromData.alarm) +", hora:"+ String (EepromData.hours) +":"+ String (EepromData.minutes) + ", 12hr:" + String (EepromData.format12hr) + ", brilho:" + String (EepromData.brightness)); if (EepromData.magic! =EEPROM_MAGIC) {Serial.println ("Inicializando EEPROM ..."); EepromData.magic =EEPROM_MAGIC; EepromData.alarm =false; EepromData.minutes =30; EepromData.hours =5; EepromData.format12hr =false; EepromData.brightness =8; EepromData.tune =0; EepromData.formatDmy =false; writeEepromData (); } Serial.println ("alarm:" + String (EepromData.alarm) + ", hora:" + String (EepromData.hours) + ":" + String (EepromData.minutes) + ", 12hr:" + String (EepromData .format12hr) + ", brilho:" + String (EepromData.brightness));} // ----------------------------- ---------------------------------- // Tocar uma melodyint playSong (const uint16_t * melody) {// Tocar cada nota na melodia até que a nota END_OF_TUNE seja encontrada musicPlaying =true; int thisNote =0; uint16_t noteRaw =pgm_read_word (&melody [thisNote ++]); while (musicPlaying &¬eRaw! =END_OF_TUNE) {testButtons (); colheita(); playNote (noteRaw); noteRaw =pgm_read_word (&melody [thisNote ++]); } // while delay (50);} // -------------------------------------- ------------------------- // Toque um único notevoid playNote (uint16_t noteRaw) {// para calcular a duração da nota, leve um segundo dividido por o tipo de nota. // por exemplo. semínima =1000/4, colcheia =1000/8, etc. uint16_t frequência =noteRaw &0x1FFF; duração uint16_t =(noteRaw &0xE000)>> 13; if (duração ==7) duração =8; uint16_t noteDuration =1800 / duração; if (freqüência! =REST) ​​{tom (SPEAKER, freqüência, noteDuração); } // para distinguir as notas, defina um tempo mínimo entre elas. // a duração da nota + 30% parece funcionar bem:uint16_t pauseBetweenNotes =(noteDuration * 13) / 10; atraso (pauseBetweenNotes); if (frequência! =REST) ​​{// interrompe a reprodução do tom:noTone (SPEAKER); }} 
Digits.h C / C ++
 / * --------------------------------------------- ------ * 7 Segment array clock * define cada dígito em um array de 6x6 bytes * ----------------------------- --------------------- * / #pragma uma vez // ---------------------- ----------------------------- // Fiação MAX7219 padrão // Ordem de dígitos 0,1,2,3,4,5 / *// Segment order _ abcdefg#define _______ B00000000#define __cd___ B00011000#define _bcde_g B00111101#define abcdefg B01111111#define __cdefg B00011111#define __c____ B00010000#define ab__efg B01100111#define abcd_fg B01111011#define abcde_g B01111101#define ab_defg B01101111#define _bc____ B00110000#define a__defg B01001111#define ____ef_ B00000110#define ___defg B00001111#define abc__fg B01110011#define a___ef_ B01000110#define _b_____ B00100000#define ab___f_ B01100010#define _bcd___ B00111000#define a___ef_ B01000110#define ab_____ B01100000#define ____e__ B00000100#define __cde_g B00011101# define a____f_ B01000010#define a_cdefg B01011111#define ___de__ B00001100#define _____f_ B00000 010#define ab___fg B01100011#define a__def_ B01001110#define __cde__ B00011100#define a___efg B01000111#define a__d___ B01001000#define abc____ B01110000#define _bc_ef_ B00110110#define ___def_ B00001110#define abc_ef_ B01110110#define _bcdef_ B00111110#define a__def_ B01001110#define abcd___ B01111000*///Segment order d e f b c a _ g#define _______ B00000000#define __cd___ B10001000#define _bcde_g B11011001#define abcdefg B11111101#define __cdefg B11101001#define __c____ B00001000#define ab__efg B01110101#define abcd_fg B10111101#define abcde_g B11011101#define ab_defg B11110101#define _bc____ B00011000#define a__defg B11100101#define ____ef_ B01100000#define ___defg B11100001#define abc__fg B00111101#define a___ef_ B01100100#define _b_____ B00010000#define ab___f_ B00110100#define _bcd___ B10011000#define a___ef_ B01100100#define ab_____ B00010100#define ____e__ B01000000#define __cde_g B11001001#define a____f_ B00100100#define a_cdefg B11101101#define ___de__ B11000000#define _____f _ B00100000#define ab___fg B00110101#define a__def_ B11100100#define __cde__ B11001000#define a___efg B01100101#define a__d___ B10000100#define abc____ B00011100#define _bc_ef_ B01111000#define ___def_ B11100000#define abc_ef_ B01111100#define _bcdef_ B11111000#define a__def_ B11100100#define abcd___ B10011100//Square Numbers//ASCII Character Set//Numbers 0 - 9//Letters A - Z//Segment order d e f b c a _ guint8_t ascii[] ={ B11111100, B00011000, B11010101, B10011101, B00111001, B10101101, B11101101, B00011100, B11111101, B10111101, B00000000, B00000000, B00000000, B00000001, B00000000, B00000000, B00000000, B01111101, B11101001, B11100100, B11011001, B11100101, B01100101, B10111101, B01111001, B00011000, B11011000, B00000000, B11100000, B00000000, B01001001, B11001001, B01110101, B00000000, B01000001, B10101101, B11100001, B11001000, B00000000, B00000000, B00000000, B10111001, B00000000, B11001100, B01010001, B10011100, B00000000, B10000000};//Digit sequence for each device (MAX7219)u int8_t digitMap[] ={5, 2, 6, 4, 1, 7, 3, 0};//------------------------------------------------------------// Digits using logical coordinates//------------------------------------------------------------const int8_t largeDigits[11][6][6] PROGMEM ={ { //0 { _______, _______, __cd___, _bcde_g, abcdefg, __cdefg }, { _______, __c____, abcdefg, ab__efg, abcd_fg, abcdefg }, { _______, abcde_g, ab_defg, _______, _bc____, a__defg }, { _______, abcdefg, ____ef_, __c____, abcdefg, ____ef_ }, { _______, abcdefg, __cdefg, abcdefg, a___efg, _______ }, { _______, abc__fg, abcdefg, ab__efg, _______, _______ } }, { //1 { _______, _______, _______, __c____, abcdefg, __cdefg }, { _______, _______, _______, abcdefg, abcdefg, ____ef_ }, { _______, _______, _bcde_g, abcdefg, a__defg, _______ }, { _______, _bc____, abcdefg, abcdefg, ____ef_, _______ }, { _______, abcdefg, abcdefg, a___ef_, _______, _______ }, { _b_____, abcdefg, abcdefg, _______, _______, _______ } }, { //2 { _______, _______, __cd___, _b cde_g, abcdefg, __cdefg }, { _______, _bc____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _______, _______, _bcd___, abcdefg, a___ef_ }, { _______, _______, _bcde_g, abcdefg, a___ef_, _______ }, { __c____, abcdefg, abcdefg, a___ef_, _______, _______ }, { _b_____, abc__fg, abcdefg, abcdefg, ab__efg, _______ } }, { //3 { _______, _______, __cd___, abcdefg, abcdefg, __cdefg }, { _______, _b_____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _______, __cd___, _bcde_g, abcdefg, a___ef_ }, { _______, _______, ab_____, abc__fg, abcdefg, ____e__ }, { _______, __cd___, __cde_g, _bcde_g, abcdefg, ____ef_ }, { _b_____, abc__fg, abcdefg, abcdefg, a____f_, _______ } }, { //4 { _______, _______, _bcd___, abcdefg, __c____, abcdefg }, { _______, __c____, abcdefg, a___ef_, abcde_g, a__defg }, { _______, abcde_g, abcdefg, _bcd___, abcdefg, ____ef_ }, { __c____, abcdefg, abcdefg, abcdefg, abcdefg, _______ }, { _______, _______, __c____, abcdefg, ____ef_, _______ }, { _______, _______, abcdefg, ab__efg, _______, _______ } }, { //5 { _______, _______, _bcde_g, abcdefg, abcdefg, abcdefg }, { _______, _bc____, abcdefg, a_cdefg, ___de__, _______ }, { _______, _______, abc__fg, abcdefg, abcdefg, ____ef_ }, { _______, _______, _______, _bc____, abcdefg, ____ef_ }, { _______, __cde_g, __cde_g, _bcde_g, abcdefg, _____f_ }, { _b_____, abcdefg, abcdefg, ab__efg, a____f_, _______ } }, { //6 { _______, _______, _______, __cd___, abcdefg, ____ef_ }, { _______, _______, _bcde_g, abcdefg, a____f_, _______ }, { _______, _bcd___, abcdefg, abcdefg, abcdefg, ____e__ }, { __c____, abcdefg, a___ef_, ab_____, abcdefg, ____ef_ }, { _bc____, abcdefg, __cdefg, _bcde_g, abcdefg, _______ }, { _______, abc__fg, abcdefg, ab__efg, _______, _______ } }, { //7 { _______, _bc____, abcdefg, abcdefg, abcdefg, __cdefg }, { _______, _b_____, ab___fg, ab___fg, abcdefg, abcdefg }, { _______, _______, _______, _bcde_g, abcdefg, a___ef_ }, { _______, _______, _bcde_g, abcdefg, ab__efg, _______ }, { _______, _bcde_g, abcdefg, a___ef_, _______, _______ }, { _b_____, abcdefg, abcdefg, _______, _______, _______ } }, { //8 { _______, _______, __cd___, abcdefg, abcdefg, __cdefg }, { _______, _bc____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _b_____, abcdefg, _bcde_g, abcdefg, a___ef_ }, { _______, _bcde_g, ab__efg, abc__fg, abcdefg, ____e__ }, { _bc____, abcdefg, __cde_g, _bcde_g, abcdefg, ____ef_ }, { _______, abc__fg, abcdefg, abcdefg, a____f_, _______ } }, { //9 { _______, _______, __cde_g, abcdefg, __cdefg, ___de__ }, { _______, _bcd___, abcdefg, ab___fg, abcd_fg, abcdefg }, { _______, abcdefg, a_cdefg, __cde__, abcdefg, a__defg }, { _______, ab_____, abcd_fg, abcdefg, abcdefg, _____f_ }, { _______, __cd___, abcdefg, ab__efg, _______, _______ }, { _b_____, abcdefg, a___ef_, _______, _______, _______ } }, { //Colon { _______, _______, _______, _______, _______, _______ }, { _______, __cde_g, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ }, { ___ ____, _______, _______, _______, _______, _______ }, { __cde_g, _______, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ } }};const int8_t smallDigits[11][5][3] PROGMEM ={ { //0 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //1 { _______, abc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bcdef_, _______ } }, { //2 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { a___ef_, a__d___, _bcd___ }, { _bc_ef_, _______, _______ }, { ___def_, a__d___, abcd___ } }, { //3 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { _______, a__def_, _bc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //4 { abc_ef_, _______, abc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bc____ }, { _______, _______, _bc_ef_ }, { _______, _______, _bcdef_ } }, { //5 { a___ef_, a__d___, abcd___ }, { _bc_ef_, _______, _______ }, { ___def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //6 { a___ef_, a__d___, abcd___ }, { _bc_ef_, _______, _______ }, { ____ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //7 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bcdef_, _______ }, }, { //8 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ____ef_, a__d___, _bc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //9 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //Hyphen { _______, _______, _______ }, { _______, _______, _______ }, { a__def_, a__d___, abcd___ }, { _______, _______, _______ }, { _______, _____ __, _______ } }};
Tunes.hC/C++
 Sem visualização (somente download). 
Button.hC/C++
/*Class:ButtonAuthor:John Bradnam ([email protected])Purpose:Arduino library to handle buttons*/#pragma once#include "Arduino.h"#define DEBOUNCE_DELAY 10//Repeat speed#define REPEAT_START_SPEED 500#define REPEAT_INCREASE_SPEED 50#define REPEAT_MAX_SPEED 50class Button{ public://Simple constructor Button(int pin); Button(int name, int pin); Button(int name, int pin, int analogLow, int analogHigh, bool activeLow =true); //Background function called when in a wait or repeat loop void Background(void (*pBackgroundFunction)()); //Repeat function called when button is pressed void Repeat(void (*pRepeatFunction)()); //Test if button is pressed bool IsDown(void); //Test whether button is pressed and released //Will call repeat function if one is provided bool Pressed(); //Return button state (HIGH or LOW) - LOW =Pressed int State(); //Return button name int Name(); private:int _name; int _pin; bool _range; int _low; int _high; bool _activeLow; void (*_repeatCallback)(void); void (*_backgroundCallback)(void);};
Button.cppC/C++
/*Class:ButtonAuthor:John Bradnam ([email protected])Purpose:Arduino library to handle buttons*/#include "Button.h"Button::Button(int pin){ _name =pin; _pin =pin; _range =false; _low =0; _high =0; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT_PULLUP);}Button::Button(int name, int pin){ _name =name; _pin =pin; _range =false; _low =0; _high =0; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT_PULLUP);}Button::Button(int name, int pin, int analogLow, int analogHigh, bool activeLow){ _name =name; _pin =pin; _range =true; _low =analogLow; _high =analogHigh; _activeLow =activeLow; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT);}//Set function to invoke in a delay or repeat loopvoid Button::Background(void (*pBackgroundFunction)()){ _backgroundCallback =pBackgroundFunction;}//Set function to invoke if repeat system requiredvoid Button::Repeat(void (*pRepeatFunction)()){ _repeatCallback =pRepeatFunction;} bool Button::IsDown(){ if (_range) { int value =analogRead(_pin); return (value>=_low &&value <_high); } else { return (digitalRead(_pin) ==LOW); }}//Tests if a button is pressed and released// returns true if the button was pressed and released// if repeat callback supplied, the callback is called while the key is pressedbool Button::Pressed(){ bool pressed =false; if (IsDown()) { unsigned long wait =millis() + DEBOUNCE_DELAY; while (millis() =time) { _repeatCallback(); unsigned long faster =speed - REPEAT_INCREASE_SPEED; if (faster>=REPEAT_MAX_SPEED) { speed =faster; } time =millis() + speed; } } pressed =true; } } return pressed;}//Return current button stateint Button::State(){ if (_range) { int value =analogRead(_pin); if (_activeLow) { return (value>=_low &&value <_high) ? LOW :HIGH; } else { return (value>=_low &&value <_high) ? HIGH :LOW; } } else { return digitalRead(_pin); }}//Return current button nameint Button::Name(){ return _name;}
Hardware_Test_V1.zipC/C++
Hardware test sketch - Turns on all segments and tests speaker
No preview (download only).

Peças personalizadas e gabinetes

Esquemas

Schematic for each MAX7219 (repeated 18 times) Holds six 7 segment 4 digit displays (6 boards required) PCB files in Eagle format eagle_files_KPhUOj6Ezv.zip

Processo de manufatura

  1. Relógio de visão pov do Arduino
  2. Simple Word Clock (Arduino)
  3. Relógio Arduino com horas de oração islâmica
  4. Relógio mestre
  5. Relógio giratório Arduino de matriz de LED único
  6. Controlando uma matriz de LED com Arduino Uno
  7. eDOT - Relógio de precisão baseado em Arduino e estação meteorológica
  8. Mini Radar com Arduino
  9. Exibição de temperatura OLED do Arduino com relógio em tempo real
  10. Despertador simples com DS1302 RTC