[Solved] Puzzling Serial.print()

I am creating a controller for a football play clock. When the controller is first powered up, I want it to send a command, Serial.print() 5 times in succession. Most of the rest of the code is unwritten, but I am getting a puzzling error in my code so far… Here is the code…

byte ReadyForPlayTime = 25;// constant, default delay of game time
byte TimeOutTime = 40;// constant, default time out time
void setup() {
  Serial.begin(9600);
  for (byte i; i < 5; i++) {
    printPlayclockCommand("PD", ReadyForPlayTime);
  }
}
void loop() {
}
void printPlayclockCommand(char command[3], byte timerTime) {
  char secondsTens = (timerTime / 10) + 48;
  char secondsOnes = (timerTime % 10) + 48;
  char centiseconds;
  if (timerTime >= 1) centiseconds = 148;
  else centiseconds = 48;
  Serial.print(command);
  Serial.print(secondsTens);
  Serial.print(secondsOnes);
  Serial.print(centiseconds);
}

I get no output when powered up… However, if I add 2 more lines of code as follows… just to test my serial is working…

byte ReadyForPlayTime = 25;// constant, default delay of game time
byte TimeOutTime = 40;// constant, default time out time
void setup() {
  Serial.begin(9600);
  char cMD[3] = "PX";
  Serial.print(cMD);
  for (byte i; i < 5; i++) {
    printPlayclockCommand("PD", ReadyForPlayTime);
  }
}
void loop() {
}
void printPlayclockCommand(char command[3], byte timerTime) {
  char secondsTens = (timerTime / 10) + 48;
  char secondsOnes = (timerTime % 10) + 48;
  char centiseconds;
  if (timerTime >= 1) centiseconds = 148;
  else centiseconds = 48;
  Serial.print(command);
  Serial.print(secondsTens);
  Serial.print(secondsOnes);
  Serial.print(centiseconds);
}

I get “PXPD25”PD25”PD25”PD25”PD25””… Exactly what I want, without the PX…

Is it a delay thing? I’ve added delay, which doesn’t fix it. Is it an if or while statement? This is on an ATmega328P, running at 16 MHz, similar enough to the UNO.

Your function should take a const char *, not a char .

I can't imagine how printing "PX" first makes you function work.

Fix the argument type, and test it again, without the two extra lines.

PaulS:
Your function should take a const char *, not a char .

I can’t imagine how printing “PX” first makes you function work.

Fix the argument type, and test it again, without the two extra lines.

I think I know what you are saying, but I don’t think I got it right, because it’s still not working…

byte ReadyForPlayTime = 25;// constant, default delay of game time
byte TimeOutTime = 40;// constant, default time out time
void setup() {
  Serial.begin(9600);
  for (byte i; i < 5; i++) {
    printPlayclockCommand("PD", ReadyForPlayTime);
  }
}
void loop() {
}
void printPlayclockCommand(const char *command, byte timerTime) {
  char secondsTens = (timerTime / 10) + 48;
  char secondsOnes = (timerTime % 10) + 48;
  char centiseconds;
  if (timerTime >= 1) centiseconds = 148;
  else centiseconds = 48;
  Serial.print(command);
  Serial.print(secondsTens);
  Serial.print(secondsOnes);
  Serial.print(centiseconds);
}

Which Arduino are you running this code on?

PaulS:
Which Arduino are you running this code on?

It's an Atmega328P, barebones, with a 16MHz crystal, simple Pierce oscillator to be clear, 2 18pF caps and 1 MOhm resistor... , a pull-up resistor on /reset with decoupling cap, decoupling caps on VCC, AVCC and AREF, and grounding on GND pins. Pin 3, TX is taken through a MAX3232 with proper pump caps, decoupling and grounding, all powered at 3.3 Volts DC...

Just out of curiosity, does adding a small delay() between begin() and the function call accomplish anything?

PaulS:
Just out of curiosity, does adding a small delay() between begin() and the function call accomplish anything?

No. I've tried delay, referencing, dereferencing, printing "" first... I'm either going to print PC or PD, so maybe I just pass it a boolean and have it evaluate the boolean and print the appropriate string literal...

I don’t understand the root cause, but if you initialize byte i = 0 in the for loop the code prints 5X

byte ReadyForPlayTime = 25;// constant, default delay of game time
byte TimeOutTime = 40;// constant, default time out time
void setup() {
  Serial.begin(9600);
 // char cMD[3] = "PX";
 // Serial.print(cMD);
  for (byte i= 0; i < 5; i++) {
    printPlayclockCommand("PD", ReadyForPlayTime);
  }
}
void loop() {
}
void printPlayclockCommand(char command[3], byte timerTime) {
  char secondsTens = (timerTime / 10) + 48;
  char secondsOnes = (timerTime % 10) + 48;
  char centiseconds;
  if (timerTime >= 1) centiseconds = 148;
  else centiseconds = 48;
  Serial.print(command);
  Serial.print(secondsTens);
  Serial.print(secondsOnes);
  Serial.print(centiseconds);
}

Does it help if you initialise i in the for loop instead if it being assigned some random value ?

Crank you warning level up to ALL. That would point you right at the mistake:

warning: ‘i’ may be used uninitialized in this function

/Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.6.21/cores/arduino/main.cpp: In function 'main':
/Users/john/Documents/Arduino/sketch_may31a/sketch_may31a.ino:6:3: warning: 'i' may be used uninitialized in this function [-Wmaybe-uninitialized]
   for (byte i; i < 5; i++)
   ^
/Users/john/Documents/Arduino/sketch_may31a/sketch_may31a.ino:6:13: note: 'i' was declared here
   for (byte i; i < 5; i++)
             ^
Sketch uses 3708 bytes (12%) of program storage space. Maximum is 28672 bytes.
Global variables use 151 bytes (5%) of dynamic memory, leaving 2409 bytes for local variables. Maximum is 2560 bytes.

cattledog:
I don't understand the root cause, but if you initialize byte i = 0 in the for loop the code prints 5X

Thank you, again!

UKHeliBob:
Does it help if you initialise i in the for loop instead if it being assigned some random value ?

It does... It's always the simple things I get hung on...

johnwasser:
Crank you warning level up to ALL. That would point you right at the mistake:

Thank you. Done.

What is the explanation for the fact that adding

 char cMD[3] = "PX";
  Serial.print(cMD);

somehow initialized i in the following for loop?

cattledog:
What is the explanation for the fact that adding

 char cMD[3] = "PX";

Serial.print(cMD);



somehow initialized i in the following for loop?

I can only postulate that i was assigned a place in memory with whatever value there, possibly above or equal to 5, causing the loop to never execute even once...
adding those two lines, by circumstance, caused i to be assigned to a place in memory where the value just happened to be 0...

cattledog:
What is the explanation for the fact that adding

 char cMD[3] = "PX";

Serial.print(cMD);



somehow initialized i in the following for loop?

No. i was always initialised but its value was not specified so was allocated a value from the memory location that the variable was located at. Adding more code changed the memory location used by i and hence its initial value.

Out of interest try

  for (static byte i; i < 5; i++)

static variables are initialised to zero if not initialised to a specific value.

UKHeliBob:
Out of interest try

  for (static byte i; i < 5; i++)

static variables are initialised to zero if not initialised to a specific value.

Tried it.
It does work.
But, I don’t want i to be static because I don’t want it to survive beyond setup.

Perehama:
Tried it.
It does work.
But, I don’t want i to be static because I don’t want it to survive beyond setup.

It was merely an illustration that initialising it to zero one way or the other makee it work properly. Just use the normal method

 for (byte i = 0; i < 5; i++)

and get on with the serious programming