Прерывания в коде

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

Есть небольшой скетч. Плата Nano (пробовал и на Uno).

int on = B00000001;
int off = B00000000;

void setup()
{
  DDRB = on;
}

void loop()
{
  noInterrupts();
  
  PORTB = on; //Turn LED on.
  delayMicroseconds(5); 
  PORTB = off; //Turn LED off.
  delayMicroseconds(5);

  interrupts();
}

Итог - на D8 импульсы и среди них небольшие пробелы по 10мкс с интервалом чуть больше миллисекунды.
Смотрел логическим анализатором, частота выборки 8МГц. noInterrupts(); потом добавил, не помогло. Как избавиться от этих пробелов?

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

даже не знаю, как на это отвечать :) Вроде человек ПОЛТОРА ГОДА занимается программирование ардуино :)

Вы в курсе. что loop() - это цикл? :)

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

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

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

вы выключили прерывания между строчками 11 и 18. Но луп - это цикл, он закольцован. После строчки 19 он идет на строку 10. и между строкой 18 и 11 у вас прерывания разрешены.

Вы можете совсем выключить прерывания. Но тогда у вас перестанет работать миллис и любые другие функции, завязанные на прерывания.

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

Простой ответ на вопрос, можно или нет?

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

Просмотрел ответ)

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

andrey3824 пишет:

Простой ответ на вопрос, можно или нет?

можно

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

b707 пишет:

andrey3824 пишет:

Простой ответ на вопрос, можно или нет?

можно

но не нужно...

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

b707 пишет:

andrey3824 пишет:

Простой ответ на вопрос, можно или нет?

можно

Можете подсказать? Сам не допилю.
С digitalWrite вроде разобрался как мог. Дальше сложнее.

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

andrey3824 пишет:

Можете подсказать? Сам не допилю.

Выключите прерывания и больше не включайте. - строку 18 сотрите да и все.

только это дурость - превращать целый МК в генератор одного сигнала. А ничего другого вы на этом МК уже делать не сможете - любое действие будет нарушать период.

Это не так делается - изучайте таймеры

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

b707 пишет:

b707 пишет:

andrey3824 пишет:

Простой ответ на вопрос, можно или нет?

можно

но не нужно...


Мне вообще нужно получить на выходе пачку импульсов с разными длительностями. 
Не силён в программировании, думал собрать таким образом один за другим импульсы. 
Но после увидел то, о чем тема. Будет мешать. Как обойти или может есть более грамотный способ собрать пачку?

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

b707 пишет:

andrey3824 пишет:

Можете подсказать? Сам не допилю.

Выключите прерывания и больше не включайте. - строку 18 сотрите да и все.

только это дурость - превращать целый МК в генератор одного сигнала. А ничего другого вы на этом МК уже делать не сможете - любое действие будет нарушать период.

Это не так делается - изучайте таймеры

Это не нужно, только для наглядности.

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

Часто делаю блинк, особенно на отдельном МК. Чисто для наглядности. Что бы видеть правильность фьюзов у заказчика.
every(1000 / 2)
  toggle(LED);
Совсем никого не напрягает.

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

смысл скетча такой. аппаратный таймер постоянно генерирует кванты (в моем случае по времени соответствующие 1 градусу поворота коленвала), мы считаем эти кванты и в момент нужных порядковых номеров квантов рулим портами, образуя необходимые пачки сигналов.   В принципе если поймете суть скетча, переделать под ваши хотелки не сложно.   

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andrey3824 пишет:
небольшие пробелы по 10мкс с интервалом чуть больше миллисекунды.

А точнее "с интервалом 1024 мкс".

Это включается подсчёте millis.

Если millis Вам не нужен - выключите и проблема уйдёт.

Если же millis нужен, то надо делать по-другому - через настройку таймеров. Но там всё непросто.

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

MaksVV пишет:

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

смысл скетча такой. аппаратный таймер постоянно генерирует кванты (в моем случае по времени соответствующие 1 градусу поворота коленвала), мы считаем эти кванты и в момент нужных порядковых номеров квантов рулим портами, образуя необходимые пачки сигналов.   В принципе если поймете суть скетча, переделать под ваши хотелки не сложно.   

