Go Down

Topic: strange issue with ethernet class (Read 833 times) previous topic - next topic

zarobhr

arduino 1.02
Uno R3
vfd\lcd display via I2C

i am using the ethernet class distributed with the IDE

here are code snippets, I have removed everything in the loop since it does not pertain to the specific issue

my goal is to be able to change the ip address via a keypad and display (i will store it later)
i would like to display and modify the existing IP (it is ip and assigned in code)
if i do this
Code: [Select]
IPAddress ip(192,168,10, 177);
lcd.print(ip)


it display correctly on lcd, if i change the 10 to 010, it will print the ip address as 192.168.8.177 instead of 192.168.10.177
i would really like to know if there is a way to the ipaddress that is stored in ip into another format so that i can display it as 192.168.010.177 (note leadng 0) so i can easily change via keypad
(that portion of code works but need 3 digits then decimal three digits the decimal etc. and i dont want to have to type the dots when typing it(also working)


Code: [Select]
#include <Keypad_I2C.h>
#include <EEPROM.h>
#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Keypad.h>
#include <MagStripe.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20,6,5,4,0,1,2,3);
int SEvent = 0;         // incoming serial byte
int EGMTx = 0;
int TimeOut =20;
byte enable[5] = {0x01,0x0E,0x01,0x45,0xD1};
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,10,177);
IPAddress gateway(192,168,10, 2);
IPAddress subnet(255, 255, 255, 0);
const byte rows = 3; //four rows
const byte cols = 4; //three columns
char keys[rows][cols] = {
  {'1','2','3','C'} ,
  {'4','5','6','0'} ,
  {'7','8','9','E'}};
byte rowPins[rows] = {0,1,2}; //connect to the row pinouts of the keypad
byte colPins[cols] = {6,5,4,3}; //connect to the column pinouts of the keypad
int i2caddress = 0x21;
Keypad_I2C keypad = Keypad_I2C( makeKeymap(keys), rowPins, colPins, rows, cols, i2caddress );
template<class T>
void MyLCD(byte col, byte row, T t);
// function definition
template<class T>
void MyLCD(byte col, byte row, T t)
{
  lcd.setCursor(col,row);
  lcd.setCursor(col,row);
  lcd.print(t);
}
MagStripe card;

/*
* Track 3 is the one that can contain the most characters (107).
* We add one more to accomodate the final '\0', as the data is a C string...
*/
static const byte DATA_BUFFER_LEN = 108;
static char data[DATA_BUFFER_LEN];
static bool cardinsert = 0;
static bool cardallin = 0;
short myChars = 0;
byte mySrvCmd = 0;
// telnet defaults to port 23
EthernetServer server(8888);
boolean alreadyConnected = false; // whether or not the client was connected previously
long previousMillis = 0;
long interval = 1000;
long lpcount = 0;
byte sendInfo = 0;
int value;
void setup() {
  lcd.begin(20, 2);
  if ( value = EEPROM.read(0) == 255)
  {
    lcd.setCursor(0, 0);
    //size_t before = getFreeMemory ();

    //lcd.print(before);
    getipaddress();
    delay(1000000);
  }



  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);
  // start listening for clients
  //server.begin();
  // Open serial communications and wait for port to open:



  lcd.print("CMS");
  lcd.setCursor(10, 0);
  lcd.print("No Card  ");
  lcd.setCursor(5, 1);
  lcd.print("Insert Card    ");
}

