Change of IP address with button and LCD display Ethernet Shield Arduino

Varley Gianini

Varley Gianini
Joined
Jan 13, 2020
Messages
4
Location
Pompeia - SP
Good morning everyone! Well I have a code here to control relays through artnet E1.31 using the Arduino Ethernet shield, but for us to change the IP address we must change the line and compile the code on the Arduino, I would like to know how can I do to put a button that makes this IP change and shows it on an LCD. Can anyone help me with this?

Follow the code below


C++:
#include <SPI.h> //Biblioteca Padrão
#include <Ethernet.h> //Biblioteca Padrão
#include <EthernetUdp.h> //Biblioteca Padrão


/* defina a sub-rede e o universo desejados (o primeiro universo é 0)
sACN começa com o universo 1, então subtraia 1 do universo sACN
para obter DMX_UNIVERSE. */
#define ARTNET_SUBNET 0 //a sub-rede padrão é 0. Não deve ser necessário alterar.
#define ARTNET_UNIVERSE 41 //primeiro universo sendo usado
#define E131_SUBNET 0 //a sub-rede padrão é 0. Não deve ser necessário alterar.
#define ETHERNET_BUFFER_MAX 640
#define ARTNET_ARTDMX 0x5000
#define ARTNET_ARTPOLL 0x2000
#define ARTNET_PORT 0x1936 //porta padrão
#define ARTNET_START_ADDRESS 18 //O byte 18 no pacote contém os valores do canal 1.
#define E131_PORT 5568 //porta padrão
#define E131_START_ADDRESS 126 //O byte 126 no pacote contém os valores do canal 1. O deslocamento é definido como um anterior.
#define STATUS_LED 13 //nos mostra quando estamos recebendo dados
#define SDCARD_CONTROL 4 //defina o pino 4 para alto para desativar a interface do cartão SD no escudo WiFi
#define NUM_RELAYS 16 //número total de relés usados

int channel; //incremento de canal


//Pinos Reles
int Relay[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};

//Configuração do cronômetro
volatile byte currentcounter = 0; //contador para recepção de dados
byte previouscounter = 0; //contador para recepção de dados
unsigned long currentDelay = 0; //valor de tempo atual para ArtNet e recepção E1.31

//Configuração Ethernet
byte mac[] = {0x00, 0xDD, 0xEE, 0x01, 0x10, 0x90};
IPAddress ip(192, 168, 0, 100); //Endereço IP do escudo Ethernet

// buffer to hold E1.31 and Artnet data
unsigned char packetBuffer[ETHERNET_BUFFER_MAX];

// Uma instância EthernetUDP para nos permitir enviar e receber pacotes sobre UDP
// aUDP cria um soquete para uma porta Art-Net
// suUDP cria um soquete para sCAN que é unicast para o endereço IP
EthernetUDP aUDP;
EthernetUDP suUDP;

void setup()
{
pinMode(STATUS_LED, OUTPUT); //LED de status de inicialização
pinMode(SDCARD_CONTROL, OUTPUT); //Inicialize o pino 4
digitalWrite(SDCARD_CONTROL, HIGH); //Defina o pino 4 para alto, pois não estamos usando a interface do cartão SD
for(int a = 0; a < NUM_RELAYS; a++) //loop para inicializar pinos de controle de relé
{
pinMode(Relay[a], OUTPUT); //inicializar pinos de saída de relé
digitalWrite(Relay[a], LOW); //defina os pinos para alto para desligar
}
Ethernet.begin(mac,ip); //Inicializar escudo Ethernet
aUDP.begin(ARTNET_PORT); //Abra a porta Artnet
suUDP.begin(E131_PORT); //Abra a porta E1.31
Serial.begin(9600); //Serial para depuração
POST(); //Execute a função de autoteste ao ligar
Serial.println("Setup Complete"); //impressão completa
}

/* artDMXReceived verifica o universo e a sub-rede, em seguida
envia os dados para os relés */