Спасибо, посмотрю.
А пока собрал скетч отдельными блоками на 4 разных кода по тому, что выше сам показал. На каждый блок прерывания выключал, так было без ошибок. Сделал по команде с цифровых пинов. 

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

andrey3824 пишет:
Еще искал как сделать однократную посылку собранной пачки при сохранении условия на цифровом пине, ничего понятного мне не нашел. В loop всё повторяется. Решение нашел - одновибратор с длительностью заведомо меньшей, чем длительность пачки, аппаратно. Мне с электроникой проще. 

Наверное это как-то можно программно организовать, не мог сообразить как это в поиске правильно обозвать. 

заводите переменную флаг . дёргаете  лаптями только в случае поднятого флага. Если флаг опустить, нога не будет  дрыгаться. 

if (флаг == true) digitalWrite (бла_бла, бла_бла);

ЗЫ. Только в лупе такие вещи не делаются. При больших частотах сигнала - только в обработчике прерывания. 

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

MaksVV пишет:

andrey3824 пишет:
Еще искал как сделать однократную посылку собранной пачки при сохранении условия на цифровом пине, ничего понятного мне не нашел. В loop всё повторяется. Решение нашел - одновибратор с длительностью заведомо меньшей, чем длительность пачки, аппаратно. Мне с электроникой проще. 

Наверное это как-то можно программно организовать, не мог сообразить как это в поиске правильно обозвать. 

заводите переменную флаг . дёргаете  лаптями только в случае поднятого флага. Если флаг опустить, нога не будет  дрыгаться. 

if (флаг == true) digitalWrite (бла_бла, бла_бла);

ЗЫ. Только в лупе такие вещи не делаются. При больших частотах сигнала - только в обработчике прерывания. 

Всё это сложновато для меня, на простой логике соберу. 
Спасибо за помощь.

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

Пока разбирался как собрать, сделал открытие.
В LOOP delay не работает, а delayMicroseconds - да. 

Добавлено.

Может что-то не так понимаю.
 

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

Вернее не в LOOP, а когда прерывания выключены.))

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

Нужно уметь и то и другое, но таймером на ардуине проще и дешевле

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

andrey3824 пишет:

Вернее не в LOOP, а когда прерывания выключены.))

Delay использует millis. А как тут уже говорили не раз - millis не работает когда прерывания запрещены.

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

А delayMicroseconds не использует millis, а просто крутит цикл необходимое число раз для выбранной задержки, поэтому от прерываний не зависит. 

Banzay1983
Offline
Зарегистрирован: 30.08.2021

по моему тут надо без delay()  это реализовывать

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

Banzay1983 пишет:

по моему тут надо без delay()  это реализовывать

тут их и нет

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

MaksVV пишет:
Интересно посмотреть как разные пачки импульсов на логике собирать.. Имхо проще таймер изучить

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

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

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

Вот код. Собирал по каким-то примерам.
Время в мкс выяснил опытным путём по лог. анализатору.

int on = B00000001;
int off = B00000000;
const int sw=10;
const int sw2=9;
const int sw3=7;
const int sw4=6;

void setup()
{
  pinMode(sw, INPUT_PULLUP);
  pinMode(sw2, INPUT_PULLUP);
  pinMode(sw3, INPUT_PULLUP);
  pinMode(sw4, INPUT_PULLUP);
  DDRB = B00000001;
 }

void loop()
{
  
  if (digitalRead(sw) == LOW)
{
  
  PORTB = on; 
  delay(400);  //START
  
  noInterrupts();   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);  //7-10
   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);   //7-10
  
  PORTB = off;
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(20); //7-19

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(26);
  PORTB = on; 
  delayMicroseconds(11); //25-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //17-10

  PORTB = off; 
  delayMicroseconds(35);
  PORTB = on; 
  delayMicroseconds(11); //34-10

  PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

  PORTB = off; 
  delayMicroseconds(69);
  PORTB = on; 
  delayMicroseconds(20); //68-19

  PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(26);
  PORTB = on; 
  delayMicroseconds(28); //25-27

   PORTB = off; 
  delayMicroseconds(26);  
  PORTB = on; //25
   
  interrupts();
}

