smooth blink

nibelung
Offline
Зарегистрирован: 21.04.2021

Купил я себе у китайцев платку с контроллером STM32F411 с завода она идет с прошитым загрузчиком под STMDUINO. При включении обнаружилось, что светодиод на этой плате плавно загорается а затем гаснет. Делает это загрузчик или прошитый для примера скетч, я тогда разбираться не стал, но эффект мне понравился.

Сейчас праздники, есть немного свободного времени. Вспомнил я про этот эффект и захотелось мне его повторить, но уже на обычной ардуинке. В качестве подопытного мыша, у меня, выступает китайский клон "SparkFun Pro Micro". Если у Вас другая Aduino, подправьте в первой строке привязку к выводу управляющему светодиодом.

#define LED  LED_BUILTIN_RX
#define INTERVAL1 (23u)
#define INTERVAL2 (24u)

void setup() {
  pinMode (LED, OUTPUT);
}

void loop() {
  static uint8_t clk1 = 0, clk2 = 0;
  static uint8_t led_state = 0;
  uint8_t now = millis();

  if (INTERVAL1 < (uint8_t)(now - clk1))
  {
    clk1 += INTERVAL1;
    led_state ^= 1;
  }

  if (INTERVAL2 < (uint8_t)(now - clk2))
  {
    clk2 += INTERVAL2;
    led_state ^= 1;
  }

  digitalWrite(LED, ((0 == led_state) ? LOW : HIGH));
 }

Всех с праздником.

Morroc
Offline
Зарегистрирован: 24.10.2016

Стандартный из Examples Fade не такой ? По описанию похоже.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Всё не так. 

Например millis() совсем не uint8_t, а совсем даже unsigned long. Можно очень даже нарваться.

Почитайте лучше "блинк без делей".

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

mykaida пишет:
Всё не так. Например millis() совсем не uint8_t, а совсем даже unsigned long. Можно очень даже нарваться.

Всё ок. Просто код нарывается на переполнение байта, а не дворда, более того, это не баг, это фича.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ну не знаю, если поменять:
 

led_state ^= 1;

на

led_state = !led_state;

вроде более читабельный код, да и по памяти:
 

Скетч использует 824 байт (2%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 12 байт (0%) динамической памяти, оставляя 2036 байт для локальных переменных. Максимум: 2048 байт.


Скетч использует 826 байт (2%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 12 байт (0%) динамической памяти, оставляя 2036 байт для локальных переменных. Максимум: 2048 байт.


А если задействовать сериал, то:

Скетч использует 2022 байт (6%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 191 байт (9%) динамической памяти, оставляя 1857 байт для локальных переменных. Максимум: 2048 байт.

Скетч использует 1918 байт (5%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 191 байт (9%) динамической памяти, оставляя 1857 байт для локальных переменных. Максимум: 2048 байт.

Не всё так однозначно, где найдёшь, где потеряешь )))

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

negavoid2 пишет:

Всё ок. Просто код нарывается на переполнение байта, а не дворда, более того, это не баг, это фича.

Фича - это косяк. Идею понял, но не одобряю.

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Мы расстроены, продолжайте держать нас в курсе :)

На самом деле, нормально. И delay использовать нормально. И даже goto (хоть оно, конечно, почти никогда и не нужно). Реальный мир - он того, не такой, как проповедуют великие теоретики, он полон компромиссов, и неудобностей, и прочего, и хоть я их (теоретиков) и уважаю, но свою голову-то на плечах тоже надо иметь.

Green
Offline
Зарегистрирован: 01.10.2015

