одной командой на все пины

ewas
Offline
Зарегистрирован: 26.09.2016

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

кусок кода

const int relay1 = 2;
const int relay2 = 3;
const int relay3 = 4;
const int relay4 = 5;
const int relay5 = 6;
const int relay6 = 7;
const int relay7 = 8;
const int relay8 = 9;
 int relayAll[] = {2,3,4,5,6,7,8,9}; //пробовал с масивом

пробовал с масивом , и с функцией loop allrele{...} 

else if(String(topic)=="PowerPanel/relay8")
    r = relay8;
 else if(String(topic)=="PowerPanel/X") //мне вот сюда нужно в место Х чтото чо обозначало все 8 реле (пинов)    
    r = X;      //мне вот сюда нужно в место Х чтото чо обозначало все 8 реле (пинов)                             
  else
    r = relay1;
  digitalWrite(r, hl); 

 

triac
triac аватар
Offline
Зарегистрирован: 03.05.2018

Команда digitalWrite пишет в один порт, она не может одновременно писать в несколько портов. Поскольку реле - устройство медленное, то вам должно быть все равно, одновременно вы ими управляете или по очереди. Напишите свою функцию управления реле, например, такую:



const int relay1 = 2;
const int relay2 = 3;
const int relay3 = 4;
const int relay4 = 5;
const int relay5 = 6;
const int relay6 = 7;
const int relay7 = 8;
const int relay8 = 9;
const int relayAll = -1;

void relayWrite(int relay_number, bool hi_lo)
{
  // если указан номер в диапазоне 2..9 то управляем реле по-отдельности
  if ((relay_number >= 2) && (relay_number <= 9))
  {
    digitalWrite(relay_number, hi_lo); 
  }
  // если указан номер -1 то управляем всеми реле сразу
  else if (relay_number == relayAll)
  {
    for (int i=2; i<=9; i++) // номера портов 2..9
    {
      digitalWrite(i, hi_lo); 
    }
  } 
}

Теперь можно написать так:

else if(String(topic)=="PowerPanel/relay8")
    relayWrite(relay8, h1);
 else if(String(topic)=="PowerPanel/X")   
    relayWrite(relayAll, h1);      // все 8 реле (пинов)                             
  else
    relayWrite(relay1, h1);

 

ewas
Offline
Зарегистрирован: 26.09.2016

здесь комментарий не пишу комментарии в коде, пока не имею возможности обкатать на компиляторе а тем более на arduino, но есть в коде сомнения и я их прокомментировал

там есть два блока 2 и 3. 2 это который я старался оставить ближе к оригиналų только использовав идею от triac, a 3 максимально подтянув под предложение от triac

а блок но.1 не совсем уверен о его местоположении в этом коде.

/*

управление блоком реле с MQTT протоколом
контролер Arduino Nano 
сетевой адаптер W5100
** в перспективе нужно добавить запись EEPROM 
для запоминания включенных реле после пропажи напряжения

*/

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
//#include <EEPROM.h>  // для запоминания включенных реле после пропажи напряжения

const int relay1 = 2;
const int relay2 = 3;
const int relay3 = 4;
const int relay4 = 5;
const int relay5 = 6;
const int relay6 = 7;
const int relay7 = 8;
const int relay8 = 9;
const int relayAll = -1;   //**добавлено  * tiac


// начало блока -1 ///*** добавлено  * tiac ***///
//

void relayWrite(int relay_number, bool hi_lo)
{
  // если указан номер в диапазоне 2..9 то управляем реле по-отдельности
  if ((relay_number >= 2) && (relay_number <= 9))
  {
    digitalWrite(relay_number, hi_lo); 
  }
  // если указан номер -1 то управляем всеми реле сразу
  else if (relay_number == relayAll)
  {
    for (int i=2; i<=9; i++) // номера портов 2..9
    {
      digitalWrite(i, hi_lo); 
    }
  } 
}

//конец блока -1////*************///////////

// Update these with values suitable for your network.
byte mac[]    = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 1, 140 };
byte ip[]     = { 192, 168, 1, 132 };


void callback(char* topic, byte* payload, unsigned int length){
	
  int r,hl;                     // инициация h и r, в блоке Но2 r - не нужно
  Serial.begin(9600);
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  
  char receivedChar = (char)payload[0];
  Serial.print(receivedChar);
  if(receivedChar=='1')
    hl = LOW;
    else
    hl = HIGH; 

// начало блока -2 ////**вариант  Но1**///

       if(String(topic)=="PowerPanel/relay1")
    r = relay1;
  else if(String(topic)=="PowerPanel/relay2")
    r = relay2;
  else if(String(topic)=="PowerPanel/relay3")
    r = relay3;
  else if(String(topic)=="PowerPanel/relay4")
    r = relay4;
  else if(String(topic)=="PowerPanel/relay5")
    r = relay5;
  else if(String(topic)=="PowerPanel/relay6")
    r = relay6;
  else if(String(topic)=="PowerPanel/relay7")
    r = relay7;
  else if(String(topic)=="PowerPanel/relay8")
    r = relay8;
 else if(String(topic)=="PowerPanel/relayAll")     
    r = relayAll;                                   
  else
    r = relay1;
  digitalWrite(r, hl); 
  Serial.println();
}

//конец блока -2//