if (digitalRead(sw2) == LOW)
{
  
  PORTB = on; 
  delay(400); //START
  
  noInterrupts();   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);  //7-10
   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);   //7-10
  
  PORTB = off;
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(20); //7-19

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(26);
  PORTB = on; 
  delayMicroseconds(11); //25-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(35);
  PORTB = on; 
  delayMicroseconds(11); //34-10

  PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

  PORTB = off; 
  delayMicroseconds(26);
  PORTB = on; 
  delayMicroseconds(11); //25-10

  PORTB = off; 
  delayMicroseconds(35);
  PORTB = on; 
  delayMicroseconds(19); //34-18

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

   PORTB = off; 
  delayMicroseconds(26);
  PORTB = on; 
  delayMicroseconds(11); //25-10

   PORTB = off; 
  delayMicroseconds(26);  //25
  PORTB = on; 
   
  interrupts();
}

if (digitalRead(sw3) == LOW)
{
   
  PORTB = on; 
  delay(400);  //START
  
  noInterrupts();   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);  //7-10
   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);   //7-10
  
  PORTB = off;
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(20); //7-19

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(26);
  PORTB = on; 
  delayMicroseconds(11); //25-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(35);
  PORTB = on; 
  delayMicroseconds(11); //34-10

  PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

  PORTB = off; 
  delayMicroseconds(52);
  PORTB = on; 
  delayMicroseconds(11); //51-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(60);
  PORTB = on; 
  delayMicroseconds(11); //59-10

   PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

   PORTB = off; 
  delayMicroseconds(52);  //51
  PORTB = on; 
   
  interrupts();
}

if (digitalRead(sw4) == LOW)
{
  
  PORTB = on; 
  delay(400);  //START
  
  noInterrupts();   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);  //7-10
   
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11);   //7-10
  
  PORTB = off;
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10
  
  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(20); //7-19

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //17-10

  PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

  PORTB = off; 
  delayMicroseconds(43);
  PORTB = on; 
  delayMicroseconds(11); //42-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

   PORTB = off; 
  delayMicroseconds(78);
  PORTB = on; 
  delayMicroseconds(11); //77-10

    PORTB = off; 
  delayMicroseconds(17);
  PORTB = on; 
  delayMicroseconds(11); //16-10

   PORTB = off; 
  delayMicroseconds(8);
  PORTB = on; 
  delayMicroseconds(11); //7-10

   PORTB = off; 
  delayMicroseconds(34);  //33
  PORTB = on; 
   
  interrupts();
}
}

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


int swo = 11;
int kn = 9;
int swoOld = 0;
int swoNew = 0;

void setup() {
  pinMode(swo, OUTPUT);
  pinMode(kn, INPUT_PULLUP);
  digitalWrite(swo, HIGH);
}

void loop() {
  swoNew = digitalRead(kn);
  if (swoOld != swoNew && swoNew == 0) {
    digitalWrite(swo, LOW);
    delayMicroseconds(20);
    digitalWrite(swo, HIGH);
    swoOld = swoNew;
    Serial.println(swoNew);
  }
  else if (swoOld != swoNew)
    swoOld = swoNew;
}
b707
Offline
Зарегистрирован: 26.05.2017

andrey3824 - и не лень было набивать 500 строк практически одинаковых операторов? про массивы и циклы не слыхали? код можно сократить раз в 10. ничего не меняя в алгоритме - просто за счет исключения повторов

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

andrey3824 пишет:

MaksVV пишет:
Интересно посмотреть как разные пачки импульсов на логике собирать.. Имхо проще таймер изучить

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

это делается на двухвходовом элементе И, при сформированном сигнале пачки, куда уж проще )))

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

Я выше отметил, что мне с электроникой проще.

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

b707 пишет:

andrey3824 - и не лень было набивать 500 строк практически одинаковых операторов? про массивы и циклы не слыхали? код можно сократить раз в 10. ничего не меняя в алгоритме - просто за счет исключения повторов

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

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

andrey3824, не заметил сразу пары крайне грубых ошибок в вашем коде, из-за которых он просто не будет работать. Вы управляете выходом строчками типа PORTB = off; или PORTB = on;

Если посмотреть самую первую строку вашего кода, мы видим что