А я вообще не понимаю этих перестраховщиков.
Простейший скетч и столько поноса.(

#define LED  LED_BUILTIN_RX
#define INTERVAL1 (23u) //на кой здесь u и скобки?
#define INTERVAL2 (24u)
#define toggle(x) digitalWrite(x, !digitalRead(x))

void setup() {
  pinMode (LED, OUTPUT);
}

void loop() {
  static uint8_t clk1 = 0, clk2 = 0; //на кой здесь 0-ли?
  static uint8_t led_state = 0; //на кой вообще этот state?
  uint8_t now = millis();

  if (INTERVAL1 < (uint8_t)(now - clk1)) //отчего бы не написать по нормальному:
  if (now - clk1 > INTERVAL1) {
  { //стиль идиотский!
    clk1 += INTERVAL1;
    led_state ^= 1; //toggle(LED); 
  }

  if (INTERVAL2 < (uint8_t)(now - clk2)) //аналогично
  {
    clk2 += INTERVAL2;
    led_state ^= 1;
  }

  digitalWrite(LED, ((0 == led_state) ? LOW : HIGH)); //это лишнее и это вообще порнография
 }

 

nibelung
Offline
Зарегистрирован: 21.04.2021

Green, прежде чем ругать чужой, работающий код, да еще с таким наездом, подумали бы хорошенько. Если чего не понятно могли бы спросить и вам бы ответили.

А так, вы только свою безграмотность продемонстрировали.

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

nibelung пишет:

Green, прежде чем ругать чужой, работающий код, да еще с таким наездом, подумали бы хорошенько. Если чего не понятно могли бы спросить и вам бы ответили.

А так, вы только свою безграмотность продемонстрировали.

nibelung - а что так резко-то? Критики не любите?

"Работающий код" не принято ругать в одном случае - когда он делает что-то важное, что до него никому не удавалось. Вы выложили элементарнейшую мигалку на эффекте интерференции - а ведете себя так, будто как минимум теорему Ферма решили...

Что касакется "безграмотности" - я бы поспорил. Попытайтесь обосновать, зачем вы написали 23u

nibelung
Offline
Зарегистрирован: 21.04.2021

b707 пишет:

Попытайтесь обосновать, зачем вы написали 23u

Чтобы объяснить компилятору, что это unsigned константа. По умолчанию все константы имеют тип int (знаковый).

b707 пишет:

nibelung - а что так резко-то? Критики не любите?

А где там критика? Только самоутверждение за счет новичка. Вот этого не люблю.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Нибелунг! Ща я встану и напишу пост в защиту тебя. Все у тебя правильно. Может слегка избыточно, но правильно и красиво.
Не будь нежным таким, как кожа на залупе, только больше троллить станут.
Некоторые перегибают в чморении новичков. Прости им. ;))

nibelung
Offline
Зарегистрирован: 21.04.2021

wdrakula пишет:
Нибелунг! Ща я встану и напишу пост в защиту тебя. Все у тебя правильно. Может слегка избыточно, но правильно и красиво. Не будь нежным таким, как кожа на залупе, только больше троллить станут. Некоторые перегибают в чморении новичков. Прости им. ;))

Спасибо на добром слове.

Им простил :))

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

nibelung пишет:

Чтобы объяснить компилятору, что это unsigned константа. По умолчанию все константы имеют тип int (знаковый).

где ты увидал в этом выражении константу?

nibelung
Offline
Зарегистрирован: 21.04.2021

Ну вот, троллинг продолжается :)))

b707 пишет:

где ты увидал в этом выражении константу?

А где ты увидал в этом выражении переменную?

 
Bruzzer
Offline
Зарегистрирован: 17.03.2020

wdrakula пишет:
... Ща я встану и ....

Не будь нежным таким, как кожа на ....

Сразу представилось общение тертого жизней члена форума с молодым и нежным.

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

wdrakula пишет:
Может слегка избыточно, но правильно и красиво. ))

"избыточно" и "красиво" вряд ли могут быть синонимами, когда мы говорим о программировании.

Добавление скобок и "u"  к величине, применяемой не в составе выражения. а отдельно - скорее свидетесльствует о том, что автор не понимает, что пишет.

Изначально еще хотел написать о избыточности явного приведения разности двух байт к типу uint8_t - но подумал, что сам, наверно, написал бы так же - просто на автомате, чтобы не задумыватся о том, какой тип тут примет компилятор. Но вряд ли такой кастинг "на всякий случай" говорит в пользу "грамотности". скорее просто лень :)

nibelung
Offline
Зарегистрирован: 21.04.2021

b707 пишет:

Изначально еще хотел написать о избыточности явного приведения разности двух байт к типу uint8_t - но подумал, что сам, наверно, написал бы так же - просто на автомате, чтобы не задумыватся о том, какой тип тут примет компилятор. 

Вот это, кстати, интересное замечание. Написал так, именно на автомате. Потом убрал приведение типа, ибо выглядит немного громоздко. Убедился, что компилятор, ожидаемо, ошибся. И вернул приведение типа на место.

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

Короче. Влад.

когда встанешь - с радостью выслушаю твою лекцию, зачем тут в выражении

#define XX (23u)

скобки и "u" . Только не вообще, а конкретно в этом коде, из первого сообщения.

 

PS   нибелунг - вопрос конкретному человеку, не вам

rkit
Offline
Зарегистрирован: 23.11.2016

Так себе код. Если добавить другую нагрузку, то будет работать плохо. Даже как учебный не годится - слишком специфичный и мудреный.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:

Короче. Влад.

когда встанешь - с радостью выслушаю твою лекцию, зачем тут в выражении

#define XX (23u)

скобки и "u" . Только не вообще, а конкретно в этом коде, из первого сообщения.

 

PS   нибелунг - вопрос конкретному человеку, не вам

По поводу неуместности Фединого toggle() в данном коде вопросов нет, надеюсь? Ок.

Сразу ответ: в этом конкретном случае ни скобки ни u не нужны. "Но есть один нюанс!" ;))

Это очень правильный подход - всегда ставить скобки и явное указание типа константы в макросах.

Макросы, в отличии от констант и константных выражений не позволяют указать тип иным способом. Макрос подставляется просто графически, как есть. Сколько уже тут было "вычислителей" времени в макросах с криками: "Памагити ниработаит!"? Так вот явное указание типа не меняет размер или скорость кода, но делает его читаемым и легко сопроводжаемым. То же касается скобок. Ставь их вообще всегда, не задумываясь, иначе будет, как в эпическом фейле Архата с его макросом, который работал ТОЛЬКО потому, что Архат, по дурости, скобки не поставил. ;)))

То есть скобки и "u" - это просто полезные привычки, как комментарии, расстановка фигурных скобок, скобки вокруг единственного оператора в if, while, for и прочее. Указывать на это, как на ошибку - высокомерие, больше похожее на дурость, уж прости.

Green
Offline
Зарегистрирован: 01.10.2015

Ух ты! Да, получилось не красиво. nibelung, я извиняюсь. По трезвому выглядит совсем иначе.(

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

nibelung пишет:

b707 пишет:

Изначально еще хотел написать о избыточности явного приведения разности двух байт к типу uint8_t - но подумал, что сам, наверно, написал бы так же - просто на автомате, чтобы не задумыватся о том, какой тип тут примет компилятор. 

Вот это, кстати, интересное замечание. Написал так, именно на автомате. Потом убрал приведение типа, ибо выглядит немного громоздко. Убедился, что компилятор, ожидаемо, ошибся. И вернул приведение типа на место.

Компилятор ошибся? - он у вас китайский. наверно...

проверим? - первое условие - без приведения типа, второе - с оным.

#define INTERVAL1 23

void setup() {
  Serial.begin(115200);
}

void loop() {
  static uint8_t clk1 = 0, clk2 = 0;
  static uint32_t my_millis = 0;
  uint8_t now = ++my_millis;
  Serial.print(now);
  Serial.print(":");
  if (INTERVAL1 < (now - clk1))
  {
    Serial.print("1");
  }
  else Serial.print("0");

  Serial.print(":");
  if (INTERVAL1 < (uint8_t)(now - clk1))
  {
    Serial.println("1");
  }
  else Serial.println("0");
}

результат

0:0:0
1:0:0
2:0:0
3:0:0
4:0:0
5:0:0
6:0:0
7:0:0
8:0:0
9:0:0
10:0:0
11:0:0
12:0:0
13:0:0
14:0:0
15:0:0
16:0:0
17:0:0
18:0:0
19:0:0
20:0:0
21:0:0
22:0:0
23:0:0
24:1:1
25:1:1
26:1:1
27:1:1
28:1:1
29:1:1
30:1:1
31:1:1
32:1:1
33:1:1
34:1:1
35:1:1
36:1:1
37:1:1
38:1:1
39:1:1
40:1:1
41:1:1
42:1:1
43:1:1
44:1:1
45:1:1
46:1:1
47:1:1
48:1:1
49:1:1
50:1:1
51:1:1
52:1:1
53:1:1
54:1:1
55:1:1
56:1:1
57:1:1
58:1:1
59:1:1
60:1:1
61:1:1
62:1:1
63:1:1
64:1:1
65:1:1
66:1:1
67:1:1
68:1:1
69:1:1
70:1:1
71:1:1
72:1:1
73:1:1
74:1:1
75:1:1
76:1:1
77:1:1
78:1:1
79:1:1
80:1:1
81:1:1
82:1:1
83:1:1
84:1:1
85:1:1
86:1:1
87:1:1
88:1:1
89:1:1
90:1:1
91:1:1
92:1:1
93:1:1
94:1:1
95:1:1
96:1:1
97:1:1
98:1:1
99:1:1
100:1:1
101:1:1
102:1:1
103:1:1
104:1:1
105:1:1
106:1:1
107:1:1
108:1:1
109:1:1
110:1:1
111:1:1
112:1:1
113:1:1
114:1:1
115:1:1
116:1:1
117:1:1
118:1:1
119:1:1
120:1:1
121:1:1
122:1:1
123:1:1
124:1:1
125:1:1
126:1:1
127:1:1
128:1:1
129:1:1
130:1:1
131:1:1
132:1:1
133:1:1
134:1:1
135:1:1
136:1:1
137:1:1
138:1:1
139:1:1
140:1:1
141:1:1
142:1:1
143:1:1
144:1:1
145:1:1
146:1:1
147:1:1
148:1:1
149:1:1
150:1:1
151:1:1
152:1:1
153:1:1
154:1:1
155:1:1
156:1:1
157:1:1
158:1:1
159:1:1
160:1:1
161:1:1
162:1:1
163:1:1
164:1:1
165:1:1
166:1:1
167:1:1
168:1:1
169:1:1
170:1:1
171:1:1
172:1:1
173:1:1
174:1:1
175:1:1
176:1:1
177:1:1
178:1:1
179:1:1
180:1:1
181:1:1
182:1:1
183:1:1
184:1:1
185:1:1
186:1:1
187:1:1
188:1:1
189:1:1
190:1:1
191:1:1
192:1:1
193:1:1
194:1:1
195:1:1
196:1:1
197:1:1
198:1:1
199:1:1
200:1:1
201:1:1
202:1:1
203:1:1
204:1:1
205:1:1
206:1:1
207:1:1
208:1:1
209:1:1
210:1:1
211:1:1
212:1:1
213:1:1
214:1:1
215:1:1
216:1:1
217:1:1
218:1:1
219:1:1
220:1:1
221:1:1
222:1:1
223:1:1
224:1:1
225:1:1
226:1:1
227:1:1
228:1:1
229:1:1
230:1:1
231:1:1
232:1:1
233:1:1
234:1:1
235:1:1
236:1:1
237:1:1
238:1:1
239:1:1
240:1:1
241:1:1
242:1:1
243:1:1
244:1:1
245:1:1
246:1:1
247:1:1
248:1:1
249:1:1
250:1:1
251:1:1
252:1:1
253:1:1
254:1:1
255:1:1

как видите, результат одинаков на всех возможных значениях

nibelung
Offline
Зарегистрирован: 21.04.2021

Green, я тоже немного погорячился, Простите если обидел.

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

wdrakula пишет:

То есть скобки и "u" - это просто полезные привычки, как комментарии, расстановка фигурных скобок, скобки вокруг единственного оператора в if, while, for и прочее.

с этим согласен. Но это как раз те самые замечания "вообще", которых я просил избежать. В конкретном коде эти элементы не обязательны, согласен? и потому Грин не так уж неправ - и уж точно его не за что было обвинять в "беграмотности".

 

А если рассматривать вообще :) - то подавать свой элементарный  код как что-то, "отлитое в бронзе", где уже нельзя поправить ни одну букву - вот это как раз глупость и заносчивость...

 