void artDMXReceived(unsigned char* pbuff)
{
if ( (pbuff[14] & 0xF) == ARTNET_UNIVERSE )
{
if ( (pbuff[14] >> 8) == ARTNET_SUBNET )
{
channel = 0; //redefinir o deslocamento do canal para 0 a cada vez através do loop
//loop liga / desliga o relé com base no valor do canal, começando no endereço inicial Artnet
for(int b = 0; b < NUM_RELAYS; b++)
{
if(pbuff[ARTNET_START_ADDRESS + channel] > 127) //se o valor do canal for maior que 127
{
digitalWrite(Relay[b], HIGH); //ligar relé
}
else
{
digitalWrite(Relay[b], LOW); //senão desligue
}
channel++; //aumentar o deslocamento do canal em 1 a cada vez por meio do loop
}
}
}
} //fim artDM recebido

/* artNetOpCode verifica se o pacote é realmente Art-Net
e retorna o opcode informando que tipo de mensagem Art-Net é. */

int artNetOpCode(unsigned char* pbuff)
{
String test = String((char*)pbuff);
if ( test.equals("Art-Net") )
{
if ( pbuff[11] >= 14 )
{ //versão do protocolo [10] hi byte [11] lo byte
return pbuff[9] *256 + pbuff[8]; //opcode lo byte first
}
}

return 0;
}

/* sacnDMXReceived verifica o universo e a sub-rede, em seguida
envia os dados para relés */

void sacnDMXReceived(unsigned char* pbuff, int count)
{
if ( pbuff[113] == E131_SUBNET )
{
int addressOffset = 125; //primeiros 125 bytes do pacote são informações de cabeçalho
if ( pbuff[addressOffset] == 0 ) //o código inicial deve ser 0
{
channel = 0; //redefinir o deslocamento do canal para 0 a cada vez através do loop
//loop liga / desliga o relé com base no valor do canal, começando no endereço inicial E1.31
for(int c = 0; c < NUM_RELAYS; c++)
{
if(pbuff[E131_START_ADDRESS + channel] > 127) //se o valor do canal for maior que 127
{
digitalWrite(Relay[c], HIGH); //ligar relé
}
else
{
digitalWrite(Relay[c], LOW); //desligue o relé
}
channel++; //incrementar o deslocamento do canal em 1
}
}
}
} //fim sacnDMXReceived



//verifica se o pacote é de dados E1.31
int checkACNHeaders(unsigned char* messagein, int messagelength)
{
if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37)
{
int addresscount = messagein[123] * 256 + messagein[124]; // número de valores mais o código inicial
return addresscount -1; //Retorne quantos valores estão no pacote.
}
return 0;
}

/************************************************************************
O loop principal verifica e lê os pacotes das duas ethernet UDP
conexões de soquete. Quando um pacote é recebido, ele é verificado para ver se
é válido e então uma das funções DMXReceived é chamada, enviando
os valores DMX para a saída. Também há um temporizador para executar um modo de espera
programa se nenhum dado for recebido por 30 segundos.
*************************************************************************/

void loop()
{
if(currentcounter != previouscounter) //o valor mudou?
{
currentDelay = millis(); //armazene o tempo desde que o valor aumentou
previouscounter = currentcounter; //defina o valor anterior igual ao valor atual
}

if(millis() - currentDelay > 30000) //o tempo desde a alteração do valor é superior a 30 segundos?
{
digitalWrite(STATUS_LED, HIGH); //desligue o LED. Não recebendo E1.31 ou ArtNet.
}

// primeiro verifique se um pacote está disponível na porta Art-Net
int packetSize = aUDP.parsePacket();
if( packetSize )
{
aUDP.read(packetBuffer, ETHERNET_BUFFER_MAX);
/* after reading the packet into the buffer, check to make sure
que é um pacote Art-Net e recupera o opcode que
diz que tipo de mensagem é */
int opcode = artNetOpCode(packetBuffer);
if ( opcode == ARTNET_ARTDMX )
{
Serial.println("ArtNet Packet Received");
artDMXReceived(packetBuffer);
currentcounter++; //aumentar o contador em 1 cada vez através
digitalWrite(STATUS_LED, HIGH); //ligue o LED de status
}
}
else
{
/* então, se ainda não houver pacote, verifique se um pacote
está disponível na porta unicastcast sACN */
packetSize = suUDP.parsePacket();
if( packetSize )
{
suUDP.read(packetBuffer, ETHERNET_BUFFER_MAX);
/* depois de ler o pacote no buffer, verifique se
que é um pacote sACN válido.*/
int count = checkACNHeaders(packetBuffer, packetSize);
if ( count )
{
Serial.println("E131 Packet Received");
sacnDMXReceived(packetBuffer, count);
currentcounter++; //aumentar o contador em 1 cada vez através
digitalWrite(STATUS_LED, LOW); //ligue o LED de status
}
}

}

} //Loop final

