return() returns 0 when val in return(val) correct

Hi:

I have been fighting with this all day. I am trying to write the values read from a DS1307 to an I2C based LCD Display.

I have the display working perfectly and can write anything I want, move the cursor around and anything else I want it to do.

I have two functions that take the value that is read from the DS1307 and split it into a Tens value and a Ones value which I want to write to the cursor locations I have set up.

Each of these functions tests the value of one of the digits and assigns the Hex code for the character to send to the LCD. Everything that goes to the LCD is in Hex.

I have the correct Hex value at the end of each function, but when I check the value in the main code that was supposed to flow through the return(val), it is always 0.

I don't understand why I am not getting the Hex value that is in the variable before the return().

I have commented all of the code including what it does and doesn't show correctly.

I would really appreciate any and all suggestions or comments on why this isn't working.

Thanks

Tim Vukman

The code from the main Loop() is here:

     byte RHours;                                // Setup holder for read of HOURS Register
     DS_register = DS_Hours;                        // Set desired address to HOURS
     read_DS1307(DS_address);                        // Pass values to Read Routine
     RHours = DS_data;                              // Save BCD returned from HOURS holder
     Serial.print("Hours Read :");                  // Debug write to show value read
     Serial.println(RHours, DEC);                  // Debug write of value returned  ****** PERFECT *******
     LCD_data  = 0x47;                              // Cursor Position for Hours
     LCD_data2 = 2;                            // Column 2
     LCD_data3 = 1;                            // Line   1
     write_AL202_triple(LCD_address, LCD_data, LCD_data2, LCD_data3);
     delay(100);     
     Split_DS1307_Tens(DS_data);                  // Split off the Tens digit from value read
     LCD_data = (DS_Tens, HEX);                      // Copy the value returned to data byte for LCD write function
     Serial.print("DS_Tens in Hours Loop: ");          // Show me what I have now ********ALWAYS 0*********
     Serial.println(DS_Tens, HEX);                      
     Serial.print("LCD Hours in hours loop: ");     // Show me what I will send ********Shows 10H****
     Serial.println(LCD_data, HEX);
     LCD_Send_Char(LCD_address);                    // Send WANTED HEX value to LCD
     delay(100);
     Split_DS1307_Ones(DS_data);                // Split off the Ones digit from value read
     LCD_data = (DS_Ones, HEX);                        // Copy the value returned to data byte for LCD write function
     Serial.print("LCD Ones in hours loop: ");      // Show me what I have now *******ALWAYS 0********
     Serial.println(LCD_data, HEX);                // Show me what I will send ********Shows 10H****
     LCD_Send_Char(LCD_address);
     delay(100);

These are the functions that split the value read from the DS1307:

//************************************************************************
// Split Byte Returned from DS1307 Read for Tens
//************************************************************************
byte Split_DS1307_Tens(byte Hours)
     {
      byte DS_Tens;
      DS_Tens = (Hours & 0xF0);                   // Take off the first digit
        if      (DS_Tens == 0) { DS_Tens = 0x30; }       // Swap the hex value in
        else if (DS_Tens == 1) { DS_Tens = 0x31; }
        else if (DS_Tens == 2) { DS_Tens = 0x32; }
        else if (DS_Tens == 3) { DS_Tens = 0x33; }
        else if (DS_Tens == 4) { DS_Tens = 0x34; }
        else if (DS_Tens == 5) { DS_Tens = 0x35; }
        else if (DS_Tens == 6) { DS_Tens = 0x36; }
        else if (DS_Tens == 7) { DS_Tens = 0x37; }
        else if (DS_Tens == 8) { DS_Tens = 0x38; }
        else if (DS_Tens == 9) { DS_Tens = 0x39; }
      Serial.print("DS_Tens *Split*:");             // Show me what I have
      Serial.println(DS_Tens, HEX);                     // ALWAYS CORRECT
       return (DS_Tens, HEX);                             //******SEEMS TO ALWAYS RETURN 0*************
       delay(100);
     } 
