Go Down

Topic: 2 Arduinos on a single 1Wire microlan? (Read 1 time) previous topic - next topic

gg123

Hi

I have been working on an Arduino control and logging system for a renewables based home central heating system.

The design uses DS18B20s (non-parasitic) to monitor temperatures at various points, and energises a couple of pump relays to distribute heating water appropriately. The data is displayed on LCD, Serial, a simple web page and logged on the Ethernet Shield's SD Card.

Although the sketch is within size limits, it seems that SRAM gets filled up and does not operate correctly unless I cut down/out various parts of the sketch.

Not wanting to compromise on the data being collected and presented (other than serial which I can do without), I was wondering if it is possible to have 2 Arduinos on the same 1wire microlan to share the load.

I am no expert, so any advice would be great to hear - although I'm guessing if both are polling on the same microlan, there will be issues - so perhaps it is possible to set one up to be passive and "eavesdrop" on the responses?

Or perhaps this should be a question about minimising SRAM usage?

Many thanks

robtillaart

Quote
The design uses DS18B20s (non-parasitic) to monitor temperatures at various points, and energises a couple of pump relays to distribute heating water appropriately. The data is displayed on LCD, Serial, a simple web page and logged on the Ethernet Shield's SD Card.

Sounds like a nice application.

Quote
Although the sketch is within size limits, it seems that SRAM gets filled up a

You can post the sketch so we can help optimize the sketches size?

Another option is to use a second Arduino and divide tasks
Arduino 1 does sensor reading and relay control and forwards its states to arduino 2
Arduino 2 does the presentation part webserver/lcd etc.


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

wildbill

As described, it sounds like it should be possible to optimize your code as Robtillart suggests. If it isn't, a mega would likely solve your SRAM issue.

gg123

Both options sound good to me. Here's the code, stolen from various sources and cobbled together.

First half:

Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SD.h>
#include <Ethernet.h>
#include <SPI.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Time.h>

//SD INTERFACE ##############################
//- uses pin 4 on ethernet shield

const int chipSelect = 4;

//RELAY SETUP #########################

const int R01 = 7;     // Relay for main CH Pump
const int R02 = 8;      // Relay for Wood Burner Pump
const int R03 = 9;      // Relay for Solar Thermal HW Pump
int R01Status;  //for holding relay status to change into text
int R02Status;  //for holding relay status to change into text
int R03Status;  //for holding relay status to change into text

// 1 WIRE####################################

#define ONE_WIRE_BUS 3 //microlan on pin 3

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

// Assign 1 wire addresses

DeviceAddress T01 = { 0x28, 0xAD, 0x34, 0x80, 0x03, 0x00, 0x00, 0xAE };     //Outside temp
DeviceAddress T02 = { 0x28, 0x58, 0x61, 0x80, 0x03, 0x00, 0x00, 0x70 };     //Hallway temp
//DeviceAddress T03 = { 0x28, 0x82, 0xAF, 0x80, 0x03, 0x00, 0x00, 0xFB };   //future
DeviceAddress T04 = { 0x28, 0x80, 0x7E, 0xAA, 0x03, 0x00, 0x00, 0x6D };     //Esse Centraliser temp
DeviceAddress T05 = { 0x28, 0xD0, 0x8E, 0xAA, 0x03, 0x00, 0x00, 0xE5 };     //Wood Burner Flow temp
DeviceAddress T06 = { 0x28, 0x6E, 0xA8, 0xAA, 0x03, 0x00, 0x00, 0x95 };     //Wood Burner Return temp
DeviceAddress T07 = { 0x28, 0x8E, 0x72, 0xAA, 0x03, 0x00, 0x00, 0x5F };     //HW Tank Top temp
DeviceAddress T08 = { 0x28, 0x21, 0x8A, 0xA9, 0x03, 0x00, 0x00, 0x37 };     //HW Tank Mid temp
DeviceAddress T09 = { 0x28, 0xFD, 0x79, 0xAA, 0x03, 0x00, 0x00, 0xEE };     //HW Tank Bottom temp
//DeviceAddress T10 = { 0x28, 0x70, 0x89, 0xAA, 0x03, 0x00, 0x00, 0xE8 };   //Solar Thermal collector temp
//DeviceAddress T11 = { 0x28, 0x8B, 0x86, 0xAA, 0x03, 0x00, 0x00, 0x0D };   //future
//DeviceAddress T12 = { 0x28, 0x80, 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x2C };   //future
//DeviceAddress T13 = { 0x28, 0xA5, 0xA1, 0xAA, 0x03, 0x00, 0x00, 0x01 };   //future
//DeviceAddress T14 = { 0x28, 0x75, 0xA6, 0xAA, 0x03, 0x00, 0x00, 0x94 };   //future
//DeviceAddress T15 = { 0x28, 0x02, 0x9F, 0xAA, 0x03, 0x00, 0x00, 0xFE };   //future
//DeviceAddress T16 = { 0x28, 0xC2, 0x8F, 0xAA, 0x03, 0x00, 0x00, 0x1D };   //future
//DeviceAddress T17 = { 0x28, 0x0F, 0xA7, 0xAA, 0x03, 0x00, 0x00, 0x0E };   //future
//DeviceAddress T18 = { 0x28, 0x46, 0x7A, 0xAA, 0x03, 0x00, 0x00, 0x5F };   //future