//Ligue a função de autoteste para verificar se tudo está conectado corretamente.
void POST()
{
digitalWrite(Relay[0], HIGH);
delay(1000);
digitalWrite(Relay[0], LOW);
digitalWrite(Relay[1], HIGH);
delay(1000);
digitalWrite(Relay[1], LOW);
digitalWrite(Relay[2], HIGH);
delay(1000);
digitalWrite(Relay[2], LOW);
digitalWrite(Relay[3], HIGH);
delay(1000);
digitalWrite(Relay[3], LOW);
digitalWrite(Relay[5], HIGH);
delay(1000);
digitalWrite(Relay[5], LOW);
digitalWrite(Relay[6], HIGH);
delay(1000);
digitalWrite(Relay[6], LOW);
digitalWrite(Relay[7], HIGH);
delay(1000);
digitalWrite(Relay[7], LOW);
digitalWrite(Relay[8], HIGH);
delay(1000);
digitalWrite(Relay[8], LOW);
Serial.println("POST Completo");
}
 

TANSA

Sparky with Blinky Lights ;-)
Generous elf
Joined
Dec 9, 2019
Messages
177
Location
Bentley Park
I am not that good at coding (Novice really)
But it is standard practice in the world of flashing lights, to keep everything on static IP's so you can easily find it and so you don't have to keep changing setting in the program that sending the data out.
 

Varley Gianini

Varley Gianini
Joined
Jan 13, 2020
Messages
4
Location
Pompeia - SP
I am not that good at coding (Novice really)
But it is standard practice in the world of flashing lights, to keep everything on static IP's so you can easily find it and so you don't have to keep changing setting in the program that sending the data out.

Yes, everyone is using IP communication, in my case I would like to add buttons to change the IP without having to connect a USB cable to the computer and send the code to the Arduino.
 

Mark_M

Annoying Elf
Joined
Dec 30, 2018
Messages
918
Location
Christmas Light world
I would like to add buttons to change the IP without having to connect a USB cable to the computer and send the code to the Arduino.
That will be a challenge. You will need an extra device to store the IP address settings. As far as I'm aware; it is hard to write a variable into the Arduino that will save when it is powered off.

As to @SAALTFAM 's comment, this is more trouble than it is worth. Your controllers should be on a static IP address anyway. You only need your computer once to change the IP address.
 
Last edited:

TANSA

Sparky with Blinky Lights ;-)
Generous elf
Joined
Dec 9, 2019
Messages
177
Location
Bentley Park
Varley the only way I can think of is to store the IP in the EEPROM, but I have heard that it can shorten the life of it.
I have never done this so I cannot comment more than that.
Happy coding.
 

Varley Gianini

Varley Gianini
Joined
Jan 13, 2020
Messages
4
Location
Pompeia - SP
Good evening everyone! understand, good for now so I will leave it for a next opportunity to do this, I thank you all for the answers, Thank you very much colleagues.
 

Barnabybear

New elf
Joined
Mar 30, 2012
Messages
42
Location
UK
Hi, as pointed out in previous posts this is possible, the user interface is quite long and gets a bit complicated particularly if you are converting HEX values in to DECIMAL to display on the screen. With regards to the eeprom it only degrades when written too, reading is not an issue if you use the ‘EEPROM.read()’ command.

Below is a video of the way this works – it is not a video of this code (sorry don’t have one online) but it will give you an idea of what is going on.


In the code below:

If a button is pressed at powerup it jumps into a user interface loop.

Displays the current values stored in eeprom.

Using two buttons the values can be changed as required.

These are then saved to eeprom.

When next powered the ‘new values’ will be used.

The code is not for the unit in the video but does a similar thing, it is posted in two parts as a large irrelevant section in the middle has been omitted. Hopefully this will give you some ideas.

Code:
#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SSD1306_128_32
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);


