Включить несколько портов одновременно

FF_Group
Offline
Зарегистрирован: 13.12.2015

Добрый день

подскажите простой вопрос как одновременно изменить состояние скажем 10 портов

вот так напрмер это можно записать?

digitalWrite((5,6,7,8,9,10), LOW);

И второй вопрос,

Мне нужно 2 раза в день на время 20-60 секунд включить 1 нагрузку.

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

void setup() {
       
    pinMode(2,OUTPUT);
    pinMode(3,OUTPUT);
    pinMode(4,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);    }


void loop() 
//запускаем в 0:00 ночи
{
  digitalWrite(13, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(4, HIGH);  
  digitalWrite(3, HIGH);  
  digitalWrite(2, HIGH);  

//пауза с 12 часов ночи до 8 утра 
delay(28800000); // 8*60*60*1000);
  
  digitalWrite(13, LOW);
  delay(1000);
  digitalWrite(12, LOW);
  delay(1000);
  digitalWrite(11, LOW);
  delay(1000);
  digitalWrite(10, LOW);
  delay(1000);
  digitalWrite(9, LOW);
  delay(1000);
  digitalWrite(8, LOW);
  delay(1000);
  digitalWrite(7, LOW);
  delay(1000);
  digitalWrite(6, LOW);
  delay(1000);
  digitalWrite(5, LOW);
  delay(1000);
  digitalWrite(4, LOW);
  delay(1000);
  digitalWrite(3, LOW);
  delay(1000);
  digitalWrite(2, LOW);
  delay(1000);
  
  digitalWrite(13, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(4, HIGH);  
  digitalWrite(3, HIGH);  
  digitalWrite(2, HIGH);  

  
  //пауза с (8 утра +12сек до 18 вечера
delay(35988000); // 10*60*60*1000 -12000);
 
    
  digitalWrite(13, LOW);
  delay(1000);
  digitalWrite(12, LOW);
  delay(1000);
  digitalWrite(11, LOW);
  delay(1000);
  digitalWrite(10, LOW);
  delay(1000);
  digitalWrite(9, LOW);
  delay(1000);
  digitalWrite(8, LOW);
  delay(1000);
  digitalWrite(7, LOW);
  delay(1000);
  digitalWrite(6, LOW);
  delay(1000);
  digitalWrite(5, LOW);
  delay(1000);
  digitalWrite(4, LOW);
  delay(1000);
  digitalWrite(3, LOW);
  delay(1000);
  digitalWrite(2, LOW);
  delay(1000);
  
  digitalWrite(13, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(4, HIGH);  
  digitalWrite(3, HIGH);  
  digitalWrite(2, HIGH);  
  
  //пауза с 18 вечера +12 сек до 0 ночи
delay(21588000); // 6*60*60*1000 -12000);

вот так пока выглядит код (секунды то я поправлю до нужных величин), писарь я еще тот...

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

 

http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry

Это для начала. Астальное в литературе и примерах.. 

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

Муж_Долговой пишет:

http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry

Это для начала. Астальное в литературе и примерах.. 


Это сложно для начинающего. Тем более что ему не нужно СТРОГО одновременно.) Проще в цикле:
 

const byte key[]   = {9,10,11,12,14,15,16,17,18,19};

  for (byte i = 0; i < sizeof(key); i++){
    pinMode(key[i], INPUT_PULLUP);

 

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

FF_Group пишет:

подскажите простой вопрос как одновременно изменить состояние скажем 10 портов

Видимо, имелось в виду "пинов".

Ответ: никак, от слова "совсем никак".

Одновременно можно менять только те пины, которые на одном порте сидят (а таких не более 8-ми по определению). Если это устраивает, то Вам уже дади ссылку. Ну и библиотека есть.

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

Green пишет:

Это для начала. Астальное в литературе и примерах.. 


Это сложно для начинающего. Тем более что ему не нужно СТРОГО одновременно.) Проще в цикле:

[/quote]

Какой же он начинающий? Четыре года на сайте.

sadman41
Offline
Зарегистрирован: 19.10.2016

4 года не срок... Тут вон люди регистрируются чтобы курсовую нахаляву заполучить, не справляются, идут в армию... там ещё на второй год пару раз остаются и всё, четыре года пролетели как миг ;)

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

Вернувшись к теме .... управлять регистрами прямыми командами не сложно. Один раз разобраться с двоичным счётом пинов в порту и  расположением самих портов.

Проблема в другом. Во время отладки и перераспределения пинов гораздо труднее пересчитать обращение в регистр и ничего не забыть.

Опять же некоторые библиотеки уже прописаны с определёнными пинами прописаны.

Сложно перенести скетч на другой МК.

Но в приведённом автором скетче конечно же регистрами управлять само проситься.

Моё мнение: Если все пины одновременно надо включать - выключать - надо в корне концепцию всего устройства менять.

sadman41
Offline
Зарегистрирован: 19.10.2016

Конечно надо. Поставить сдвиговый регистр с защёлкой, например.

FF_Group
Offline
Зарегистрирован: 13.12.2015

спасибо за ответы

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

Возвращаюсь к вопросу.

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

еще есть вопрос

вот так можно паузы писать? То есть сразу в скобках проводить арифметические действия?

 

void setup() {
    int T;
    T=10000;

void loop()
 {

//пауза с 12 часов ночи до 8 утра 
delay( 8*60*60*1000);

digitalWrite(13, LOW);
  delay(T);
 delay(T+1000);
}

 

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

паузы так писать можно, но остальной код совершенно нерабочий. Переменная Т определена в setup и потому в loop работать не будет. Сам setup не закрыт...

Ну и вообще, если вы будуете задавать время с помощью delay() - больше одного реле у вас в проекте работать не будет, а в первом сообщении вам вроде требовалось много портов

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

Да и строка №9. Формально-то оно правильно, но выглядит просто страшно.

FF_Group
Offline
Зарегистрирован: 13.12.2015

b707 пишет:

остальной код совершенно нерабочий. Переменная Т определена в setup и потому в loop работать не будет. Сам setup не закрыт...

вопрос только в незакрытом сетапе? или переменную надо из сетапа вынести выше?

b707 пишет:
если вы будуете задавать время с помощью delay() - больше одного реле у вас в проекте работать не будет, а в первом сообщении вам вроде требовалось много портов

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

 

а вобще сейчас в голову пришла еще мысль.

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

реле управляет мотором шнека.

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

только это я буду месяц писать;)

bwn
Offline
Зарегистрирован: 25.08.2014

FF_Group пишет:

только это я буду месяц писать;)

Если почитаете статьи в секретном блоге, то все пойдет быстрее.

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

ЕвгенийП пишет:

Да и строка №9. Формально-то оно правильно, но выглядит просто страшно.

А оно точно формально правильно?

У меня - выводит 29696.

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

void loop() {
  Serial.println(8*60*60*1000);
  delay(1000);
}

 

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

Точно правильно. У Вас неудачный тест. Параметр delay описан как uint32_t, поэтому корректный тест выглядит так:

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

void __delay(uint32_t d) {
	Serial.println(d);
}

void loop() {
	__delay(8*60*60*1000);
	delay(1000);
}

 

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

Во блин. Я тоже на этом попался.( Век живи - век учись.(

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

ЕвгенийП пишет:

Точно правильно. У Вас неудачный тест. Параметр delay описан как uint32_t, поэтому корректный тест выглядит так:

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

void __delay(uint32_t d) {
	Serial.println(d);
}

void loop() {
	__delay(8*60*60*1000);
	delay(1000);
}

Странно это.

А по моей логике сначала должны проводться вычисления в int, и только потом получившееся 29696 приводится к типу uint32_t. И, кстати, натурные эксперименты это подтверждают, - вывод не поменялся.

 

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

Да, наверное, это меня переклинило. Может, о другом думал.

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

Ага. Сбивают тут, понимаешь, с пути истинного, своим авторитетом.) Достаточтно что бы один из операндов был int32_t, даже без явного указания.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Green пишет:

Ага. Сбивают тут, понимаешь, с пути истинного, своим авторитетом.) Достаточтно что бы один из операндов был int32_t, даже без явного указания.

Нет.

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

Тема второй раз поднимается, в первый я и не понял в чём подвох )))

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

