Sunday, January 29, 2012

sensorNET - code

As promised on my last post, here's the code as it stands today new items tagged as [NEW]:

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).
8. [NEW]: console automatically scans up to 32 client addresses and gets board id number (to be used to collect list of commands for the board from the server) for the ones it finds.
9. [NEW]: device scanning is shown through a serial connection for debugging purposes
10. [NEW]: started developing client board code (already receives scanning command from master and replies with code id number).
11. [NEW]: Client HW includes dipswithes to set client address.
12. [NEW]: Main console HW includes 20nF capacitor between RESET and GND to allow for proper reset of the wiznet Ethernet chip (I was having trouble with this), so I think the capacitor is a requirement.

I am currently at the point where I need to start testing the physical devices with the server software. I already have some read and write APIs and a some degree of interaction with the server (create users, create feeds, etc) that I will start using until the final server code is developed by my colleagues. I will have to develop a simple client database (see my previous post on this). Probably at the end of next week I will be able to start posting some of teh server side software along with the device software.

code is posted after the break (note two segments, one for the console, another for the client) BEFORE USING run this through a text editor like notepad and replace "lessthen" by "<" - I had to do it to allow it to be posted on the blog and not be used as a HTML tag:

//MASTER CONSOLE CODE:


#include lessthenSPI.h>
#include lessthenEthernet.h>
#include lessthenEEPROM.h>
#include lessthenWire.h>

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 };
byte server_address[] = { 0, 0, 0, 0 };
int state = 0;
int incomingByte;
int char_count;
char netstring[37];//size of set network parameters string
char serverstring[12];//size of server address
char device_id[32];

EthernetServer server(80);

void setup() {
  
  Serial.begin(115200);  
  Wire.begin();
  
  //intialize device_id array:
  for (int i = 0; i lessthensizeof(device_id); i++){
   device_id[i] = 0x00;//0x00 means no device on that address
  }
  
  //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();
  get_server_address();
  
  //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 {
      print_dhcp_ip();
      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();
    Serial.print(" ");
    Ethernet.begin(mac, ip_static, subnet, gateway);
  }
  
  print_server_address();
  
  server.begin();
  
  //scan i2c bus devices:
  scan_devices();
  
}

void loop() {
  //listen for incoming Ethernet connections:
  //jumps to web_functions.ino
  listenForEthernetClients();
  
  //listen for incoming serial connections:
  if (Serial.available() > 0){
    
    incomingByte = Serial.read();
    
    if (incomingByte == 0x31 && state == 0){
      //request network info
      if (is_dhcp()){
        Serial.print ("\nDHCP ");
        print_dhcp_ip();
      }     
      else {
        Serial.print ("\nSTATIC ");
        print_static_ip();       
        print_subnet();
        print_gateway();
      }
      print_server_address();
    }
    else if (incomingByte == 0x32 && state == 0){
      //this is a request to set network parameters
      char_count = 0;
      state = 1;
    }
    else if (incomingByte == 0x33 && state == 0){
      //this is a request to set the server address:
      char_count = 0;
      state = 2;
    }
    
    if (state == 2 && char_count lessthen= 12){
      //we are going to send the server address:
      serverstring[char_count] = incomingByte;
      char_count++;
      if (char_count == 13){
        int j = 1;
        for (int i = 22; i lessthen= 25; i++){
          EEPROM.write(i,convert_to_number(serverstring[j],serverstring[j+1],serverstring[j+2]));
          j = j + 3;
        }        
        state = 0;
      }
    }
    
    if (state == 1 && char_count lessthen= 37){
      //see specs of the string to send on the comments file
      //with 37 chars
      netstring[char_count] = incomingByte;
      char_count++;
      //on the last char received, organize stuff and write to EEPROM:
      if (char_count == 38) {
        
        if (netstring[1] == 0x42) EEPROM.write(3,0);//static chosen "B"
        else EEPROM.write(3,1);//dhcp was chosen
        
        int j = 2;
        for (int i = 10; i lessthen= 21; i++){
            EEPROM.write(i,convert_to_number(netstring[j], netstring[j+1], netstring[j+2]));
            j = j + 3;
        }     
        state = 0;
      }
    }  
  }
  //get devices info:
  
  //send sensor data out:
  
  //get eventual data in from server:
  
  //act on data in from server:
  
  delay(1);
}

void print_dhcp_ip(){
      Serial.print("IP: ");
      Serial.print(Ethernet.localIP()); 
}

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; ilessthen6; i++) mac[i] = EEPROM.read(i+4);
}

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

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

void print_server_address(){       
  Serial.print (" Server: ");
  for (int i = 0; i lessthen 4; i++){
    Serial.print (server_address[i]);
    if (i != 3) Serial.print (".");
    else Serial.print ("\n");
  }   
}

void print_subnet(){
  Serial.print ("SN: ");
  for (int i = 0; i lessthen 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 lessthen 4; i++){
    Serial.print (gateway[i]);
    if (i != 3) Serial.print (".");
    else Serial.print (" ");
  } 
}

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

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

void get_server_address(){
  for (int i=0; ilessthen4; i++) server_address[i] = EEPROM.read(i+22); 
}

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

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();
  }
}#include lessthenSPI.h>
#include lessthenEthernet.h>
#include lessthenEEPROM.h>
#include lessthenWire.h>

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 };
byte server_address[] = { 0, 0, 0, 0 };
int state = 0;
int incomingByte;
int char_count;
char netstring[37];//size of set network parameters string
char serverstring[12];//size of server address
char device_id[32];