nibelung
Offline
Зарегистрирован: 21.04.2021

b707 пишет:

nibelung пишет:

b707 пишет:

Изначально еще хотел написать о избыточности явного приведения разности двух байт к типу uint8_t - но подумал, что сам, наверно, написал бы так же - просто на автомате, чтобы не задумыватся о том, какой тип тут примет компилятор. 

Вот это, кстати, интересное замечание. Написал так, именно на автомате. Потом убрал приведение типа, ибо выглядит немного громоздко. Убедился, что компилятор, ожидаемо, ошибся. И вернул приведение типа на место.

Компилятор ошибся? - он у вас китайский. наверно...

проверим? - первое условие - без приведения типа, второе - с оным.

#define INTERVAL1 23

void setup() {
  Serial.begin(115200);
}

void loop() {
  static uint8_t clk1 = 0, clk2 = 0;
  static uint32_t my_millis = 0;
  uint8_t now = ++my_millis;
  Serial.print(now);
  Serial.print(":");
  if (INTERVAL1 < (now - clk1))
  {
    Serial.print("1");
  }
  else Serial.print("0");

  Serial.print(":");
  if (INTERVAL1 < (uint8_t)(now - clk1))
  {
    Serial.println("1");
  }
  else Serial.println("0");
}

результат

0:0:0
1:0:0
2:0:0
3:0:0
4:0:0
5:0:0
6:0:0
7:0:0
8:0:0
9:0:0
10:0:0
11:0:0
12:0:0
13:0:0
14:0:0
15:0:0
16:0:0
17:0:0
18:0:0
19:0:0
20:0:0
21:0:0
22:0:0
23:0:0
24:1:1
25:1:1
26:1:1
27:1:1
28:1:1
29:1:1
30:1:1
31:1:1
32:1:1
33:1:1
34:1:1
35:1:1
36:1:1
37:1:1
38:1:1
39:1:1
40:1:1
41:1:1
42:1:1
43:1:1
44:1:1
45:1:1
46:1:1
47:1:1
48:1:1
49:1:1
50:1:1
51:1:1
52:1:1
53:1:1
54:1:1
55:1:1
56:1:1
57:1:1
58:1:1
59:1:1
60:1:1
61:1:1
62:1:1
63:1:1
64:1:1
65:1:1
66:1:1
67:1:1
68:1:1
69:1:1
70:1:1
71:1:1
72:1:1
73:1:1
74:1:1
75:1:1
76:1:1
77:1:1
78:1:1
79:1:1
80:1:1
81:1:1
82:1:1
83:1:1
84:1:1
85:1:1
86:1:1
87:1:1
88:1:1
89:1:1
90:1:1
91:1:1
92:1:1
93:1:1
94:1:1
95:1:1
96:1:1
97:1:1
98:1:1
99:1:1
100:1:1
101:1:1
102:1:1
103:1:1
104:1:1
105:1:1
106:1:1
107:1:1
108:1:1
109:1:1
110:1:1
111:1:1
112:1:1
113:1:1
114:1:1
115:1:1
116:1:1
117:1:1
118:1:1
119:1:1
120:1:1
121:1:1
122:1:1
123:1:1
124:1:1
125:1:1
126:1:1
127:1:1
128:1:1
129:1:1
130:1:1
131:1:1
132:1:1
133:1:1
134:1:1
135:1:1
136:1:1
137:1:1
138:1:1
139:1:1
140:1:1
141:1:1
142:1:1
143:1:1
144:1:1
145:1:1
146:1:1
147:1:1
148:1:1
149:1:1
150:1:1
151:1:1
152:1:1
153:1:1
154:1:1
155:1:1
156:1:1
157:1:1
158:1:1
159:1:1
160:1:1
161:1:1
162:1:1
163:1:1
164:1:1
165:1:1
166:1:1
167:1:1
168:1:1
169:1:1
170:1:1
171:1:1
172:1:1
173:1:1
174:1:1
175:1:1
176:1:1
177:1:1
178:1:1
179:1:1
180:1:1
181:1:1
182:1:1
183:1:1
184:1:1
185:1:1
186:1:1
187:1:1
188:1:1
189:1:1
190:1:1
191:1:1
192:1:1
193:1:1
194:1:1
195:1:1
196:1:1
197:1:1
198:1:1
199:1:1
200:1:1
201:1:1
202:1:1
203:1:1
204:1:1
205:1:1
206:1:1
207:1:1
208:1:1
209:1:1
210:1:1
211:1:1
212:1:1
213:1:1
214:1:1
215:1:1
216:1:1
217:1:1
218:1:1
219:1:1
220:1:1
221:1:1
222:1:1
223:1:1
224:1:1
225:1:1
226:1:1
227:1:1
228:1:1
229:1:1
230:1:1
231:1:1
232:1:1
233:1:1
234:1:1
235:1:1
236:1:1
237:1:1
238:1:1
239:1:1
240:1:1
241:1:1
242:1:1
243:1:1
244:1:1
245:1:1
246:1:1
247:1:1
248:1:1
249:1:1
250:1:1
251:1:1
252:1:1
253:1:1
254:1:1
255:1:1