on = B00000001;

То есть полностью ваше выражение получается таким

PORTB = B00000001;

Вы понимаете, что происходит в этой строке? - думаю нет. Я вам обьясню. Этой записью вы не только выставляете единицу на пине B0, но и обнуляете все пины от B1 до B7. Положим, не все из них есть на Нано, но пины с B1 по B5 - это пины 9-13 ардуино.

А теперь посмотрите в свой код. Разве эти пины у вас не используются? Ваш пин SW - это пин 10, а SW2 - это пин 9. Записывая разом весь порт B - вы можете попрощаться с любыми разумными значениями на этих двух входах.

Ровно тоже самое относится к выставлению режима в регистре DDRB в строке 14 - присваивая ему единицу, вы тупо стираете результат коман pinMode() на пару строк выше

int on = B00000001;
int off = B00000000;
const int sw=10;
const int sw2=9;
const int sw3=7;
const int sw4=6;

void setup()
{
  pinMode(sw, INPUT_PULLUP);
  pinMode(sw2, INPUT_PULLUP);
  pinMode(sw3, INPUT_PULLUP);
  pinMode(sw4, INPUT_PULLUP);
  DDRB = B00000001;
 }

присваивать целиком весь порт командой PORTB = B00000001;, когда вам нужно поменять один пин - в корне неверно. вам нужно записывать единицу не во весь порт, а только в младший бит порта, не трогая при этом остальные биты. Как это делать - ищите в разделе справки Ардуино "битовые операции"

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

b707 пишет:

andrey3824, не заметил сразу пары крайне грубых ошибок в вашем коде, из-за которых он просто не будет работать. Вы управляете выходом строчками типа PORTB = off; или PORTB = on;

Если посмотреть самую первую строку вашего кода, мы видим что

on = B00000001;

То есть полностью ваше выражение получается таким

PORTB = B00000001;

Вы понимаете, что происходит в этой строке? - думаю нет. Я вам обьясню. Этой записью вы не только выставляете единицу на пине B0, но и обнуляете все пины от B1 до B7. Положим, не все из них есть на Нано, но пины с B1 по B5 - это пины 9-13 ардуино.

А теперь посмотрите в свой код. Разве эти пины у вас не используются? Ваш пин SW - это пин 10, а SW2 - это пин 9. Записывая разом весь порт B - вы можете попрощаться с любыми разумными значениями на этих двух входах.

Ровно тоже самое относится к выставлению режима в регистре DDRB в строке 14 - присваивая ему единицу, вы тупо стираете результат коман pinMode() на пару строк выше

int on = B00000001;
int off = B00000000;
const int sw=10;
const int sw2=9;
const int sw3=7;
const int sw4=6;

void setup()
{
  pinMode(sw, INPUT_PULLUP);
  pinMode(sw2, INPUT_PULLUP);
  pinMode(sw3, INPUT_PULLUP);
  pinMode(sw4, INPUT_PULLUP);
  DDRB = B00000001;
 }

присваивать целиком весь порт командой PORTB = B00000001;, когда вам нужно поменять один пин - в корне неверно. вам нужно записывать единицу не во весь порт, а только в младший бит порта, не трогая при этом остальные биты. Как это делать - ищите в разделе справки Ардуино "битовые операции"

int on = B11111111;
int off = B11111110; // так не исключает
const int sw=9;
const int sw2=10;
const int sw3=7;
const int sw4=6;

void setup()
{
  pinMode(sw, INPUT_PULLUP);
  pinMode(sw2, INPUT_PULLUP);
  pinMode(sw3, INPUT_PULLUP);
  pinMode(sw4, INPUT_PULLUP);
  DDRB = B00000001;
 }

Сделал так.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

andrey3824 пишет:

Сделал так.

Напрасно. Это те же яйтса.

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

Проверил, так работает.

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

С массивами не стал разбираться, сложновато для меня.
Раз в год нужно что-то собрать. Просишь помощи, камнями забросают.
 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

С таким подходом 

andrey3824 пишет:
С массивами не стал разбираться

Еще и валунами завалят.  Жди. 

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

andrey3824 пишет:

Проверил, так работает.

неа, вам это кажется.  Не работает.