// ETHERNET #######################################

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //ethernet shield MAC address
byte ip[] = { 192,168,0,77 }; // Ethernet IP local IP address
Server server(80); // Ethernet port numnber

//LIQUID CRYSTAL

LiquidCrystal_I2C lcd(0x27,16,2);  //16 x 2 LCD definition
const int buttonPin = 2;  //defines button pin to switch on LCD display
int buttonState = 0;    // holder for the button pressed or not

void setup(void)
{
//RELAY Startup

pinMode(R01, OUTPUT);
digitalWrite (R01, HIGH);  //to avoid relay firing on startup make sure set to high here
pinMode(R02, OUTPUT); 
digitalWrite (R02, HIGH);  //to avoid relay firing on startup make sure set to high here

  //START ETHERNET
 
Ethernet.begin(mac, ip);
server.begin();
 
  //START 1 WIRE LIBRARY#########
Serial.begin(9600);
sensors.begin();
// set the resolution to 10 bit
sensors.setResolution(T01, 10);
sensors.setResolution(T02, 10);
//sensors.setResolution(T03, 10);
sensors.setResolution(T04, 10);
sensors.setResolution(T05, 10);
sensors.setResolution(T06, 10);
sensors.setResolution(T07, 10);
sensors.setResolution(T08, 10);
sensors.setResolution(T11, 10);
//sensors.setResolution(T10, 10);

//ENTER TIME #########################

setTime(12,0,0,10,3,12); // set time to noon Jan 1 2011

//START CARD ###
Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
 
//LCD STARTUP ######

pinMode(buttonPin, INPUT);
lcd.init();               
}

//SETUP TIME for serial print#################################################

void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
}
void printDigits(int digits){
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}


// VOID LOOP ###################################################

void loop(void)
{
//THERMOSTATS ###############

//turn main CH pump on and off based on centraliser temp
{if ((sensors.getTempC(T04)) > 52 && (digitalRead(R01) == 1)) digitalWrite (R01, LOW);  //CH pump starts when centraliser temp > 52
else if ((sensors.getTempC(T04)) < 49 && (digitalRead(R01) == 0)) digitalWrite (R01, HIGH); //if relay energised and drops below 50 turn off
}
//turn on WBS pump when WBS feed up to temperature
{if ((sensors.getTempC(T05)) > 75 && (digitalRead(R02) == 0)) digitalWrite (R02, LOW); //pump on if > temperature and pump is off
else if ((sensors.getTempC(T05)) < 73 && (digitalRead(R02) == 0)) digitalWrite (8, HIGH); //pump off if < temp and pump was on
}
  //SERIAL OUTPUT DATA #######

delay(2000);
digitalClockDisplay();
Serial.print(", ");
sensors.requestTemperatures();
Serial.print("Outside Temp: ");
Serial.print(sensors.getTempC(T01));
Serial.print(", ");
Serial.print("Inside Temp: ");
Serial.print(sensors.getTempC(T02));
//etc etc for other readings

Serial.println();

// SD CARD OUTPUT DATA ########

  File dataFile = SD.open("Test.txt", FILE_WRITE);

gg123

Second half:

Code: [Select]
// if the file is available, write to it:
  if (dataFile) {
    dataFile.print(year());
    dataFile.print("-");
    dataFile.print(month());
    dataFile.print("-");
    dataFile.print(day());
    dataFile.print(" ");
    dataFile.print(hour());
    dataFile.print(":");
    dataFile.print(minute());
    dataFile.print(":");
    dataFile.print(second());
    dataFile.print(",");
    dataFile.print(sensors.getTempC(T01));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T02));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T04));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T07));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T08));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T09));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T05));
    dataFile.print(",");
     dataFile.print(sensors.getTempC(T06));
    dataFile.print(",");
    dataFile.print(digitalRead(R01)*-1+1);
    dataFile.print(",");
    dataFile.println(digitalRead(R02)*-1+1);
    dataFile.close();
   
  } 
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening .txt file");
}