как видите, результат одинаков на всех возможных значениях

Так уж и "на всех возможных значениях"?

"clk1" вы менять поленились, а ошибки проявляются, когда происходит переполнение.

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

nibelung пишет:

Так уж и "на всех возможных значениях"?

"clk1" вы менять поленились, а ошибки проявляются, когда происходит переполнение.

Свою точку зрения кодом я подтвердил.

Если не согласны - давайте сделаем так. Вы выкладываете коротенький код, который демонстрирует, что с приведением типа и без него условие if формирует разный результат - тогда и обсудим.

 

nibelung
Offline
Зарегистрирован: 21.04.2021

Немного поправил ваш код.

#define INTERVAL1 23

void setup() {
  Serial.begin(115200);
}

void loop() {
  static uint8_t clk1 = 100, clk2 = 0;
  static uint32_t my_millis = 0;
  uint8_t now = ++my_millis;
  Serial.print(now);
  Serial.print(":");
  if (INTERVAL1 < (now - clk1))
  {
    Serial.print("1");
  }
  else Serial.print("0");

  Serial.print(":");
  if (INTERVAL1 < (uint8_t)(now - clk1))
  {
    Serial.println("1");
  }
  else Serial.println("0");
}

разница совсем небольшая, только clk1 инициализировал отличным от нуля значением.

а вот вывод

0:0:1
1:0:1
2:0:1
3:0:1
4:0:1
5:0:1
6:0:1
7:0:1
8:0:1
9:0:1
10:0:1
11:0:1
12:0:1
13:0:1
14:0:1
15:0:1
16:0:1
17:0:1
18:0:1
19:0:1
20:0:1
21:0:1
22:0:1
23:0:1
24:0:1
25:0:1
26:0:1
27:0:1
28:0:1
29:0:1
30:0:1
31:0:1
32:0:1
33:0:1
34:0:1
35:0:1
36:0:1
37:0:1
38:0:1
39:0:1
40:0:1
41:0:1
42:0:1
43:0:1
44:0:1
45:0:1
46:0:1
47:0:1
48:0:1
49:0:1
50:0:1
51:0:1
52:0:1
53:0:1
54:0:1
55:0:1
56:0:1
57:0:1
58:0:1
59:0:1
60:0:1
61:0:1
62:0:1
63:0:1
64:0:1
65:0:1
66:0:1
67:0:1
68:0:1
69:0:1
70:0:1
71:0:1
72:0:1
73:0:1
74:0:1
75:0:1
76:0:1
77:0:1
78:0:1
79:0:1
80:0:1
81:0:1
82:0:1
83:0:1
84:0:1
85:0:1
86:0:1
87:0:1
88:0:1
89:0:1
90:0:1
91:0:1
92:0:1
93:0:1
94:0:1
95:0:1
96:0:1
97:0:1
98:0:1
99:0:1
100:0:0
101:0:0
102:0:0
103:0:0
104:0:0
105:0:0
106:0:0
107:0:0
108:0:0
109:0:0
110:0:0
111:0:0
112:0:0
113:0:0
114:0:0
115:0:0
116:0:0
117:0:0
118:0:0
119:0:0
120:0:0
121:0:0
122:0:0
123:0:0
124:1:1
125:1:1
126:1:1
127:1:1
128:1:1
129:1:1
130:1:1
131:1:1
132:1:1
133:1:1
134:1:1
135:1:1
136:1:1
137:1:1
138:1:1
139:1:1
140:1:1
141:1:1
142:1:1
143:1:1
144:1:1
145:1:1
146:1:1
147:1:1
148:1:1
149:1:1
150:1:1
151:1:1
152:1:1
153:1:1
154:1:1
155:1:1
156:1:1
157:1:1
158:1:1
159:1:1
160:1:1
161:1:1
162:1:1
163:1:1
164:1:1
165:1:1
166:1:1
167:1:1
168:1:1
169:1:1
170:1:1
171:1:1
172:1:1
173:1:1
174:1:1
175:1:1
176:1:1
177:1:1
178:1:1
179:1:1
180:1:1
181:1:1
182:1:1
183:1:1
184:1:1
185:1:1
186:1:1
187:1:1
188:1:1
189:1:1
190:1:1
191:1:1
192:1:1
193:1:1
194:1:1
195:1:1
196:1:1
197:1:1
198:1:1
199:1:1
200:1:1
201:1:1
202:1:1
203:1:1
204:1:1
205:1:1
206:1:1
207:1:1
208:1:1
209:1:1
210:1:1
211:1:1
212:1:1
213:1:1
214:1:1
215:1:1
216:1:1
217:1:1
218:1:1
219:1:1
220:1:1
221:1:1
222:1:1
223:1:1
224:1:1
225:1:1
226:1:1
227:1:1
228:1:1
229:1:1
230:1:1
231:1:1
232:1:1
233:1:1
234:1:1
235:1:1
236:1:1
237:1:1
238:1:1
239:1:1
240:1:1
241:1:1
242:1:1
243:1:1
244:1:1
245:1:1
246:1:1
247:1:1
248:1:1
249:1:1
250:1:1
251:1:1
252:1:1
253:1:1
254:1:1
255:1:1

как видите не везде результат одинаков.

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

ок, очко в вашу пользу

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:

ок, очко в вашу пользу

Упрямый, но честный! ;))

Это же история, как раз из той области, в которой был мой срач с Андриано. Неявное преобразование между знаковым и беззнаковым. Если не поставить явное преобразование, то будут эти самые грабли. Как же можно забыть такую тему? ;))))

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:
подавать свой элементарный  код

Код на интерференции двух волн не элементарный, а красивый, признай. Много тут новичков, способных выдать такое?

И нормально оформленное. Поправить "ради красоты" там можно только строчку:

digitalWrite(LED, ((0 == led_state) ? LOW : HIGH));

заменив на:

digitalWrite(LED,  led_state ? HIGH : LOW);

или просто

digitalWrite(LED,  led_state );

;))))))

Green
Offline
Зарегистрирован: 01.10.2015

Я намекал на такое. Хотя знаю, что Влад это не приветствует.

#define LED       LED_BUILTIN
#define INTERVAL1 23
#define INTERVAL2 24
#define toggle(x) digitalWrite(x, !digitalRead(x))

void setup() {
  pinMode (LED, OUTPUT);
}

void loop() {
  static uint8_t clk1, clk2;
  
  uint8_t now = millis();
  if ((uint8_t)(now - clk1) > INTERVAL1) {
    clk1 += INTERVAL1;
    toggle(LED);
  }
  if ((uint8_t)(now - clk2) > INTERVAL2) {
    clk2 += INTERVAL2;
    toggle(LED); 
  }
}
nibelung
Offline
Зарегистрирован: 21.04.2021

Green пишет:

Я намекал на такое. Хотя знаю, что Влад это не приветствует.

#define LED       LED_BUILTIN
#define INTERVAL1 23
#define INTERVAL2 24
#define toggle(x) digitalWrite(x, !digitalRead(x))

void setup() {
  pinMode (LED, OUTPUT);
}

