Analog.read interfering with Serial.print?

Hey all! I've been working on a complicated project involving multiple Arduinos integrated into some on my vehicle's functions. This particular function I'm augmenting is the Air Conditioner indication. The OEM indication is the use of LEDs to show a certain function is in use (auto, A/C, Front + Rear control, etc).

My first iteration was to simply replicate the indication on an OLED screen which worked pretty well. The next iteration I'm working on involves communicating status over the serial bus. I'm running into a problem with the MonitorInputs function I created (Analog.read) interfering with a simple response function (Serial1Rply). When I comment out the MonitorInputs function the Serial1Rply function works (I receive the reply code when prompted from the IDE Serial Monitor).

I'd greatly appreciate anyone taking a peek at my code below for any obvious errors. Also, not sure if this is a known issue but I've also used a function to print the analog inputs over the Serial bus to the IDE Serial Monitor.

//  NOTE: Pro Micro board appears as Leonardo
//  NOTE: Ensure SEPU has common ground with system

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, & Wire, OLED_RESET);

int FDEF_Pin = A0;  //FDEF Input
int RDEF_Pin = A1;  //RDEF Input
int AUTO_Pin = A2;  //AUTO Input
int AC_Pin = A3;  //A/C Input
int CIRC_Pin = A4;  //CIRC Input
int FR_Pin = A5;  //F+R Input

int FDEF_State = 0;
int RDEF_State = 0;
int AUTO_State = 0;
int AC_State = 0;
int CIRC_State = 0;
int FR_State = 0;

//int CMD_CODE;
//int RPLY_CODE;

int TestMode = 1; //Default to display test on startup

void indicatorTest0() //indicatorTest(void) 
{
  display.clearDisplay();
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0,0); // Start at top-left corner (x, y)
  display.print("FDEF");
  display.setCursor(80, 0);
  display.print("RDEF");
  display.setCursor(0, 24);
  display.print("AUTO");
  display.setCursor(92, 24);
  display.print("A/C");
  display.setCursor(0, 49);
  display.print("CIRC");
  display.setCursor(92, 49);
  display.print("F+R"); 
  display.drawLine(0, 17, 127, 17, WHITE);
  display.drawLine(0, 43, 127, 43, WHITE);
  display.drawLine(64, 0, 64, 63, WHITE);
  display.display();
}

void indicatorOff() //indicatorTest(void) 
{
  //display.clearDisplay();
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(0,0); // Start at top-left corner (x, y)
  display.print("FDEF");
  display.setCursor(80, 0);
  display.print("RDEF");
  display.setCursor(0, 24);
  display.print("AUTO");
  display.setCursor(92, 24);
  display.print("A/C");
  display.setCursor(0, 49);
  display.print("CIRC");
  display.setCursor(92, 49);
  display.print("F+R"); 
  display.setTextColor(SSD1306_WHITE);
  display.drawLine(0, 17, 127, 17, WHITE);
  display.drawLine(0, 43, 127, 43, WHITE);
  display.drawLine(64, 0, 64, 63, WHITE);
  display.display();
}

void PrintFDEF_On()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0,0); // Start at top-left corner (x, y)
  display.print("FDEF");
  display.display();
}

void PrintFDEF_Off()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(0,0); // Start at top-left corner (x, y)
  display.print("FDEF");
  display.display();
}

void PrintRDEF_On()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(80, 0); // Start at top-left corner (x, y)
  display.print("RDEF");
  display.display();
}

void PrintRDEF_Off()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(80, 0); // Start at top-left corner (x, y)
  display.print("RDEF");
  display.display();
}

void PrintAUTO_On()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 24); // Start at top-left corner (x, y)
  display.print("AUTO");
  display.display();
}

void PrintAUTO_Off()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(0, 24); // Start at top-left corner (x, y)
  display.print("AUTO");
  display.display();
}

void PrintAC_On()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(92, 24); // Start at top-left corner (x, y)
  display.print("A/C");
  display.display();
}

void PrintAC_Off()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(92, 24); // Start at top-left corner (x, y)
  display.print("A/C");
  display.display();
}


void PrintCIRC_On()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 49); // Start at top-left corner (x, y)
  display.print("CIRC");
  display.display();
}

void PrintCIRC_Off()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(0, 49); // Start at top-left corner (x, y)
  display.print("CIRC");
  display.display();
}

void PrintFR_On()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(92, 49); // Start at top-left corner (x, y)
  display.print("F+R");
  display.display();
}

void PrintFR_Off()
{
  display.setTextSize(2); // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_BLACK); // Draw white text
  display.setCursor(92, 49); // Start at top-left corner (x, y)
  display.print("F+R");
  display.display();
}

void MonitorFDEF()
{
  FDEF_State = analogRead(A0);
  delay(120);
  if (FDEF_State>=350)
  {
    PrintFDEF_Off();
  }
  else if (FDEF_State<=330)
  {
     PrintFDEF_On();
  }
  else
  {
    
  }
}