//************************************************************************
// Split Byte Returned from DS1307 Read for Ones
//************************************************************************
byte Split_DS1307_Ones(byte Hours)
     {
      byte DS_Ones;
      DS_Ones = (Hours & 0x0F);                   // Take off the second digit
        if      (DS_Ones == 0) { DS_Ones = 0x30; }       // Swap the hex value in
        else if (DS_Ones == 1) { DS_Ones = 0x31; }
        else if (DS_Ones == 2) { DS_Ones = 0x32; }
        else if (DS_Ones == 3) { DS_Ones = 0x33; }
        else if (DS_Ones == 4) { DS_Ones = 0x34; }
        else if (DS_Ones == 5) { DS_Ones = 0x35; }
        else if (DS_Ones == 6) { DS_Ones = 0x36; }
        else if (DS_Ones == 7) { DS_Ones = 0x37; }
        else if (DS_Ones == 8) { DS_Ones = 0x38; }
        else if (DS_Ones == 9) { DS_Ones = 0x39; }
      Serial.print("DS_Ones *Split*:");                // Show me what I have
      Serial.println(DS_Ones, HEX);                     // ALWAYS CORRECT
        return (DS_Ones);                              //******SEEMS TO ALWAYS RETURN 0************* 
        delay(100);
     }

This is the code that sends the Hex value to the LCD:

//************************************************************************
// LCD Send Single Character Function                   *****VERIFIED*****
//************************************************************************
void LCD_Send_Char(byte LCD_address)
     {
     Wire.beginTransmission(LCD_address); 
     Wire.send(LCD_data);
      Serial.print("LCD_data Send Single: ");          // Shows the value sent
      Serial.println(LCD_data, HEX);                       // Currently *****ALWAYS 10H*******
     Wire.endTransmission();
     delay(100);
     }

Tim,

The expressions

LCD_data = (DS_Ones, HEX);

and

return (DS_Tens, HEX);

do not do what you expect. The first expression does not somehow copy DS_One in "hex format" to LCD_data. Instead it uses the C/C++ comma operator (Comma operator - Wikipedia) to copy the value HEX to LCD_data. HEX is a constant defined as 16, and that's why you're getting unexpected 0x10s everywhere.

Regards,

Mikal

Thanks for the quick reply Mikal:

I shall have to ponder how to do what I thought I was doing. Your absolutely correct in what I thought it was doing.

Nuts!

tim

It looks like your split functions just returns the ascii values of the number.

byte Split_DS1307_Tens(byte Hours)
{
byte DS_Tens;
DS_Tens = (Hours & 0xF0); // Take off the first digit
return DS_Tens + 0x31 ; // return the ascii value
}

Its not clear why or how hex values are used. If the above doesn't solve your problem then perhaps you could clarify how you want to use hex values

No problem, Tim.

One other thing I observe... The block

DS_Tens = (Hours & 0xF0);                   // Take off the first digit
  if      (DS_Tens == 0) { DS_Tens = 0x30; }       // Swap the hex value in
  else if (DS_Tens == 1) { DS_Tens = 0x31; }
  else if (DS_Tens == 2) { DS_Tens = 0x32; }
  else if (DS_Tens == 3) { DS_Tens = 0x33; }
  else if (DS_Tens == 4) { DS_Tens = 0x34; }
  else if (DS_Tens == 5) { DS_Tens = 0x35; }
  else if (DS_Tens == 6) { DS_Tens = 0x36; }
  else if (DS_Tens == 7) { DS_Tens = 0x37; }
  else if (DS_Tens == 8) { DS_Tens = 0x38; }
  else if (DS_Tens == 9) { DS_Tens = 0x39; }

will not do what you expect because DS_Tens can never be 1-9 (although it could be 0).

Mikal

Sorry, mem! Cross post. :slight_smile:

A small mod:

byte Split_DS1307_Tens(byte Hours)
{
byte DS_Tens;
DS_Tens = (Hours & 0xF0); // Take off the first digit
return (DS_Tens >> 4) + '0'; // return the ascii value
}

This assume that "Hours" is stored in BCD which seems a little dubious to me too, mem.

Mikal

(DS_Tens >> 4) + '0'

I would have never thought of that!

I always use (DS_Tens >> 4) | 0x30

My thanks to all:

This i2c display can be controlled either through Hex, Decimal or ASCII. (Matrix Orbital AL202) and I went with Hex as it seemed the easiest for me, but it really doesn't matter. I have gone through all of my display code and changed everything over to decimal. I am able to write to it and post whatever characters I want as I was before.

What I can't seem to do it pass the values back from my routine that splits the digits I get from reading the DS1307. I believe that I have correctly incorporated the code suggestions, but I still get the same results.

Here is the current code based on Grumpy_Mike's latest suggestion.

//************************************************************************
// Split Byte Returned from DS1307 Read for Tens
//************************************************************************
byte Split_DS1307_Tens(byte Hours)
     {
      byte DS_Tens;
      DS_Tens = (Hours & 0xF0);                     // Take off the first digit
      Serial.print("DS_Tens *Split*:");              // Show me what I have
      Serial.println(DS_Tens, DEC);                  // ALWAYS CORRECT
      return (DS_Tens>>4) | 0x30;
      delay(100);
     } 
//************************************************************************
// Split Byte Returned from DS1307 Read for Ones
//************************************************************************
byte Split_DS1307_Ones(byte Hours)
     {
      byte DS_Ones;
      DS_Ones = (Hours & 0x0F);
      Serial.print("DS_Ones *Split*:");              // Show me what I have
      Serial.println(DS_Ones, DEC);                  // ALWAYS CORRECT
      return (DS_Ones) | 0x30;      // Take off the second digit
      delay(100);
     }

My code that calls these routines from Loop():

     byte RHours;                           // Setup holder for read of HOURS Register
     DS_register = DS_Hours;                // Set desired address to HOURS
     read_DS1307(DS_address);               // Pass values to Read Routine
     RHours = bcdToDec(DS_data);                      // Save DECIMAL returned from HOURS holder
     Serial.print("Hours Read :");          // Debug write to show value read
     Serial.println(RHours, DEC);           // Debug write of value returned  ****** PERFECT *******
     LCD_data  = 71;                        // Cursor Position for Hours
     LCD_data2 = 2;                         // Column 2
     LCD_data3 = 1;                         // Line   1
     write_AL202_triple(LCD_address, LCD_data, LCD_data2, LCD_data3);
     delay(100);     
     Split_DS1307_Tens(DS_data);                   // Split off the Tens digit from value read
     LCD_data = (DS_Tens);                    // Copy the value returned to data byte for LCD write function
     Serial.print("DS_Tens in Hours Loop: ");      // Show me what I have now ********ALWAYS 0*********
     Serial.println(DS_Tens, DEC);                      
     Serial.print("LCD Tens in hours loop: ");    
     Serial.println(LCD_data, DEC);
     LCD_Send_Char(LCD_address);                   // Send WANT HEX value to LCD
     delay(100);
     Split_DS1307_Ones(DS_data);                   // Split off the Ones digit from value read
     LCD_data = (DS_Ones);                    // Copy the value returned to data byte for LCD write function
     Serial.print("DS Ones in hours loop: ");     // Show me what I have now *******ALWAYS 0********
     Serial.println(DS_Ones, DEC);                
     Serial.print("LCD Ones in hours loop: ");     // Show me what I have now *******ALWAYS 0********
     Serial.println(LCD_data, DEC);                
     LCD_Send_Char(LCD_address);
     delay(100);

and the code that sends the character :

//************************************************************************
// LCD Send Single Character Function                   *****VERIFIED*****
//************************************************************************
void LCD_Send_Char(byte LCD_address)
     {
     Wire.beginTransmission(LCD_address); 
     Wire.send(LCD_data);
      Serial.print("LCD_data Send Single: ");  // Shows the value sent
      Serial.println(LCD_data, DEC);           
     Wire.endTransmission();
     delay(100);
     }