// начало блока -3**---или всё же вариант Но2 с такой идеей ---добавлено  * tiac //

       if(String(topic)=="PowerPanel/relay1")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay2")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay3")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay4")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay5")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay6")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay7")
    relayWrite(relay1, hl);
  else if(String(topic)=="PowerPanel/relay8")
    relayWrite(relay1, hl);
 else if(String(topic)=="PowerPanel/relayAll")     
    relayWrite(relayAll, hl);                                   
  else
    relayWrite(relay1, hl);

   digitalWrite(hl); //  этот наверное тоже не нужен ?
  Serial.println();
}

//конец блока -3//************//////


EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

void reconnect() 
{
 // Loop пока мы не подключимся
  while (!client.connected()) 
 {
    Serial.println("Attempting MQTT connection...");
 // Attempt to connect
    if (client.connect("arduinoPowerPanel")) 
        {
        Serial.println("connected");
        }
        else 
        {
          Serial.print("failed, rc=");
          Serial.print(client.state());
          Serial.println(" try again in 5 seconds");
          delay(5000);
        }
    
  }
}

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  
 // Каждый вывод подключается к реле в режиме OUTPUT,
 
 for(int i = 0; i < 8; i++){ //цикл, который будет повторяться 8 раз
 pinMode(relayAll[i],OUTPUT); //устанавливаем каждый PIN в режим OUTPUT
 } //можно и так если без цикла
 /*     
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  pinMode(relay6, OUTPUT);
  pinMode(relay7, OUTPUT);
  pinMode(relay8, OUTPUT);
    */
    
  if (client.connect("arduinoPowerPanel")) 
   {
    Serial.println ("online");
    client.publish("PowerPanel/relay1", "1");
    client.subscribe("PowerPanel/relay1");
    client.publish("PowerPanel/relay2", "1");
    client.subscribe("PowerPanel/relay2");
    client.publish("PowerPanel/relay3", "1");
    client.subscribe("PowerPanel/relay3");
    client.publish("PowerPanel/relay4", "1");
    client.subscribe("PowerPanel/relay4");
    client.publish("PowerPanel/relay5", "1");
    client.subscribe("PowerPanel/relay5");
    client.publish("PowerPanel/relay6", "1");
    client.subscribe("PowerPanel/relay6");
    client.publish("PowerPanel/relay7", "1");
    client.subscribe("PowerPanel/relay7");
    client.publish("PowerPanel/relay8", "1");
    client.subscribe("PowerPanel/relay8");
    client.publish("PowerPanel/relayAll", "1"); //*** здесь новое пока не обкатанное 
    client.subscribe("PowerPanel/relayAll"); //*** здесь новое пока не обкатанное  
 
   }
}

void loop()
{
   if (!client.connected()) 
      {
       reconnect();
      }
  client.loop();
}

 

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

Могу еще такой вариант предложить:

uint8_t writeToPort(const uint8_t _port, const uint8_t _value)
{
  volatile uint8_t *portRegister;

  portRegister = portOutputRegister(_port);
  if (NOT_A_PORT == portRegister) return false;
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {  
    *portRegister = _value;
  }
  return true;
}

writeToPort(0, B10100101) - в порт A
writeToPort(3, B10100101) - в порт D (пины D7..D0)

Будет выставлять все пины разом.

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

ewas пишет:

 но есть в коде сомнения и я их прокомментировал

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

По сути вашего кода у меня есть вполне обоснованное сомнение, что такое количество String-ов поместится в оперативку Нано.  Вы обращаетесь с памятью крайне неэкономно. С 178 по 195 строчку у вас 18 почти одинаковых строк, которые можно сократить до одной-двух.

ewas
Offline
Зарегистрирован: 26.09.2016

b707 пишет:

если есть реальные вопросы - пишите конкретно. А ради ваших "сомнений", которые еще и в коде надо искать - копаться в нескольких сотнях строк вряд ли кому интересно.

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

b707 пишет:

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

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

b707 пишет:

По сути вашего кода у меня есть вполне обоснованное сомнение, что такое количество String-ов поместится в оперативку Нано.  Вы обращаетесь с памятью крайне неэкономно. С 178 по 195 строчку у вас 18 почти одинаковых строк, которые можно сократить до одной-двух.

 Без доп добавок код рабочий и памяти хватает и быстродействия, не знаю как и не вижу смысла чтобы его как- то усложнять для того что бы сэкономить память. Как локально с веб интерфейса сервера работает, с мобилы отдалённо тоже без нареканий.Я считаю, что это довольно интересный проект если кому нужно управлять нагрузками через интернет, по wifi есть на esp, вот есть теперь на проводах, только пока нет чтобы одной кнопкой можно было всё on/off.

ewas
Offline
Зарегистрирован: 26.09.2016

sadman41 пишет:

Будет выставлять все пины разом.

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

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

ewas пишет:

sadman41 пишет:

Будет выставлять все пины разом.

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

Есть такая опасность. Я у себя ее решаю простой защитной маской (просто вырезал из этого кода, чтобы не усложнять): *portRegister = (*portRegister & port_protect[_port]) | (_value & ~port_protect[_port]); - в port_protect храню битовые маски, которые говорят - разрешено менять состояние конкретного пина или нет. Пока работает.