void loop() {

}
void getipaddress()
{
  //char IPaddr[16]= {'0','0','0','.','0','0','0','.','0','0','0','.','0','0','0'    };
  char IPaddr[16]= {ip};
  boolean goodIP = false;
  byte IPpos = 1 ;
  lcd.setCursor(7,0);
  lcd.print("Enter IP Address");
  lcd.setCursor(1,1);
  lcd.print(ip);
  //lcd.print("000.000.000.000");
  lcd.setCursor(1,1);
  lcd.blink();
  do
  {
    char key = keypad.getKey();

    if (key != NO_KEY){
      if (key == 'C')//backup
      {
        if (IPpos == 5 || IPpos == 9 || IPpos == 13)//skip over decimal
        {
          IPpos -= 2;
          lcd.setCursor(IPpos, 1);
        }
        else if (IPpos == 1) //dont pass to left of first digit of ip
        {
        }
        else
        {
          IPpos -= 1;
          lcd.setCursor(IPpos, 1);
        }
      }
      else if(key == 'E')
      {
        //code to validate and save to eeprom
        wdt_enable (WDTO_1S);
        while (true) ;



        if (IPpos == 15)
        {
          lcd.setCursor(4, 0);

          lcd.print(IPaddr);
        }
        else if (IPpos == 3 || IPpos == 7 || IPpos == 11)
        {
          lcd.setCursor(IPpos+2, 1);
          IPpos += 2;
        }
        else
        {
          lcd.setCursor(IPpos+1, 1);

          IPpos += 1;
        }
      }
      else
      {
        if (IPpos == 1 || IPpos == 5 || IPpos == 9 || IPpos == 13)
        {
          if (key > '2')
          {
            key = '2';
          }
          lcd.setCursor(IPpos, 1);
          IPaddr[IPpos - 1] = key;
          lcd.print(key);
          IPpos += 1;
        }
        else if (IPpos == 2 || IPpos == 6 || IPpos == 10 || IPpos == 14)
        {
          if (IPaddr[IPpos - 2] == '2' && key > '5')
          {
            key = '5';
          }
          lcd.setCursor(IPpos, 1);
          IPaddr[IPpos - 1] = key;
          lcd.print(key);
          IPpos += 1;
        }
        else if (IPpos == 3 || IPpos == 7 || IPpos == 11 || IPpos == 15)//skip over decimal
        {
          if (IPaddr[IPpos - 3] == '2' && IPaddr[IPpos - 2] == '5' && key > '5')
          {
            key = '5';
          }
          else if (IPaddr[IPpos - 3] == '0' && IPaddr[IPpos - 2] == '0' && key == '0' && (IPpos == 3 || IPpos == 15))
          {
            key = '1';
          }
          lcd.setCursor(IPpos, 1);
          IPaddr[IPpos - 1] = key;
          lcd.print(key);
          if (IPpos == 15)
          {
            lcd.setCursor(IPpos , 1);
          }
          else
          {
            lcd.setCursor(IPpos+2, 1);
            IPpos += 2;
          }
        }

        else
        {
          //lcd.setCursor(IPpos, 1);
          //lcd.print(key);
          //IPpos += 1;
        }
      }
    }
  }
  while (goodIP == false);
}


PaulS

Quote
it display correctly on lcd, if i change the 10 to 010, it will print the ip address as 192.168.8.177 instead of 192.168.10.177

That happens because any constant that starts with a 0 is an octal constant. 010 = 8.

Quote
i would really like to know if there is a way to the ipaddress that is stored in ip into another format so that i can display it as 192.168.010.177 (note leadng 0) so i can easily change via keypad

Sure. Store the data as a string. Parse and convert to int as required.

zarobhr

#2
Jan 02, 2013, 09:42 pm Last Edit: Jan 02, 2013, 09:45 pm by zarobhr Reason: 1

Quote
it display correctly on lcd, if i change the 10 to 010, it will print the ip address as 192.168.8.177 instead of 192.168.10.177

That happens because any constant that starts with a 0 is an octal constant. 010 = 8.

Quote
i would really like to know if there is a way to the ipaddress that is stored in ip into another format so that i can display it as 192.168.010.177 (note leadng 0) so i can easily change via keypad

Sure. Store the data as a string. Parse and convert to int as required.

Thanks good to know about leading 0,

since i am pulling the ip address from the the ethernet library and it appears to be stored as a 4 byte array so i can do a loop through that array to get each octet. is there a command to take the numerice value 192 or any value in that case and convert to a char array so char myarray[0] would = 1, myarray[1] would = 9, myarray[2] would = 2, etc, etc or would i have to convert to a string first then parse it out and take each character to the array