DetSimen пишет:

Нет.

Лаконично.
- что да?
- тоже нет.

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

Green пишет:
Достаточтно что бы один из операндов был int32_t, даже без явного указания.
Правильно дида говорит - нет! Там принцип-то просто как валенок. Запомните

1. Преобразование производится только тогда, когда реально нужно.

2. Все операции "*" выполняются слева направо.

Вот и всё. Т.е. не просто "один", а первый. Ну, или не первый, но такой, что "до него" никаких неприятностей не произошло.

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

) Вот вам "простой как валенок" пример:  __delay(8*60*60*33000);
Что там насчёт первого? И "до него никаких неприятностей" - что за выражение?)
 

 

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

Первый - int, второй тоже, перемножается как инт и результат инт. Этот результат умножается на третий (тоже инт) результат - инт), этот результат на четвёртый. Результат опять инт, но это уже неверно -  возникло переполнение. Т.е. в данном примере лонгом может быть дюбой член, но в общем случае - любой, но стоящий ДО переполнения. Вот в этот пример добавьте справа ещё один сомножитель (хоть * 2). И получите, что делать его лонгом бесполезно - ошибка уже появилась до него.

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

ОК. Все верно. А то я уже начал было сомневаться в теории. Подумал, может уже чего улучшили.)

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

 

