ходики Ждуна MAX7219 8х8

skoctehs
Offline
Зарегистрирован: 27.02.2016

Скорее милый сувенир, чем полезные часы.

Но они как-то  успокаивают что ли.

Динамика смены цифр аналогична ходу маятника, задается в массиве  const int scrt[9]

Были придуманы и запрограммированы за вечер, ничего лишнего™.

Установка даты D2 общий, а D3-D6 соответственно часы +- минуты+- .

Точность хода часов обеспечивает  функция millis().

Обмен данными с MAX7219 обеспечивает SPI.

конец июня 2019г. ШК

/*
  Basic code for using Maxim MAX7219/MAX7221 with Arduino.
  Wire the Arduino and the MAX7219/MAX7221 together as follows:
  | Arduino   | MAX7219/MAX7221 |
  | --------- | --------------- |
  | MOSI (11) | DIN (1)         |
  | SCK (13)  | CLK (13)        |
  | I/O (9)*  | LOAD/CS (12)    |
    * - This should match the LOAD_PIN constant defined below.

  For the rest of the wiring follow the wiring diagram found in the datasheet.

  Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
  Author:  Nicholas Dobie <nick@nickdobie.com>
  Date:    30 December 2013
  License: WTFPL (http://www.wtfpl.net/)
 */



#include <SPI.h>

// What pin on the Arduino connects to the LOAD/CS pin on the MAX7219/MAX7221
#define LOAD_PIN 9
#define pkey 300

const byte dg[40] = {30, 33, 33, 30, 0, 34, 63, 32, 34, 49, 41, 38, 18, 33, 37, 26, 24, 20, 63, 16, 23, 37, 37, 25, 30, 37, 37, 25, 00, 01, 57, 07, 26, 37, 37, 26, 6, 41, 41, 30};
const int scrt[9] = { 495, 205, 157, 133, 117, 106, 97, 90, 80};
byte hr = 12;
byte mn = 34;
byte sc = 56;
byte dh, dm, eh, em;
byte ii, zx, zy, zz, zt = 0;

byte pics[25];

byte hod = 0;
unsigned long tempus,tmkey;
unsigned long tmscr;

/**
 * Transfers data to a MAX7219/MAX7221 register.
 *
 * @param address The register to load data into
 * @param value   Value to store in the register
 */
void maxTransfer(uint8_t address, uint8_t value) {
  // Ensure LOAD/CS is LOW
  digitalWrite(LOAD_PIN, LOW);
  // Send the register address
  SPI.transfer(address);
  // Send the value
  SPI.transfer(value);
  // Tell chip to load in data
  digitalWrite(LOAD_PIN, HIGH);
}


void setup() {
  // Set load pin to output
  pinMode(LOAD_PIN, OUTPUT);
  // Reverse the SPI transfer to send the MSB first
  SPI.setBitOrder(MSBFIRST);
  // Start SPI
  SPI.begin();
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);

  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);

  maxTransfer(0x0F, 0x00);
  // Disable mode B
  maxTransfer(0x09, 0x00);
  // Use lowest intensity
  maxTransfer(0x0A, 0x00);
  // scan all
  maxTransfer(0x0B, 0x07);
  for (uint8_t i = 1; i < 9; ++i)
  {
    maxTransfer(i, 0);
  }
  // Turn on chip
  maxTransfer(0x0C, 0x01);

  format_pics();
  tempus = millis() + 1000;
  zt = 0;
  tmscr = millis() +  scrt[zt];
  zy = 0;
tmkey = millis() + pkey;

}


void gettime() {
  dh = hr / 10;
  eh = hr - 10 * dh;
  dm = mn / 10;
  em = mn - 10 * dm;
}

void getdg(byte am) {
  ii = am * 4; // adres digit
  for (uint8_t i3 = ii; i3 < ii + 4; ++i3)
  {
    if (zx < 6) pics[zx] = dg[i3];
    if (zx > 5)     pics[zx] = dg[i3] * 4;
    if (zx > 17)     pics[zx] = dg[i3];


    zx++;
  }
}

void format_pics() {
  gettime();

  zx = 0;
  pics[zx] = 0; // space
  zx++; //1
  getdg(dh);//5
  pics[zx] = 0; // space
  zx++;//6
  getdg(eh);//10
  pics[zx] = 0; // space
  zx++;//11
  pics[zx] = 18 * 4; // dots
  zx++;//12
  pics[zx] = 0; // space
  zx++;//13
  getdg(dm);//17
  pics[zx] = 0; // space
  zx++;//18
  getdg(em);//22
  pics[zx] = 0; // space

  //23 byte  0-22




}

void scr()
{
  for (byte k = 1; k < 9; ++k)  {
    zz = zy + k - 1;
    
    //11 выводим в 4 и 5 позицию
    if (zz==11) {if ((k==4)||(k==5))    maxTransfer(k, pics[zz]);} else maxTransfer(k, pics[zz]);
    
  }

}

