max6675+ethernet+sd card

Hello
I am trying to combine all these devices with no luck.
I know because all of them use the spi that I have to enable/disable each one to get the other one working.
But so far I dont get any luck.
I have the program running until I use the ethernet to write data to an mysql server. It jams...

Before i use the max6675 library I disable pin 53 on mega, to disable ethernet, and then enable it again after reading.
Is this right ?
I read somewhere that to use hte sd card library I have to disable the ethernet chip.
But so far I didn't understand how do I do it....
Another thing I noticed is that if I use array to store my data the program keeps haging.

I am using arduino mega+oficial ethernet shield+max6675 I set up.
Can someone help me understand why my program hangs ?

Any help would be great.

Thanks

José

From Portugal.

Can someone help me understand why my program hangs ?

Can anyone but you see your code?

Please keep in mind that I am still a bbeginner. So my programing skill are not the best.
That is why I didnt posted the code in the first post because I am afraid you are not able to follow it.
So if you have any questions please ask.

here you have the main code:

#include <OneWire.h>
#include <SPI.h>
#include <Ethernet.h>
#include <DHT.h>
#include "max6675.h"

#define DHTPIN 23     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);

int thermoDO = 31;
int thermoCS = 26;
int thermoCLK = 29;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); // Inicialization of the MAX6675 board used for the thermocouple of the Caldeira


// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
EthernetServer server(80);


OneWire  ds22(22);  // on pin 22 Sensor colocado no anexo
OneWire  ds24(24);  // on pin 24 sensor colocado junto ao quadro electrico
OneWire  ds27(27);  // on pin 27 sensor colocado na cozinha por cima do armário
OneWire  ds25(25);  // on pin 25 sensor colocado na sala por cima da televisão 
OneWire  ds30(30);   // on pin 30 2 sensores colocados um no tubo de entrada da caldeira e outro no tubo de saida


byte sensor1[8] = {
  0x28, 0xF0, 0xA9, 0xA5, 0x03, 0x00, 0x00, 0x60};
byte sensor2[8]= {  
  0x28, 0x6, 0x9F, 0xA5, 0x03, 0x00, 0x00, 0xB8};
byte sensor3[8]= {  
  0x28, 0x3D, 0xB4, 0xA5, 0x03, 0x00, 0x00, 0x25};
byte sensor4[8]= {  
  0x28, 0xDD, 0xC2, 0xA5, 0x03, 0x00, 0x00, 0xFD};
byte sensor5[8]= {  
  0x10, 0x54, 0xF0, 0x3B, 0x02, 0x08, 0x00, 0x4A}; //Sensor colocado no tubo de entrada de água para a caldeira
byte sensor6[8]= {  
  0x10, 0x8D, 0xE9, 0x3B, 0x02, 0x08, 0x00, 0x97}; //Sensor colocado no tubo de saida de água para a caldeira

int count=0;
int count2=0;
double sumlight;
double avrlight;
double sumtext;
double avrtext;
double sumhum1;
double avrhum1;
double sumtanex;
double sumtcor;
double avrtanex;
double avrtcor;
double avrtcoz;
double sumtcoz;  
double avrtsal;
double sumtsal; 
double avrcaldin;
double sumcaldin;
double avrcaldout;
double sumcaldout;
double avrcaldeira;
double sumcaldeira;


void setup(void) {
  // start the serial library:
  Serial.begin(9600);
  pinMode(10, OUTPUT);  
  dht.begin();
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print("."); 
  }
  Serial.println();
  server.begin();
}

