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:

sensorNET - Project Update

I have been working on the sensorNET project and I thought it was time for an update on where I am at the moment. As I go about developing the code, new questions arise and sometimes, those questions push the project into some new direction I never considered before.

Consider the following shematic:
The connections from the console to the client boards is nothing new (we distribute both power and data connections to the clients). There's also nothing new in that the main console connects to a main server that organizes and saves data sent from the console and makes that data available through user interaction with read and write APIs (the thingspeak and pachube model).

New proposed server extra-functionality
If we consider the above, however a few questions arise, specially if we want to make this project truly universal, to the point where anybody can contribute with new client boards. Those new client boards need to have a set of commands that the main console cannot know beforehand and must be declared to the main console afterwards without reloading firmware.

Since we are connected to the internet (or to a LAN server) anyway, we may store the parameters of each new board on that server and then send the configuration to the main console once it detects that type of client connected to it. If we follow a clear standard it is possible for he main console to handle future boards.

Conceptually, the main server will require a table to store new device data (table_device: id, developer_name, board name, description) and another to store the list of commands the new client may receive from the master console (table_device_command: id, device_id, command_value, command_description).

Developers of new client boards need only to register their boards and specify their commands. Needless to say this allows for complex boards, capable of simultaneous input and output. For example, we can have a board that has a temperature sensor and a relay output. Sending a 0x01 to the i2C address that board is connected to will make the board send the temperature value back, if we send a 0x02, we activate the relay. Sending 0x03 deactivates the relay.

The concept of rules
After the user configures the network parameters and the server address on the main console using a serial connection (possibly dedicated configuration software will have to be developed, more on this on another post), we are left with a board connected to I/O and in turn connected to the internet. The input data may be local or remote and we may act on the world depending on the data received. For example if we consider a system that contains two relays (R1 and R2), one controllable LED, a local temperature sensor (that may live on the same board as the relays or on another connected to the same console) but also reads a temperature feed from another public feed from another user available on the server. In summary we have:

a) one local input (temperature)
b) one remote input (temperature from another feed)
c) one output R1
d) one output R2
e) one output controllable LED L1

and we would like to achieve the following:

1. post our temperature data to a public feed on the network server
2. activate relay 1 if local temperature above 25
3. activate relay 2 if remote temperature above 25
4. deactivate relay 1 if local temperature below 22
5. deactivate relay 2 if remote temperature below 22
6. activate LED if both local and remote temperature above 25
7. achieve this without uploading new firmware on the main console

To do this we could make use of the concept of rules, which is a list of actions specified on the server that would look a bit like a list of firewall rules. These are then uploaded to the main console that saves them on EEPROM and then starts playing the new rules after a reset (I can't get rid of the need to do a board reset).

Because we are connected to a server some of the actions to be taken (Outputs) may be on server side, for example send an email or an sms through a sms service.

I'm quite confident I can achieve what I describe above. See my next post for the status of the programming on the project and for the code as it is at the moment.

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):

Monday, January 16, 2012

sensorNET - Maximum sensor cable distance

While developing the boards for the sensorNET project, I thought about using i2C as the bus the client sensors connect to. This is because atMEGA328P supports it well and the wire library for the arduino is stable and mature. The problem I thought I could have was related to the maximum cable length specified for the i2C protocol which is, after all, used as inter-chip communicator, i.e. between chips that are located quite close, often within the same PCB.

The maximum cable capacitance for use with i2C seems to be between 400 to 500 pF (see this and this). I think at this point it is reasonable to assume I will be using 4 core cables (2 supply + 2 data, SCL and SDA) and probably we will go to something similar to CAT-5 cable (2 + 2+ 2 extra), depending on cost.

The capacitance of cat-5 cable is 50 to 70pF per meter at 100KHz (see here, page 10). Considering the worst case scenario (400/ 70 =) 5.7m is therefore the maximum cable length between the sensors and the main console. This seems very reasonable to me.

Friday, January 13, 2012

sensorNET - utility to initialize arduino EEPROM

On the sensorNEt project I'm saving data to EEPROM and, during development, I have the need to test programming with the EEPROM as it comes from factory, i.e. with all bytes set to 0xFF. because I write and clear the memory meny times, I needed a fast program to re-initialize the EEPROM to 0xFF. Yes it's simple but it's always a good sketch to keep on the utilities folder (besides, it displays a nice progress line on the serial monitor!!.

Here it goes:

