Mysteries of Serial.parseInt()

This code works perfectly on a Nano clone with a CH340 UART chip and old bootloader:

    Serial.print(F("Adjust = ")); Serial.println(Adjust);
    Serial.println(F("Enter new Adjust value, or [Enter]"));
    while (!Serial.available());
    
    if((Serial.peek() == 13) || (Serial.peek() == 10)) nothing = true;
    newAdjust = Serial.parseInt(SKIP_NONE);       // Adjust can be negative
    if ((newAdjust) || !nothing) Adjust = newAdjust;
    Serial.print(F("Adjust = ")); Serial.println(Adjust);
    while(Serial.available()) Serial.read();
    Serial.println(F("Waiting for IR transmission..."));

The default value of Adjust is 40, but if I type in 46 in the serial monitor, the code reads that fine, and prints out 46.

But it doesn't work on a Pro Mini connected with an FTDI UART module. It only gets the first digit of the 46, and prints out 4.

Same processor, but I guess different bootloaders. Anyway, can anyone explain what's happening?

try put a small delay between while(...) and Serial print.
Like delay(20);

This code won't compile or upload to the Arduino!

Please read the forum guide in the sticky post.

1 Like

With SKIP_NONE Nothing is skipped, and the stream is not touched unless the first waiting character is valid. So if you have CR or LF as the first byte then you won’t read anything.

Are you sure the Serial Monitor was configured the right way ? What’s your line ending?

Yes indeed, but what makes no sense is that it gets the first digit, but not the second. I did try inserting a delay to make sure everything would have been received, but it made no difference.

I would like to do an experiment designed to see if it's the difference in UART chips or the difference in bootloaders that selects the problem. I would connect power, ground, Tx and Rx from the FTDI module directly to the corresponding pins on the Nano. If the Nano still works, then the FTDI isn't the problem. But of course the Nano's CH340 is still connected to Rx and Tx, and I don't know if that could result in a short. Do you think that's safe to try?

I've tried all four options. None of them work. I still just get the first digit. This is just crazy.

I think what @PaulRB was suggesting is that you post a complete it compiles and we can run it for ourselves sketch which demonstrates the problem.

I know that's what I am asking you to do now.

TIA

a7

That kinda shows you don’t understand how the parseInt() function works… (it has a défaut 1s timeout)

Show us yout full code

Here's the full code.

// IRCaptureRaw.ino   Rev 2
// for ATmega328P processors (Uno, Nano, ProMini - 8 or 16MHz)
// This captures incoming IR from a remote control as raw data.
// An IR receiver module should be connected to D8.
// The Adjust variable adjusts time between On and Off periods since
//   receivers may turn on faster than they turn off, or vice versa.
// Results will include any repeats.
// The displayed numbers alternate between transmitting and idle states.

const int maxEntries = 650;
unsigned int bitTime[maxEntries];                 // store uSeconds in each state
int Adjust = 40, newAdjust;                       // receiver turn on, turn off times not the same
const byte recvPin = 8;
volatile unsigned int timerMSB, capMSB;           // third byte of 24-bit timer (ICR1 = 1st two)
volatile bool Capture;                            // a state change occurred, and time was captured
unsigned long timerLO, timerHI, newTime, prevTime;
int i, j, k, maxMSB;
bool activeLO;                                    // receiver output is low when receiving carrier
bool Waiting, Start, nothing;

void setup() {

  delay(1000);
  Serial.begin (115200);
  Serial.println();
  pinMode(recvPin, INPUT_PULLUP);
  activeLO = true;                                // assume no transmission happening now
  if (!digitalRead(recvPin)) activeLO = false;
  maxMSB = 30 >> (F_CPU == 8000000);              // capture time = 1 sec
  Serial.println(maxMSB);  
  cli();
  TCCR1A = 0;                                     // set up Timer1
  TCCR1B = 0;
  TCCR1C = 0;
  TCNT0  = 0;                                     // clear Timer1
  TIFR1  = 0xFF;                                  // clear flags
  TIMSK1 = 0b00100001;                            // enable capture and overflow interrupt (GPS)
  TIFR1  = 0xFF;                                  // clear flags
  TCCR1A = 0b00000000;                            // Normal mode, no output, WGM #0
  sei();
  Start = true;
}