//ETHERNET webpage output:

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 (c == '\n' && current_line_is_blank) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
         
//Temp etc readings fow webpage:
          {
            client.print("<h1>Heating Control System Status</h1>");
            client.print("<body style=\"background-color:PowderBlue;\">");
           
            client.print("<table border=\"1\"><tr><td>Outside Temp: </td><td>");
            client.print(sensors.getTempC(T01));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>Downtstairs Hall Temp: </td><td>");
            client.print(sensors.getTempC(T02));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>Centraliser Temp: </td><td>");
            client.print(sensors.getTempC(T04));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>Hot Water Top Temp: </td><td>");
            client.print(sensors.getTempC(T07));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>Hot Water Mid Temp: </td><td>");
            client.print(sensors.getTempC(T08));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>Hot Water Bottom Temp: </td><td>");
            client.print(sensors.getTempC(T09));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>WBS Flow Temp: </td><td>");
            client.print(sensors.getTempC(T05));
            client.print("</td></tr>"); //end table row 
           
            client.print("<tr><td>WBS Return Temp: </td><td>");
            client.print(sensors.getTempC(T06));
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>CH Pump Status: </td><td>");
            R01Status = digitalRead(R01);
            if (R01Status = HIGH) {client.print("Off");}
            else client.print("On");
            client.print("</td></tr>"); //end table row
           
            client.print("<tr><td>WBS Pump Status: </td><td>");
            R02Status = digitalRead(R02);
            if (R02Status = HIGH) {client.print("Off");}
            else client.print("On");
            client.print("</td></tr>"); //end table row
           
           delay(1000);
          }
          break;
        }
        if (c == '\n') {
          current_line_is_blank = true;
        }
        else if (c != '\r') {
          current_line_is_blank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }

//LCD ########

buttonState = digitalRead(buttonPin);  //if button is pushed or not
 
  {if (buttonState == LOW){  //LOW = button pressed
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
    lcd.print("Central = ");
    lcd.print(sensors.getTempC(T04));
    lcd.setCursor(0,1);
    lcd.print("CH Pump = ");
    lcd.print((digitalRead(R01) * -1 +1));
    delay(2000);
    lcd.clear();
   
    lcd.setCursor(0,0);
    lcd.print("HW Top = ");
    lcd.print(sensors.getTempC(T07));
    lcd.setCursor(0,1);
    lcd.print("HW Mid = ");
    lcd.print(sensors.getTempC(T08));
    delay(2000);
    lcd.clear();
 
  lcd.setCursor(0,0);
  lcd.print("WBS = ");
  lcd.print(sensors.getTempC(T06));
  lcd.print(" / ");
  lcd.print(sensors.getTempC(T05));
  lcd.setCursor(0,1);
  lcd.print("WBS Pump = ");
  lcd.print((digitalRead(R02) * -1 +1));
  delay(2000);
  lcd.clear();}
 
  else { //turn of display if button not pressed
  lcd.noDisplay();
  lcd.noBacklight();
  }}

}

wildbill

You have a large amount of text in your various prints and displays. They take up space in SRAM. Move them to progmem using the F() macro. That should take care of the problem.

gg123

Thanks - is there a recommended starting point for learning about progmem and the F() macro for this application?

robtillaart


- http://arduino.cc/en/Reference/PROGMEM -

I would give the SD-datafile the name YYYYMMDD.txt (e.g.20121221) so you do not need to write it in every entry of your log.

A quick glimpse of the code shows that you do a read of the temp sensors in an if statement and later you do a read to write in the datafile. This can result in minor differences.

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Go Up