void loop(void) {
  int i=0;
  double temparray[6];
  String namearray[9];
  float dataarray[9];
  float sumarray[9];
  float avrarray[9];

  namearray[0]="Exterior";
  namearray[1]="Humidade";
  namearray[2]="Luminusidade";
  namearray[3]="Anexo";
  namearray[4]="Corredor";
  namearray[5]="Cozinha";
  namearray[6]="Sala";
  namearray[7]="Caldeira";
  namearray[8]="Entrada";
  namearray[9]="Saida";


  dataarray[0]=dht.readTemperature();
  dataarray[1]=dht.readHumidity();
  dataarray[2]=analogRead(A0);
  dataarray[3]=getTemperature(22,sensor1);
  dataarray[4]=getTemperature(24,sensor2);
  dataarray[5]=getTemperature(27,sensor3);
  dataarray[6]=getTemperature(25,sensor4);
  dataarray[7]=thermocouple.readCelsius();
  dataarray[8]=getTemperature(30,sensor5);
  dataarray[9]=getTemperature(30,sensor6);

  count++;
  count2++;
  for (byte i=0;i<9;i++){
    sumarray[i]=sumarray[i]+dataarray[i];
    avrarray[i]=sumarray[i]/count2;
  }


  Serial.print("Temp Exterior=");
  Serial.println(dataarray[0]);
  Serial.print("Humidade=");
  Serial.println(dataarray[1]);
  Serial.print("Luz=");
  Serial.println(dataarray[2]);
  Serial.print("Temp Anexo=");
  Serial.println(dataarray[3]);
  Serial.print("Temp Corredor=");
  Serial.println(dataarray[4]);
  Serial.print("Temp Cozinha=");
  Serial.println(dataarray[5]);
  Serial.print("Temp Sala=");
  Serial.println(dataarray[6]);
  Serial.print("Temp caldeira in=");
  Serial.println(dataarray[8]);
  Serial.print("Temp caldeira out=");
  Serial.println(dataarray[9]);
  Serial.print("Temp caldeira=");
  Serial.println(dataarray[7]);

  for (byte i=0;i<9;i++){
    Serial.println(sumarray[i]);
    Serial.println(avrarray[i]);
  }

  Serial.print(" Numero medicoes: ");
  Serial.println(count);
  Serial.println(count2);

  if (count2==60) {
    Serial.print(" Count2=60. Connecting .... ");
    Serial.println(count2); 

    temparray[0]=dataarray[0];
    temparray[1]=dataarray[1];
    temparray[2]=dataarray[2];
    temparray[3]=dataarray[3];
    temparray[4]=dataarray[4];
    temparray[5]=dataarray[5];
    temparray[6]=dataarray[6];

    escreve(temparray); // chama a função para escrever dados na BD do servidor domotica

    for (byte i=0;i<9;i++){
      sumarray[i]=0;
      avrarray[i]=0;
    }

    count2=0;
  }

  delay (5000);
}

I will make another post with the code for the functions.

Please help me...

José

Here you can see the code I have for the functions that are in a separed tab

//***********************************************************************
//Temperatura
//***********************************************************************

float getTemperature(int porta, byte* address){
double celsius;
  byte data[12];
  byte present = 0;
   byte type_s;

  switch (address[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    case 0x22:
     type_s = 0;
      break;
 } 

   switch(porta){
     
      case 22:
  //reset the bus
         ds22.reset();
  //select our sensor
         ds22.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
         ds22.write(0x44,1);
  delay(1000);
  //reset the bus
         present=ds22.reset();
  //select our sensor
          ds22.select(address);
  //read the scratchpad (BEh)
          ds22.write(0xBE);
          for (byte i=0;i<9;i++){
              data[i] = ds22.read();
          }
      break;
            case 24:
  //reset the bus
         ds24.reset();
  //select our sensor
         ds24.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
         ds24.write(0x44,1);
  delay(1000);
  //reset the bus
          present=ds24.reset();
  //select our sensor
          ds24.select(address);
  //read the scratchpad (BEh)
          ds24.write(0xBE);
          for (byte i=0;i<9;i++){
              data[i] = ds24.read();
          }
      break;
                  case 27:
  //reset the bus
         ds27.reset();
  //select our sensor
         ds27.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
         ds27.write(0x44,1);
  delay(1000);
  //reset the bus
          present=ds27.reset();
  //select our sensor
          ds27.select(address);
  //read the scratchpad (BEh)
          ds27.write(0xBE);
          for (byte i=0;i<9;i++){
              data[i] = ds27.read();
          }
      break;
      
      case 25:
  //reset the bus
         ds25.reset();
  //select our sensor
         ds25.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
         ds25.write(0x44,1);
  delay(1000);
  //reset the bus
          present=ds25.reset();
  //select our sensor
          ds25.select(address);
  //read the scratchpad (BEh)
          ds25.write(0xBE);
          for (byte i=0;i<9;i++){
              data[i] = ds25.read();
          }
      break;
      
            case 30:
  //reset the bus
         ds30.reset();
  //select our sensor
         ds30.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
         ds30.write(0x44,1);
  delay(1000);
  //reset the bus
         present=ds30.reset();
  //select our sensor
          ds30.select(address);
  //read the scratchpad (BEh)
          ds30.write(0xBE);
          for (byte i=0;i<9;i++){
              data[i] = ds30.read();
          }
      break;
   }

unsigned int raw = (data[1] << 8) | data[0];
   if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    unsigned char t_mask[4] = {0x7, 0x3, 0x1, 0x0};
    byte cfg = (data[4] & 0x60) >> 5;
    raw &= ~t_mask[cfg];
  }

  celsius = (float)raw / 16.0;
return celsius;}

