Go Down

Topic: Arduino UNO + Ethernet Shield + Cliente Pachube (COSM) + RTC DS1307 (Read 2597 times) previous topic - next topic

Hola! Os comento por partes para que todo se pueda entender de forma sencilla.

Paso 1:
Le he montado a mi Arduino UNO R3 una shield para Ethernet y va fenomenal. Tras eso he cargado un programa para conectarme al web service de Pachube (ahora llamado COSM) y dar información de sensores (por ahora el valor de los sensores es una variable interna que voy cambiando de valor para simplificar un poco las cosas).
Hasta aquí todo correcto.

Paso 2:
A continuación he instalado un módulo de hora basado en el RTC DS1307 a través de interfaz I2C (lo conecto a los pines analógicos 4 y 5 de Arduino). Una vez puesto el reloj en hora he intentando hacer un programa que guarde la información de un sensor, junto a la marca de tiempo suministrada por el RTC DS1307, en una tarjeta micro SD (la shield Ethernet incorpora un slot para este tipo de tarjetas). Esto también funciona sin problema.

PROBLEMA: al intentar unir Paso 1 con Paso 2: o sea que en el mismo programa, teniendo conectada la shield Ethernet y el RTC DS1307 a través de I2C (pines A4 y A5), se actualice el valor del sensor en Pachube y también se guarde dicha lectura, junto a la hora actual del reloj, en la tarjeta micro SD.

Os paso el código a ver si alguien con conocimientos, tiempo y que se apiade de mi puede orientarme.

Code: [Select]

//******************************************____ LIBRERÍAS ____*******************************************
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <Wire.h>
//********************************************************************************************************


//******************************************____ CONSTANTES ____******************************************
#define APIKEY              // your cosm api key
#define FEEDID              // your feed ID
#define USERAGENT       // user agent is the project name
#define maxLength 100
#define maxLength2 500
//********************************************************************************************************


//******************************************____ VARIABLES ____*******************************************
uint8_t hora,minuto,segundo;
int hora_int, minuto_int, segundo_int, contador_SD = 0;
double sensorReading;
boolean subir = true;
byte mac[]     = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
byte ip[]      = {  192,  168,    1,  180  };
byte gateway[] = {  192,  168,    1,    1  };
byte subnet[]  = {  255,  255,  255,    0  };
File archivo;
Sd2Card card;
SdVolume volume;
SdFile root;
EthernetClient client;
IPAddress server(216,52,233,121);              // numeric IP for api.cosm.com
unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; // delay between updates to Cosm.com
String fecha = String("11/08/2012 -- Sábado");
String texto = String(maxLength);
String ls = String(maxLength2);

char fechaChar[] = "11/08/2012 -- Sábado";
char* textoChar[2];
//********************************************************************************************************



void setup()
{
  Serial.begin(9600);

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // DHCP failed, so use a fixed IP address:
    Ethernet.begin(mac, ip);
  }

  pinMode(10, OUTPUT);
 
  sensorReading = 30;
 
  Serial.println("************_ Sketch 'RELOJ 4' _************");
  Serial.println("Inicializando tarjeta SD...");
  SD.begin(4);
  card.init(SPI_HALF_SPEED, 4);
  volume.init(card);
  root.openRoot(volume);
  archivo = SD.open("hora.txt", FILE_WRITE);
 
  Wire.begin();
}

void loop()
{
  if (client.available()) {
    char c = client.read();
  }
 
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
 
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    sendData(sensorReading);
    sensorReading = modificacionValor(sensorReading);
    contador_SD++;
  }
 
  if(contador_SD >= 3){
    archivo.close();
    archivo = SD.open("hora.txt", FILE_WRITE);
    contador_SD = 0;
  }
 
  lastConnected = client.connected();
}

void sendData(double sensor) {
 
  char aux[20];
  // if there's a successful connection:
  if (client.connect(server, 80)) {
   
    Serial.println("connecting...");
    // send the HTTP PUT request:
   
    //SI COMENTO DESDE AQUÍ (con un comentario de bloque)...

    client.print("PUT /v2/feeds/");
    client.print(FEEDID);
    client.println(".csv HTTP/1.1");
    client.println("Host: api.cosm.com");
    client.print("X-ApiKey: ");
    client.println(APIKEY);
    client.print("User-Agent: ");
    client.println(USERAGENT);
    client.print("Content-Length: ");

    // calculate the length of the sensor reading in bytes:
    // 8 bytes for "sensor1," + number of digits of the data:
    int thisLength = 8 + getLength(sensor);
    //int thisLength = 2 + getLength(sensor);
    client.println(thisLength);

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: text/csv");
    client.println("Connection: close");
    client.println();

    // here's the actual content of the PUT request:
    client.print("sensor1,");
    client.println(sensor);                                       

    //...HASTA AQUÍ EL CÓDIGO se ejecuta pero obviamente no actualiza datos en el servicio Pachube...
    // Si no lo comento no parece que que funcione ya que la salida serie no muestra nada...
   
    leehora();
   
    char* textoChar[]= {fechaChar , " || Temperatura: " , " || Hora: " ,":"};
    Serial.print("Datos para escribir en la tarjeta SD: '");
    Serial.print(textoChar[0]);
    Serial.print(textoChar[1]);
    Serial.print(sensorReading);
    Serial.print(textoChar[2]);
    Serial.print(hora);
    Serial.print(textoChar[3]);
    Serial.print(minuto);
    Serial.print(textoChar[3]);
    Serial.print(segundo);
    Serial.print("'");
   
    archivo.print(textoChar[0]);
    archivo.print(textoChar[1]);
    archivo.print(sensorReading);
    archivo.print(textoChar[2]);
    archivo.print(hora);
    archivo.print(textoChar[3]);
    archivo.print(minuto);
    archivo.print(textoChar[3]);
    archivo.print(segundo);
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
   // note the time that the connection was made or attempted:
  lastConnectionTime = millis();
}


void leehora() {
  Wire.beginTransmission(0x68);
  Wire.write((byte)0);
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3);
  byte cadena[3];
  int i;
  for(i=0; i<3; i++) {
    cadena[i] = Wire.read();
    //Serial.print(cadena[i]);
  }
  segundo = bcd2bin(cadena[0] & 0x7F);
  minuto = bcd2bin(cadena[1]);
  hora = bcd2bin(cadena[2]);
}

int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten,
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}

double modificacionValor(double sensorReading){
  double res;
 
  if(sensorReading<40 && subir){
    res = sensorReading + 0.1;// = analogRead(A0);
  }else if(sensorReading>=40){
    res = sensorReading - 0.1;
    subir = false;
  }else if(sensorReading<=30){
    res = sensorReading + 0.1;
    subir = true;
  }else {
    res = sensorReading - 0.1;   
  }
 
  return res;
}

static uint8_t bcd2bin (uint8_t val) {
  return val - 6 * (val >> 4);
}

static int bin2bcd (int val) {
  return val + 6 * (val / 10);
}



Como se puede ver en el código que hay arriba (he omitido los valores APIKEY, FEEDID y USERAGENT que para poder probarlo debereis emplear los vuestros) en la función 'sendData' es donde, según active/desactive una parte de código funciona (pero no me hace lo que necesito) o no me funciona...

Si alguna parte no la explico bien por favor preguntarme y os doy más detalles...

¡Muchas gracias por adelantado!

Saludos.

Hola. Según he continuado investigando el problema puede estar en el que el pin A4 se usa para la tarjeta SD presente en la shield Ethernet y precisamente ese pin (junto con el A5) es utilizado en el protocolo I2C a través de la librería wire.h para la comunicación con el RTC DS1307.
Voy a probar a escribir en la SD desde la shield Ethernet sin usar para nada el tema de la conectividad IP y a la vez probaré a emplear el RTC. Si eso no falla el error debería estar, por descarte, al emplear Ethernet + SD + RTC a la misma vez sin hacer el cambio oportuno de pines (si es que fuese posible que no lo se).

Cualquier aportación en bienvenida. Gracias.

Saludos.

Heke

El reloj usa el protocolo i2c

Me da a mi que es la tarjeta microSD y el controlador ethernet el que creo que estan usando las lineas MOSI, MISO y SCK a la vez y creo que es ahi tu conflicto.

¿Puede ser?
CUIDADO !! MIS POST NO SON APTOS PARA MENORES. SI ERES MENOR DE 14 AÑOS DEBES DE LEERLOS ACOMPAÑADO DE UN ADULTO

flico

La shield ethernet no usa el A4 y A5 por lo que no puede entrar en conflicto con el DS1307.

http://shieldlist.org/arduino/Ethernet-v5

Aunque no lo usas en el código publicado haces mención a la entrada analogica 0 que si la usa la shield

res = sensorReading + 0.1;// = analogRead(A0);
Trabajando en ...

    * Control Domotico (En montaje ...)
    http://casitadomotica.blogspot.com/
 

[url=https://bitbucket.org/fmalpartida


La shield ethernet no usa el A4 y A5 por lo que no puede entrar en conflicto con el DS1307.

http://shieldlist.org/arduino/Ethernet-v5

Aunque no lo usas en el código publicado haces mención a la entrada analogica 0 que si la usa la shield

res = sensorReading + 0.1;// = analogRead(A0);


Hola flico. El código "analogRead(A0);" está comentado así que no influye (se me quedó ahí, ya lo he borrado para no liar las cosas).

Finalmente he logrado solucionar el problema y funciona perfectamente  XD. Resulta que la memoria RAM que tiene el Arduino UNO (SRAM) es de 2KB y yo me había acercado hasta los 1850 bytes. De esta forma los restantes 198 bytes (2KB = 2048 bytes) no son suficientes para que las librerías Ethernet y SD puedan funcionar y por eso se quedaba bloqueado. He recurrido a disminuir el tamaño de ejecución en memoria eliminando constantes de tipo char (texto) y aplicando el modificador PROGMEM. Tras esos cambios la suma de "data" y "bss" (comando "avr-size") es 1625 bytes y funciona a la perfección (empíricamente parece ser que si sobrepaso los 1750 bytes aprox falla).

Os dejo una captura del cálculo de bytes con el comando "avr-size":



Espero que a alguien le resulte útil esta información.

Gracias por las respuestas aportadas.

Saludos.


shifty3d

Hola tendrás tu código actualizado, no encuentro forma que funcione.
He probado varios server y cuando incluyo  la librería Wire  deja de funcionar el servidor.
Gracias

Go Up