EthernetServer server(80);

void setup() {
  
  Serial.begin(115200);  
  Wire.begin();
  
  //intialize device_id array:
  for (int i = 0; i lessthensizeof(device_id); i++){
   device_id[i] = 0x00;//0x00 means no device on that address
  }
  
  //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();
  get_server_address();
  
  //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 {
      print_dhcp_ip();
      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();
    Serial.print(" ");
    Ethernet.begin(mac, ip_static, subnet, gateway);
  }
  
  print_server_address();
  
  server.begin();
  
  //scan i2c bus devices:
  scan_devices();
  
}

void loop() {
  //listen for incoming Ethernet connections:
  //jumps to web_functions.ino
  listenForEthernetClients();
  
  //listen for incoming serial connections:
  if (Serial.available() > 0){
    
    incomingByte = Serial.read();
    
    if (incomingByte == 0x31 && state == 0){
      //request network info
      if (is_dhcp()){
        Serial.print ("\nDHCP ");
        print_dhcp_ip();
      }     
      else {
        Serial.print ("\nSTATIC ");
        print_static_ip();       
        print_subnet();
        print_gateway();
      }
      print_server_address();
    }
    else if (incomingByte == 0x32 && state == 0){
      //this is a request to set network parameters
      char_count = 0;
      state = 1;
    }
    else if (incomingByte == 0x33 && state == 0){
      //this is a request to set the server address:
      char_count = 0;
      state = 2;
    }
    
    if (state == 2 && char_count lessthen= 12){
      //we are going to send the server address:
      serverstring[char_count] = incomingByte;
      char_count++;
      if (char_count == 13){
        int j = 1;
        for (int i = 22; i lessthen= 25; i++){
          EEPROM.write(i,convert_to_number(serverstring[j],serverstring[j+1],serverstring[j+2]));
          j = j + 3;
        }        
        state = 0;
      }
    }
    
    if (state == 1 && char_count lessthen= 37){
      //see specs of the string to send on the comments file
      //with 37 chars
      netstring[char_count] = incomingByte;
      char_count++;
      //on the last char received, organize stuff and write to EEPROM:
      if (char_count == 38) {
        
        if (netstring[1] == 0x42) EEPROM.write(3,0);//static chosen "B"
        else EEPROM.write(3,1);//dhcp was chosen
        
        int j = 2;
        for (int i = 10; i lessthen= 21; i++){
            EEPROM.write(i,convert_to_number(netstring[j], netstring[j+1], netstring[j+2]));
            j = j + 3;
        }     
        state = 0;
      }
    }  
  }
  //get devices info:
  
  //send sensor data out:
  
  //get eventual data in from server:
  
  //act on data in from server:
  
  delay(1);
}

void print_dhcp_ip(){
      Serial.print("IP: ");
      Serial.print(Ethernet.localIP()); 
}

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; ilessthen6; i++) mac[i] = EEPROM.read(i+4);
}

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

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

void print_server_address(){       
  Serial.print (" Server: ");
  for (int i = 0; i lessthen 4; i++){
    Serial.print (server_address[i]);
    if (i != 3) Serial.print (".");
    else Serial.print ("\n");
  }   
}

void print_subnet(){
  Serial.print ("SN: ");
  for (int i = 0; i lessthen 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 lessthen 4; i++){
    Serial.print (gateway[i]);
    if (i != 3) Serial.print (".");
    else Serial.print (" ");
  } 
}

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

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

void get_server_address(){
  for (int i=0; ilessthen4; i++) server_address[i] = EEPROM.read(i+22); 
}

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

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();
  }
}
//CLIENT CODE:
#include ;

byte address_bit_4 = 2;
byte address_bit_3 = 3;
byte address_bit_2 = 4;
byte address_bit_1 = 5;
byte address_bit_0 = 6;
byte i2c_address = 0x00;

void setup(){
  
  Serial.begin(115200);
  //read the dipswitches to get device address:
  //dipswitches connected to D2, D3, D4, D5, D6 with pull down resistors
  pinMode(address_bit_4, INPUT);
  pinMode(address_bit_3, INPUT);
  pinMode(address_bit_2, INPUT);
  pinMode(address_bit_1, INPUT);
  pinMode(address_bit_0, INPUT);
  
  address_bit_4 = digitalRead(address_bit_4);
  address_bit_3 = digitalRead(address_bit_3);
  address_bit_2 = digitalRead(address_bit_2);
  address_bit_1 = digitalRead(address_bit_1);
  address_bit_0 = digitalRead(address_bit_0);
  
  i2c_address = address_bit_4 << 4 | address_bit_3 << 3 | address_bit_2 << 2 | address_bit_1 << 1 | address_bit_0;
  
  //set slave wire address to that value:
  Wire.begin(i2c_address);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
}

void loop(){
  //collect sensor data
  
}

void requestEvent(){
  //0xFF, respond to scan_devices function from master,
  //0x00, identifies this board type
  byte aknowledge_array[2] = {0xFF, 0x01};
  Wire.write(aknowledge_array, sizeof(aknowledge_array));
  //send data or activate local output depending on master command
}

void receiveEvent(int howMany){
 //slave receives different commands from master, what does it do for each?
}

No comments: