Круглые часы на адресной светодиодной ленте

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
@feniragon, Ситуация такая же, как и ранее описывал:
когда должны отображать часовую стрелку
58,59, 0 - то 0 остается фоном.
59,0,1 - нормально;
0,1,2 - 0 фон;
1,2,3 - 1 фон;
2,3,4 - 2 фон;
3,4,5 - 3 фон;
4,5,6 - уже как положено
Сейчас костылёк допилю, погоняю 6 часов.
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
Ну, не удержался и сделал такое:
int i = 0;
for (i = 0; i < LEDCOUNT; i++)
strip.setPixelColor(i, R, G, B); //заливаем контур (60 светодиодов)
for (i = FIRSTLEDID%5; i < FIRSTLEDID%5+LEDCOUNT; i = i+5)
strip.setPixelColor(i, 0, G + PLUS, B); // заливаем зеленые разделители

hoursDelta = m/12;
int currentHourLed;
currentHourLed = FIRSTLEDID + h*5; //для всех остальных часов
int LedH1 = (currentHourLed - 1)% LEDCOUNT + hoursDelta;
int LedH2 = (currentHourLed)% LEDCOUNT + hoursDelta;
int LedH3 = (currentHourLed + 1)% LEDCOUNT + hoursDelta;

if (LedH1 > 59){
strip.setPixelColor(LedH1 - 60, 250, 0, 0);
strip.setPixelColor(LedH2, 250, 0, 0);
strip.setPixelColor(LedH3, 250 ,0 ,0);
}
if (LedH3 > 59){
strip.setPixelColor(LedH1, 250, 0, 0);
strip.setPixelColor(LedH2, 250, 0, 0);
strip.setPixelColor(LedH3 - 60, 250 ,0 ,0);
}
else{
strip.setPixelColor(LedH1, 250, 0, 0);
strip.setPixelColor(LedH2, 250, 0, 0);
strip.setPixelColor(LedH3, 250 ,0 ,0);
}
strip.setPixelColor((FIRSTLEDID+m) % LEDCOUNT, 250, 0, 250); //Рисуем "минуту"
strip.show();

При FIRSTLEDID !=0 все показывает замечательно. Сейчас поизучаю без костыля
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
При h == 6
55 4 57 5 58 59 60
55 4 58 5 58 59 60
55 4 59 5 58 59 60
90 0 0 6 29 30 31
90 0 1 6 29 30 31
90 0 2 6 29 30 31
90 0 3 6 29 30 31
90 0 4 6 29 30 31
90 0 5 6 29 30 31
90 0 6 6 29 30 31
90 0 7 6 29 30 31
90 0 8 6 29 30 31
90 0 9 6 29 30 31
90 0 10 6 29 30 31
90 0 11 6 29 30 31
90 1 12 6 30 31 32
90 1 13 6 30 31 32
90 1 14 6 30 31 32
90 1 15 6 30 31 32
90 1 16 6 30 31 32
90 1 17 6 30 31 32
90 1 18 6 30 31 32
90 1 19 6 30 31 32
90 1 20 6 30 31 32
90 1 21 6 30 31 32
90 1 22 6 30 31 32
90 1 23 6 30 31 32
90 2 24 6 31 32 33
90 2 25 6 31 32 33
90 2 26 6 31 32 33
90 2 27 6 31 32 33
90 2 28 6 31 32 33
90 2 29 6 31 32 33
90 2 30 6 31 32 33
90 2 31 6 31 32 33
90 2 32 6 31 32 33
90 2 33 6 31 32 33
90 2 34 6 31 32 33
90 2 35 6 31 32 33
90 3 36 6 32 33 34
90 3 37 6 32 33 34
90 3 38 6 32 33 34
90 3 39 6 32 33 34
90 3 40 6 32 33 34
90 3 41 6 32 33 34
90 3 42 6 32 33 34
90 3 43 6 32 33 34
90 3 44 6 32 33 34
90 3 45 6 32 33 34
90 3 46 6 32 33 34
90 3 47 6 32 33 34
90 4 48 6 33 34 35
90 4 49 6 33 34 35
90 4 50 6 33 34 35
90 4 51 6 33 34 35
90 4 52 6 33 34 35
90 4 53 6 33 34 35
90 4 54 6 33 34 35
90 4 55 6 33 34 35
90 4 56 6 33 34 35
90 4 57 6 33 34 35
90 4 58 6 33 34 35
90 4 59 6 33 34 35
65 0 0 7 4 5 6
65 0 1 7 4 5 6
65 0 2 7 4 5 6