Теперь sw и sw1 всегда HIGH

 

Вот вы жалуетесь, что вам не помогают. А нафига вам помогать, если даже при прямом указании, что надо исправить и как - вы этого не делаете? Для кого я написал "Как это делать - ищите в разделе справки Ардуино "битовые операции". Вы этот раздел читали?

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

Посмотрите здесь https://doc.arduino.ua/ru/prog/BitSet и здесь https://doc.arduino.ua/ru/prog/BitClear - установит и сбросить бит не задевая другие. Всё делается на уровне ассемблера - быстро. Ещё надо помнить какой бит - номер, а не значение. Ваш долгий digitalWrite(swo, HIGH); swo - 11 нога это PB3 заменяется на быстрый bitSet(PORTB,3); и LOW в bitClear(PORTB,3). Другие биты не изменяются. Перед началом вывода надо переключить ногу порта на вывод командой bitSet(DDRB,3); . 

Ещё очень полезная функция https://doc.arduino.ua/ru/prog/Bit - не надо помнить двоичное значение. 

C for просто - набиваем массивы задержек и крутим. 

byte d1[] = {8, 8, 8, 8, 8, 17, 8, 8, 8, 8, 26, 8, 8, 8, 17, 35, 78, 69, 78, 78, 78, 78, 26, 26};
byte d2[] = {11, 11, 11, 11, 11, 11, 11, 11, 11, 20, 11, 11, 11, 11, 11, 11, 11, 11, 20, 11, 11, 11, 11, 28};

void setup() {
  // здесь ничего не надо, все порты после старта на ввод
  // если надо подтянуть к единице вставляем bitSet(PORTD, 6);  
}

void loop() {
  if (bitRead(PIND, 6) != bit(6)) // D10 - бит 6 порта D, bit(6) только для примера, если надо сравнить с единицей. А сейчас можно написать ==LOW или ==0
  {
    bitSet(DDRB, 3);
    bitSet(PORTB, 3);
    delay(400);  //START
    noInterrupts();
    for (byte i = 0; i < 25; i++) {
      bitClear(PORTB, 3);
      delayMicroseconds(d1[i]);
      bitSet(PORTB, 3);
      delayMicroseconds(d2[i]);
    };
    // bitClear(PORTB, 3); Здесь ноль просится, а то нелогичненько получается
    interrupts();
  }
  // ...  и.т.д.
}

 

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

nik182 вангую не в коня корм :) Ему по буквам разжевывать надо :)

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

Посмотрим. Вроде по буквам разжевал.

Upper
Offline
Зарегистрирован: 23.06.2020

nik182 пишет:

Посмотрим. Вроде по буквам разжевал.

Не могу понять в каком случае выражение в строке 10 имеет смысл, т.е. для какого это примера?

if (bitRead(PIND, 6) != bit(6)) // D10 - бит 6 порта D, bit(6) только для примера, если надо сравнить с единицей.

bitRead(PIND, 6) равен или 0 или 1     
bit(6)                  равен всегда 64  и они не могут быть равны.

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

Да. Это я тупанул. Действительно bitRead 0 или 1. Это я по привычки когда сравниваешь регистр PIND == B100000  проще написать PIND == bit(6) - нули считать не надо. А правильно вообще длинно (PIND & B100000) == B100000 . Написать bitRead(PIND, 6) == 1 проще а после компиляции результат получится одинаковым. Написать можно if(!bitRead(PIND, 6)). 

Pyotr
Offline
Зарегистрирован: 12.03.2014

andrey3824 пишет:

Пока разбирался как собрать, сделал открытие.
В LOOP delay не работает, если прерывания отключены, а delayMicroseconds - да. 

Надо правильный делей()  юзать))

const byte led = 13;

void setup() {                
  pinMode(led, OUTPUT);  
  cli();   
}

void loop() {
  digitalWrite(led, HIGH);  
  delayMy(10);
  digitalWrite(led, LOW);   
  delayMy(990);
}

void delayMy(word ms){
  byte tcnt0 = TCNT0;
  byte tic = 250;
  while(ms > 0){
    while(TCNT0 == tcnt0){}
    tcnt0 += tic;
    while(TCNT0 != tcnt0){}
    ms--;
  }
}

