Please help me understand this behavior

Can someone please help me to understand why the arduino nano with atmega328P behaves in the way I am about to describe:

Here is the code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

int state_override;

#define UI_IX_SET 0
#define UI_IX_RUN 2
#define UI_IX_JOG 1
#define UI_FUNC_LEN 2

#define CNC_RLY_OUT_PIN 12
//
//#define MODE_SET 2
//#define MODE_RUN 1
//#define MODE_JOG 3
//int display_mode;

//Stepper constants and variables
#define PULSE_OUT_PIN 2
#define DIR_OUT_PIN 3

//Plasma Cutter constants and variables
#define START_IN_PIN 4
#define MOVE_IN_PIN 5

int start_signal;
int move_signal;

//THC Constants and variables

#define STATE_IDLE 0
#define STATE_PIERCE 1
#define STATE_CUT 2
#define STATE_SET 3
#define STATE_JOG 4
#define STATE_UNKNOWN -1
#define VOLTAGE_DIVIDER 50

#define DISPLAY_REFRESH_RATE 20
#define DISPLAY_I2C_ADDR 0x27

const int target_voltage = 85;
long read_voltage;
int status_enable = 1;

//
// Management of LCD
//
LiquidCrystal_I2C lcd(DISPLAY_I2C_ADDR, 16, 2);
void init_lcd() {
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(4, 0);
}

char ui_line1[16];
char ui_line2[16];

void paint_display() {
  lcd.setCursor(0, 0);
  lcd.print(ui_line1);
  lcd.setCursor(0, 1);
  lcd.print(ui_line2);
}


#define RL_ST_ON 1
#define RL_ST_OFF 0

class Relay {
  public:
    int state = -1;
    int pin = -1;

    void init(int pin_no) {
      this->pin = pin_no;
      pinMode(this->pin, OUTPUT);
      this->state = digitalRead(this->pin);
    }

    void on(const char * call) {
      if (this->state != RL_ST_ON) {
        log(1, call);
        this->state = RL_ST_ON;
        digitalWrite(this->pin, HIGH);
      }
    }

    void off(const char * call) {
      if (this->state != RL_ST_OFF) {

        log(0, call);
        this->state = RL_ST_OFF;
        digitalWrite(this->pin, LOW);
      }
    }

    void log(int s, char * c) {
      char b[32];
      sprintf(b, "[RELAY %d] %s", s, c);
      Serial.println(b);
    }

    int get_state() {
      return this->state;
    }

};

Relay relay;


class TTYTerminal {
  public:
    int cmd_i = 0;
    int input_rec = 0;
    char command[128];
    char tty_command[128];

    void receive() {
      char input;

      while (Serial.available()) {
        input = (char)Serial.read();
        if (input != '\n') {
          command[cmd_i] = input;
          cmd_i++;
          command[cmd_i] = '\0';
        } else {
          sprintf(tty_command, "%s", command);
          cmd_i = 0;
          sprintf(command, "");
          input_rec = 1;
        }
      }
    }

    void process(void function(char *)) {
      if (this->input_rec == 1) {
        this->input_rec = 0;
        function(this->tty_command);
      }
    }
};

TTYTerminal terminal;

class Signal {
  public:
    static const int MODE_DEFER = 0;
    static const int MODE_PULSE = 1;
    static const int MODE_UNTIL = 2;
    static const int MODE_PAUSE = 3;

    static const int LOOP_BOUND = 10;
    static const int LOOP_END = 30;

    long steps = 0;
    int mode = 0;
    int dir = 0;
    int toggle = 0;
    int activate = 0;
    int r_dir = 0;
    long trajectory = 0;
    int until_active = 0;

    int limit = 0;
    long limit_cnt = 0;
    int enable_sr = 1;

    void process() {


      if (this->enable_sr == 0) {
        Serial.println("SR DISABLED");
        return;
      }
int flag=2;
      switch (this->mode) {
        case 0: {
            digitalWrite(PULSE_OUT_PIN, HIGH);
            digitalWrite(DIR_OUT_PIN, LOW);
            break;
          }
        case 1:

        if(flag == 0) {
          Serial.println(0);
        }else if(flag == 1) {
          Serial.print(0);
        }else if(flag = 2) {
          
        }
       
         
          pulse_drive();
          break;
      }
    }

