Ethernet Nano MQTT Dimmer

I have this MQTT dimmer project using an arduino Nano/ENC28j69 ethernet shield and I have come to an impass, just finding it hard to work out what is going on.
I have it connected to my Broker and I am recieving strPayload, if I adjust the brightness on my Broker.
If I uncomment any of the lines of code marked "THIS LINE" it fails to connect to the Broker. I think if I can utilise these lines I may be able to use the srcPayload number to turn into a useful action. Is anyone out there with any knowledge of this and can point me in the right direction. There is suprisingly little pointers on the net.- Code

#include <EthernetENC.h>
#include <PubSubClient.h>
#include <RBDdimmer.h>
#include <SPI.h>
#include  <TimerOne.h>

#define outputPin1 3 // from pin 2 nano to pin marked PSM on robot dyn module
#define zerocross  2 // from pin 2 nano to pin marked z-c on robot dyn module

unsigned long hammertime = 30; // used fo millis timig
byte mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //mac address
byte ip[] = {192, 168, 1, 128 }; // fixed ip on lan
const char* mqtt_server = "192.168.1.256";
const char* mqttUser = "user";
const char* mqttPassword = "pass";

volatile int i = 0;             // Variable to use as a counter volatile as it is in an interrupt
volatile boolean zero_cross = 0; // Boolean to store a "switch" to tell us if we have crossed zero

int updateInterval = 4000; // Interval in milliseconds
int dim1 = 0;  // Dimming level (0-100)  0 = on, 100 = 0ff
int dim_actual = 0;

int inc = 1;                    // counting up or down, 1=up, -1=down
int freqStep = 100;

dimmerLamp dimmer_1(outputPin1);

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient espClient;
PubSubClient client(espClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("nano1", mqttUser, mqttPassword)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }

}
void zero_cross_detect() {
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i = 0;
  digitalWrite(outputPin1, LOW);       // turn off TRIAC (and AC)
}

// Turn on the TRIAC at the appropriate time
void dim_check() {
  if (zero_cross == true) {
    if (i >= dim1) {
      digitalWrite(outputPin1, HIGH); // turn on light
      i = 0; // reset time step counter
      zero_cross = false; //reset zero cross detection
    }
    else {
      i++; // increment time step counter
    }
  }
}
void setup()  {
  // attachInterrupt(0, zero_cross_detect, RISING); // THIS LINE   // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);
  pinMode(2, OUTPUT);

  Serial.begin(9600);
  delay(100);
  Ethernet.begin(mac, ip);
  client.setServer(mqtt_server, 1883);
  client.setKeepAlive( 90 );
  client.setCallback(callback);
  dimmer_1.begin (NORMAL_MODE, ON);
  dimmer_1.setPower(50);
  client.subscribe("lgt1_command");
  client.publish("lgt1_state", "Dimmer1 connected");

}
//Callback function. Checks payload and update variable "dim1" with the value from mqtt.
void callback(char* topic, byte* Payload, unsigned int length) {
  char msgBuffer[40];
  Payload[length] = '\0';            // terminate string with '0'
  String strPayload = String((char*)Payload);  // convert to string
  Serial.print("strPayload =  ");
  Serial.println(strPayload); //can use this if using longer southbound topics
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");//MQTT_BROKER
  for (int i = 0; i < length; i++)
    Serial.print((char)Payload[i]);
  Serial.println();
  Serial.println(Payload[0]);
  dim1 = strPayload.toInt();

}
void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (millis() - hammertime > updateInterval)
  { hammertime = millis();

    delay(50);

    //if (dim1 != dim_actual)  // THIS LINE
    dimmer_1.setPower(dim1);   // THIS LINE
    // delay(1000);
    dim_actual = dim1;
    char msgBuffer2[20];
    itoa(dim1, msgBuffer2, 10);
    client.subscribe("lgt1_brightness_command");
    client.publish("lgt1_brightness", msgBuffer2);

  }
}

can you upload a text copy (not screen image) of the serial monitor output during a run of the program which shows the problem you have