Только это зло))

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

b707 пишет:

andrey3824 пишет:

Проверил, так работает.

неа, вам это кажется.  Не работает.

Теперь sw и sw1 всегда HIGH

 

Вот вы жалуетесь, что вам не помогают. А нафига вам помогать, если даже при прямом указании, что надо исправить и как - вы этого не делаете? Для кого я написал "Как это делать - ищите в разделе справки Ардуино "битовые операции". Вы этот раздел читали?

Я объясню, что видел.
В старом коде после первого LOW на входе там появлялся минус. Объяснили, понял - почему.
Сделал поправку, проверил. Массу на ногу - работает. Убираю массу - не работает. Снова масса - работает. 
Мне пока больше и не нужно. Последняя пачка улетела после убирания массы, на входе снова "1". Дальше всё в рабочем состоянии.
А по битовым пробовал, тоже получалось, переделывать больше. Сложение, умножение.
Последний вариант удобнее показался.

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

b707 пишет:

nik182 вангую не в коня корм :) Ему по буквам разжевывать надо :)

Вникаю как могу. Кто на что учился.

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

nik182 пишет:

Посмотрите здесь https://doc.arduino.ua/ru/prog/BitSet и здесь https://doc.arduino.ua/ru/prog/BitClear - установит и сбросить бит не задевая другие. Всё делается на уровне ассемблера - быстро. Ещё надо помнить какой бит - номер, а не значение. Ваш долгий digitalWrite(swo, HIGH); swo - 11 нога это PB3 заменяется на быстрый bitSet(PORTB,3); и LOW в bitClear(PORTB,3). Другие биты не изменяются. Перед началом вывода надо переключить ногу порта на вывод командой bitSet(DDRB,3); . 

Ещё очень полезная функция https://doc.arduino.ua/ru/prog/Bit - не надо помнить двоичное значение. 

C for просто - набиваем массивы задержек и крутим. 

byte d1[] = {8, 8, 8, 8, 8, 17, 8, 8, 8, 8, 26, 8, 8, 8, 17, 35, 78, 69, 78, 78, 78, 78, 26, 26};
byte d2[] = {11, 11, 11, 11, 11, 11, 11, 11, 11, 20, 11, 11, 11, 11, 11, 11, 11, 11, 20, 11, 11, 11, 11, 28};

void setup() {
  // здесь ничего не надо, все порты после старта на ввод
  // если надо подтянуть к единице вставляем bitSet(PORTD, 6);  
}

void loop() {
  if (bitRead(PIND, 6) != bit(6)) // D10 - бит 6 порта D, bit(6) только для примера, если надо сравнить с единицей. А сейчас можно написать ==LOW или ==0
  {
    bitSet(DDRB, 3);
    bitSet(PORTB, 3);
    delay(400);  //START
    noInterrupts();
    for (byte i = 0; i < 25; i++) {
      bitClear(PORTB, 3);
      delayMicroseconds(d1[i]);
      bitSet(PORTB, 3);
      delayMicroseconds(d2[i]);
    };
    // bitClear(PORTB, 3); Здесь ноль просится, а то нелогичненько получается
    interrupts();
  }
  // ...  и.т.д.
}

 

Спасибо за помощь)
Насчет D10 - это вроде порт В, а не D (8-13)

Я сам когда пытался с массивом сделать, не мог найти как правильно в delayMicroseconds массив прописать.

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

Да. Как то как. D10 это PB2. Куда то я не туда посмотрел. Будет if (!bitRead(PINВ, 2). А PB3 это D11, который я как выход прописывал. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Pyotr пишет:

void delayMy(word ms){
  byte tcnt0 = TCNT0;
  byte tic = 250;
  while(ms > 0){
    while(TCNT0 == tcnt0){}
    tcnt0 += tic;
    while(TCNT0 != tcnt0){}
    ms--;
  }
}

Фига-се!

«Если у тебя спрошено будет: что полезнее, солнце или месяц? – ответствуй: месяц. Ибо солнце светит днем, когда и без того светло; а месяц – ночью»
(Козьма Петрович Прутков, «Мысли и афоризмы», афоризм №51)