// variables for screen and menu
int screen_position = 0; // button a postion.
int A_100 = 0; // value for 100s digit.
int A_10 = 0; // value for 10s digit.
int A_1 = 0; // value for 1s digit.
int B_100 = 0; // value for 100s digit.
int B_10 = 0; // value for 10s digit.
int B_1 = 0; // value for 1s digit.
int A_eeprom; // stored pixel value.
int B_eeprom; // stored pixel value.
int button_1 = 12; // button pin.
int button_2 = 11; // button pin.
int screen_short = 8; // screen detect pin.

// variables.
int count_A; 
int count_B;


void setup() {
  solid_led(); // sets onboard LED on.
  // read previously set values
  A_eeprom = ((EEPROM.read(0) * 256) + EEPROM.read(1)); // read eeprom.
  B_eeprom = ((EEPROM.read(2) * 256) + EEPROM.read(3)); // read eeprom.
  count_A = ((A_eeprom * 24) - 1);
  count_B = (((A_eeprom + B_eeprom) * 24) - 1);

  //  setup and menu if button pressed at power up.
  pinMode(button_2, INPUT_PULLUP); // set button input with pullup.
  delay(1);
  if (digitalRead(button_2) == LOW) { // check if pin is low - screen connected.
    pinMode(button_1, INPUT_PULLUP); // set button input with pullup.
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // start oled instance.
    display.clearDisplay(); // clear display.
    display.setTextSize(2); // set text size to 2.
    display.setTextColor(WHITE); // set text colour to white.
    A_100 = A_eeprom / 100; // calculate 100s digit.
    A_eeprom -= A_100 * 100; // subtract 100s digit.
    A_10 = A_eeprom / 10; // calculate 10s digit.
    A_eeprom -= A_10 * 10; // subtract 10s digit.
    A_1 = A_eeprom; // calculate 1s digit.
    B_100 = B_eeprom / 100; // calculate 100s digit.
    B_eeprom -= B_100 * 100; // subtract 100s digit.
    B_10 = B_eeprom / 10; // calculate 10s digit.
    B_eeprom -= B_10 * 10; // subtract 10s digit.
    B_1 = B_eeprom; // calculate 1s digit.
    pix_num_find(); // run the menu function.
  }
Code:
// all below here is menu and screen functions only called if screen fitted.
void pix_num_find() { // the menu function.
  for (;;) { // start endless loop.
    if (digitalRead(button_1) == LOW) screen_position++; // if button 'a' pressed increment position.
    if (screen_position > 7) screen_position = 1; // if at end of menu goto start.
    switch (screen_position) { // switch dependant on button 'a' value.
      case 0:
        display.clearDisplay(); // clear display.
        display.setCursor(0, 0); // set curser to line 0 left position.
        display.print("Renard"); // text to print on screen.
        display.setCursor(25, 16); // set curser to line 2 left position.
        display.print("PLUS 0.4"); // text to print on screen.
        display.display(); // update screen and display new text.
        delay(1000); // delay.
        break; // back to the start and do it all again.

      case 1:
        if (digitalRead(button_2) == LOW) A_100++; // if button 'b' pressed increment 100s value.
        if (A_100 > 9) A_100 = 0; // if value more than 9 set back to 0.
        set_screen(); // function to update screen with new values.
        delay(500); // delay.
        flash_screen_1(); // a screen update with the current digit masked out.
        delay(500); // delay.
        break; // back to the start and do it all again.

      case 2:
        if (digitalRead(button_2) == LOW) A_10++;
        if (A_10 > 9) A_10 = 0;
        set_screen();
        delay(500);
        flash_screen_2();
        delay(500);
        break;

      case 3:
        if (digitalRead(button_2) == LOW) A_1++;
        if (A_1 > 9) A_1 = 0;
        set_screen();
        delay(500);
        flash_screen_3();
        delay(500);
        break;

      case 4:
        if (digitalRead(button_2) == LOW) B_100++;
        if (B_100 > 9) B_100 = 0;
        set_screen();
        delay(500);
        flash_screen_4();
        delay(500);
        break;

      case 5:
        if (digitalRead(button_2) == LOW) B_10++;
        if (B_10 > 9) B_10 = 0;
        set_screen();
        delay(500);
        flash_screen_5();
        delay(500);
        break;

      case 6:
        if (digitalRead(button_2) == LOW) B_1++;
        if (B_1 > 9) B_1 = 0;
        set_screen();
        delay(500);
        flash_screen_6();
        delay(500);
        break;

      case 7: // the save values bit of the menu.
        if (digitalRead(button_2) == LOW) { // if button 'b' pressed to save.
          // add up 100s + 10s + 1s to gat a decimal value.
          EEPROM.update(0, ((A_100 * 100) + (A_10 * 10) + A_1 >> 8)); // write to eeprom bits [15:8].
          EEPROM.update(1, ((A_100 * 100) + (A_10 * 10) + A_1)); // write to eeprom bits [7:0].
          EEPROM.update(2, ((B_100 * 100) + (B_10 * 10) + B_1 >> 8)); // write to eeprom bits [15:8].
          EEPROM.update(3, ((B_100 * 100) + (B_10 * 10) + B_1)); // write to eeprom bits [7:0].
          delay(500); // delay
          display.clearDisplay(); // clear display.
          display.setCursor(0, 0); display.print("A now "); // set cursor and print text.
          display.print((EEPROM.read(0) * 256) + EEPROM.read(1)); // read eeprom and convert to decimal number.
          display.setCursor(0, 16); display.print("B now "); // set cursor and print text.
          display.print((EEPROM.read(2) * 256) + EEPROM.read(3)); // read eeprom and convert to decimal number.
          display.display(); // update display.
          screen_position = 1; // reset menu position to start.
          delay(5000); // delay.
          break; // back to the start and do it all again.
        }
        display.clearDisplay(); // if button 'b' not pressed.
        display.setCursor(0, 0); display.print("Set val's?"); // set cursor and print text.
        display.setCursor(0, 16); display.print((A_100 * 100) + (A_10 * 10) + A_1); // set cursor and calculate value as digits.
        display.print(" & "); display.print((B_100 * 100) + (B_10 * 10) + B_1); // set cursor and calculate value as decimal digits.
        display.display(); // update display.
        delay(1000); // delay.
        break; // back to the start and do it all again.
    }
  }
}
void set_screen() {
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0, 0); display.print("OutA = "); display.print(A_100); display.print(A_10); display.print(A_1);
  display.setCursor(0, 16); display.print("OutB = "); display.print(B_100); display.print(B_10); display.print(B_1);
  display.display();
}