void loop() {

  if(Start) {                                     // initialize everything on start or restart
    Start = false;
    i = 0;
    j = 1;
    Waiting = true;
    Capture = false;
    nothing = false;
    cli();
    if (activeLO) TCCR1B = 0b00000010;      // falling edge capture, timer1 on, prescale /8
    else TCCR1B = 0b01000010;               // rising edge capture, timer1 on, prescale /8
    TIFR1  = 0xFF;                          // clear flags register
    sei();

    Serial.print(F("Adjust = ")); Serial.println(Adjust);
    Serial.println(F("Enter new Adjust value, or [Enter]"));
    while (!Serial.available());
    
    if((Serial.peek() == 13) || (Serial.peek() == 10)) nothing = true;
    newAdjust = Serial.parseInt(SKIP_NONE);       // Adjust can be negative
    if ((newAdjust) || !nothing) Adjust = newAdjust;
    Serial.print(F("Adjust = ")); Serial.println(Adjust);
    while(Serial.available()) Serial.read();
    Serial.println(F("Waiting for IR transmission..."));
    TIMSK0 = 0;                                   // Disable Timer0 interrupts (millis)
  }

  if (Waiting) {                                  // keep MSB cleared
    if (timerMSB) timerMSB = 0;
  }

  if(Capture) {                                   // input has changed state
    Capture = false;
    Waiting = false;
    timerLO = ICR1;                               // read timer values
    timerHI = capMSB;
    newTime = (timerHI << 16) + timerLO;          // combine timer counts to one long value
    if (maxMSB == 30) newTime = (newTime +1) >> 1;
    if (i) {                                      // skip i=0
      bitTime[i] = newTime - prevTime;            // collect duration and activity state
    }
    prevTime = newTime;                           // prepare for next state change
   TCCR1B ^= 0b01000000;                          // switch to capture on opposite edge
    i++;
  }

  if ((timerMSB > maxMSB) || (i > maxEntries)) {  // collect data for one second after first
    TCCR1B &= 0xFE;                               // stop Timer1 clock
    TIMSK0 = 1;                                   // resume millis interrupt
    for (k = 1; k < i; k++) {                     // adjust on (Mark) and off (Space) times
      if (k & 1) bitTime[k] -= Adjust;            // shift Adjust from On to Off
      else bitTime[k] += Adjust;
    }
    Serial.println();                             // display output
    Serial.println(F("    On    Off     On    Off     On    Off     On    Off"));
    Serial.println();
    while (j < i) {
      for (k = 0; k < 8; k++) {
        Serial.print(" ");
        if (bitTime[j] <10000) Serial.print(" ");
        if (bitTime[j] < 1000) Serial.print(" ");
        if (bitTime[j] < 100) Serial.print(" ");
        if (bitTime[j] < 10) Serial.print(" ");
        Serial.print (bitTime[j]);
        j++;
        if (j == i) break;
        else Serial.print (",");
      }
      Serial.println();
    }
    Serial.println();
    Start = true;
  }
}

ISR(TIMER1_CAPT_vect) {
  capMSB = timerMSB;                              // also capture MSB at same instant
  Capture = true;
}

ISR(TIMER1_OVF_vect) {
  timerMSB++;                                     // increment MSB on overflow
}

I have further information. Instead of trying to see if the Nano produces the same problem with the FTDI UART module, I dug out a CP2102 UART module, and a CH340G UART module from my junque box, and tried both of them with the Pro Mini.

And I have the same single-character response with both of them as I did with the FTDI module. So I think that narrows it down to either the bootloader and fuses, or something the IDE is doing in compiling for the Pro Mini that it isn't doing for the Nano.

I should have said that this is a 3.3V 8MHz Pro Mini from 2016, and I'm pretty sure the 328P is genuine. But I've never actually looked at the bootloader, and I need to do that. And I'm running IDE v1.8.8. The Boards.txt file says the bootloader for the 5V 16MHz Pro Mini is the same as the Nano Old Bootloader. But the 8MHz Pro Mini has a different bootloader, so perhaps there's a problem there.

Dumbass!!!!

It was just that 115200 is too fast for 8MHz. But 57600 works just fine - both digits even.

Very sorry to have wasted everyone's time. But thanks very much for all the comments.

1 Like

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