    void pulse_drive() {

      digitalWrite(DIR_OUT_PIN, this->dir);
      digitalWrite(PULSE_OUT_PIN, toggle);
      this->toggle = !this->toggle;

//      if (this->dir == 0) {
//        this->trajectory++;
//      } else {
//        this->trajectory--;
//      }
//      steps++;
//      report();

    }


    void until(int cycles) {
      this->until_active = 1;
      this->limit = cycles;
      this->limit_cnt = 0;
      this->mode = 2;
    }

    void set_direction(int d) {

      this->dir = d;
    }

    int get_direction() {
      return this->dir;
    }

    int get_steps() {
      return this->steps;
    }

    long get_trajectory() {
      return this->trajectory;
    }

    void set_mode(int m) {
      this->mode = m;
    }

    void enable() {
      this->enable_sr = 1;
    }

    void disable() {
      this->enable_sr = 0;
    }

    int get_enable() {
      return this->enable_sr;
    }

       int get_mode() {
      return this->mode;
    }




    void report() {
      Serial.print(this->get_trajectory());
      Serial.print(F(", "));
      Serial.print(this->get_steps());
      Serial.print(F(", "));
      Serial.print(this->get_direction());
      Serial.println();
    }
};



//
//Management of ADC
//
#define MAX_SAMPLES 25

double voltage_samples[MAX_SAMPLES];
int sample_index = 0;
int sample_count = 0;

#define ADC_I2C_ADDR 8

void add_sample(double s) {
  if (sample_index >= MAX_SAMPLES) {
    sample_index = 0;
  }
  if (sample_count >= MAX_SAMPLES) {
    sample_count = MAX_SAMPLES;
  }
  voltage_samples[sample_index++] = s;
  sample_count++;

}

Signal SR;


void init_timer() {
  cli();          // disable all interrupts

  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 8khz increments
  OCR2A = 219;// = (16*10^6) / (8000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS21 bit for 8 prescaler
  TCCR2B |= (1 << CS21);
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);

  sei();           // enable
}

int atw = 0;

ISR(TIMER2_COMPA_vect) {
  SR.process();
}

double average_voltage() {
  long acc = 0;
  int i = 0;
  for (i = 0; i < sample_count; i++) {
    acc += voltage_samples[i];
  }
  return acc / sample_count;
}

void poll_adc() {

  Wire.requestFrom(ADC_I2C_ADDR, 8, false );

  char input_c = (char) - 1;
  int idx = 0;
  char buf[12];
  while (Wire.available() && input_c != 0) {
    input_c = Wire.read();
    if (input_c != 0) {
      buf[idx++] = input_c;
    } else {
      buf[idx] = '\0';
      idx = 0;
    }
  }
  read_voltage = atof(buf);;
  add_sample(read_voltage);

}



//
//Management of switches
//
#define SW1_IN_PIN 6
#define SW2_IN_PIN 7
#define SW3_IN_PIN 8
#define SW_UP 1
#define SW_MID 2
#define SW_DOWN 3

int switch_ps = -1;
int switch_pins[] = { SW1_IN_PIN, SW2_IN_PIN, SW3_IN_PIN };
int switches[] = { SW_UP, SW_MID, SW_DOWN };

int setup_switches() {
  pinMode(SW1_IN_PIN, INPUT_PULLUP);
  pinMode(SW2_IN_PIN, INPUT_PULLUP);
  pinMode(SW3_IN_PIN, INPUT_PULLUP);
}

int prev_switch = -1;
long switch_ts = 0;
int scan_switches() {
  int i;
  for (i = 0; i < sizeof(switch_pins) / sizeof(switch_pins[0]); i++) {
    if (digitalRead(switch_pins[i]) == LOW) {
      long ts = millis();
      if (switches[i] != prev_switch && ts - switch_ts > 50) {
        prev_switch = switches[i];
        return switches[i];
      }
    } else {
      prev_switch = -1;
    }
  }
  return -1;
}


int current_state = STATE_UNKNOWN;