А так ?

delay(8L*60L*60L*33000L);

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно просто 8L в первой позиции, но потом константы местами не переставлять.

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

Прошу простить, за возможно идиотский вопрос. Сколько займет процедура "зажигания" пинов в скетче? И в чем надобность "зажигать" пины абсолютно синхронно?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

если пины в ОДНОМ порту, то их можно зажигать за 2 или 4 (не помню) такта процессора ОДНОВРЕМЕННО.  Зачем - ХЗ. 

SLKH
Offline
Зарегистрирован: 17.08.2015

Sonologist пишет:

И в чем надобность "зажигать" пины абсолютно синхронно?

В вопросе от ТС - ни в чём. Просто он спросил совсем не то, что хотел.

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

DetSimen пишет:

если пины в ОДНОМ порту, то их можно зажигать за 2 или 4 (не помню) такта процессора ОДНОВРЕМЕННО.  Зачем - ХЗ. 

что-то многовато, по идее должно за такт

-NMi-
Онлайн
Зарегистрирован: 20.08.2018

CLR R0 - 1 такт

OUT PORTB,R0 - 1 такт

SER R0 - 1 такт

OUT PORTB,R0 - 1 такт

Итого 4 такта чтоб "дрыгануть" весь порт целиком.

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

-NMi- пишет:

CLR R0 - 1 такт

OUT PORTB,R0 - 1 такт

SER R0 - 1 такт

OUT PORTB,R0 - 1 такт

Итого 4 такта чтоб "дрыгануть" весь порт целиком.

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

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

блин, с x86 перепутал.  да. ты прав, NMi.

FF_Group
Offline
Зарегистрирован: 13.12.2015

SLKH пишет:

Sonologist пишет:

И в чем надобность "зажигать" пины абсолютно синхронно?

В вопросе от ТС - ни в чём. Просто он спросил совсем не то, что хотел.

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

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

мне нужно ежедневно в 8 утра и 6 вечера включать "единовременно" (не абсолютно синхронно, и даже не обязательно одновременно) 10 пинов но на разное время работы реле.

Реле в системе только одно, и переключается разьемом "мама" для финишной подстройки работы шнека.

 

-NMi-
Онлайн
Зарегистрирован: 20.08.2018

ua6em пишет:

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

Сбросятся.

Тут два варианта:

SBI или CBI - это побитно с портом.

Либо применить маску с прочитанного с порта, AND или OR в зависимости от "сбросить" или "выставить"

Третий вариант (опционально) --- XOR с маской, так мы "передёргиваем" бит или биты, естественно по маске, в порту (8 бит)

Ваащпе вариантов можно накрапать много... всё зависит от "полёта" мысли :))

-NMi-
Онлайн
Зарегистрирован: 20.08.2018

FF_Group пишет:

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

2 - 10 пинов но на разное время работы реле.

1 - можно и одной командой.

2 - можно, но несколькими командами (не более 15-ти команд ASM)

Как? Элементарно...     Стакан ---> Деду, закусь ---> мне     :))

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

-NMi- пишет:

2 - можно, но несколькими командами (не более 15-ти команд ASM)

Как? Элементарно...     Стакан ---> Деду, закусь ---> мне     :))

Но здесь только две команды! А где остальные 13? Мож на них там и мне чего перепадёт?

-NMi-
Онлайн
Зарегистрирован: 20.08.2018

DetSimen пишет:

если пины в ОДНОМ порту, то их можно зажигать за 2 или 4 (не помню) такта процессора ОДНОВРЕМЕННО. 

А ежли "накатить" стакан-другой, то можно придумать способ и одновременно и не в одном а в нескольких портах (правда не все камни это держут) одновременно. Читаем датащи, фканце, описание портов проца.  :))

-NMi-
Онлайн
Зарегистрирован: 20.08.2018

ЕвгенийП пишет:

Но здесь только две команды! А где остальные 13? Мож на них там и мне чего перепадёт?

Умом процессор не понять, пока не выпито 0,5   ... попЫтки глубже понимать уже подразумевают ЛИТР!!!

asam
Онлайн
Зарегистрирован: 12.12.2018

FF_Group пишет:

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

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

Цитата:

мне нужно ежедневно в 8 утра и 6 вечера включать "единовременно" (не абсолютно синхронно, и даже не обязательно одновременно) 10 пинов но на разное время работы реле.