//***********************************************************************
//Escever dados na base de dados
//***********************************************************************
void escreve(double temparray[5]){
  int i;
if (client.connect("192.168.1.15", 80)) {
    Serial.println("connecting...");}


  client.print("GET /arduino.php?");
  Serial.print("GET /arduino.php?");     
  for (i=0; i<7; i++)
  {
    client.print("t");
    Serial.print("t");
    client.print(i);
    Serial.print(i);
    client.print("=");
    Serial.print("=");
    client.print(temparray[i]);
    Serial.print(temparray[i]);
    if (i < 7-1)
    {
      client.print("&&");
      Serial.print("&&");
    }

  }  

  client.println(" HTTP/1.1");
  Serial.println(" HTTP/1.1");
  client.println("Host: 192.168.1.15");
  Serial.println("Host: 192.168.1.15");
  client.println("User-Agent: Arduino");
  Serial.println("User-Agent: Arduino");
  client.println("Accept: text/html");
  Serial.println("Accept: text/html");
  client.println("Connection: close");
  Serial.println("Connection: close");
  client.println();
  Serial.println();


  delay(500);                                                //
  while (client.connected() && client.available()) {          // when connected and availabe:
    char c = client.read();                                    // read the answer of the server and
    Serial.print(c);                                            // print it to serial port     
  }                                                           //   
  Serial.println();                                            //      
  client.stop();                                              //  stop the connection and set
}

Again any help will be apreciated.

José

  double temparray[6];
  String namearray[9];
  float dataarray[9];
  float sumarray[9];
  float avrarray[9];

  namearray[0]="Exterior";
  namearray[1]="Humidade";
  namearray[2]="Luminusidade";
  namearray[3]="Anexo";
  namearray[4]="Corredor";
  namearray[5]="Cozinha";
  namearray[6]="Sala";
  namearray[7]="Caldeira";
  namearray[8]="Entrada";
  namearray[9]="Saida";

Is there some reason to delete and recreate these every pass through loop?

Have you some reason for needing to wrap the char array data in a resource intensive class?

    temparray[0]=dataarray[0];
    temparray[1]=dataarray[1];
    temparray[2]=dataarray[2];
    temparray[3]=dataarray[3];
    temparray[4]=dataarray[4];
    temparray[5]=dataarray[5];
    temparray[6]=dataarray[6];

    escreve(temparray); // chama a função para escrever dados na BD do servidor domotica

Why do you need to make a copy of this data before passing it to a function? You should simply write the function so it doesn't mangle the input data.

Your indenting
makes your code very
hard to read. Use the Tools

  • Auto Format menut
    item to indent consistently.
    temparray[0]=dataarray[0];
    temparray[1]=dataarray[1];
    temparray[2]=dataarray[2];
    temparray[3]=dataarray[3];
    temparray[4]=dataarray[4];
    temparray[5]=dataarray[5];
    temparray[6]=dataarray[6];

    escreve(temparray); // chama a função para escrever dados na BD do servidor domotica