void MonitorRDEF()
{
  RDEF_State = analogRead(A1);
  delay(120);
  if (RDEF_State>=350)
  {
    PrintRDEF_Off();
  }
  else if (RDEF_State<=330)
  {
    PrintRDEF_On();
  }
  else
  {
    
  }
}

void MonitorAUTO()
{
  AUTO_State = analogRead(A2);
  delay(120);
  if (AUTO_State>=350)
  {
    PrintAUTO_Off();
  }
  else if (AUTO_State<=330)
  {
    PrintAUTO_On();
  }
  else
  {
    
  }
}

void MonitorAC()
{
  AC_State = analogRead(A3);
  delay(120);
  if (AC_State>=350)
  {
    PrintAC_Off();
  }
  else if (AC_State<=330)
  {
    PrintAC_On();
  }
  else
  {
    
  }
}

void MonitorCIRC()
{
  CIRC_State = analogRead(A4);
  delay(120);
  if (CIRC_State>=350)
  {
    PrintCIRC_Off();
  }
  else if (CIRC_State<=330)
  {
    PrintCIRC_On();
  }
  else
  {
    
  }
}

void MonitorFR()
{
  FR_State = analogRead(A5);
  delay(120);
  if (FR_State>=350)
  {
    PrintFR_Off();
  }
  else if (FR_State<=330)
  {
    PrintFR_On();
  }
  else
  {
    
  }
}

void MonitorInputs()
{
  MonitorFDEF();
  MonitorRDEF();
  MonitorAUTO();
  MonitorAC();
  MonitorCIRC();
  MonitorFR();
}

void PrintInputs()
{
  Serial.print("FDEF_State ");
  Serial.println(FDEF_State);
  Serial.print("RDEF_State ");
  Serial.println(RDEF_State);
  Serial.print("AUTO_State ");
  Serial.println(AUTO_State);
  Serial.print("AC_State ");
  Serial.println(AC_State);
  Serial.print("CIRC_State ");
  Serial.println(CIRC_State);
  Serial.print("FR_State ");
  Serial.println(FR_State); 
}

void Serial1Rply()
{
  if (Serial.available()) {
    int CMD_CODE = Serial.parseInt();
    int RPLY_CODE = (CMD_CODE + 1);
    if (CMD_CODE==9002)
    {
      Serial.print("Response: ");
      Serial.println(RPLY_CODE);
    }
    else
    {
      
    }
  }
}