void loop() {

  if (millis() > tmscr) {  // horizont
    if (hod == 0) zy++;
    if (hod == 1) zy--;
    if (zy == 0)   hod = 0;
    if (zy == 15)   hod = 1;
    zt = zy; // 0 1 2 17
    if (zt > 7) zt = 15 - zt;
    tmscr = millis() + scrt[zt];
    scr();
  }


  if (millis() > tempus) {  // ход часов
    tempus = millis() + 1000;
    seci();
  }

  //
  if (millis() > tmkey) {  // ход часов
    tmkey = millis() + pkey;
    key();
  }
}
void key()
{
  digitalWrite(2, LOW);
  if (!digitalRead(3)) {
    hr++;
    if (hr>23)hr=0;
    format_pics();
    scr();
  }

  if (!digitalRead(5))
  { mn++;
    if (mn>59)mn=0;
    format_pics();
    scr();
  }
  if (!digitalRead(4)) {
    hr--;
    if (hr==0)hr=23;
    format_pics();
    scr();
  }

  if (!digitalRead(6))
  { mn--;
    if (mn==0)mn=59;
    format_pics();
    scr();
  }
  digitalWrite(2, HIGH);
}


void seci()
{
  sc++;
  if (sc > 59)
  {
    sc = 0;
    mn++;
    if (mn > 59) {
      mn = 0;
      hr++;
    }
    if (hr > 23) {
      hr = 0;
    }
    format_pics();
  }
}

 

skoctehs
Offline
Зарегистрирован: 27.02.2016
b707
Offline
Зарегистрирован: 26.05.2017

красиво!

Поставил плюсик

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Действительно красиво - я не удержался, залил и посмотрел живьем.

skoctehs
Offline
Зарегистрирован: 27.02.2016

const char now[] = __TIME__;

// 12в ленты часы ЗВЕЗДА и минуты стрелки динамическая индикация
// uln2003a+bc237 2s8550 3pcs
// stm8s103
// таблица выводы - стрелки
/*       13   14   15
   12 = h0    h4    h8
   11   m0    m20   m40
   10   h1    h5    h9
   9    m5    m25    m45
   8    h2    h6     h10
   7    m10   m30    m50
   6    h3    h7     h11
   5    m15    m35   m55
*/
boolean svd;
long mms, msl;
byte tt1, tt2, ma, mb, ha, hb, minut, mnn, hours, hnn, sec, led_c , lz = 0;
int z;
const int scrt[12] = { 495, 205, 157, 133, 117, 106, 106, 117, 133, 157, 205, 495};
const int t10000=10000;
void corr_h() {
  // выбор стрелки часовой

  hnn = hours;
  if (hnn == 0) {
    ha = 13;
    hb = 12;
  }
  if (hnn == 1) {
    ha = 13;
    hb = 10;
  }
  if (hnn == 2) {
    ha = 13;
    hb = 8;
  }
  if (hnn == 3) {
    ha = 13;
    hb = 6;
  }
  if (hnn == 4) {
    ha = 14;
    hb = 12;
  }
  if (hnn == 5) {
    ha = 14;
    hb = 10;
  }
  if (hnn == 6) {
    ha = 14;
    hb = 8;
  }
  if (hnn == 7) {
    ha = 14;
    hb = 6;
  }
  if (hnn == 8) {
    ha = 15;
    hb = 12;
  }
  if (hnn == 9) {
    ha = 15;
    hb = 10;
  }
  if (hnn == 10) {
    ha = 15;
    hb = 8;
  }
  if (hnn == 11) {
    ha = 15;
    hb = 6;
  }

}



void corr_m() {
  // выбор стрелки минутной
  if (mnn == 0) {
    ma = 13;
    mb = 11;
  }
  if (mnn == 5) {
    ma = 13;
    mb = 9;
  }
  if (mnn == 10) {
    ma = 13;
    mb = 7;
  }
  if (mnn == 15) {
    ma = 13;
    mb = 5;
  }
  if (mnn == 20) {
    ma = 14;
    mb = 11;
  }
  if (mnn == 25) {
    ma = 14;
    mb = 9;
  }
  if (mnn == 30) {
    ma = 14;
    mb = 7;
  }
  if (mnn == 35) {
    ma = 14;
    mb = 5;
  }
  if (mnn == 40) {
    ma = 15;
    mb = 11;
  }
  if (mnn == 45) {
    ma = 15;
    mb = 9;
  }
  if (mnn == 50) {
    ma = 15;
    mb = 7;
  }
  if (mnn == 55) {
    ma = 15;
    mb = 5;
  }

}