<snip>
void escreve(double temparray[5]){

Why pass a 7 element array to a function that expects a 5 element array?
Why store 7 elements in a 6 element array?

  for (i=0; i<7; i++)
  {
    client.print(temparray[i]);
    Serial.print(temparray[i]);

Why use 7 elements of a 5 element array?

#include "max6675.h"

You never use anything, that I can see, from this file. Why include it?

Hello Paul
First of all thank you for all your help and comments.
Like I said I knew my code was not ok, that's why I didn't posted at the beginning.
I will go trough your comments.

The first one , do you suggest doing this in another way ? I thought that array's were a good thing, or is it because its a string array ?

Second, the idea is to pass the avrarray, but I am trying to fix my problem and then go and optimize the code.

What do you mean by using tools+auto format menu ?

The indexes of the arrays will be correct after I solve my problem.
Regarding the #include "max6675.h" this is the library for the MAX6675.

My major problem is the combination of multiple SPI devices and the way to disable one in order to use the other.

THanks

José

The first one , do you suggest doing this in another way ? I thought that array's were a good thing, or is it because its a string array ?

I'd suggest making them global arrays, and using char * instead of String.

Second, the idea is to pass the avrarray, but I am trying to fix my problem and then go and optimize the code.

Making sure that the declared array size is appropriate for the data that you want to store in it, and making sure that the function knows the correct size of the array is NOT optimization that can be put off until later.

What do you mean by using tools+auto format menu ?

Exactly what I said. There is a Tools menu. Look for it. I'm sure you've used it before. There is an item on that menu, Auto Format. Use it. Regularly until you get in the habit of properly indenting code as you go.

The indexes of the arrays will be correct after I solve my problem.

If you deliberately leave mistakes in you code, don't expect us to keep trying to help you.

Regarding the...this is the library for the MAX6675.

That you are not using in the code.

What slave select pin are you going to use for the device? What does the device do? Do you know how to communicate with the device?

Looking at the SD library or the Ethernet library, to see how they manage to activate the correct SPI device would be useful. That there is a library to communicate with your device gives hope that that library also knows how to activate the correct SPI device.

Without doing anything explicit to choose the device, what problems are you having?

Yes I know I have mistakes, but for now I want to figure out how to call the devices.
The dataarray[7]=thermocouple.readCelsius(); uses the max6675 library.
My problem is that the program hangs randomly,
Its running fine until it simply stops, when I use the Ethernet shield it always stops.
I believe it has to do with the fact that both the Ethernet shield and the max6675 works on the SPI bus and when I am using one of them I am not calling the functions on the correct manner.
Meaning that I should use the slave pin as an input when I call the functions in order to the device to be activated.

Was I clear enough ?

Thanks

José

How is the max6675 slave select connected to the Mega?
The w5100 uses digital pin 10 for the slave select.
The SD uses digital pin 4 for the slave select.
The max6675 uses what pin for the slave select?

edit: It may be better to explain exactly how the max6675 SPI interface is connected to the Arduino, not just the slave select.

The Max31855 is newer than the Max6675, but I had the max6675 already in house.
Adafruit has a nice tutorial how to use the Max6675/Max31855

Basically you have besides the vcc and the grd pins, the following connections:

CLK (clock) is an input to the MAX6675/MAX31855 (output from microcontroller) which indicates when to present another bit of data
DO (data out) is an output from the MAX6675/MAX31855 (input to the microcontroller) which carries each bit of data
CS (chip select) is an input to the MAX6675/MAX31855 (output from the microcontroller) which tells the chip when its time to read the thermocouple and output more data.

For example, how do use the SD card together with the ethernet part ?
Do I have to put the pin 4 high in order to use the sd card ?
After reading the card, do I have to put it low in order for the Ethernet to work ? Or can I simply move forward and leave the pin 4 high ?

José

CLK (clock) is an input to the MAX6675/MAX31855 (output from microcontroller) which indicates when to present another bit of data
DO (data out) is an output from the MAX6675/MAX31855 (input to the microcontroller) which carries each bit of data
CS (chip select) is an input to the MAX6675/MAX31855 (output from the microcontroller) which tells the chip when its time to read the thermocouple and output more data.

I know all that. I want to know where they are connected on the Arduino. Fill out the form:
CLK = digital pin ___
D0 = digital pin ___
CS = digital pin ___

If you give me that, I can give you a setup function that will get them all working together.

Sorry I didn't understand your question at first.
Here are the pin connections.

int thermoDO = 31;
int thermoCS = 26;
int thermoCLK = 29;

Please keep in mind that I am using arduino mega.

Thanks

José

I use a Mega also. That is what I was counting on.

I do not understand why that library does not use the hardware SPI bus. It uses the standard mode 0 configuration. It seems easy enough to set the interface.

Are you willing to experiment? If so, do you have other devices connected to other pins? I am planning on using digital pin 9 as the slave select pin for the max. Is anything on that pin?

Here is the plan:
CLK = digital pin 52 (SCK)
DO = digital pin 50 (MISO)
CS = digital pin 9

I'm not going to use their library, and go directly to the IC itself. Is that ok with you? You can always change it back if you don't like the results. :wink:

Thanks
Yes I am willing to try anything.
So you think the Mac6675 is not using the SPI bus ?
Should I look for a diferent library ? One that uses the SPI ?
Why use the digital 9 ? Why not the 49 for example to keep the wires together ?

Thanks

José

OK! Digital pin 49 is the slave select for the max. The others should be connected as above.

Try this code to start. This will check that the SD and w5100 are starting ok with the max connected.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

void setup() {
  Serial.begin(9600);
  
  // disable w5100 SPI
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  
  // disable max6675
  pinMode(49,OUTPUT);
  digitalWrite(49,HIGH);
  
  Serial.print("Starting SD..");
  if(!SD.begin(4)) Serial.println("fail");
  else Serial.println("ok");

  Serial.print("Starting w5100..");
  if(!Ethernet.begin(mac)) Serial.println("failed");
  else Serial.println(Ethernet.localIP());

  // the w5100 begin function returns with the SPI enabled, so disable it
  digitalWrite(10,HIGH);

  Serial.println("Setup complete");
}

void loop() {
  
}

The SD.begin(4) function will fail if no card in the slot.
Do those two devices start ok?

edit: My web browser is double posting copy and paste again. I removed the additional code. ??

Hello
thanks for your time.
I do not have the board here with me, I shell try this tonight. I will post the results as soon as possible.

Thanks for your time.

José

No problem. I know it is a little confusing at first. :slight_smile:

I made a change to the w5100 setup code in the post above. The ethernet library has a bug that leaves the w5100 SPI enabled after the Ethernet.begin() call.

If that works, we will start reading the max6675 in the loop() section every second to test it.

This is a quite big domotica project. At least big for me.
I plan to monitor the temperature all the rooms from my house.
Now I have temp sensors in: Outside (using a dth22)
Kitchen with DS18S20
living room with DS18S20
corridor with DS18S20
Garage with DS18S20

I have a humidity sensor outside (DTH22) and a Light sensor using an LDR.

All this is already running and writing data to an mysql server using PhP.

I plan now to monitor our eating system.
I have an thermocouple inside the burning chamber connected to the Max6675 and two DS18S20 one in the water input and the other in the water output of the burning chamber.
I also have a rele controlling the pump, so it will turn on the pump when the temp in the burning chamber reaches 60º.

I plan to change the program so when it starts it reads a configuration file from the sd card, later I plan to implement an webpage where I can change the config file in the card.
I also plan to control the air intake in the burning chamber as function of the chamber temperature and the rooms temperatures.

On a later stage I plan to install electro-valves in the eating block in each room to control the water flux according to the comfort temperature set in the config file.

Was this clear enough to show you the motivation of my project ?

José

I don't see a problem. That is a good reason to get this on the standard SPI bus. I have the max6675 code ready for you when you verify the test code above works. I'm still running tests on it. I don't have a max6675, so I am injecting values into the SPI transfer function to verify the conversion to Celsius.

edit: OK, enough testing. If the test above works, this should also.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

void setup() {
  Serial.begin(9600);
  
  // disable w5100 SPI
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  
  // disable max6675 SPI
  pinMode(49,OUTPUT);
  digitalWrite(49,HIGH);
  
  Serial.print("Starting SD..");
  if(!SD.begin(4)) Serial.println("fail");
  else Serial.println("ok");

  Serial.print("Starting w5100..");
  if(!Ethernet.begin(mac)) Serial.println("failed");
  else Serial.println(Ethernet.localIP());
  digitalWrite(10,HIGH);

  Serial.println("Setup complete");
}

void loop() {
  delay(1000);

  // thisTemp gets temp in 1/4 degrees C
  int thisTemp = readMax();
  
  Serial.print(thisTemp/4,DEC);
  Serial.print(".");
  Serial.println((thisTemp%4) * 25,DEC);
}

int  readMax() {
  int maxLow;
  int maxData;
  
  //  enable max SPI
  digitalWrite(49,LOW);

  // do the 16 bit read  
  maxData = SPI.transfer(0x00);
  maxLow = SPI.transfer(0x00);
  
  // disable max SPI
  digitalWrite(49,HIGH); 

  // convert to an integer from the two bytes
  maxData = maxData << 8;
  maxData = maxData | (maxLow & 0xff);

  // shift temp reading into position
  maxData = maxData >> 3;
  
  // return 1/4 degrees Celsius
  return maxData;
}

The ethernet library has a bug that leaves the w5100 SPI enabled after the Ethernet.begin() call.

There could be hardware issues as well. Which version of the ethernet shield do you have? An early version may have a bug.

The W5100 is not a well behaved SPI device in that MISO does not go into a high impedance state when CS is deselected. There is a separate enable input that is required to cause MISO to go hi-Z. In a stroke of anti-genius, Wiznet made the two pins opposite logic (one active high, the other active low) so you can't just tie them together to get correct output.

IIRC very early versions of the ethernet shield tied the enable input active, so that effectively you could never send the W5100 MISO into hi-Z, so you could never connect a second peripheral to the SPI bus. Later versions added a transistor to act as an inverter and activate CS and enable pins with a single input line, making the shield compatible with other SPI devices.

-j