Реле в системе только одно, и переключается разьемом "мама" для финишной подстройки работы шнека.

 

Не могу понять, что означает "10 пинов но на разное время работы реле" и причем здесь мама и шнек?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

#pragma pack(push,1)
typedef struct
{
 uint8_t pin;
 uint16_t workTimeInSeconds;
 uint32_t startedAt;

} WorkSetting;
#pragma pack(pop)

WorkSetting WorkSettings[] = {

	{2, 10, 0},
	{3, 20, 0},
	{4, 30, 0},
	{5, 15, 0},
	{6, 20, 0},
	{7, 30, 0},
	{8, 60, 0},
	{9, 44, 0},
	{10, 99, 0},
	{11, 120, 0},

};

void setup()
{
	const size_t cnt = sizeof(WorkSettings)/sizeof(WorkSettings[0]);
	for(size_t i=0;i<cnt;i++)
	{
		pinMode(WorkSettings[i].pin,OUTPUT);
	}
}

void loop()
{
	const size_t cnt = sizeof(WorkSettings)/sizeof(WorkSettings[0]);

	if(время_8_утра или время_6_вечера)
	{
		
		for(size_t i=0;i<cnt;i++)
		{
			if(WorkSettings[i].startedAt == 0)
			{
				digitalWrite(WorkSettings[i].pin,HIGH);
				WorkSettings[i].startedAt = millis();
			}
		}		
	}

	uint32_t now = millis();

	for(size_t i=0;i<cnt;i++)
	{
		if(WorkSettings[i].startedAt > 0)
		{
			uint32_t interval = 1000UL * WorkSettings[i].workTimeInSeconds;
			if(now - WorkSettings[i].startedAt > interval)
			{
				WorkSettings[i].startedAt = 0;
				digitalWrite(WorkSettings[i].pin,LOW);
			}
		}
	}
}
FF_Group
Offline
Зарегистрирован: 13.12.2015

asam пишет:

Не могу понять, что означает "10 пинов но на разное время работы реле" и причем здесь мама и шнек?

Ардуино управляет всего лишь одним приводом шнека через реле.
Опытным путем установлено что за 60 секунд шнек нагружает необходимую массу "материала". Но поскольку поставщик материала может измениться изменится насыпная плотность и нужно будет заставить шнек работать 55 или 65 секунд. И что бы каждый раз не лезть в скетч нужно что бы все пины были настроены на разную продолжительность работы, но включались примерно в 8 утра и 18 вечера.
То есть беру просто управляющий провод от реле и переключаю на соседний пин и время подачи материала сокоащается или увеличивается.

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

FF_Group][quote=asam пишет:

То есть беру просто управляющий провод от реле и переключаю на соседний пин и время подачи материала сокоащается или увеличивается.

как всё запущено...а две кнопки управления временем не достаточно?

asam
Онлайн
Зарегистрирован: 12.12.2018

FF_Group пишет:
Ардуино управляет всего лишь одним приводом шнека через реле. Опытным путем установлено что за 60 секунд шнек нагружает необходимую массу "материала". Но поскольку поставщик материала может измениться изменится насыпная плотность и нужно будет заставить шнек работать 55 или 65 секунд. И что бы каждый раз не лезть в скетч нужно что бы все пины были настроены на разную продолжительность работы, но включались примерно в 8 утра и 18 вечера. То есть беру просто управляющий провод от реле и переключаю на соседний пин и время подачи материала сокоащается или увеличивается.

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

-NMi-
Онлайн
Зарегистрирован: 20.08.2018

FF_Group пишет:

Опытным путем установлено что за 60 секунд шнек нагружает необходимую массу "материала". Но поскольку поставщик материала может измениться изменится насыпная плотность и нужно будет заставить шнек работать 55 или 65 секунд. И что бы каждый раз не лезть в скетч нужно что бы все пины были настроены на разную продолжительность работы, но включались примерно в 8 утра и 18 вечера.

Ну дык паставь RTC и LCD и клавиатуру и сделай меню да и управляй ты хоть часами, хоть секундами... да хоть чем. Неужели для тебя это так трудно???

sadman41
Offline
Зарегистрирован: 19.10.2016

Обычный галетник для выбора входа, который будет определять время работы: D2 - 45 сек, D3 - 50 секунд и т.д.

FF_Group
Offline
Зарегистрирован: 13.12.2015

Трудно... И кнопки трудно, уж молчу про ЛСД с меню
Но ЛСД с меню конечно самый крутой вариант

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

Не, ну если ЛСД, то оно, конечно тяжело. Да и недёшево.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

с ЛСД еще и глючно.