Там либо доп условие надо втыкать, либо у меня воображение дальше не работает.

Воткнул hoursDelta = round(m/12.0);
55 5 58 5 59 60 61
55 5 59 5 59 60 61
90 0 0 6 29 30 31
90 0 1 6 29 30 31
90 0 2 6 29 30 31
90 0 3 6 29 30 31
90 0 4 6 29 30 31
90 0 5 6 29 30 31
90 1 6 6 30 31 32
90 1 7 6 30 31 32
90 1 8 6 30 31 32
90 1 9 6 30 31 32
90 1 10 6 30 31 32
90 1 11 6 30 31 32
90 1 12 6 30 31 32
90 1 13 6 30 31 32
90 1 14 6 30 31 32
90 1 15 6 30 31 32
90 1 16 6 30 31 32
90 1 17 6 30 31 32
90 2 18 6 31 32 33
90 2 19 6 31 32 33
90 2 20 6 31 32 33
90 2 21 6 31 32 33
90 2 22 6 31 32 33
90 2 23 6 31 32 33
90 2 24 6 31 32 33
90 2 25 6 31 32 33
90 2 26 6 31 32 33
90 2 27 6 31 32 33
90 2 28 6 31 32 33
90 2 29 6 31 32 33
90 3 30 6 32 33 34
90 3 31 6 32 33 34
90 3 32 6 32 33 34
90 3 33 6 32 33 34
90 3 34 6 32 33 34
90 3 35 6 32 33 34
90 3 36 6 32 33 34
90 3 37 6 32 33 34
90 3 38 6 32 33 34
90 3 39 6 32 33 34
90 3 40 6 32 33 34
90 3 41 6 32 33 34
90 4 42 6 33 34 35
90 4 43 6 33 34 35
90 4 44 6 33 34 35
90 4 45 6 33 34 35
90 4 46 6 33 34 35
90 4 47 6 33 34 35
90 4 48 6 33 34 35
90 4 49 6 33 34 35
90 4 50 6 33 34 35
90 4 51 6 33 34 35
90 4 52 6 33 34 35
90 4 53 6 33 34 35
90 5 54 6 34 35 36
90 5 55 6 34 35 36
90 5 56 6 34 35 36
90 5 57 6 34 35 36
90 5 58 6 34 35 36
90 5 59 6 34 35 36
65 0 0 7 4 5 6
65 0 1 7 4 5 6
 