void setup() {
  Serial.begin(115200);
  Serial.println(F("------------- TORCH_HEIGHT_CONTROLLER v3 [THC]----------"));
  Serial.println(F("[THC] Comms Initialized."));
  relay.init(CNC_RLY_OUT_PIN);

  Wire.begin();
  Serial.println(F("[THC] I2C Bus Initialized."));
  setup_switches();

  pinMode(CNC_RLY_OUT_PIN, OUTPUT);

  pinMode(PULSE_OUT_PIN, OUTPUT);
  pinMode(DIR_OUT_PIN, OUTPUT);
  pinMode(START_IN_PIN, INPUT);
  pinMode(MOVE_IN_PIN, INPUT);
  //  pinMode(MODE_IN_PIN, INPUT);

  init_lcd();
  init_timer();

  Serial.println(F("[THC] Setup complete."));

}


void log_state(int st) {
  Serial.print(F("STATE CHANGED TO: "));
  if (st == STATE_SET) {
    Serial.println(F("STATE SET"));
  }
  if (st == STATE_JOG) {
    Serial.println(F("STATE JOG"));
  }
  if (st == STATE_IDLE) {
    Serial.println(F("IDLE"));
  }
  if (st == STATE_PIERCE) {
    Serial.println(F("PIERCE"));
  }
  if (st == STATE_CUT) {
    Serial.println(F("CUT"));
  }
  if (st == STATE_UNKNOWN) {
    Serial.println(F("UNKNOWN"));
  }
}

int current_state_pv = -1;


void get_status() {
  start_signal = digitalRead(START_IN_PIN);
  move_signal = digitalRead(MOVE_IN_PIN);

  if (status_enable == 1) {
    if (start_signal == 1 && move_signal == 1) {
      relay.on("get_status");
      current_state = STATE_CUT;
    }
    else if (start_signal == 1 && move_signal == 0) {
      relay.on("get_status");
      current_state = STATE_PIERCE;
    }
    else if (start_signal == 0 and move_signal == 0) {
      relay.off("get_status");
      current_state = STATE_IDLE;
    } else {
      relay.off("get_status");
      current_state = STATE_UNKNOWN;
      Serial.print(F("START_SIGNAL: "));
      Serial.print(start_signal);
      Serial.print(F("  MOVE_SIGNAL: "));
      Serial.println(move_signal);
    }
  }

  if (current_state != current_state_pv) {
    current_state_pv = current_state;
    log_state(current_state);
  }
  poll_adc();
}

int debug_ui = 0;

void ui_set(int sw_in) {

  switch (sw_in) {
    case SW_UP: {
        //        target_voltage++;
        break;
      }
    case SW_DOWN: {
        //        target_voltage--;
        break;
      }
    default: {

      }
  }
  sprintf(ui_line1, "SET_LINE_1");
  sprintf(ui_line2, "SET_LINE_2");
  paint_display();

}

void log_info() {
  double d = average_voltage();
  Serial.print(target_voltage);
  Serial.print(F(", "));
  Serial.print(d);
  Serial.print(F(", "));
  Serial.print(d - target_voltage);
  Serial.print(F(", "));
  Serial.print(SR.get_trajectory());
  Serial.print(F(", "));
  Serial.print(SR.get_steps());
  Serial.print(F(", "));
  Serial.print(SR.get_direction());
  Serial.println();
}

void track_torch() {
  double d = average_voltage();

  if ( d <= 75.0 ) {
    Serial.println(F(" Z"));
    relay.off("get_status");
    SR.set_mode(2);
    return;
  }

  double delta = abs(target_voltage - d);
  if (target_voltage < d && delta < 2.0 ) {
    SR.set_direction(0);
    SR.set_mode(1);
    relay.on("get_status");
  }
  else if (target_voltage > d && delta < 2.0 ) {
    SR.set_direction(1);
    SR.set_mode(1);
    relay.on("get_status");
  }
  else {
    relay.off("get_status");
    SR.set_mode(2);
  }
}

void ui_run(int sw_in) {

  if (current_state == STATE_CUT) {
    track_torch();
    //    log_info();
  }

  sprintf(ui_line1, "TARGET: %d     ", target_voltage);
  sprintf(ui_line2, "V %d S %d       ", average_voltage(), current_state);
  paint_display();

}
int jog_cnt = 0;
int prev_entry = 0;
void ui_jog(int sw_in) {

  if (sw_in != -1) {
    switch (sw_in) {
      case SW_UP: {
          SR.set_direction(1);
          SR.until(250);
          break;
        }
      case SW_DOWN: {
          SR.set_direction(0);
          SR.until(250);
          break;
        }
      default: {
        }
    }
  }

  sprintf(ui_line1, "[ JOG Z-AXIS ]");
  //  sprintf(ui_line2, "Z-POS: %d   ", SR.get_zpos());

  paint_display();

}



