Newbie, Reading serial data.

I have written some code to interface with an older module called a Pocket Watch B, it’s a RTC module. Basically it all works, but I’m having a weird problem I can’t seem to solve.

I’ve tried to set up code so that the Arduino only responds when I ask a question.

It responds, but I have to ask twice…to get the right time from the module, and I can’t figure out why.

Any help appreciated.

Program attached.

PocketWatchB.ino (3.31 KB)

Any good reason that you didn’t post your code?

I did post the code.

/*
An attemp to communicate with a Pocket Watch B module
seconds, minutes, hours, days,months, years low, years high
0 1 2 3 4 5 6
*/

// Golbal variables
int goDoIt;
int setTimeFlag = 0;
int setAlarmFlag = 0;
int buzzCount = 0;
int buzzCountMax = 30;
const int buzzer = 7; //buzzer to arduino pin 7
const int alarmPin = 9;

void setup() {
// initialize both serial ports:
Serial.begin(9600);
Serial1.begin(9600);
pinMode(7, OUTPUT);
pinMode(9, INPUT);
}

void loop() {
if (setTimeFlag == 1) {
setTheTime();
setTimeFlag = 0;
}

if (setAlarmFlag == 1) {
setAlarmTime();
readAlarmTime();
setAlarmFlag = 0;
}

delay (100);

if (Serial.available()) {
goDoIt = Serial.read();
Serial.print(goDoIt);
Serial.print("\n");
Serial.print("\r");
if (goDoIt == 49) {
readTheTime();
playBuzzer();
}
}
if (buzzCount <= buzzCountMax) {
soundAlarm();
}
}