void loop() {
  static uint8_t clk1, clk2;
  
  uint8_t now = millis();
  if ((uint8_t)(now - clk1) > INTERVAL1) {
    clk1 += INTERVAL1;
    toggle(LED);
  }
  if ((uint8_t)(now - clk2) > INTERVAL2) {
    clk2 += INTERVAL2;
    toggle(LED); 
  }
}

Такое тоже работать будет, но есть маааленький косячок.

Когда условия по INTERVAL1 и INTERVAL2 выполнятся на одном проходе Loop, у вас на диоде получится очень короткий импульс, а по задумке его там быть не должно.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

nibelung пишет:

Green пишет:

Я намекал на такое. Хотя знаю, что Влад это не приветствует.

#define LED       LED_BUILTIN
#define INTERVAL1 23
#define INTERVAL2 24
#define toggle(x) digitalWrite(x, !digitalRead(x))

void setup() {
  pinMode (LED, OUTPUT);
}

void loop() {
  static uint8_t clk1, clk2;
  
  uint8_t now = millis();
  if ((uint8_t)(now - clk1) > INTERVAL1) {
    clk1 += INTERVAL1;
    toggle(LED);
  }
  if ((uint8_t)(now - clk2) > INTERVAL2) {
    clk2 += INTERVAL2;
    toggle(LED); 
  }
}

Такое тоже работать будет, но есть маааленький косячок.

Когда условия по INTERVAL1 и INTERVAL2 выполнятся на одном проходе Loop, у вас на диоде получится очень короткий импульс, а по задумке его там быть не должно.

Вот именно про это я написал, когда сказал, что Федин toggle() неуместен.

nibelung
Offline
Зарегистрирован: 21.04.2021

И еще

void loop() {
  static uint8_t clk1, clk2;

Это, все таки, объявление глобальных переменных с областью видимости, ограниченной, функцией Loop. Их желательно явно инициализировать.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

nibelung пишет:

И еще

void loop() {
  static uint8_t clk1, clk2;

Это, все таки, объявление глобальных переменных с областью видимости, ограниченной, функцией Loop. Их желательно явно инициализировать.

а тут ты неправ... ;))) хороший тон, но необязательно. Ну и слово "глобальные" совершенно не к месту и не в тему.

nik182
Offline
Зарегистрирован: 04.05.2015

Пожалуйста объясните, зачем объявлять переменные локально для проектов на МК. Я понимаю зачем для ББ, но МК? Программа память не экономит. Несколько подпрограмм и так разберуться  какие переменные используются, а если про волатильные вспомнить - всё равно приходится глобальными объявлять. На хороший тон не ссылаться. Есть ли какие ни будь другие преимущества? В циклах можно областью видимости обойтись. 

nibelung
Offline
Зарегистрирован: 21.04.2021

wdrakula пишет:

nibelung пишет:

И еще

void loop() {
  static uint8_t clk1, clk2;

Это, все таки, объявление глобальных переменных с областью видимости, ограниченной, функцией Loop. Их желательно явно инициализировать.

а тут ты неправ... ;))) хороший тон, но необязательно. Ну и слово "глобальные" совершенно не к месту и не в тему.

Дык я и написал "желательно", а не "обязательно". Именно хороший тон.

По поводу слова "глобальный" спорить не буду.

staticheskie-lokalnye-peremennye

"Когда static применяется к локальной переменной, это приводит к тому, что компилятор создает долговременную область для хранения переменной почти таким же способом, как это делается для глобальной переменной. Ключевое различие между статической локальной и глобальной переменными заключается в том, что статическая локальная переменная остается известной только в том блоке, в котором она была объявлена. Проще говоря, статическая локальная переменная - это локальная переменная, сохраняющая свое значение между вызовами функций."

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

nik182 пишет:

Пожалуйста объясните, зачем объявлять переменные локально для проектов на МК. Я понимаю зачем для ББ, но МК? Программа память не экономит. Несколько подпрограмм и так разберуться  какие переменные используются, а если про волатильные вспомнить - всё равно приходится глобальными объявлять. На хороший тон не ссылаться. Есть ли какие ни будь другие преимущества? В циклах можно областью видимости обойтись. 

Ни за чем, кроме хорошего тона и удобства сопровождения. Ничто так не кричит об "авторе-чайнике", как обилие глобалов. Даже сам, через (для меня) два-три месяца, уже не помнишь, что  и для чего заведено. Объявления статиков там, где они используются, дает возможность вспомнить подробности. Это не говоря про совместную разработку. Тут даже комментировать нечего.

Короче так: если в программе много глобальных переменных - лучше не платить такому автору вообще! ;))) Ну я бы не стал и клиентам бы не посоветовал! ;))

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

nibelung пишет:

"Когда static применяется к локальной переменной, это приводит к тому, что компилятор создает долговременную область для хранения переменной почти таким же способом, как это делается для глобальной переменной. Ключевое различие между статической локальной и глобальной переменными заключается в том, что статическая локальная переменная остается известной только в том блоке, в котором она была объявлена. Проще говоря, статическая локальная переменная - это локальная переменная, сохраняющая свое значение между вызовами функций."