int watch_pin;
int watch_active = 0;

void process_serial_event(char * tty_command) {

  if ( strcmp( tty_command, "" ) == 0 ) {
    return;
  }

  char * command = strtok(tty_command, "=");
  char * argument = strtok(0, "=");
  char buff[64];
  sprintf(buff, "");

  if (strcmp(command, "$so") == 0) {
    state_override = atoi(argument);
    sprintf(buff, "[SO]: %d", state_override);
  }
  if (strcmp(command, "$set-state") == 0) {
    current_state = atoi(argument);
    sprintf(buff, "[CURRENT STATE]: %d", current_state);
  }
  if (strcmp(command, "$get-state") == 0) {
    sprintf(buff, "[CURRENT STATE]: %d", current_state);
  }
  if (strcmp(command, "$set-target") == 0) {
    //    target_voltage = atoi(argument);
    sprintf(buff, "[TARGET VOLTAGE]: %d", target_voltage);
  }
  if (strcmp( command, "$get-target") == 0) {
    Serial.println(target_voltage);
    sprintf(buff, "[TARGET VOLTAGE]: %d", target_voltage);
  }

  if (strcmp( command, "$exec-relay") == 0) {
    digitalWrite(CNC_RLY_OUT_PIN, atoi(argument));
    sprintf(buff, "[RELAY]: %s", argument);
  }
  if (strcmp( command, "$get-pin") == 0) {
    sprintf(buff, "[PIN %s]: %d", argument, digitalRead(atoi(argument)));
  }
  if (strcmp( command, "$set-pin") == 0) {
    char * pinno = strtok(argument, ",");
    char * pinval = strtok(0, ",");
    digitalWrite(atoi(pinno), atoi(pinval));
    sprintf(buff, "[PIN %s]: %d", pinno, digitalRead(atoi(pinno)));
  }

  if (strcmp( command, "$get-avg") == 0) {
    char d_str[8];
    dtostrf(average_voltage(), 6, 2, d_str);
    sprintf(buff, "[AVG VOLTS]: %s", d_str);
  }

  if (strcmp( command, "$set-enable") == 0) {
    status_enable = atoi(argument);
    sprintf(buff, "[STAT-ENABLE]: %d", status_enable);
  }

  if (strcmp( command, "$move-up") == 0) {
    int m_arg = atoi(argument);
    if (m_arg == 1) {
      status_enable = 0;
      relay.on("tty");
      SR.set_direction(1);
      SR.set_mode(1);
    } else {
      status_enable = 1;
      relay.off("tty");
      SR.set_mode(0);
    }

    sprintf(buff, "[MOVE-UP]: %d, %d, %d", m_arg, status_enable, relay.get_state());

  }


  if (strcmp( command, "$watch-pin") == 0) {
    watch_pin = atoi(argument);
    if(watch_pin == 0) {
      watch_active = 0;
    }else{
      watch_active = 1;
    }
  }



  if (strcmp( command, "$dump-adc") == 0) {
    int iadc = 0;
    for (iadc = 0; iadc < 100; iadc++) {
      Serial.print(F("[ADC]: "));
      Serial.println(read_voltage);
      sprintf(buff, "[ADC_DUMP]: ");
    }
  }


  Serial.println(buff);
  strcpy(tty_command, "");


}

void log_debug() {
  char buf[256];
  sprintf(buf, "%d, %d, %d, %d, %d", SR.get_enable(), SR.get_mode(), digitalRead(12), digitalRead(2), digitalRead(3) );
}

char * get_pins() {
  char buf[13];
  sprintf(buf, "%d%d%d%d%d%d%d%d%d", 
  digitalRead(2),
  digitalRead(3),
  digitalRead(4),
  digitalRead(5),
  digitalRead(6),
  digitalRead(7),
  digitalRead(8),
  digitalRead(9),
  digitalRead(10));
  Serial.print(buf);
  return buf;
}

