need to connect 3 arduino's

Hello

I need to communicate values between 3 or more arduino's who can i do that??.

Like this arduino 1 and 2 send and read values from arduino 1 .

All arduinos will be 30 meters apart and need to be connected by cable.

You can use I2C:

http://www.arduino.cc/playground/Learning/I2C

Mowcius

You can use I2C

Not for a 30 metre cable you can't.

Ahh good point... I didn't see that.

Mowcius

for 30 meters what i can use ??? or can i boost the signal ???

serilal or even better RS485

serilal or even better RS485

With a reasonable cable

Who do i do that??? Do you know any example???

Ummmmm..........I really not the best person to chip into this conversation, but could something like SERIAL RF DATA LINK be an option.

http://www.electronickits.com/kit/complete/RF_Transmitters/k173.htm

This is a good starting point:

http://real2electronics.blogspot.com/2009/09/arduino-and-rs485-english-version.html

Ummmmm..........I really not the best person to chip into this conversation

Yeah I second that... ;D

All arduinos will be 30 meters apart and need to be connected by cable.

Mowcius

without designing your own interface to something else like mentioned above, Ethernet?

I have 2 arduinos communicating over a distance of 45 meters using newsoftserial, on the same connections I have piggybacked a third arduino so that it receives the same data at the same time as the 2nd one. Theres no handshaking so its just a stream of binary highs and lows, digital pins are very high impedence so you can probably feed many from the same output. I'm planning on sticking a 4th arduino piggybacking on the serial connection to number 2 on number 1. Keep the speed down and it will go a long way, mines running at 9600, all the data collected by all the arduinos sensors is available to them all its just 16 bytes of information being ferried around and updated between the 3/4 arduinos. Strictly speaking 2 of the 4 are just displays and are 'read only' but with a little more thought to the timing of the transmissions, I don't see a reason why they all can't transmit as well.

pluggy can you post your code pls of the master and slave arduino

Rather involved as they do quite a bit of stuff besides the communicating :

This is the master which has an ethernet shield so I can access it remotely :

if you find the bits with mySerial thats the communication between the arduinos.

// bidectional data for remote displays.


#include <Ethernet.h>
#include <OneWire.h>
#include <NewSoftSerial.h>



NewSoftSerial mySerial(8,9);

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 
  192, 168, 0, 201 };
//byte gateway[] = { 192, 168, 0, 1 };   //your router's IP address
//byte subnet[] = { 255, 255, 255, 0 };    //subnet mask of the network 

int ledPin = 0; // Pin 13 guzzled by ethernet
int dallasPin = 1;
int litePin = 0;
byte rxdata[30];
byte livedata[30];
byte rxdallas1;
byte rxdallas2;
byte rxdallas3;
byte rxdallas4;
byte cksum = 0;
int  rxlite;
unsigned int checksumtot = 0;


unsigned int lastgas;
unsigned int lastgas2;
unsigned long sec5loop;
unsigned long time = 0;
unsigned long time1;
unsigned long timerxlast;
unsigned long mins = 60000;
unsigned long blinktime = 0;
unsigned long totalblinks = 0; // blinks since start
unsigned long blinksmin = 0; // blinks this minute
unsigned long blinkshour = 0; // blinks this Hour
unsigned long lastblink = 0;
unsigned long prevblink = 0;
unsigned long secs = 0;
unsigned long hrs = 3600000;
unsigned long elaphrs = 0;
unsigned long elapmin = 0;
unsigned long gastimes[15];
byte dallasadd1[8];
byte data[8];
int gaspulsemin;
int i;
int dallas1;
float lightworship;
float lightfellowship;
int lite;
boolean lighton = false;
float watts1 = 0; // on elapsed time since last blink
unsigned int watts;
float rollavwatts = 100; 
float blinktimefloat = 0; 
float temp1 = 0; 
float temp = 0;
Server server(80);
OneWire  ds(dallasPin); 

void setup()
{
  Ethernet.begin(mac, ip);
  //Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  pinMode(ledPin, OUTPUT);
  mySerial.begin(9600);
  attachInterrupt(0, blink, RISING);
  ds.reset();
  ds.reset_search();
  ds.search(dallasadd1);
  ds.select(dallasadd1);
  ds.write(0x44,1); 
}