void key_k() {
  // обработка кнопок
bool k0=digitalRead(0);
bool k1=digitalRead(1);
  if (k0 == 0) tt1++ ; else tt1 = 0;
  if (k1 == 0) tt2++ ; else tt2 = 0;
if ((tt1*tt2)>75) {
  minut=0;
  sec=0;
  mms = millis() + t10000;
}
  // 1 цикл опроса  8 ms * 50 = 400мс
  if (tt1 > 50) {
    hours++;
    tt1 = 0;
    if (hours > 11)hours = 0;
    corr_h();
  }
  if (tt2 > 50) {
    minut = minut + 5;
    tt2 = 0;
    if (minut > 59) minut = 0;

    mnn = minut;
    mnn = 5 * byte(mnn / 5); // округляем до 5 минутки
    corr_m();
    mnn = minut;
  }

}



void disp() {
  // часовая стрелка
  digitalWrite(ha, HIGH);   // turn the LED on (HIGH is the voltage level)
  digitalWrite(hb, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2);                       // wait for a second
  digitalWrite(ha, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(hb, LOW);    // turn the LED off by making the voltage LOW

  // минутная стрелка
  digitalWrite(ma, HIGH);   // turn the LED on (HIGH is the voltage level)
  digitalWrite(mb, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2);                       // wait for a second
  digitalWrite(ma, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(mb, LOW);    // turn the LED off by making the voltage LOW
}

void  circl_m() {
  // оборот  минутной стрелки
  for (z = 0; z < 12; z++) {
    // минутная стрелка
    mnn = minut + z * 5 ; //(0-55 = 0-11)
    if (mnn > 59) mnn = mnn - 60; // проходим ноль
    mnn = 5 * byte(mnn / 5); // округляем до 5 минутки

    corr_m();
    digitalWrite(ma, HIGH);   // turn the LED on (HIGH is the voltage level)
    digitalWrite(mb, HIGH);   // turn the LED on (HIGH is the voltage level)

    delay(scrt[z]);                       // wait for a second
    digitalWrite(ma, LOW);    // turn the LED off by making the voltage LOW
    digitalWrite(mb, LOW);    // turn the LED off by making the voltage LOW

  }
  //  коррекция индикации
  mnn = minut;
  mnn = 5 * byte(mnn / 5); // округляем до 5 минутки
  corr_m();
  mnn = minut;
  if (hnn != hours) corr_h(); // коррекция часовой стрелки
}

void clc() {
  //  тик так 10 секунд

  mms = millis() + t10000;
  sec++;
  if (sec > 5) {
    minut++;
    sec = 0;
    if (minut > 59) {
      hours++;
      minut = 0;
      if (hours > 11) hours = 0;
    }
    // смена минуты - эффект круга
    circl_m();
  }
}


void led() {

  // раз в полсекунды
  // раз в 5 секунд моргаем сколько минут от стрелки прошло 19:53 - 3 минуты
  //  svd = !svd; // инверсия светодиода
  // моргаем сколько неполных минут до 5
  mnn = minut;
  mnn = 5 * byte(mnn / 5);
  lz = (minut - mnn + 1) * 2 + 1; // 2 4 6 8 10
  if (lz > led_c) svd = HIGH; else svd = LOW;

  if (bitRead(led_c, 0)) svd = LOW;

  digitalWrite(2, svd);    // светодиодик
  msl = millis() + 500;
  led_c++;
  if (led_c > 15) led_c = 1;
}


void setup() {
  pinMode(0, INPUT); // кнопка перевода часов
  pinMode(1, INPUT);// кнопка перевода минут
  pinMode(2, OUTPUT); // индикатор секунд
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  hours =  4;
  minut = 40;
  hours =  atoi(&now[0]);
  minut = atoi(&now[3]);
  msl = millis() + 500;
  mms = millis() + t10000;
  circl_m();
}

void loop() {

  key_k(); // контроль кнопок
  if (mms < millis()) clc(); // ход часов и мигание светодиода
  if (msl < millis() )led(); // мигание светодиода
  disp(); // индикация стрелок
}

 

skoctehs
Offline
Зарегистрирован: 27.02.2016

Собрано на STM8S103,ULN2003,S8550,BC237

использовал кусочки ленты 12в (по 3 светодиода) 

b707
Offline
Зарегистрирован: 26.05.2017

 Пишете для стм8 в ардуино иде? А что за аддон? Как поддержка, глюки есть? Много ли библиотек поддерживается?

skoctehs
Offline
Зарегистрирован: 27.02.2016

b707 пишет:

 Пишете для стм8 в ардуино иде?

первый раз = это ответ и на другие вопросы :)

А что за аддон?

устанавливается как новая плата (по инструкции  с инета, делал в прошлом году - а допаял  часы вчера)

не помогу = лучше вам поискать лично

Как поддержка, глюки есть?

тут вроде ок всё

Много ли библиотек поддерживается?

столкнулся mstimer2 не поддерживает - да и не искал вот

вроде есть I2C

использовал ST-LINK

по мне выходит самый  бюджетный вариант для разных глупостей

сорри, если не помог

Deniskyn
Offline
Зарегистрирован: 13.04.2019

Видео не доступно......

skoctehs
Offline
Зарегистрирован: 27.02.2016

https://disk.yandex.ru/i/ooZdR9avVFIEKA
Первую конструкцию разобрал