void callback(char* topic, byte* Payload, unsigned int length)
{
  char msgBuffer[40];
  Payload[length] = '\0';            // terminate string with '0'

I am not sure that this is a good idea

Suppose that the Payload array is 22 characters in length then its array index values will be 0 to 21 but you are setting Payload[22], which does not exist, to '\0' and are probably writing to memory used by another variable

This is my favourite way of extracting the payload as a C style string

void callback(char* topic, byte* payload, unsigned int length)
{
    char message[50];
    memcpy(message, payload, length);  // copy the payload
    message[length] = '\0';            // turn it into a string

many thanks again I have done as you sugested and I sure it is an improvement but the code will not allow me to uncomment marked as "THIS LINE". all the best

many thanks Horace here is a printout from the serial -
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...connected
strPayload =
Message arrived [lgt1_brightness_command] 140
49
strPayload =
Message arrived [lgt1_brightness_command] 84
56
strPayload =
Message arrived [lgt1_brightness_command] 38
51
strPayload =
Message arrived [lgt1_brightness_command] 252
50

you appear to be receiving data from your MQTT broker - is it correct?
can you call

dimmer_1.setPower(dim1); 

in the callback() routine
if you are passing dim1 to loop() you should declare it volatile or the optimiser may throw statements away, e.g.

volatile int dim1 = 0;  // Dimming level (0-100)  0 = on, 100 = 0ff

Please post your code as it is now if you have changed it to use my method to convert the payload into a C style string

this is updated code still working on compile error 'message was not declared in this scope'

#include <EthernetENC.h>
#include <PubSubClient.h>
#include <RBDdimmer.h>
#include <SPI.h>
#include  <TimerOne.h>

#define outputPin1 3 // from pin 3 nano to pin marked PSM on robot dyn module
#define zerocross  2 // from pin 2 nano to pin marked z-c on robot dyn module

unsigned long hammertime = 30; // used fo millis timig
byte mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //mac address
byte ip[] = {192, 168, 1, 128 }; // fixed ip on lan
const char* mqtt_server = "192.168.1.200";
const char* mqttUser = "user";
const char* mqttPassword = "pass";

volatile int i = 0;             // Variable to use as a counter volatile as it is in an interrupt
volatile boolean zero_cross = 0; // Boolean to store a "switch" to tell us if we have crossed zero

int updateInterval = 4000; // Interval in milliseconds
int dim1 = 0;  // Dimming level (0-100)  0 = on, 100 = 0ff
int dim_actual = 0;

int inc = 1;                    // counting up or down, 1=up, -1=down
int freqStep = 100;

dimmerLamp dimmer_1(outputPin1);

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient espClient;
PubSubClient client(espClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("nano1", mqttUser, mqttPassword)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }

}
void zero_cross_detect() {
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i = 0;
  digitalWrite(outputPin1, LOW);       // turn off TRIAC (and AC)
}

// Turn on the TRIAC at the appropriate time
void dim_check() {
  if (zero_cross == true) {
    if (i >= dim1) {
      digitalWrite(outputPin1, HIGH); // turn on light
      i = 0; // reset time step counter
      zero_cross = false; //reset zero cross detection
    }
    else {
      i++; // increment time step counter
    }
  }
}
void setup()  {
  // attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);
  pinMode(2, OUTPUT);

  Serial.begin(9600);
  delay(100);
  Ethernet.begin(mac, ip);
  client.setServer(mqtt_server, 1883);
  client.setKeepAlive( 90 );
  client.setCallback(callback);
  dimmer_1.begin (NORMAL_MODE, ON);
  dimmer_1.setPower(50);
  client.subscribe("lgt1_command");
  client.publish("lgt1_state", "Dimmer1 connected");

}
//Callback function. Checks payload and update variable "dim1" with the value from mqtt.
void callback(char* topic, byte* Payload, unsigned int length) {
  //char msgBuffer[40];
  char message[50];
  memcpy(message, Payload, length);  // copy the payload
  message[length] = '\0';            // turn it into a string
  //Payload[length] = '\0';            // terminate string with '0'
  String strPayload = String((char*)Payload);  // convert to string
  Serial.print("strPayload =  ");
  Serial.println(strPayload); //can use this if using longer southbound topics
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");//MQTT_BROKER
  for (int i = 0; i < length; i++)
    Serial.print((char)Payload[i]);
  Serial.println();
  Serial.println(Payload[0]);
  //dim1 = strPayload.toInt();
  volatile int dim1 = 0;
}
void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (millis() - hammertime > updateInterval)
  { hammertime = millis();

    delay(50);

    //if (dim1 != dim_actual)
    //dimmer_1.setPower(dim1);
    // delay(1000);
    //dim_actual = dim1;
    char msgBuffer2[20];
    //itoa(dim1, msgBuffer2, 10);
    itoa(dim1, message, 10);
    client.subscribe("lgt1_brightness_command");
    client.publish("lgt1_brightness", msgBuffer2);

  }
}