void loop()
{
  time = millis();
  elaphrs = int(time / 3600000);
  elapmin = elaphrs * 3600000;
  elapmin = time - elapmin;
  elapmin = elapmin / 60000;
  if (mySerial.available() > 15) {
    for (int c2 =0; c2 <= 15; c2++){ 

      rxdata[c2] = mySerial.read();
    }

    checksumtot = 0;
    for (int c2 =0; c2 <= 14; c2++){
      checksumtot = checksumtot + rxdata[c2];
    };  
    cksum = byte(checksumtot % 256);  
    if (cksum = rxdata[15]){
      timerxlast = time;
      rxdallas1= rxdata[0];
      rxdallas2= rxdata[1];
      rxdallas3= rxdata[2];
      rxdallas4= rxdata[3];
      rxlite = rxdata[4] * 256 + rxdata[5];
      //gaspulsemin = rxdata[14];
      lastgas = rxdata[12] * 256 + rxdata[13];
      if (lastgas != lastgas2){
        lastgas2 = lastgas;
        for (int c2 =0; c2 <= 13; c2++){ 
          gastimes[c2] = gastimes[c2 + 1];
        }
        gastimes[14] = time;
      }
    }
  }

  if (time >= secs){  // 1 second loop

    secs = time + 1000;
    blinktime = max(lastblink - prevblink,time - lastblink);
    blinktimefloat = float(blinktime) / 5;
    watts1 = 3600000 / blinktimefloat;
    watts = int(watts1);
    ds.reset();
    ds.select(dallasadd1);    
    ds.write(0xBE);         // Read Scratchpad
    for ( i = 0; i < 9; i++) { 
      data[i] = ds.read(); 
    }; 
    dallas1 = (data[1] << 8) + data[0];
    temp = float(dallas1);
    temp1 = temp/16;
    ds.reset();
    ds.select(dallasadd1);
    ds.write(0x44,1); 
    lite = analogRead(0); 
    lightworship = float(lightworship * 0.8 + lite * 0.2);
    lightfellowship = float(rxlite * 0.8 + lite * 0.2);
    
    gaspulsemin = 0;
    for (int i =0; i <= 14; i++){
      if (gastimes[i] > (time - 60000)){
        gaspulsemin = gaspulsemin + 1;
      }
    }
    
  };
 
  if (time >= mins){  // 1 minute loop
    mins = time + 60000;
    blinksmin = 0; 
    rollavwatts = rollavwatts * 0.98 + watts1 * 0.02; 
  };
  if (time >= hrs){  // 1 Hour loop
    hrs = time + 3600000;
    blinkshour = 0; 
  };

  if (time >= sec5loop){  // 5 second loop data transfer
    mySerial.flush(); 
    sec5loop = time + 5000;
    for (int c2 =0; c2 <= 15; c2++){ 
      livedata[c2] = rxdata[c2];
    }
    livedata[6] = lite / 256;
    livedata[7] = lite % 256;  
    livedata[8] = watts / 256;
    livedata[9] = watts % 256;
    
    //livedata[14] = byte(gaspulsemin);       
    for (int i =0; i <= 14; i++){
      checksumtot = checksumtot + livedata[i];
    };  
    livedata[15] = byte(checksumtot % 256);  
    //mySerial.flush();
    for (int i = 0; i <= 15; i++){ 
      mySerial.print(livedata[i]);
    }
  };

  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("Welcome to the Majestic Monitor");
          client.println("
");
          client.print("Milliseconds since start : ");
          client.print(time);
          client.println("
");
          client.print("Hours , Minutes since Start : ");
          client.print(elaphrs);
          client.print(" ");
          client.print(elapmin);
          client.println("
");
          client.print("Blinks Total , Last Min , Last Hour : ");
          client.print(totalblinks);
          client.print(" ");
          client.print(blinksmin);
          client.print(" ");
          client.print(blinkshour);
          client.println("
");
          client.print("Last Blink , Prev Blink, Last - Prev: ");
          client.print(lastblink);
          client.print(" ");
          client.print(prevblink);
          client.print(" ");
          client.print(lastblink-prevblink);
          client.println("
");
          client.print("Watts , Rolling Average Watts: ");
          client.print(watts1);
          client.print(" ");
          client.print(rollavwatts);
          client.println("
");
          client.print("Light Level: ");
          client.print(int(lightworship));
          client.print(" ");
          client.print(int(lightfellowship),DEC);
          client.println("
");
          client.print("Digital Thermometers : ");
          client.print(temp1);
          client.print(" Deg C ");
          client.print(dallas1);
          client.print(" ");
          client.print(rxdallas1,DEC);
          client.print(" ");
          client.print(rxdallas2,DEC);
          client.print(" ");
          client.print(rxdallas3,DEC);
          client.print(" ");
          client.print(rxdallas4,DEC);
          client.print(" ");
          client.println("
");
          client.print("Gas : ");
          client.print(gaspulsemin);
          client.print(" ");
          client.print(lastgas);
          client.print(" ");
          client.print(lastgas2);
          client.print(" times ");
          for( i = 0; i < 14; i++) {
           client.print(gastimes[i]/100); 
           client.print(" "); 
          }
          ;
          client.println("
");
          client.print("Checksums : ");
          client.print(cksum,DEC);
          client.print(" ");
          client.print(rxdata[15],DEC);
          client.print(" ");
          client.print(timerxlast);
          client.println("
");
          break;
        }
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } 
        else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

void blink()
{

  if (time - lastblink > 500){
    lighton = true;  
    prevblink = lastblink;
    lastblink = time;
    totalblinks ++;
    blinksmin ++;
    blinkshour ++;
  }
}

You can look at the web output here :

http://majestic81.plus.com/

Slave in next post :

//  Includes whole data for serial displays


#include <NewSoftSerial.h>
#include <OneWire.h>

NewSoftSerial mySerial(9,10);

byte rxdata[20];  // incoming master data transfer 
byte livedata[20];  // outgoing master data transfer 
int powerled = 16; // set to 16 on production 
int relay2 = 17; // analogue pin3
int relay3 = 18; // analogue pin4
int gasoptsens = 19; // analogue pin5 
int dallasPin = 13; 
unsigned int wattage;
byte dallasadd1[8];
byte dallasadd2[8];
byte dallasadd3[8];
byte dallasadd4[8];
byte data[8];
//byte gasppm = 0;
//int i;

unsigned int checksumtot = 0;
byte checksum;
byte gasppm;
byte gasppm2;
float temp;
float temp1;
int dallas1;
int dallas2;
int dallas3;
int dallas4;
byte gassensor;
float light;
int lite;
char serinput;


unsigned long time;
unsigned long lastmin = 0;
unsigned long secloop;
unsigned long minloop;
unsigned long loop1 = 1000;
unsigned long loop2;
unsigned long loop3;
unsigned long gastimes[25];



//unsigned long lastgastime = 0;
unsigned int lastgas = 0;
unsigned int lastgasr = 0;
boolean led1 = false;
boolean led2 = false;
boolean led3 = false;
boolean gaslow = false;

byte fanstate = 0;
byte cksum = 0;
OneWire  ds(dallasPin); 




void setup()  

{

  pinMode(powerled, OUTPUT);  // red LED for Fan
  pinMode(relay2, OUTPUT);  // Green LED for Boiler
  pinMode(relay3, OUTPUT);   // Green LED for Motorised valves
  //pinMode(relay3, OUTPUT);
  pinMode(gasoptsens,INPUT);
  //pinMode(relay4, OUTPUT);
  Serial.begin(115200);
  mySerial.begin(9600);
  dallas1 = 0;

  ds.reset();
  ds.reset_search();
  ds.search(dallasadd1);
  ds.search(dallasadd2);
  ds.search(dallasadd3);
  ds.search(dallasadd4);
  ds.reset();
  ds.select(dallasadd1);
  ds.write(0x44,1); 
  ds.reset();
  ds.select(dallasadd2);
  ds.write(0x44,1); 
  ds.reset();
  ds.select(dallasadd3);
  ds.write(0x44,1); 
  ds.reset();
  ds.select(dallasadd4);
  ds.write(0x44,1); 

}



void loop()                     // run over and over again

{

  time = millis();
  if (time > 60000){
      lastmin = time - 60000;
    };
  gassensor = digitalRead(gasoptsens);
  if (gassensor < 1){
    gaslow = true;
  };
  if (gassensor > 0 && gaslow){
    led2 = true;
    gaslow = false; 
    lastgas = time % 65536;
    Serial.print("GAS ");
    Serial.println(lastgas);
    for (int i =0; i <= 19; i++){
      gastimes[i] = gastimes[i + 1];
    };
    gastimes[20] = time;
    
   
  };


  if (mySerial.available() > 15) {
    for (int i =0; i <= 15; i++){ 
      rxdata[i] = mySerial.read();
    }

    checksumtot = 0;
    for (int i =0; i <= 14; i ++){
      checksumtot = checksumtot + rxdata[i];
    };  
    cksum = byte(checksumtot % 256);  
    if (cksum = rxdata[15]){
      for (int i =0; i <= 15; i++){ 
        livedata[i] = rxdata[i];
      }
    }
  } 
  /*
    livedata[0] = byte(dallas1);
   livedata[1] = byte(dallas2);
   livedata[2] = byte(dallas3);
   livedata[3] = byte(dallas4);
   lite = int(light);
   livedata[4] = lite / 256;
   livedata[5] = lite % 256;
   // livedata[6] = worshiplight / 256;
   // livedata[7] = worshiplight % 256;
   // livedata[8] = watts / 256;
   // livedata[9] = watts % 256;
   // livedata[10] = Worship temp1;
   //livedata[11] = Worship temp2 future;
   //livedata[12] =  byte( frogburgers ); //Spare;
   livedata[13] = 0; //Spare;
   
   livedata[14] = byte( gasppm ); 
   checksumtot = 0;
   for (int i =0; i <= 14; i++){
   checksumtot = checksumtot + rxdata[i];
   };  
   livedata[15] = byte(checksumtot % 256);  
   }
   
   */


  if (time >= loop2){ 
    loop2 = time + 500;
    //Serial.println(gassensor);
    if (led2){ 
      digitalWrite(relay2, HIGH); 
      led2 = false; 
    }
    else
    { 
      digitalWrite(relay2, LOW); 
      //led2 = true;
    };
  };


  if (time >= loop1 ){ 
    loop1 = time + 1000;

    if (led1){ 
      digitalWrite(powerled, HIGH); 
      led1 = false; 

    }
    else
    { 
      digitalWrite(powerled, LOW); 
      led1 = true;
    };

  }

  if (time >= secloop){  // 5 second loop

      secloop = time + 5000;
    light = light * 0.9 + analogRead(0) * 0.1; 

    //   Stops none connected Dallases crashing it.
    ds.reset();
    ds.select(dallasadd1);    
    ds.write(0xBE);         // Read Scratchpad
    for (int i = 0; i < 9; i++) { 
      data[i] = ds.read(); 
    }; 
    dallas1 = (data[1] << 8) + data[0];
    if (dallas1 < -10){
      dallas1 = dallas1 + 256;
    };
    ds.reset();
    ds.select(dallasadd2);    
    ds.write(0xBE);         // Read Scratchpad
    for (int i = 0; i < 9; i++) { 
      data[i] = ds.read(); 
    }; 
    dallas2 = (data[1] << 8) + data[0];
    if (dallas2 < -10){
      dallas2 = dallas2 + 256;
    };
    ds.reset();
    ds.select(dallasadd3);    
    ds.write(0xBE);         // Read Scratchpad
    for (int i = 0; i < 9; i++) { 
      data[i] = ds.read(); 
    }; 
    dallas3 = (data[1] << 8) + data[0];
    if (dallas3 < -10){
      dallas3 = dallas3 + 256;
    };
    ds.reset();
    ds.select(dallasadd4);    
    ds.write(0xBE);         // Read Scratchpad
    for (int i = 0; i < 9; i++) { 
      data[i] = ds.read(); 
    }; 
    dallas4 = (data[1] << 8) + data[0];
    if (dallas4 < -10){
      dallas4 = dallas4 + 256;
    };
    ds.reset();
    ds.select(dallasadd1);
    ds.write(0x44,1); 
    ds.reset();
    ds.select(dallasadd2);
    ds.write(0x44,1); 
    ds.reset();
    ds.select(dallasadd3);
    ds.write(0x44,1);
    ds.reset();
    ds.select(dallasadd4);
    ds.write(0x44,1);
    livedata[0] = byte(dallas1);
    livedata[1] = byte(dallas2);
    livedata[2] = byte(dallas3);
    livedata[3] = byte(dallas4);
    lite = int(light);
    livedata[4] = lite / 256;
    livedata[5] = lite % 256;
    // livedata[6] = worshiplight / 256;
    // livedata[7] = worshiplight % 256;
    // livedata[8] = watts / 256;
    // livedata[9] = watts % 256;
    // livedata[10] = Worship temp1;
    //livedata[11] = Worship temp2 future;
    gasppm2 = 0;
    for (int i =0; i <= 20; i++){
      if (gastimes[i] > lastmin){ 
        gasppm2 = gasppm2 + 1 ;};
    };
    wattage = livedata[8] * 256 + livedata[9];
    livedata[12] =  lastgas / 256;
    livedata[13] = lastgas % 256;
    lastgasr = rxdata[12] * 256 + rxdata[13]; // recontructed from other end
    gasppm = gasppm2;
    livedata[14] = gasppm2; 
    checksumtot = 0;
    for (int i =0; i <= 14; i++){
      checksumtot = checksumtot + livedata[i];
    };  
    livedata[15] = byte(checksumtot % 256);  
    //mySerial.flush();
    for (int i = 0; i <= 15; i++){ 
      mySerial.print(livedata[i]);
    }

    Serial.print("Temp ");
    Serial.print(dallas1);
    Serial.print(" ");
    Serial.print(dallas2);
    Serial.print(" Li ");
    Serial.print(dallas1);
    Serial.print(" chksum : ");
    Serial.print(checksumtot,DEC);

    Serial.print(" ");

    Serial.print(livedata[15],DEC);
    //frogburgers = 0;
    Serial.print(" Gas ");
    Serial.print(lastgasr);
    Serial.print(" ");
    Serial.print(gasppm,DEC);
    Serial.print(" ");
    Serial.println(gasppm2,DEC);
    //Serial.println("");
    Serial.print("Wattage ");
    Serial.println(wattage);
  }
}

Again mySerial is the communication between the arduinos.

This is the display which connects to the slave on the same pins as the link to the master.

It uses plain old Serial instead of newsoftserial and has a LCD display:

#include <LiquidCrystal.h>

byte rxdata[30];  // incoming master data transfer 
byte livedata[30];  // outgoing master data transfer 
byte cksum = 0;
byte yelLED = 9;
byte greLED = 10;
byte redLED = 11;
int relay1 = 13; // set to 16 on production 
int wattage = 1700;
int blinks ;
int blinksdone = 0 ;
unsigned int checksumtot = 0;
unsigned long time;
unsigned long loop2 = 5000;
unsigned long loop3 = 10000;
unsigned long loop1 = 1000;
boolean led1 = false;
char buff[15];
float elec;
float gas;
LiquidCrystal lcd(3, 4, 8, 7, 6, 5);
//NewSoftSerial mySerial(9,10);

void setup()  

{
  Serial.begin(9600);
  //mySerial.begin(9600);
  pinMode(relay1, OUTPUT);  // red LED for Fan
  pinMode(yelLED, OUTPUT);
  pinMode(greLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  led1 = false;
  lcd.begin(16, 2);
  for (int i =0; i <= 15; i++){ 
    livedata[i] = 0;
  }
  //mySerial.print("Hello Stephen");  
}



void loop()                     // run over and over again

{

  time = millis();
  if (time >= loop1){
    loop1 = time + 1000;
    if (led1){ 
      digitalWrite(relay1, HIGH); 
      led1 = false; 
    }
    else
    { 
      digitalWrite(relay1, LOW); 
      //led1 = true;

    };
    if (elec < 320 && gas < 1){ 
      digitalWrite(greLED, HIGH); 
      //led1 = false; 
    }
    else
    { 
      digitalWrite(greLED, LOW); 
      //led1 = true;

    };
  }  

  if (Serial.available() > 15) {
    for (int i =0; i <= 15; i++){ 
      rxdata[i] = Serial.read();
    }
    //led1 = true;
    checksumtot = 0;
    for (int i =0; i <= 14; i ++){
      checksumtot = checksumtot + rxdata[i];
    };  
    cksum = byte(checksumtot % 256);  
    if (cksum = rxdata[15]){
      //if (cksum = 112){  
      for (int i =0; i <= 15; i++){ 
        livedata[i] = rxdata[i];
      }
      led1 = true;
      Serial.flush();
    } 
  }

  if (time >= loop3){ 
    //lcd.clear();
    loop3 = loop3 + 10000;
    lcd.setCursor(0,0); 
    //lcd.print("Pstr  Genr  Fell");
    lcd.print("Electic Gas     ");
    elec = float(livedata[8] * 256 + livedata[9]);
    gas = float(livedata[14]);
    gas = gas * 6600;
    // test data
    //elec = 1760;
    //gas = 45912;
    // end test data

    floatToString(elec,buff);
    lcd.setCursor(0,1); 
    lcd.print("                ");
    lcd.setCursor(0,1); 
    lcd.print(buff);
    floatToString(gas,buff);
    lcd.setCursor(8,1); 
    lcd.print(buff);
  }

  if (time >= loop2){  // 10 second loop
    lcd.clear();

    lcd.setCursor(0,0); 
    lcd.print("Pstr  Genr  Fell");
    loop2 = loop2 + 10000;

    dallasToString(livedata[0],buff);
    lcd.setCursor(0,1); 
    lcd.print(buff);
    lcd.print((char)223);  // degree symbol
    dallasToString(livedata[2],buff);
    lcd.setCursor(6,1); 
    lcd.print(buff);
    lcd.print((char)223);  // degree symbol
    dallasToString(livedata[1],buff);
    lcd.setCursor(12,1); 
    lcd.print(buff);
    lcd.print((char)223);  // degree symbol
    //led1=true;


  } 
}

void dallasToString(byte froggy, char *buff)

{
  float fred;
  int froggy2;
  fred = float(froggy) / 2;

  froggy2 = (fred - (int)fred) * 10;
  sprintf(buff,"%0d.%d", (int)fred,froggy2 ); 

}



void floatToString(float froggy, char *buff)

{

  //sprintf(buff,"%0dW", (int)froggy ); 

  float fred;
  int froggy2;
  int froggy3;
  fred = float(froggy) / 1000;

  froggy2 = (fred - (int)fred) * 100;

  sprintf(buff,"%0d.%1dkW", (int)fred,froggy2); 


}

/*
 livedata[0] = byte(dallas1);
 livedata[1] = byte(dallas2);
 livedata[2] = byte(dallas3);
 livedata[3] = byte(dallas4);
 lite = int(light);
 livedata[4] = lite / 256;
 livedata[5] = lite % 256;
 
 livedata[6] = worshiplight / 256;
 livedata[7] = worshiplight % 256;
 livedata[8] = watts / 256;
 livedata[9] = watts % 256;
 livedata[10] = Worship temp1;
 livedata[11] = Worship temp2 future;
 
 // for testing
 livedata[6] = 2;
 livedata[7] = 48;
 livedata[8] = 5;
 livedata[9] = 178;
 livedata[10] = 31;
 livedata[11] = 0;
 
 
 // end for testing
 livedata[12] =  0; //Spare;
 livedata[13] = 0; //Spare;
 livedata[14] = gaspulsemin; 
 */

The 4th arduino will be the same as this, but piggybacked on the Master end on the pins that communicate with the slave.

Physically, only the master is a ‘real’ arduino, the slave is an RBBB
http://www.moderndevice.com/products/rbbb-kit and the displays are complete homebrews : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260399444. They are connected together with cat5e network cable, this also powers the slave and display units on spare conductors (ie only one power supply for all 3/4 arduinos). The voltage drops a little over the 45m run but nothing to worry about (its around 4.6 volts at the far end).

tks i'm going to take a look