Изменено:

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
А, и еще вот чего изменил:
// обработка кнопок
currentMillis = millis();
if (currentMillis - pause > PAUSEPERIOD) {
pause = currentMillis;
if (!digitalRead(keyHor)){
h++;
fillLED();
}
if (!digitalRead(keyMin)){
m++;
fillLED();
}

А то подводить неудобно, раз в минуту же перерисовывается.
 

feniragon

✩✩✩✩✩✩✩
31 Июл 2018
87
5
55 5 58 5 59 60 61
55 5 59 5 59 60 61
1. Ну вот посмотри откуда берутся номера диодов и почему.. и какие должны быть. Ведь у нас же не может быть 60 и 61 диода, правильно?

90 0 0 6 29 30 31
90 0 1 6 29 30 31
90 0 2 6 29 30 31
90 0 3 6 29 30 31
90 0 4 6 29 30 31
90 0 5 6 29 30 31
90 1 6 6 30 31 32
90 1 7 6 30 31 32
90 1 8 6 30 31 32
90 1 9 6 30 31 32
2. Не правда ли ситуация с минутами лучше из-за округления? Это поясню - не очевидный момент:
m/12 мы делим, получаем дробное число, так? 4,75. Но на выходе нужно ЦЕЛОЕ число. Эта операция деления не округляет, а отбрасывает дробную часть числа, возвращая целую. Таким образом получаем фигню.

3. А вот почему у тебя получается currentHourLed = 90, когда по формуле должно быть 60
И как следствие не те номера диодов - смотри что ты менял. Ибо
currentHourLed = FIRSTLEDID + h*5 = 30 + 6*5 = 60

При currentHourLed = 90 по формулам
(currentHourLed - 1)% LEDCOUNT + hoursDelta, имеем 29, 30, 31

Если у тебя стартовый диод 30 - то в 6 часов должны светиться диоды 59,0,1. А вот если 12(0) часов то эти же 29, 30, 31 и будут.
 
Изменено:

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
Да, при 59 минут + 1 = увеличивается час - это меня вполне устраивает. И 12 - это 0, тоже как бы вот тут оговорено
if (h>11) {
h = 0;
}
В общем, если при расчетах (currentHourLed - 1)% LEDCOUNT + hoursDelta параметр (currentHourLed - 1) принимает значение 59, то имеем 59%60 + hoursDelta , то есть 59 + (от 0 до 4). И получаем номера несуществующих диодов. Остальные значения работают корректно при FIRSTLEDID != 0. При 0-м значении FIRSTLEDID и h == 0 имеем

currentHourLed = FIRSTLEDID + LEDCOUNT превращается в 0+60
(currentHourLed - 1)% LEDCOUNT + hoursDelta соответственно в (60 - 1)%60 + hoursDelta, что приводит опять к несуществующим значениям.

В принципе, это справедливо для любого вычисления strip.setPixelColor((currentHourLed(+/-1) )% LEDCOUNT, где в делимом прорастает значение 59. И сразу же + 1 ==> мы вываливаемся за пределы. При значении 60 похожая ситуация, но менее заметная ==> 0 - 1 и в отрицательное значение ушли.

Ход размышлений правильный?
 
Изменено:

feniragon

✩✩✩✩✩✩✩
31 Июл 2018
87
5
@seve_len, нет. Ты не учитываешь 11+1=0. Смотри, вот в твоем куске h = 12 и сразу идет перерисовка. fillLED. Или не так? Я вообще не понимаю зачем этот вызов тут....

В остальном да. Смотришь куда нужно
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
@feniragon, подводить неудобно. ты накликал, ждешь около минуты и только тогда результат. А так - жмакнул кнопку и перерисовалось

Смотри, вот в твоем куске h = 12 и сразу идет перерисовка. fillLED
да, так и есть. Только визуально этого не шибко заметно, поэтому я и забил)

Редко при подведении через 12 часов проскакиваешь, во всяком случае у меня это не особо получалось. Можно воткнуть

if (!digitalRead(keyHor)){
h++;
if (h>11) {
h = 0;
}
fillLED();
}
 
Изменено:

feniragon

✩✩✩✩✩✩✩
31 Июл 2018
87
5
Плохая затея ориентироваться на то, что видно. Это ж программирование. Перед тем как увидеть что-то может пройти 100500 инструкций..

вообще эту проверку можно вынести внутрь fillLED. По логике не очень, но удобнее
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
Хе-хе, это да) Так и есть, и с минутами аналогично. Ща тогда в fillLED это перетащу. А вот что делать с вышеобозначенным значением в 59 - пока кроме костыля ничего в голову не лезет. Ну да ладно, свежая мысля - она приходит опосля. Может, надо как-нибудь с другой стороны зайти...
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
Собственно, именно отсюда я и хотел начать.


Я уже начал подумывать о массиве. Нуачо, минуты-то ладно, а вот под часовую двухмерник сколхозить и ай-на-нэ его. Или это трэш и угар?
 

feniragon

✩✩✩✩✩✩✩
31 Июл 2018
87
5
@seve_len, да, это треш) проверь формулу. В ней и проблема. Если сдаешься - дам ответ.
Если в притык не понимаешь - просто обдумай что происходит логически со стрелками по этой формуле
 
Изменено:

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
@feniragon, привет! Меня тут мысля посетила, но пока проверить не могу..... А если к вычислению
(currentHourLed - 1)% LEDCOUNT + hoursDelta добавить постобработку типа
((currentHourLed - 1)% LEDCOUNT + hoursDelta)%LEDCOUNT

Тогда (по идее) при значениях выше 59 будет в остатке (если я все правильно понимаю) от 0 до 3, то есть (59+4)%60 = 3.
Блин, а 4-ки то не будет.. надо еще покубатурить.

А 4-ка-то нам особо и не нужна вроде в остатке... Блин, как домой доберусь - проверю
 

feniragon

✩✩✩✩✩✩✩
31 Июл 2018
87
5
@seve_len, ты очень близок. А в чем разница (((60 + 30) % 60) + 25)%60 и ( 60 +30 + 25)%60 ?