in VB i have a num2BCD funtion that does this (takes any value and converts to a byte array but know clue how do to on arduno

PaulS

Quote
is there a command to take the numerice value 192 or any value in that case and convert to a char array

itoa()

zarobhr


Quote
is there a command to take the numerice value 192 or any value in that case and convert to a char array

itoa()



thanks again now hopefully just one more question is there an equivalent to array.copy so that i may take the array that was created with itoa() which i will do for all 4 octets and merge or copy them into the 1 bigger array that will have all elements of the ip address,

then once ip address is changed then i will take information back to the ip address format  using atoi() i assume

Code: [Select]
char octet[3] = {}; 
char IPaddr [16] = {};
itoa ( ip[0], octet, 10 );
array.copy(octet,0,IPaddr,0,3); // looking for a way to do this in arduino
itoa ( ip[1], octet, 10 );
array.copy(octet,0,IPaddr,3,3); // looking for a way to do this in arduino
  boolean goodIP = false;
  byte IPpos = 1 ;
  lcd.setCursor(7,0);
  lcd.print("Enter IP Address");
  lcd.setCursor(1,1);
  for (byte xxx = 0; xxx < 16; xxx++)
  {
  lcd.print(IPaddr[xxx]);
  }

zarobhr

I think this needs moved to programming since not really a ethernet issue although it is an ip address

Getting Closer found memcpy

now need to figure a way to pad octet with leading 0 if the value was 99 or less

my ouput looks like this

X92.168.20X.177    where X is a block(garbage character) the first on on first char i am unsure why it is a block
the second X is becuase i need to figure a way to do a leading 0 if value is less than 99



Code: [Select]
char octet[3] = {}; 
char IPaddr [15] = {};
itoa ( ip[0], octet, 10 );
memcpy(IPaddr  , octet, 3);
itoa ( ip[1], octet, 10 );
memcpy(IPaddr + 4 ,octet, 3);
itoa ( ip[2], octet, 10 );
memcpy(IPaddr +8, octet,3);
itoa ( ip[3], octet, 10 );
memcpy(IPaddr + 12 ,octet,3);
IPaddr[3] = '.';
IPaddr[7] = '.';
IPaddr[11] = '.';
  boolean goodIP = false;
  byte IPpos = 1 ;
  lcd.setCursor(7,0);
  lcd.print("Enter IP Address");
  lcd.setCursor(1,1);
  for (byte xxx = 0; xxx < 15; xxx++)
  {
  lcd.print(IPaddr[xxx]);
  }

PaulS

Quote
is there an equivalent to array.copy so that i may take the array that was created with itoa() which i will do for all 4 octets and merge or copy them into the 1 bigger array that will have all elements of the ip address,

I was going to recommend strcpy(). I think you'll find that does what you want better.

The array passed to itoa() needs to be big enough to hold the integer value as a string AND the terminating NULL. "192" is 3 bytes. The terminating NULL makes 4. Your octet array is too small.

IPaddr is too small, too. 192.168.010.001 is 15 bytes. The terminating NULL makes 16.

zarobhr

#7
Jan 03, 2013, 10:29 pm Last Edit: Jan 03, 2013, 10:33 pm by zarobhr Reason: 1

Quote
is there an equivalent to array.copy so that i may take the array that was created with itoa() which i will do for all 4 octets and merge or copy them into the 1 bigger array that will have all elements of the ip address,

I was going to recommend strcpy(). I think you'll find that does what you want better.

The array passed to itoa() needs to be big enough to hold the integer value as a string AND the terminating NULL. "192" is 3 bytes. The terminating NULL makes 4. Your octet array is too small.

IPaddr is too small, too. 192.168.010.001 is 15 bytes. The terminating NULL makes 16.

i looked at strcpy() and unless i missed it i didnt see where you could copy only certain length of the char arry i changed the size of the octet{4] and IPaddr[16] as mention i also looped it and finally have the result i want. now to put the changed ip backto to the ip address format

thanks for the help

here is the final code that you all helped with
Code: [Select]
char IPaddr [16]= "000.000.000.000";
  char octet[4] = {}; 
  byte pad = 0;
  for (byte AA = 0; AA < 4; AA++)
  {
    pad = 0;
    if (ip[AA]<100){
      pad = 1;
    }
    if (ip[AA]<10) {
      pad = 2;
    }
    itoa ( ip[AA], octet, 10 );
    memcpy(IPaddr + (AA * 4  + pad) , octet, 3-pad);

here is the entire function final code
Code: [Select]
void getipaddress()
{
 char IPaddr [16]= "000.000.000.000";
 char octet[4] = {};  
 byte pad = 0;
 for (byte AA = 0; AA < 4; AA++)
 {
   pad = 0;
   if (ip[AA]<100){
     pad = 1;
   }
   if (ip[AA]<10) {
     pad = 2;
   }
   itoa ( ip[AA], octet, 10 );
   memcpy(IPaddr + (AA * 4  + pad) , octet, 3-pad);
 }
 boolean goodIP = false;
 byte IPpos = 1 ;
 lcd.setCursor(7,0);
 lcd.print("Enter IP Address");
 lcd.setCursor(1,1);
 for (byte xxx = 0; xxx < 15; xxx++)
 {
   lcd.print(IPaddr[xxx]);
 }
 //lcd.print("000.000.000.000");
 lcd.setCursor(1,1);
 lcd.blink();
 do
 {
   char key = keypad.getKey();

   if (key != NO_KEY){
     if (key == 'C')//backup
     {
       if (IPpos == 5 || IPpos == 9 || IPpos == 13)//skip over decimal
       {
         IPpos -= 2;
         lcd.setCursor(IPpos, 1);
       }
       else if (IPpos == 1) //dont pass to left of first digit of ip
       {
       }
       else
       {
         IPpos -= 1;
         lcd.setCursor(IPpos, 1);
       }
     }
     else if(key == 'E')
     {
       //code to validate and save to eeprom also E move char by char to end to move to a diff location
       //wdt_enable (WDTO_1S); // this is there just to play with WDT reset
       //while (true) ;        //when E is press
       if (IPpos == 15)
       {
         lcd.setCursor(4, 0);

         lcd.print(IPaddr); // this is where  will call code to save ip address if E is pressed and on last digit of ip
       }
       else if (IPpos == 3 || IPpos == 7 || IPpos == 11)
       {
         lcd.setCursor(IPpos+2, 1);
         IPpos += 2;
       }
       else
       {
         lcd.setCursor(IPpos+1, 1);

         IPpos += 1;
       }
     }
     else
     {
       if (IPpos == 1 || IPpos == 5 || IPpos == 9 || IPpos == 13)
       {
         if (key > '2')
         {
           key = '2';
         }
         lcd.setCursor(IPpos, 1);
         IPaddr[IPpos - 1] = key;
         lcd.print(key);
         IPpos += 1;
       }
       else if (IPpos == 2 || IPpos == 6 || IPpos == 10 || IPpos == 14)
       {
         if (IPaddr[IPpos - 2] == '2' && key > '5')
         {
           key = '5';
         }
         lcd.setCursor(IPpos, 1);
         IPaddr[IPpos - 1] = key;
         lcd.print(key);
         IPpos += 1;
       }
       else if (IPpos == 3 || IPpos == 7 || IPpos == 11 || IPpos == 15)//skip over decimal
       {
         if (IPaddr[IPpos - 3] == '2' && IPaddr[IPpos - 2] == '5' && key > '5')
         {
           key = '5';
         }
         else if (IPaddr[IPpos - 3] == '0' && IPaddr[IPpos - 2] == '0' && key == '0' && (IPpos == 3 || IPpos == 15))
         {
           key = '1';
         }
         lcd.setCursor(IPpos, 1);
         IPaddr[IPpos - 1] = key;
         lcd.print(key);
         if (IPpos == 15)
         {
           lcd.setCursor(IPpos , 1);
         }
         else
         {
           lcd.setCursor(IPpos+2, 1);
           IPpos += 2;
         }
       }

       else
       {
         //lcd.setCursor(IPpos, 1);
         //lcd.print(key);
         //IPpos += 1;
       }
     }
   }
 }
 while (goodIP == false);

PaulS

Quote
i looked at strcpy() and unless i missed it i didnt see where you could copy only certain length of the char arry

Why do you want to copy only part of octet? Maybe what you are looking for is strcat() to append octet onto the end of IPaddr.

Go Up