The message array is declared in the callback() function so you cannot access it in loop()

Declare it as global for a quick fix

you have defined

volatile int dim1 = 0;

global and in callback () (makeing it local)
remove the volatile int in callback()

Thank you Horace and helibob
I ran into too many errors ititially so I made a fresh start at implimenting your sugestions and got it to compile with nor errors.
I have maked with "CHANGE1" where I have changed the code.
Again I can send from broker and it is recieved in serial. But if I do try and un-comment

//if (dim1 != dim_actual)
    //dimmer_1.setPower(dim1);
    // delay(1000);
    //dim_actual = dim1;

It fails to connect with broker
Here is code with changes so far

#include <EthernetENC.h>
#include <PubSubClient.h>
#include <RBDdimmer.h>
#include <SPI.h>
#include  <TimerOne.h>

#define outputPin1 3 // from pin 2 nano to pin marked PSM on robot dyn module
#define zerocross  2 // from pin 2 nano to pin marked z-c on robot dyn module

unsigned long hammertime = 30; // used fo millis timig
byte mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //mac address
byte ip[] = {192, 168, 1, 256 }; // fixed ip on lan
const char* mqtt_server = "192.168.1.128";
const char* mqttUser = "user";
const char* mqttPassword = "pass";

volatile int i = 0;             // Variable to use as a counter volatile as it is in an interrupt
volatile boolean zero_cross = 0; // Boolean to store a "switch" to tell us if we have crossed zero

int updateInterval = 4000; // Interval in milliseconds
volatile int dim1 = 0;  // Dimming level (0-100)  0 = on, 100 = 0ff //CHANGE1
int dim_actual = 0;

int inc = 1;                    // counting up or down, 1=up, -1=down
int freqStep = 100;

dimmerLamp dimmer_1(outputPin1);

// Callback function header
void callback(char* topic, byte* Payload, unsigned int length);//CHANGE1

EthernetClient espClient;
PubSubClient client(espClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("nano1", mqttUser, mqttPassword)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }

}
void zero_cross_detect() {
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i = 0;
  digitalWrite(outputPin1, LOW);       // turn off TRIAC (and AC)
}

// Turn on the TRIAC at the appropriate time
void dim_check() {
  if (zero_cross == true) {
    if (i >= dim1) {
      digitalWrite(outputPin1, HIGH); // turn on light
      i = 0; // reset time step counter
      zero_cross = false; //reset zero cross detection
    }
    else {
      i++; // increment time step counter
    }
  }
}
void setup()  {
  // attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);
  pinMode(2, OUTPUT);         //CHANGE1

  Serial.begin(9600);
  delay(100);
  Ethernet.begin(mac, ip);
  client.setServer(mqtt_server, 1883);
  client.setKeepAlive( 90 );
  client.setCallback(callback);
  dimmer_1.begin (NORMAL_MODE, ON);
  dimmer_1.setPower(50);
  client.subscribe("lgt1_command");
  client.publish("lgt1_state", "Dimmer1 connected");

}
//Callback function. Checks payload and update variable "dim1" with the value from mqtt.
void callback(char* topic, byte* Payload, unsigned int length) {
  char msgBuffer[50];                //CHANGE1
  memcpy(msgBuffer, Payload, length);  // copy the payload    //CHANGE1
  msgBuffer[length] = '\0';            // turn it into a string    //CHANGE1

  //char msgBuffer[40];
  //Payload[length] = '\0';            // terminate string with '0'
  String strPayload = String((char*)Payload);  // convert to string
  Serial.print("strPayload =  ");
  Serial.println(strPayload); //can use this if using longer southbound topics
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");//MQTT_BROKER
  for (int i = 0; i < length; i++)
    Serial.print((char)Payload[i]);
  Serial.println();
  Serial.println(Payload[0]);
  dim1 = strPayload.toInt();

}
void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (millis() - hammertime > updateInterval)
  { hammertime = millis();

    delay(50);

    //if (dim1 != dim_actual)
    //dimmer_1.setPower(dim1);
    // delay(1000);
    //dim_actual = dim1;
    char msgBuffer[50];  //CHANGE1
    itoa(dim1, msgBuffer, 10);  //CHANGE1
    client.subscribe("lgt1_brightness_command");  
    client.publish("lgt1_brightness", msgBuffer);  //CHANGE1


  }
}