int readTheTime() {
// Send read time to the PWB
byte readTime = {0x55, 0x12};
byte theTime[7];
Serial1.write(readTime,2);
// Serial1.write(readTime);
// read from port 1, send to port 0:
// seconds, minutes, hours, days, months, years low, and years high

if (Serial1.available()) {
Serial1.readBytes(theTime, 7);
Serial.print(theTime[2],DEC);
Serial.print(":");
Serial.print(theTime[1], DEC);
Serial.print(":");
Serial.print(theTime[0],DEC);
Serial.print(" “);
Serial.print(theTime[4], DEC);
Serial.print (”/");
Serial.print(theTime[3],DEC);
Serial.print("/");
Serial.print(theTime[6]),DEC;
Serial.print(theTime[5],DEC);
Serial.print(’\n’);
Serial.print(’\r’);
}
return 0;
}

int setTheTime() {
byte setTime = {85, 16, 0, 50, 15, 4, 1, 20, 20};
Serial1.write(setTime, 9);
return 0;
}

int setAlarmTime() {
byte turnAlarmOff = {85, 21};
Serial1.write(turnAlarmOff,2);
// 12:30:00 1/5/2020
// seconds,minutes, hours, days, months, years low, years high
byte setAlarmData = {85, 17, 0, 00, 16, 12, 1, 20, 20};
Serial1.write(setAlarmData,9);
byte turnAlarmOn = {85, 20};
Serial1.write(turnAlarmOn,2);
return 0;
}

int readAlarmTime() {
byte readAlarmCode = {85, 19};
byte alarmTime[7];
Serial1.write(readAlarmCode, 2);
if (Serial1.available()) {
Serial1.readBytes(alarmTime, 7);
Serial.print(alarmTime[2],DEC);
Serial.print(":");
Serial.print(alarmTime[1], DEC);
Serial.print(":");
Serial.print(alarmTime[0],DEC);
Serial.print(" “);
Serial.print(alarmTime[4], DEC);
Serial.print (”/");
Serial.print(alarmTime[3],DEC);
Serial.print("/");
Serial.print(alarmTime[6]),DEC;
Serial.print(alarmTime[5],DEC);
Serial.print(’\n’);
}
return 0;
}

int playBuzzer() {
tone(buzzer, 500); // Send 1KHz sound signal…
delay(100); // …for 1 sec
noTone(buzzer); // Stop sound…
return 0;
}

int soundAlarm() {
int alarmVal = digitalRead(alarmPin);
if (alarmVal == HIGH) {
while(buzzCount <= buzzCountMax) {
tone(buzzer, 1000);
delay(100);
tone(buzzer, 500);
delay(100);
buzzCount++;
noTone(buzzer);
}
return 0;
}
}

It is easier for people to help you if you include short programs in your Post so they don’t have to download them. See General Guidance and How to use the forum

/*
  An attemp to communicate with a Pocket Watch B module
  seconds, minutes, hours, days,months, years low, years high
     0        1       2      3     4      5            6
*/

// Golbal variables
int goDoIt;
int setTimeFlag = 0;
int setAlarmFlag = 0;
int buzzCount = 0;
int buzzCountMax = 30;
const int buzzer = 7; //buzzer to arduino pin 7
const int alarmPin = 9;
  
void setup() {
  // initialize both serial ports:
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(7, OUTPUT);
  pinMode(9, INPUT);
  }

void loop() {
   if (setTimeFlag == 1) {
   setTheTime();
   setTimeFlag = 0;
   }

   if (setAlarmFlag == 1) {
    setAlarmTime();
    readAlarmTime();
    setAlarmFlag = 0;
   }

    delay (100);

   if (Serial.available()) {
   goDoIt = Serial.read();
   Serial.print(goDoIt);
   Serial.print("\n");
   Serial.print("\r");
   if (goDoIt == 49) {
      readTheTime();
      playBuzzer();
    }
   }
   if (buzzCount <= buzzCountMax) {
   soundAlarm();
   }
  }

int readTheTime() {
  // Send read time to the PWB
  byte readTime[] = {0x55, 0x12};
  byte theTime[7];
  Serial1.write(readTime,2);
  // Serial1.write(readTime);
  // read from port 1, send to port 0:
  // seconds, minutes, hours, days, months, years low, and years high
  
  if (Serial1.available()) {
    Serial1.readBytes(theTime, 7);
    Serial.print(theTime[2],DEC);
    Serial.print(":");
    Serial.print(theTime[1], DEC);
    Serial.print(":");
    Serial.print(theTime[0],DEC);
    Serial.print(" ");
    Serial.print(theTime[4], DEC);
    Serial.print ("/");
    Serial.print(theTime[3],DEC);
    Serial.print("/");
    Serial.print(theTime[6]),DEC;
    Serial.print(theTime[5],DEC);
    Serial.print('\n');
    Serial.print('\r');
  }
return 0;
}

int setTheTime() {
  byte setTime[] = {85, 16, 0, 50, 15, 4, 1, 20, 20};
  Serial1.write(setTime, 9);
  return 0;
}

int setAlarmTime() {
  byte turnAlarmOff[] = {85, 21};
  Serial1.write(turnAlarmOff,2);
  // 12:30:00 1/5/2020
  // seconds,minutes, hours, days, months, years low, years high
  byte setAlarmData[] = {85, 17, 0, 00, 16, 12, 1, 20, 20};
  Serial1.write(setAlarmData,9);
  byte turnAlarmOn[] = {85, 20};
  Serial1.write(turnAlarmOn,2);
  return 0;
}

int readAlarmTime() {
  byte readAlarmCode[] = {85, 19};
  byte alarmTime[7];
  Serial1.write(readAlarmCode, 2);
  if (Serial1.available()) {
    Serial1.readBytes(alarmTime, 7);
    Serial.print(alarmTime[2],DEC);
    Serial.print(":");
    Serial.print(alarmTime[1], DEC);
    Serial.print(":");
    Serial.print(alarmTime[0],DEC);
    Serial.print(" ");
    Serial.print(alarmTime[4], DEC);
    Serial.print ("/");
    Serial.print(alarmTime[3],DEC);
    Serial.print("/");
    Serial.print(alarmTime[6]),DEC;
    Serial.print(alarmTime[5],DEC);
    Serial.print('\n');
  }
  return 0;
}

int playBuzzer() {
  tone(buzzer, 500); // Send 1KHz sound signal...
  delay(100);        // ...for 1 sec
  noTone(buzzer);     // Stop sound...
  return 0;
  }

int soundAlarm() {
  int alarmVal = digitalRead(alarmPin);
  if (alarmVal == HIGH) {
      while(buzzCount <= buzzCountMax) {
      tone(buzzer, 1000);
      delay(100);
      tone(buzzer, 500);
      delay(100);
      buzzCount++;
      noTone(buzzer);
      }
   return 0;
  }
}

…R

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

Also, there is a simple user-input example in Planning and Implementing a Program

...R

Robin2…

As far as I can tell I didn’t break any of the rules on the forum as specified. My program is short < 150 lines.

I will review your information.

Thank you.
Jim

 if (goDoIt == 49)

Did you mean if (goDoIt == '1')?

Nope, that's where I started the Arduino console or PuTTY sends back 1 = ACSII = 49. That's not my problem.

My problem is that I have to ask twice to get what I'm asking for.

It's like I'm getting data stuck in a buffer or something.

For example...

PuTTY connection to Arduino... I hit a "1" 17:24:28 1/12/2020

Wait a little.... "1" again... 17:24:30 1/12/2020

Then "1" again... 17:26:1 1/12/2020 Which it the right time.

I'm really baffled by this. Which is why I posted. I'm not sure how to fix it.

I'm not really a Newbie, just new to Arduino. I've been doing this stuff for about 20 years. Confused as to why it's not working the way I think it should work.

I have looked at this program over and over, and can't figure out why it does what it does.

Everything up to the point of setting up the IF loop to only respond if serial data in = 1 was working perfectly.

I've had my buddies look at the program, they think it's ok.

I posted here because I have no one else to ask to figure it out on my own.

jhamelic: It responds, but I have to ask twice...to get the right time from the module, and I can't figure out why.

Now that we have finally got the program in an easy-to-study format can you tell us what part of the program this refers to - what part needs to be done twice?

Also, please post a link to the datasheet for the RTC clock you are using.

My wild (very wild) guess is that there are some extraneous characters in the data going to the RTC (or coming from it) so that the communication is not in sync and they get cleared out by the second request.

...R

The Pocket Watch B module is older. I was using it on a Basic Stamp.

I’ve modified my code a little playing with delay’s in different places. The datasheet states that there must be at least 500 microseconds between TX and RX.

I’m still getting the same results. A what I’m going to call “ghost data” coming back at this point.

Serial Monitor with timestamp turned on. Keep in mind the time between the PC and RTC is a little off.

20:46:20.603 → 20:46:13 1/14/2020 <—Last time I checked

20:53:16.531 → 20:46:16 1/14/2020 <–Check again at 20:53

20:53:18.570 → 20:53:12 1/14/2020 ← Second check, correct on-board time comes back.

Next step is to break out the Oscilloscope to see if I can see a response from the module several seconds later.

Since the module is older I didn’t have any luck finding a live link to it, so I’m attaching a copy.

PWB_DS_1.pdf (131 KB)

Try adding this before readTheTime():

while(Serial1.available())
  Serial1.read();

and change:

  if (Serial1.available()) {
    Serial1.readBytes(theTime, 7);
    Serial.print(theTime[2],DEC);
    Serial.print(":");
    Serial.print(theTime[1], DEC);
    ...
  }

to this:

  while (Serial1.available() < 7);

  Serial1.readBytes(theTime, 7);
  Serial.print(theTime[2],DEC);
  Serial.print(":");
  Serial.print(theTime[1], DEC);
  ...

I can’t guarantee that the above changes will fix it, but it should help to ensure there aren’t any buffering issues. Also note that the second change is blocking code (to lazy rn to make it non-blocking, would require a refactor of your entire code more or less).

You can try this variant of your code (compiles, not tested…):

/*
  An attempt to communicate with a Pocket Watch B module
  seconds, minutes, hours, days,months, years low, years high
     0        1       2      3     4      5            6
*/

// Golbal variables
int goDoIt;
int setTimeFlag = 0;
int setAlarmFlag = 0;
int buzzCount = 0;
int buzzCountMax = 30;
const int buzzer = 7; //buzzer to arduino pin 7
const int alarmPin = 9;
  
void setup() 
{
    // initialize both serial ports:
    Serial.begin(9600);
    Serial1.begin(9600);
    pinMode(buzzer, OUTPUT);
    pinMode(alarmPin, INPUT);
    
}//setup

void loop() 
{
    if (setTimeFlag == 1) 
    {
        setTheTime();
        setTimeFlag = 0;
        
    }//if

    if( setAlarmFlag == 1 ) 
    {
        setAlarmTime();
        readAlarmTime();
        setAlarmFlag = 0;
        
    }//if

    delay (100);

    if (Serial.available()) 
    {
        goDoIt = Serial.read();
        Serial.print(goDoIt);
        Serial.print("\n");
        Serial.print("\r");
        if (goDoIt == 49) 
        {
            readTheTime();
            playBuzzer();
            
        }//if
        
    }//if
   
    if( buzzCount <= buzzCountMax ) 
    {
        soundAlarm();
        
    }//if
    
}//loop

int setTheTime() 
{
    byte setTime[] = {85, 16, 0, 50, 15, 4, 1, 20, 20};
    Serial1.write(setTime, 9);
    
    return 0;
}

int setAlarmTime() 
{
    byte turnAlarmOff[] = {85, 21};
    
    Serial1.write(turnAlarmOff,2);
    
    // 12:30:00 1/5/2020
    // seconds,minutes, hours, days, months, years low, years high
    byte setAlarmData[] = {85, 17, 0, 00, 16, 12, 1, 20, 20};
    Serial1.write(setAlarmData,9);
    
    byte turnAlarmOn[] = {85, 20};
    Serial1.write(turnAlarmOn,2);
    
    return 0;
}

bool readPocketWatch( byte *Msg, byte numTXBytes, byte *Reply, byte numRXBytes, unsigned long tOut )
{
    unsigned long
        timeRX;

    //flush any lingering characters from RX buffer
    while( Serial1.available() > 0 )
        Serial1.read();
        
    Serial1.write( Msg, numTXBytes );
    timeRX = millis();
    
    while( true )
    {
        if( millis() - timeRX >= tOut )
            return false;
                
        if( Serial1.available() > 0 )
        {
            do
            {
                *Reply = Serial1.read();
                Reply++;
                
                numRXBytes--;
                if( numRXBytes == 0 )
                    return true;
                                    
            }while( Serial1.available() > 0 );
            
        }//if
        
    }//while
        
}//readPocketWatch

int readTheTime() 
{
    // Send read time to the PWB
    byte readTime[] = {0x55, 0x12};
    byte theTime[7];

    if( readPocketWatch( readTime, 2, theTime, 7, 2000 ) )
    {
        Serial.print( theTime[2],DEC );
        Serial.print( ":" );
        Serial.print( theTime[1], DEC );
        Serial.print( ":" );
        Serial.print( theTime[0],DEC );
        Serial.print( " " );
        Serial.print( theTime[4], DEC );
        Serial.print( "/" );
        Serial.print( theTime[3],DEC );
        Serial.print( "/" );
        Serial.print( theTime[6], DEC );
        Serial.print( theTime[5], DEC );
        Serial.print( "\n" );
        
    }//if
    else
        Serial.print( "readTheTime: Timeout waiting for reply\n" );
        
    return 0;
    
}//readTheTime

int readAlarmTime() 
{
    byte readAlarmCode[] = {85, 19};
    byte alarmTime[7];
    
    if( readPocketWatch( readAlarmCode, 2, alarmTime, 7, 2000 ) )
    {
        Serial.print( alarmTime[2], DEC );
        Serial.print( ":");
        Serial.print( alarmTime[1], DEC );
        Serial.print( ":");
        Serial.print( alarmTime[0],DEC );
        Serial.print( " ");
        Serial.print( alarmTime[4], DEC );
        Serial.print( "/");
        Serial.print( alarmTime[3],DEC );
        Serial.print( "/");
        Serial.print( alarmTime[6], DEC );
        Serial.print( alarmTime[5], DEC );
        Serial.print( "\n" );
        
    }//if
    else
        Serial.print( "readAlarmTime: Timeout waiting for reply.\n" );
            
    return 0;
    
}//readAlarmTime

int playBuzzer() 
{
    tone( buzzer, 500 ); // Send 1KHz sound signal...
    delay( 100 );        // ...for 1 sec
    noTone( buzzer );     // Stop sound...
    
    return 0;
    
}//playBuzzer

int soundAlarm() 
{
    int alarmVal = digitalRead(alarmPin);
    if( alarmVal == HIGH ) 
    {
        while(buzzCount <= buzzCountMax) 
        {
            tone(buzzer, 1000);
            delay(100);
            tone(buzzer, 500);
            delay(100);
            buzzCount++;
            noTone(buzzer);
            
        }//while
        
        return 0;
        
    }//if
    
}//soundAlarm