void serial_watch() {

  char buff[64];
  sprintf(buff, "");
  if(watch_active == 1) {
    switch(watch_pin) {
      case -1:
        sprintf(buff, "[WATCH(B)]: %s", get_pins());
        break;

       default:
        int pin_val = digitalRead(watch_pin);
        sprintf(buff, "[WATCH]: (%d, %d)", watch_pin, pin_val);
    }
 
  Serial.println(buff);
  }
}

void (*ui_functions[])(int) = { ui_set, ui_jog, ui_run };

int ui_index = 0;

int switch_pv = -2;


/*

  #define UI_IX_SET 0
  #define UI_IX_RUN 2
  #define UI_IX_JOG 1
  #define UI_FUNC_LEN 2
*/

long cnter = 0;
void loop() {

  //    Serial.print("Traject: ");
  //    Serial.println(SR.get_trajectory());

  terminal.process(process_serial_event);
  serial_watch();

  int sw_in = scan_switches();
  if (sw_in != switch_pv) {
    switch_pv = sw_in;
    ui_index = (sw_in == SW_MID) ? ui_index + 1 : ui_index;
    if (ui_index > UI_FUNC_LEN - 1) {
      ui_index = 0;
    }
  }
  get_status();
  if (current_state == STATE_CUT || current_state == STATE_PIERCE) {
    ui_index = UI_IX_RUN;
  } else {
    SR.set_mode(0);
  }
  ui_functions[ui_index](sw_in);
  paint_display();
  sw_in = -1;
}

void serialEvent() {
  terminal.receive();
}

On line 179 there is a variable named flag. If I compile the code with flag=0, flash it, then enter $move-up=1 into the serial monitor then I get a steady pulse generated on the pin labeled D2.

If line 179 is changed to flag = 1 then I do NOT get a pulse generated on the pin labeled D2.

If line 179 is changed to flag = 2 then I do NOT get a pulse generated on the pin labeled D2.

None of the print statements in the process method are supposed to exist they are only there to aid in debugging. However it only generates the pulse with a println present. This is not the first time that I have run into this issue.

Thank you....

You set it to 2 in your "if"

Yes, the assignment vs comparison will trip you up.
But the code seems very convoluted to perform relatively simple tasks.

Maybe you’d like to explain what you’re trying to achieve, accompanied by a schematic diagram - and friendly contributors might help you plan it better.

What is this weird looking expression supposed to do? I know what it does.

I am building a torch height controller for a CNC plasma cutting system. The schematic diagram is irrelevant to this question.

Accept my apology if I sound rude because I know that help received on this forum is voluntary, but did anyone who responded actually read the part of the post where I described the problem? I'm asking this because while there have been several responses, none of them appear to have anything to do with the issue I posted about.

Why does the inclusion of the serial.println() statement allow the pulse to be generated but a serial.print() or no print statement and it does not generate the pulse.

Thanks for pointing that out. This if/else construct was added as a way to demonstrate the problem to the forum readers so it is not what is causing the issue that I described.

[quote]What is this weird looking expression supposed to do? I know what it does.

[/quote]
It does this

char c = '-1';

but without the compiler warning.

If developing a cnc torch height controller is a relatively simple task then I am afraid to see what a complex task would like. sorry, I'm not blinking an LED.

Two characters would fit in an int, but not a char.

What did you intend?

Do you seriously think that this line of code is what is causing the problem that I described above?

No, not at all, I was puzzled by your "explanation".

Just trying to calibrate here.

I'm not a c++ programmer. The only experience I have is the 18 years I spent developing banking, airline and financial software.

I do not think that I am going to get an answer to my question here. I would have posted a specific set of lines describing the problem but then people would complain that all of the code was not present as that is a default response on this board. Then if include all of the code it becomes a huge distraction. Either way there will not likely be any discussion relevant to the actual topic.

Me neither.

Have you tried:

? I've found that sometimes I can get the else if to work and sometimes it does not.

That’s scary.

Oh, I'm sure it me who is doing the thing incorrectly and one day, I'll figure it out.

Then post an MRE. That would be the smallest COMPLETE code that compiles and demonstrates the problem (and only the specific) problem. Many times when creating such an example you'll find your coding error yourself.

On the other hand, espousing a crappy attitude is not conducive to getting free help.

No it doesn’t, it does this

char c = -1;

You post nearly 800 lines of poorly-structured code with not a single meaningful comment, and no trace or debug prints, so I suspect you're probably right.

Good luck.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.