/*this sketch initializes EEPROM with 255 for all addresses*/
/*for atMEGA 328P */
#include <EEPROM.h>
void setup(){
  Serial.begin(9600);
  Serial.println("Started!");
  int counter = 0;
  //write a new "." every counter_step
  int counter_step = 32;
  int current_step = 32;
  for (int i = 0; i < 1024; i++){
    EEPROM.write(i, 0xFF);
    if (counter == current_step){
      Serial.print(".");
      current_step = current_step + counter_step;
    }
    counter++;    
  }
  Serial.println();
  Serial.println("Complete! EEPROM reinitialized!");
}
void loop(){
//nothing to do here! 
}

sensorNET - configure network parameters on the main console

After some thought I decided the following regarding the code for the main sensorNET console:

1. Main console system, comes out of the box with DHCP support (I have this currently running rock-solid). This will work for 90% of the users.
2. If the user requires static IP addresses he/ she can do so by plugin in an USB cable and configure the console that way. I still have to decide if I will make a program to interface with the console (although only for windows as that's the only platform I can really program stuff for) or through some kind of serial interface.

Here's the header of the latest .ino file:

/*
console13012012.ino
This version features:
1. DHCP client coded in (implemented).
2. Possibility of changing network configuration through serial connection (development).
Serial comms protocol:
a) console receives a 1 (SEND OUT COMMAND network info command):
serial send out current network configuration as:
[STATIC or DHCP] IP: XXX.XXX.XXX.XXX SN: XXX.XXX.XXX.XXX GW: XXX.XXX.XXX.XXX
info. This is fetched from EEPROM if static or SRAM if DHCP.
b) console receives a 2 (STANDBY for option DHCP or STATIC)
if receive "DHCP" run DHCP code
if receive "STATIC":
request IP address, format XXX.XXX.XXX.XXX (must be valid),
request and standby for subnet, format XXX.XXX.XXX.XXX (must be valid)
request and standby for gateway, format XXX.XXX.XXX.XXX (can be empty)
Save data to EEPROM
Perform hard reset to activate changes
**proceed only when above code is rock solid**
4. user logs in to assigned/ chosen IP address with a browser and gets
diags + sensor list on browser window.
*/

First version of the .ino file to be published within a week with at least the above implemented.

Sunday, January 8, 2012

Force internet connections through one specific network adapter with windows 7

For the sensorNET project, I'm using a development PC (simply my personal laptop) to develop the code for the two main components of the system, namely the main console and the client sensor boards. To do that I need to be connected to the main console on a LAN as this is the use normal users will give the system.

To that end, I connected a cable from my computer to a router. At the same time I need to keep using the internet which, in my case, is accessible through my wireless adapter. The problem is that as soon as I connect the wired network, I loose internet connectivity. As soon as I unplug the cable, the wireless internet connection resumes.

What I think is happening is that the computer routes the traffic that is meant to the internet through the wired connection whenever the connection is available. Apparently windows chooses the adapter with the wider bandwidth to route internet traffic through. How can I prevent this from happening? How can I force internet traffic through one specific adapter?

Depending on your requirements, one of the easiest ways is to go to Network Connections -> right click the wired connection icon -> choose properties -> select "Internet Protocol Version 4 (TCP/ IPv4)" -> click the "Properties" button.

Now on the window that appears, force the computer to use a specific IP address and subnet mask (in my case respectively 10.0.0.14 and 255.255.255.0) but leave the default gateway empty. If you fill in the default gateway IP with the IP of your LAN router, the wireless internet connection will still not work.

This will work. But what if I want the wired connection to use a DHCP assigned IP address? The problem is that on the "Internet Protocol Version 4 (TCP/ IPv4)" properties window, if you choose the option to Obtain an IP address automatically, the setup will not work again!

So we need another solution to the problem in case DHCP assigned IP addresses are required.

The first thing is to keep both interfaces on automatically assigned IP addresses, because this is our requirement, next issue the following command on the command prompt:

c:\ netstat -rn | more

Note the table at the top called "Interface list" and see all your NICs on the list. Just to confirm you are in the right place, see the first number on the left that is a 1 and confirm that corresponds to "Software Loopback Interface 1".

You will also note that the number on the left for your wireless adapter is higher than the one for your wired NIC. This is what makes the computer choose one or the other when both are available - the one with the lowest number is used first. We need to change the priority of the cards (or, in this case, we need to change the metric of the wireless card so that it is lower than the wired card).

Go to "Local Area Connection Properties", the properties window we used before but this time open the one for the wireless card - we want to change it's metric to make it lower than the wired card.  Select "Internet Protocol Version 4 (TCP/ IPv4)" -> click the "Properties" button -> click "Advanced..." and uncheck "Automatic metric". Insert any number lower than the number of your wired NIC but that does not yet exist on the list.

Save your changes and verify that the internet packages are now routed through the wireless connection and forever will be unless you go back on these changes.