This is the routine to convert BCD to Decimal:

//************************************************************************
// Convert binary coded decimal to normal decimal numbers
//************************************************************************
byte bcdToDec(byte val)
    {
    return ( (val/16*10) + (val%16) );
    }

Here is what is displayed by all the Serial.print statements with my comments added after the fact:

Loop                      // this is to say I'm finished setup()

Clock Register :0             //  this is the seconds register of the DS1307

Seconds Read :12           // this is what was received from reading it

LCD_data : 12                // this is what should get passed although I am not doing anything with the LCD here yet.
                                     //  The only part I am testing is the hours right now.
Clock Register :1            // DS1307 Minutes register

Minutes Read :6             // reading from minutes register

Clock Register :2           // This is the DS1307 Hours register

Hours Read :7               // Here is what is in that register

DS_Tens *Split*:0                // the tens value inside the split routine - correct data or no data.  I think correct

DS_Tens in Hours Loop: 0       // the tens value once it is back in the main loop

LCD Tens in hours loop: 0       // the tens value in the main loop that will be sent to the display

LCD_data Send Single: 0        //  the value inside the send routine.

DS_Ones *Split*:7                 // the value of the units inside the split routine - correct value

DS Ones in hours loop: 0         // the value back in the main loop - Lost the data or none returned

LCD Ones in hours loop: 0       // the value to send to the LCD

LCD_data Send Single: 0         // the value that is sent from the character send routine.

I don't understand why this doesn't work. I think it should work whether I send to the LCD in Hex or Decimal or ASCII.

I did try setting all of my LCD code using the ASCII format as well, and the results are the same.

The LCD wants to see
LCD_address
LCD_command
LCD_data

In the case of setting up row and column, these are sent as two separate values after the LCD_command to set cursor position.

In the case of sending a character, the process is to write to the LCD without the LCD_command
LCD_address
LCD_data

I am not sure what little detail I am missing

All help greatly appreciated.

Thanks

Tim Vukman

Tim,

One problem is that you have written the Split* functions to return a byte, but then you are ignoring the return value. I'm guessing you need something like

DS_Tens = Split_DS1307_Tens(RHours);
DS_Ones = Split_DS1307_Ones(RHours);

Grumpy Mike,
We were always taught to use '0' instead of 0x30, because (a) it's more readable, and (b) you never know when your code might be ported to a computer which uses a non-ASCII encoding scheme like EBCDIC where 0x30 is NOT the character code for '0'. I haven't seen an EBCDIC machine in a long time, but I still prefer the notation. I do like your bitwise | though. That's probably a bit faster than +.

Mikal

We were always taught to use

That's my trouble I was never taught anything, in those days you had to make it up yourself.
I don't think that + is intrinsically any faster than | what would speed it up is to make sure you always do it on bytes.

Thanks Mikal:

That was the secret answer. I did not see that at all. I added the DS_Tens = to the front of my function call in the main loop and the problem is solved.

I have one other return() that is bringing back a value and that is the read function. In looking at it more closely, the return is redundant in that the value is already assigned to the variable before the return is executed. In that return I also had return(val, HEX) so it's a good thing that it was being bypassed.

The reason for the (*,HEX) started from using Serial.print statements. If I don't have the , HEX I will either get nothing printed or a small box. When I add the ,HEX the value is printed in HEX, or DEC, or BIN, depending on which one I use. That made me think that it was how one designated which base was being assigned for the value.

Thanks for your help - again :slight_smile: and to all who answered

Tim

You're welcome! Glad it's working.

Yeah, it's unfortunate that

f(2, HEX);

means something so different in C than

f = (2, HEX);

but you probably won't make that mistake again! Good luck!

Mikal

No, I won't make that mistake again.

I have finished the entire display setup :slight_smile: It's a template where only the data is updated.

The next step is to make the updating smarter so that the information will only update when it changes rather than rewriting everything each time through the main loop.

19:30:35 ALARM: OFF
10/13/08 MONDAY

It fits nicely on the 20 character display.

Tim