откуда ты 4ку нашел? У нас три диода светятся. А в остатке от 60 будут числа 0-59
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
@feniragon, Согласен, математику подзабываю, нету разницы. 4-ка - затупил, выше поправился вроде. Ну да, я просто недопетрил сразу, функция % неочевидна новичку
Приду домой (благо, уже скоро), запотестю
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
Хе-хе, жёваный крот, оно работает!!!!
#include <SPI.h>
#include "Adafruit_NeoPixel.h"
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, 12, NEO_GRB + NEO_KHZ800);

#define keyHor 5 //кнопки
#define keyMin 4
const int R = 6; //сделано для упрощения подбора цветов и яркости
const int G = 6;
const int B = 6;
const int FIRSTLEDID = 30;
const int LEDCOUNT = 60;
const unsigned int MINUTEPERIOD = 60000; // минута в ms
const unsigned int PAUSEPERIOD = 200;
const int PLUS = 20;
unsigned long currentMillis;
unsigned long timing; //для счетчика времени
unsigned long pause; //для обработки кнопок
int m = 0; //минуты
int h = 0; //часы
int hoursDelta = 0;

void setup() {
strip.begin(); // Функция begin() настроит порт Arduino и выставит значения по умолчанию.
strip.show(); // Функция show() передаст команду на выключение всем пикселям.
Serial.begin(9600);

pinMode(keyHor, INPUT_PULLUP);
pinMode(keyMin, INPUT_PULLUP);
timing = millis();
pause = millis();
}

void fillLED(){
if (m > 59) { // добавил, дабы не выйти за допустимые пределы значений
m = 0;
}
if (h>11) {
h = 0;
}

int i = 0;
for (i = 0; i < LEDCOUNT; i++)
strip.setPixelColor(i, R, G, B); //заливаем контур (60 светодиодов)
for (i = FIRSTLEDID%5; i < FIRSTLEDID%5+LEDCOUNT; i = i+5)
strip.setPixelColor(i, R, G + PLUS, B); // заливаем зеленые разделители

hoursDelta = round(m/12.0);
int currentHourLed;

currentHourLed = FIRSTLEDID + h*5; //для ВСЕХ положений часовой стрелки

strip.setPixelColor((currentHourLed - 1 + hoursDelta)%LEDCOUNT, 250, 20, 0);
strip.setPixelColor((currentHourLed + hoursDelta)%LEDCOUNT, 250, 20, 0);
strip.setPixelColor((currentHourLed + 1 + hoursDelta)%LEDCOUNT, 250 ,20 ,0);

strip.setPixelColor((FIRSTLEDID+m) % LEDCOUNT, 0, 250, 250); //Рисуем "минуту"
strip.show();

}

void loop() {
currentMillis = millis();
if (currentMillis - timing >= MINUTEPERIOD) {
timing = currentMillis;
m++;
if (m > 59) {
m = 0;
h++;
}
if (h>11) {
h = 0;
}
fillLED();
}

// обработка кнопок
currentMillis = millis();
if (currentMillis - pause > PAUSEPERIOD) {
pause = currentMillis;
if (!digitalRead(keyHor)){
h++;
fillLED(); // Добавил вызов для отображения изменений, иначе коррективы видны при следующей отрисовке ( до 60 сек)
}
if (!digitalRead(keyMin)){
m++;
fillLED(); // Добавил вызов для отображения изменений, иначе коррективы видны при следующей отрисовке ( до 60 сек)
}
}
}

@feniragon, Спасибище тебе огромное!!!! Возможно, что эту конструкцию можно еще оптимизировать, но я пока вообще не вижу, что. Блин, это было очень интересно! Еще раз спасибо!
 

feniragon

✩✩✩✩✩✩✩
31 Июл 2018
87
5
@seve_len,
int currentHourLed = FIRSTLEDID + h*5; //для ВСЕХ положений часовой стрелки

можно сразу инициализировать переменную

не правильно будет работать в 0часов 2 минуты если начало в нулевом диоде.

Для исправления можно сделать проверку if h>13 h=1 и сразу инициализировать h=12

Две проверки явно лишние
 

seve_len

✩✩✩✩✩✩✩
13 Сен 2018
70
3
40
@feniragon,
Точно, она же теперь фиксированная.
Проверил, с 0:00 по 0:05 включительно при нулевом диоде

Не совсем понял, две проверки в fillLED() ? Это про нынешние проверки значений часов и минут?