void setup() 
{
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 
  {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
 delay(1000);
 display.clearDisplay();

 pinMode(FDEF_Pin, INPUT);
 pinMode(RDEF_Pin, INPUT);
 pinMode(AUTO_Pin, INPUT);
 pinMode(AC_Pin, INPUT);
 pinMode(CIRC_Pin, INPUT);
 pinMode(FR_Pin, INPUT);

}

void loop()
{
  while (true)
  {
    //MonitorInputs();
    PrintInputs();
    Serial1Rply();
    /*if (TestMode == 1)
    {
      indicatorTest0();
      TestMode = (TestMode - 1);
      delay(3000);
      indicatorOff();
    }
    else
    {
      
    }*/
  }
}

Which arduino are you using? A pro micro does not have A4 or A5.

Are you getting anything in the Serial monitor when you uncomment MonitorInputs? The only problem I see is that the delays will case a very sluggish response to any serial input.

lot of code to look thru.

consider


struct Input_s{
    byte    pin;
    byte    state;
    int     val;
    byte    row;
    byte    col;
    const char *label;
};

Input_s  inputs [] = {
    { A0, 0, 0,  0,  0, "FDEF" },
    { A1, 0, 0, 80,  0, "RDEF" },
    { A2, 0, 0,  0, 24, "AUTO" },
    { A3, 0, 0, 92, 24, "A/C"  },
};

#define N_INPS  (sizeof(inputs)/sizeof(Input_s))

char s [80];

// -----------------------------------------------------------------------------
#if 0
void
inpDisp (
    Input_s  *p)
{
    display.setTextSize (2); // Normal 1:1 pixel scale

    if (p->state)
        display.setTextColor (SSD1306_WHITE); // Draw white text
    else
        display.setTextColor (SSD1306_BLACK); // Draw white text

    display.setCursor (p->row, p->col); // Start at top-left corner (x, y)
    display.print     (p->label);

    display.display();
}
#endif

// -----------------------------------------------------------------------------
void
inpChk (
    Input_s  *p)
{
    p->val = analogRead (p->pin);

    if (p->state)  {
        if (330 > p->val)
            p->state = 0;
    }
    else  {
        if (350 < p->val)
            p->state = 1;
    }

#if 0
    sprintf (s, "%s: %6d %d %s", __func__, val, p->state, p->label);
    Serial.println (s);
#endif
}

// -----------------------------------------------------------------------------
void
inpPr ()
{
    Input_s *p = & inputs [0];
    for (unsigned n = 0; n < N_INPS; n++, p++)  {
        sprintf (s, " %4d %d %s,", p->val, p->state, p->label);
        Serial.print (s);
    }
    Serial.println ();
}

// -----------------------------------------------------------------------------
void serial1Rply ()
{
    if (Serial.available()) {
        int resp = 0;
        int cmd  = Serial.parseInt ();

        switch (cmd)  {
        case 9002:
            resp = cmd + 1;
            break;

        default:   
            sprintf (s, "%s: %d", __func__, cmd);
            Serial.println (s);
            break;
        }

        if (resp)  {
            sprintf (s, "%s: cmd %d, resp %d", __func__, cmd, resp);
            Serial.println (s);
        }
    }
}

// -----------------------------------------------------------------------------
void loop()
{
    Input_s *p = & inputs [0];
    for (unsigned n = 0; n < N_INPS; n++, p++)
        inpChk (p);

    inpPr ();

    serial1Rply ();

    delay (1000);
}

void setup()
{
    Serial.begin (9600);
}

@david_2018 - Sorry for the confusion. I was swapping between a Pro Micro, Uno, and Nano for troubleshooting and had to change the analog assignments to make the code work. Organization is not my strong suit!

The system works by reading the voltage of the indicator circuit after it's conditioned through a voltage divider (12v reduced to ~2v). From there the intent is to send that measurement through Serial to the "main computer." With the MonitorInputs function uncommented I can get the PrintInputs to work over the Serial Monitor, but not the Serial1Rply function. I initially put the delays in the measurement segment to prevent "switch chatter". I've since added smoothing capacitors to deal with some of the erratic readings and the delays are a holdover until I can prove I'm getting a more consistent reading otherwise.

@gcjr - Thank you for streamlining my code. I haven't tested it yet but it is levels above my skill. In fact, I have to read up on the operators and syntax you used before I can even form an intelligent response. A good opportunity to have a deeper understanding of Arduino coding, for sure. Let me digest your response for a bit.

Just to get the conversation going... the struct syntax creates a variable with multiple characteristics similar to a function with multiple arguments...is that correct? A lot of your response is going over my head so I need to do some homework but I definitely see potential to clean up a lot of my other sketches.

Do not see any obvious problems with using a pro micro, the uno and nano are likely running short of dynamic memory, the display will allocate 1024 bytes for a buffer. The uno/nano also used A4 and A5 for the I2C bus.

it defines a composite variable composed of other primitive variables (e.g. int, char, ...) or structs using "." or "->" to reference them. i guess structs are the most basic form of an object, encapsulating all information associated with that "thing".

creating an array of structs make it easy to process multiple structs within a loop

Not sure what problem you are having, your original code appears to work properly on a nano even when MonitorInputs() is un-commented.

@david_2018 Yeah, I'm still getting the same problem with the Nano using my old code... I had to install a CH34x driver to use the Nano to begin with. Does this sound familiar to you?

@gcjr Your code works like a champ. Much appreciation. Going to have to read more on this style of coding.

So I messed around uncommenting some things and uploading the resulting code and somehow it just started working.

It works as expected...weird...and this is a RexQualis Nano...

rather than cut & paste code, develop data driven code using common sub-functions that operate on some common data structure. fixes and enhances involve modify data minimizing programming experience

I'm decomposing your code and had some questions:

const char *label;
--What is the purpose of the * operator in front of label? Are you identifying "label" as an object to point to?

#define N_INPS (sizeof(inputs)/sizeof(Input_s))
--Can you explain the meaning of this line? Are you deriving the number or bytes or objects in the inputs/Input_s arrays?

char s [80];
--Was 80 chosen for a reason? Could this be smaller?

void inpDisp ( Input_s *p)
Could the pointer/dereferencer *p be any character (a, b, c, etc.)?

if (p->state)
--Does C++ assume the condition for state is true for if/false for else?

I have more questions but don't want to go overboard. Thank you for all the help!

identifies it as a pointer (the address) of a char or char array (c-string)

should note that the c-string is allocated outside of the struct its address is used in

the size of inputs in the definition is not specified, the compiler can figure this out by the # of values being specified. and this makes it easier to add to the list (simply add another line of values)

but the size of the array needs to be known and the "sizeof()" operator is used during compilations to provide the size. however, "sizeof()" provide the size in bytes. so the total size of the array is divided by the size of an individual line to determine the # of array values, in this case 4

yes, but why worry about for such a trivial program. if size becomes an issue, a string could be dynamically allocated on the stack in each function needed one

no, it's a pointer to an Input_s structure

there's no need to explicitly test of that "state == true". if state is true, the condition is true.

you are introducing almost 1 second delay every loop iteration, which mean your serial runs with 1 second interval which is not a good idea

to slow down the prints during debugging.
obviously not needed

Serialreply function is called from the same loop with 1 second interval, which op claims starts malfunctioning when monitors added, which introduce the aforementioned delay

so the delay added in my code is the cause of the problem in the OPs code ?

I was commenting on OPs code

in the OPs code, there only a 1 sec delay in setup(). there's a 3 sec delay commented out in loop

or are you referring to the accumulated delays in the monitor functions?

yes, each adds 120ms which amounts to a bit less than a second