Это ты дискуссию со мной предлагаешь? ;)) Очень мило, с твоей стороны, но я, пожалуй, воздержусь. ;))

nibelung
Offline
Зарегистрирован: 21.04.2021

wdrakula пишет:

nibelung пишет:

"Когда static применяется к локальной переменной, это приводит к тому, что компилятор создает долговременную область для хранения переменной почти таким же способом, как это делается для глобальной переменной. Ключевое различие между статической локальной и глобальной переменными заключается в том, что статическая локальная переменная остается известной только в том блоке, в котором она была объявлена. Проще говоря, статическая локальная переменная - это локальная переменная, сохраняющая свое значение между вызовами функций."

Это ты дискуссию со мной предлагаешь? ;)) Очень мило, с твоей стороны, но я, пожалуй, воздержусь. ;))

Завсегда приятно поговорить с умным и образованным человеком ;)) Но нет, я же признал, что слово "глобальные" там не совсем в тему.

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

wdrakula пишет:

Это ты дискуссию со мной предлагаешь? ;)) Очень мило, с твоей стороны, но я, пожалуй, воздержусь. ;))

какой-то ты, Влад, сегодня, не такой :)  Не заболел? :) не чувствуется привычной бодрости в общении с новичками :)

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

wdrakula пишет:

Это ты дискуссию со мной предлагаешь? ;)) Очень мило, с твоей стороны, но я, пожалуй, воздержусь. ;))

какой-то ты, Влад, сегодня, не такой :)  Не заболел? :) не чувствуется привычной бодрости в общении с новичками :)

последствия  Короны сказываются и, как показала практика у каждого они свои ...

таки и не понял почему всё таки не?:
 

  static bool led_state = 0;

 

nibelung
Offline
Зарегистрирован: 21.04.2021

ua6em пишет:

таки и не понял почему всё таки не?:

 

  static bool led_state = 0;

 

Да можно и так. Ошибкой не будет использование любого варианта. Так что, это из разряда личных предпочтений.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

nibelung пишет:

ua6em пишет:

таки и не понял почему всё таки не?:

 

  static bool led_state = 0;

 

Да можно и так. Ошибкой не будет использование любого варианта. Так что, это из разряда личных предпочтений.

я бы не был столь категоричным, если тип переменной bool, то это даёт экономию памяти программ 2 байта и памяти ОЗУ байт... если применять не битовую математику для изменения значения переменной...точнее  знающие подскажут

 

nibelung
Offline
Зарегистрирован: 21.04.2021

ua6em пишет:

nibelung пишет:

ua6em пишет:

таки и не понял почему всё таки не?:

 

  static bool led_state = 0;

 

Да можно и так. Ошибкой не будет использование любого варианта. Так что, это из разряда личных предпочтений.

я бы не был столь категоричным, если тип переменной bool, то это даёт экономию памяти программ 2 байта и памяти ОЗУ байт... если применять не битовую математику для изменения значения переменной...точнее  знающие подскажут

 

Я бы с вами согласился, если бы тип int менялся на bool. Но, в данном случае, меняется uint8_t на bool. Оба типа размерностью в один байт, так что экономии не будет.

Jaeger
Jaeger аватар
Offline
Зарегистрирован: 23.03.2018

   Если рассматривать данную функцию с точки зрения практического применения, то очевидно, что для нормальной работы она требует стабильного короткого цикла и вызов ее в основном лупе не всегда приведет к корректной её работе. Например в блинке с делеями она работать не будет. Выход - разместить функцию в прерывании таймера, например вариант в TMR0: 

#define LED_IN  PB5  //LED_BUILTIN

void setup() {
  cli();                  //stop interrupts
  OCR0A = 0;
  TIMSK0 |= _BV(OCIE0A);  //Разрешить прерывание Timer0 по совпадению
  sei();                  //allow interrupts
  DDRB |= _BV(LED_IN);    // вывод на выход
 }

void loop() {
 
 }
 //************************InterruptTMR0****************************
ISR(TIMER0_COMPA_vect) {

#define INTERVAL1 23
#define INTERVAL2 24
static uint8_t  clk1 = 0, 
                clk2 = 0,
                now  = 0,
                led_state = 0;

  if ((uint8_t)(++now - clk1) > INTERVAL1)
  {
    clk1 += INTERVAL1;
    led_state ^= 1;
  }

  if ((uint8_t)(now - clk2) > INTERVAL2)
  {
    clk2 += INTERVAL2;
    led_state ^= 1;
  }
  //digitalWrite(LED, led_state);
  (led_state)? (PORTB |= _BV(LED_IN)): (PORTB &= ~_BV(LED_IN));
  
 }