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....