Unless/until it connects then nothing much else matters as long as the code compiles

Which broker are you using locally ?
Are you sure that it is running ?
Are you sure that its IP address is correct ?

void loop()
{
  if (!client.connected()) {
    reconnect();
  } else
{ serial.println( "connected");}





delay(50);

    if (dim1 != dim_actual)
{
    dimmer_1.setPower(dim1);
    delay(1000);
    dim_actual = dim1;
    }
char msgBuffer[50];  //CHANGE1

Well that can be proved. Does it print connected with the code uncommented?

I am using Home assistant locally and it is stable and been running for about a year, the ip is correct, I just change it when I post the code.
The Nano does connect with broker and I can see on the logs of the broker. It does recieve dimmer inputs that I do on home assistant as the code is but if I un comment any of those lines in the loop the Nano fails to connect. It is so strange as it will complie OK. Thanks again

noted that callback() is using the String class - not recommended on a micro with limited SRAM such as the Nano - memory can become fragmented and give unpredictable results

I have added extra lines (marked "CHANGE2")to the loop and it is still connected to broker, but still stuck if I uncomment out those other lines. The light bulb I have hooked up to my testing setup is now being randomly triggered its like a disco in here, This I think has something do to with the zero crossing routine, I am unable to comple if I uncomment out

void setup()  {
  //attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection

the code in the loop changes2

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (millis() - hammertime > updateInterval)
  { hammertime = millis();

    delay(50);

    //if (dim1 != dim_actual)
    //dimmer_1.setPower(dim1);
    // delay(1000);
    dim_actual = dim1;//CHANGE2
    zero_cross_detect();//CHANGE2
    dim_check();//CHANGE2
    char msgBuffer[50];  
    itoa(dim1, msgBuffer, 10);  
    client.subscribe("lgt1_brightness_command");  
    client.publish("lgt1_brightness", msgBuffer);  

Thanks Horace I will give it some thought

So you are indicating that the Serial prints continue to print out but the code in loop() is not running? How can the program be stuck when the program keeps on printing? Perhaps you mean to use another word besides "stuck"? Could you restate your issue and not use the word "stuck" with your restatement? Could you better describe the problem?

If you make this change

Serial.println(" A ");
  if (dim1 != dim_actual)
{
dimmer_1.setPower(dim1);
   delay(1000);
}
 Serial.println( "B");

is it still stuck?

Stuck would be that it prints A but not B.

Thanks, Idahowalker I thought, great this may shed some light on the problem. I have done as you suggested, unfortunately the serial prints neither A or B and the connection with the broker stops working. I have tried this a couple of times to make sure.

Before I inserted your code, the program runs and connects to the broker but for some reason as soon as I make if (dim1 != dim_actual) available in the loop or your suggestion, the program appears to freeze even though it compiles without errors. Thanks again

try this version of callbnack() with String removed

//Callback function. Checks payload and update variable "dim1" with the value from mqtt.
void callback(char* topic, byte* Payload, unsigned int length) {
  //char msgBuffer[50];                //CHANGE1
  //memcpy(msgBuffer, Payload, length);  // copy the payload    //CHANGE1
  //msgBuffer[length] = '\0';            // turn it into a string    //CHANGE1

  //char msgBuffer[40];
  //Payload[length] = '\0';            // terminate string with '0'
  //String strPayload = String((char*)Payload);  // convert to string
  //Serial.print("strPayload =  ");
 // Serial.println(Payload); //can use this if using longer southbound topics
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");//MQTT_BROKER
  for (int i = 0; i < length; i++)
    Serial.print((char)Payload[i]);
  Serial.println();
 // Serial.println(Payload[0]);
  dim1 = atoi(Payload);//strPayload.toInt();

}

noted when building the Nano memory usage is reported as

Sketch uses 22918 bytes (74%) of program storage space. Maximum is 30720 bytes.
Global variables use 1516 bytes (74%) of dynamic memory, leaving 532 bytes for local variables. Maximum is 2048 bytes.

don't know how much SRAM ethernet, MQTT, etc uses but you could be running of memory for local variables