Friday, January 20, 2012

sensorNET - console code status on the 20th January 2012

I completed the network setup console code. The code posted below includes:

1. Ability to choose DHCP or static.
2. If static, ability to set IP, subnet and gateway addresses.
3. Saves settings to EEPROM so they are available even after power down.
4. DHCP selected out of the box
5. EEPROM space for MAC address and device serial number
6. Configuration done by Serial connection at 115200baud
7. Rock solid with 12V power supply (will reset randomly with USB power only).

Things that I would like to solve with this version:

1. Ability to auto reset to activate changes (currently the user needs to use the reset button).

Next steps:

0. Organize the code in several files, instead of one large one (main, i2c, serial_comms, webclient, webserver).
1. Box the prototype boards (both main console and sensor board prototype)
2. Add screw terminal connections
3. Code i2C implementation in the main console and, at the same time,
5. code i2C code implementation on the client sensor board

code after the break (compiles with Arduino IDE version 1):



#include SPI.h> //add smaller than signal
#include Ethernet.h>  //add smaller than signal
#include EEPROM.h>  //add smaller than signal


byte ip_static[] = { 0, 0, 0, 0 };
byte mac[] = { 0, 0, 0, 0, 0, 0 };
byte subnet[] = { 0, 0, 0, 0 };
byte gateway[] = { 0, 0, 0, 0 };
int state = 0;
int incomingByte;
int char_count;
char netstring[46];


EthernetServer server(80);


void setup() {
  
  Serial.begin(115200);  


  //is this the first time running the program?
  if (EEPROM.read(2) == 255){
    //if so, we need to program the ROM with defaults (basically set DHCP):
    EEPROM.write(3, 1); 
    //and also save the intended MAC address of the console:
    EEPROM.write(4, 0x00);
    EEPROM.write(5, 0xAA);
    EEPROM.write(6, 0xBB);
    EEPROM.write(7, 0xCC);
    EEPROM.write(8, 0xDE);
    EEPROM.write(9, 0x02);
    //and also program the device serial number:
    EEPROM.write(0, 0); //most significant byte of serial number
    EEPROM.write(1, 1); //least significant byte of serial number
    //and set address 2 to 0 to indicate this has run before
    EEPROM.write(2, 0);
    //after the line above there's no way to repeat the code above
    //unless we run another program on the avr that initializes EEPROM
    //address 2 to 255.
  }
  
  //now, load configuration values from EEPROM, and initialize console:
  
  //load saved MAC address
  get_mac();
  
  //it's DHCP, ask for network config data:
  if (is_dhcp()){  
    Serial.print("\nDHCP request..."); 
    if (Ethernet.begin(mac) == 0) Serial.println("request failed");
    else { 
      Serial.print("IP: ");
      Serial.print(Ethernet.localIP());
      Ethernet.begin(mac, Ethernet.localIP());
    }
  }
  
  //ok, it's not DHCP, it's static:
  else {    
    Serial.print("\nSTATIC ");  
    get_static_ip();  
    get_subnet();
    get_gateway();
    print_static_ip();       
    print_subnet();
    print_gateway();
    Ethernet.begin(mac, ip_static, subnet, gateway);
  }
  
  server.begin();
  
}


void loop() {
  //listen for incoming Ethernet connections:
  //jumps to web_functions.ino
  listenForEthernetClients();
  
  //listen for incoming serial connections:
  //jumps to serial_functions.ino
  if (Serial.available() > 0){
    
    incomingByte = Serial.read();
    
    if (incomingByte == 0x31 && state == 0){
      //request network info
      if (is_dhcp()){
        Serial.print ("\nDHCP ");
        Serial.print ("IP: ");
        Serial.print (Ethernet.localIP());
      }     
      else {
        Serial.print ("\nSTATIC ");
        print_static_ip();       
        print_subnet();
        print_gateway();
      }
    }
    else if (incomingByte == 0x32 && state == 0){
      //this is a request to set network parameters
      char_count = 0;
      state = 1;
    }
    if (state == 1 && char_count <= 46){
      //send a long string with format [A=DHCP,B=STATIC]000.000.000.000000.000.000.000
      //with 46 chars
      netstring[char_count] = incomingByte;
      char_count++;
      //on the last char received, organize stuff and write to EEPROM:
      if (char_count == 47) {
        
        if (netstring[1] == 0x42) EEPROM.write(3,0);//static chosen "B"
        else EEPROM.write(3,1);//dhcp
        
        EEPROM.write(10, convert_to_number(netstring[2],netstring[3],netstring[4]));
        EEPROM.write(11, convert_to_number(netstring[6],netstring[7],netstring[8]));
        EEPROM.write(12, convert_to_number(netstring[10],netstring[11],netstring[12]));
        EEPROM.write(13, convert_to_number(netstring[14],netstring[15],netstring[16]));
        
        EEPROM.write(14, convert_to_number(netstring[17],netstring[18],netstring[19]));
        EEPROM.write(15, convert_to_number(netstring[21],netstring[22],netstring[23]));
        EEPROM.write(16, convert_to_number(netstring[25],netstring[26],netstring[27]));
        EEPROM.write(17, convert_to_number(netstring[29],netstring[30],netstring[31]));
        
        EEPROM.write(18, convert_to_number(netstring[32],netstring[33],netstring[34]));
        EEPROM.write(19, convert_to_number(netstring[36],netstring[37],netstring[38]));
        EEPROM.write(20, convert_to_number(netstring[40],netstring[41],netstring[42]));
        EEPROM.write(21, convert_to_number(netstring[44],netstring[45],netstring[46]));


        state = 0;
      }
    }  
  }
  
  //listen for new sensor connections:
  
  //send sensor data out:
  delay(1);
}


byte convert_to_number(byte char1, byte char2, byte char3){
  byte value = (char1-0x30)*100 + (char2-0x30)*10 + (char3-0x30);
  return value;  
}


void get_mac(){  
  for (int i=0; i<6; i++) mac[i] = EEPROM.read(i+4);
}


void get_static_ip(){
  for (int i=0; i<4; i++) ip_static[i] = EEPROM.read(i+10);
}


void print_static_ip(){       
  Serial.print (" IP: ");
  for (int i = 0; i < 4; i++){
    Serial.print (ip_static[i]);
    if (i != 3) Serial.print (".");
    else Serial.print (" ");
  }   
}


void print_subnet(){
  Serial.print ("SN: ");
  for (int i = 0; i < 4; i++){
    Serial.print (subnet[i]);
    if (i != 3) Serial.print (".");
    else Serial.print (" ");
  }  
}


void print_gateway(){
  Serial.print ("GW: ");
  for (int i = 0; i < 4; i++){
    Serial.print (gateway[i]);
    if (i != 3) Serial.print (".");
    else Serial.print (" ");
  } 
}


void get_subnet(){
  for (int i=0; i<4; i++) subnet[i] = EEPROM.read(i+14);
}


void get_gateway(){
  for (int i=0; i<4; i++) gateway[i] = EEPROM.read(i+18);
}


boolean is_dhcp(){
  boolean dhcp = true;
  if (EEPROM.read(3) == 0) dhcp = false;
  return dhcp;
}


/********************************************************************/
//Related to Ethernet connections
/********************************************************************/


void listenForEthernetClients() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("Got a client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          // print the current readings, in HTML format:
          client.print("Test");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}

No comments: