Помогите создать Arduino команду, для включения несколько пинов

Тема в разделе "Arduino & Shields", создана пользователем woow, 12 мар 2018.

  1. woow

    woow Гик

    Задуман такой проект для управления блоком из 8 реле при помощи Arduino+W5100(можно и любой другой сетевой модуль).
    В найденном интернете скече убрал всё для меня не нужное и добавил то что нужно и подстроил для себя, что-бы можно было управлять 8-ю реле по mqtt протоколу.
    Всё работает, команды посылаются ответы состояния приходят (между прочем хорошая и дешёвая альтернатива реле управляемым по LAN).
    1. Вопрос возник, когда захотелось иметь команду включения/отключения всех реле одной командой.
    Конечно можно сделать послание команд со стороны умного дома по mqtt, но это в крайнем случае.
    2. Вопрос. Неплохо было бы всё записывать в память EEPROM состояние пинов, если при сбое питания всё восстанавливалось в последнее состояние.
    Выкладываю скеч. Знаками //*// обозначены безуспешные попытки решения данного вопроса
    Код (C++):
    /*
    connect to mqtt server, send and recive
    Arduino Nano
    W5100
    */


    #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[] = { 2, 3, 4, 5, 6, 7, 8, 9 };  
    //*//  int pinCount = 8;                                  

    // 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;
      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;
           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;
        //back;
     
      digitalWrite(r, hl);
      Serial.println();
    }

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

    void reconnect()
    {
    // Loop until we're reconnected
      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);
     
      pinMode(relay1, OUTPUT);
      pinMode(relay2, OUTPUT);
      pinMode(relay3, OUTPUT);
      pinMode(relay4, OUTPUT);
      pinMode(relay5, OUTPUT);
      pinMode(relay6, OUTPUT);
      pinMode(relay7, OUTPUT);
      pinMode(relay8, OUTPUT);

    //*//  for (int thisPin = 0; thisPin < pinCount; thisPin++) {pinMode(relayAll[thisPin], OUTPUT);}
    //*//  for (int thisPin;) {pinMode(relayAll[thisPin], OUTPUT);}
     
      if (client.connect("arduinoPowerPanel"))
       {
        Serial.print("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();
    }
     
  2. fogary

    fogary Гик

    Например:
    Код (C++):
    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 = 255;                                
    else
      r = relay1;

    if (r == 255)
      for (byte i = 0; i < pinCount - 1; i++)
        digitalWrite(relayAll[i], hl);
    else
      digitalWrite(r, hl);
     
  3. DetSimen

    DetSimen Guest

    if(strcmp(topic,"PowerPanel/relay1") . . . .. ;
     
  4. woow

    woow Гик

    ммда дёрнуло меня...
    Спасибо за помощь всё сработало, вкл/выкл все реле но вылезла другая проблема, по mqtt отправляется ответ статуса только 1 или 0, по адресу PowerPanel/relayAll , а ведь нужно что он менялся на всех восьми реле. Что опят какой- то массив создавать?
     
  5. fogary

    fogary Гик

    Ткните в коде, в каком месте возвращается статус реле?
     
  6. Можно так:
    void onPins()
    {
    digitalWrite(нужный пин, состояние);
    И т.д.
    }

    А потом в loop(е)
    onPins();
     
  7. woow

    woow Гик

    Вы наверное не так поняли. В этом скетче всё отлично работает, управляется всё по MQTT протоколу, по лан сети принимает команды и отсылает ответы о состоянии, но есть одна неточность, когда посылаешь команду чтобы включить все реле одной командой она выполняется, но вот ответ возвращается не по всем реле и сервере не отображается изменившееся статус
    subscribe "PowerPanel/relayAll" -- publish "PowerPanel/relayAll", "1", а надо как-то так PowerPanel/relay1, PowerPanel/relay2...., PowerPanel/relayAll
    или не не прав.
     
  8. b707

    b707 Гуру

    По команде relayAll надо не только включать каждое реле по списку, но и менять их статус. В коде, что вам написал Fogary в сообщении #2 в отработку команды (r==255) добавьте
    Код (C++):
    if (r == 255)
      for (byte i = 0; i < pinCount - 1; i++) {
        digitalWrite(relayAll[i], hl);
        String ss = "PowerPanel/relay" + String(i+1);
        client.publish(ss, "1");
        client.subscribe(ss); }
    else
      digitalWrite(r, hl);
     
  9. woow

    woow Гик

    Спасибо что помогаете, как бы идею понял , но почему то в этом месте

    error: 'client' was not declared in this scope

    client.publish( ss, "1" );

    если переношу эти две строки
    client.publish( ss, "1" );
    client.subscribe( ss );
    в условие
    if (client.connect("arduinoPowerPanel"))
    {...
    тогда ошибки не показывает, но также ни чего и не происходит нового скетч работает по предыдущему сценарию.
    Код (C++):
    /*
    connect to mqtt server, send and recive
    Arduino Nano
    W5100
    HL-58S
    */


    #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[] = { 2, 3, 4, 5, 6, 7, 8, 9 };  
    int pinCount = 9;
                                       

    // 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;
      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;
           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 = 255;                              
      else
        r = relay1;

      if (r == 255)

      for (byte i = 0; i < pinCount - 1; i++)
    //   digitalWrite(relayAll[i], hl);
       {
        digitalWrite(relayAll[i], hl);
        String ss = "PowerPanel/relay" + String(i+1);
        client.publish( ss, "1" );
        client.subscribe( ss );
        }
       
      else
         digitalWrite(r, hl);
     
    }

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

    void reconnect()
    {
    // Loop until we're reconnected
      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);
     
      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.print("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");
        //client.publish("ss", "1");
        //client.subscribe("ss");
       
        }
       }

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

    b707 Гуру

    Строчки
    Код (C++):
    EthernetClient ethClient;
    PubSubClient client(server, 1883, callback, ethClient);
     
    перенесите выше процедуры callback() - это же должно быть очевидно...

    Вы совсем ничего в этой программе не понимаете? - списали код в инете?
     
  11. woow

    woow Гик

    А почему вас это удивляет, ведь на этом форуме около 90% таких как я. Я в первом посте написал что это всё выудил в инете. Собирал из кусков методом проб и ошибок. Но вот именного такого не нашёл.
    Этот https://hi-lab.ru/ АМС такие возможности и имеет, но туда вникать всё это из за нескольких реле стоит ли. По моему очень не плохое и довольно простое и дешёвое устройство которое можно без проблем согласовать как с Domoticz, OpenHab, MojorDomo и прочих платформ умного дома, там где можно проложить кабеля. Вот если не нужно включение всех реле сразу а управлять отдельными нагрузками, можно уже пользоваться, это открытый проект :)
    Была такая мысль переставить эти строки выше, но когда это сделал посыпалось уже н-цать строк ошибок в том числе и в езернет библиотеках, как -то не вникал особо что там не так, вернул всё в прежнее состояние.
     
  12. Arduino_man

    Arduino_man Гик

    Лучше так:
    Код (C++):
    void onPins()
    {
    digitalWrite(нужный пин, состояние);
    // И т.д.
    }

    А потом в loop(е)
    //onPins();