void flash_screen_1() {
  display.clearDisplay();
  display.setCursor(0, 0); display.print("OutA = "); display.print(" "); display.print(A_10); display.print(A_1);
  display.setCursor(0, 16); display.print("OutB = "); display.print(B_100); display.print(B_10); display.print(B_1);
  display.display();
}

void flash_screen_2() {
  display.clearDisplay();
  display.setCursor(0, 0); display.print("OutA = "); display.print(A_100); display.print(" "); display.print(A_1);
  display.setCursor(0, 16); display.print("OutB = "); display.print(B_100); display.print(B_10); display.print(B_1);
  display.display();
}

void flash_screen_3() {
  display.clearDisplay();
  display.setCursor(0, 0); display.print("OutA = "); display.print(A_100); display.print(A_10); display.print(" ");
  display.setCursor(0, 16); display.print("OutB = "); display.print(B_100); display.print(B_10); display.print(B_1);
  display.display();
}

void flash_screen_4() {
  display.clearDisplay();
  display.setCursor(0, 0); display.print("OutA = "); display.print(A_100); display.print(A_10); display.print(A_1);
  display.setCursor(0, 16); display.print("OutB = "); display.print(" "); display.print(B_10); display.print(B_1);
  display.display();
}

void flash_screen_5() {
  display.clearDisplay();
  display.setCursor(0, 0); display.print("OutA = "); display.print(A_100); display.print(A_10); display.print(A_1);
  display.setCursor(0, 16); display.print("OutB = "); display.print(B_100); display.print(" "); display.print(B_1);
  display.display();
}

void flash_screen_6() {
  display.clearDisplay();
  display.setCursor(0, 0); display.print("OutA = "); display.print(A_100); display.print(A_10); display.print(A_1);
  display.setCursor(0, 16); display.print("OutB = "); display.print(B_100); display.print(B_10); display.print(" ");
  display.display();
}

void solid_led() {
  DDRB = DDRB | B00100000; // set port B [5] as output
  delayMicroseconds(1);
  PORTB = PORTB | B00100000; // set port B [5] high
  delay(1000);
}
void loop() {
  // put your main code here, to run repeatedly:
}
 
Top