50 NTC o DS18B20 con un arduino UNO [SOLUCIONADO casi]

Hola,
quisiera conectar unos 50 NTC a un arduino UNO para medir la temperatura interior de una colmena, y guardar los datos cada x minutos en una SD.
Para leer temperaturas tendría ir seleccionado cada NTC, y para ello necesitaría 6 pines digitales (2^6 = 64). No conozco mucho el tema, creo que necesitaría algún chip 7400 de tipo multiplexor... ¿Alguna idea?

Curro92

¿Y si en vez de NTC usas DS18B20?

Ventajas, el protocolo es el 1 wire, solo empleas un pin, puedes poner en cascada hasta 100 dispositivos y hasta una distancia de 200 metros. (estos datos los lei pero no he localizado la hoja oficial que lo corrobora)

Tambien ganas en precision, una sonda digital te da una medida de temperatura independiente de la resistencia del cable o interferencias, una analogica no.

Cadda DS18B20 tiene una MAC unica con lo que identificarlas es por software y encima las puedes conseguir estancas:

Puedes usar multiplexores de 8 canales como el 4051, asi por cada entrada analogica tienes 8 termistores conectados.

74HC_HCT4051.pdf (217 KB)

sin duda DS18B20, yo tambien los uso y son una maravilla.

Usar sensores onewire como el DS18B20 es una opcion muy buena, lo unico que para tener 50 dispositivos conectados un pushpull pasivo con una resistencia no es nada recomendable. En estos casos hay que usar un pushpull activo.

Gracias a todos.

El DS18B20 me gusta, pero 50pcs me salen por treinta y tantos euros.

Esta tarde he encontrado otra posibilidad mucho más viable económicamente. Un montaje de 8 x 4051 que consume 6 pines digitales y uno analógico
http://modelrail.otenko.com/arduino/multiplexing-photodetectors-to-detect-train-occupancy

También existe una librería para ese montaje:

El presupuesto (vía extremo oriente):

  • 50 pcs NTC: 3.7€
    -10 pcs 4051: 2€
  • 1 Pro Mini con atmega320 16MHz: 4.71€
  • SD Card module: 1.06€ (falta la tarjeta)
  • DS1307 RTC (Battery include): 1.72€

Total: 13,19€

Un datalogger que va a medir la temperatura interior de la colmena simultáneamente en 50 puntos distintos cada 10 minutos, anotando además año, mes, día, hora, minuto. Los NTC los voy a incluir en los bastidores de cuadros de cera antes de que formen los panales.

Te dejo este enlace por si te vale de ayuda.

te vale la pena por 20 euros la cantidad de cable que tienes que tirar adicional? yo sigo viendo mejor opción el DS18B20, ademas que la señal es digital y no analogica, que tambien lo veo una ventaja

Vaya, Sergegsx me ha dejado otra vez con dudas, en lo de la maraña de cables tiene razón.

flico: podrías explicar muy brevemenete qué es eso de "pushpull activo"?

En el datasheet aparecen dos formas de conectar:

  1. Supplying the Parasite-Powered DS18B20 During Temperature Conversions
  2. Powering the DS18B20 with an External Supply

Cuando mencionas "pushpull activo" te refieres a la segunda?

Supongo que lo que quiere decir es esto:

Parasite power mode
When operating in parasite power mode, only two wires are required: one data wire, and ground. At the master, a 4.7k pull-up resistor must be connected to the 1-wire bus. When the line is in a "high" state, the device pulls current to charge an internal capacitor.

This current is usually very small, but may go as high as 1.5 mA when doing a temperature conversion or writing EEPROM. When a slave device is performing one these operations, the bus master must keep the bus pulled high to provide power until the operation completes; a delay of 750ms is required for a DS18S20 temperature conversion. The master can't do anything during this time, like issuing commands to other devices, or polling for the slave's operation to be completed. To support this, the OneWire library makes it possible to have the bus held high after the data is written.

Cuando hay mucho conectado al 1 wire, se puede emplear en paralelo un mosfet para mandarle la tension directa, sin limite de corriente por los "altos consumos" en los momentos de la lectura como esta nota de aplicacion:

Añado que con el modo tradicional (vcc-gnd-data) no hace falta, solo calcular la resistencia un poco mas baja:
http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf

Normal (external supply) mode
With an external supply, three wires are required: the bus wire, ground, and power. The 4.7k pull-up resistor is still required on the bus wire. As the bus is free for data transfer, the microcontroller can continually poll the state of a device doing a conversion. This way, a conversion request can finish as soon as the device reports being done, as opposed to having to wait 750ms in "parasite" power mode.

Note on resistors:
For larger networks, you can try smaller resistors.
The ATmega328/168 datasheet indicates starting at 1k6 and a number of users have found smaller to work better on larger networks.

Solo es que durante el tiempo de conversión activas el Pin del mosfet. Suele ser como maximo 750ms el tiempo que dura la conversión pero se acorta si bajas la resolución.

Unas pruebas que hice llegue a los 200m leyendo dispositivos onewire de dos hilos y 750ms de pushpull que en modo pasivo no leía nada mas que un dispositivo. Pero claro era en dos hilos.

Gracias de nuevo
resumiendo: si pongo tres cables (vcc-gnd-data) me olvido del mosfet.
Sobre poner resistencia menor, según el datasheet

Note on resistors:
For larger networks, you can try smaller resistors.
The ATmega328/168 datasheet indicates starting at 1k6 and a number of users have found smaller to work better on larger networks.

¿Se supone que debo poner algo entre 1k6 y 4k7? Probaré.

Y ya que sois tan amables, otra pregunta: Cómo calcularía el consumo en mA de una red de 50 DS18B20? Si el consumo fuera continuo usaría un téster, pero cambia según esté midiendo o no cada sensor. Según el datasheet:

  • active current (cuando está leyendo): 1mA
  • standby current: 750nA
  • sink current: 1mA
  • DQ Input Current : 5uA (cuando la línea DQ está alta)

No controlo los dos últimos...

Hola Curro92

Empleando la configuracion de 3 cables, ya lleva alimentacion separada, la resistencia es un simple pullup, casi pogo la mano en el fuego por el valor de 1k5 para las 50.

Si la distancia es grande, 100m p.ej. usa cable cat6.

Por lo demas debe de funcionar sin problemas...

Suerte electro-Apicultor. XD

Gracias, Heke

Estoy probando varios DS18B20 conectados a un Arduino. Uso la librería DallasTemperature

Para saber el número de sensores, utilizo la función correspondiente

devicecount = sensors.getDeviceCount();

Y luego busco el ID de cada sensor para identificarlo

for(n=0;n< devicecount; n++)
      sensors.getAddress(addresses[n], n);

Por otro lado, externamente a los sensores les identifico con unas marcas (con un pintauñas reciclado). Apretando con los dedos los sensores uno a uno, veo en cuál sube la temperatura y puedo asociar el ID y las marcas de pintura.

Mi pregunta es: al usar sensors.getDeviceCount() ¿siempre saldrán en el mismo orden los sensores? O pueden salir en un orden aleatorio?

Hola Curro

Cuando haces un devicecount lo que hace es enumerar los sensores que tiene conectados, el orden no depende de eso.

Cada sensor tiene lo que se llama una mac o para mas sencillo digamos que un DNI, y ese numero es fijo de cada sensor, lo pongas al principio o al final de una hilera.

Es un numero estampado internamente (electronicamente) como si fuera la IP de un ordenador, da igual donde vaya cuando tu accedes al dispositivo X siempre sera a él.

Como bien decis los dispositivos onewire tienen un dni o ROM de 8 bytes.
El primer byte de la ROM define el tipo de dispositivo 0x28 DS18B20 0x10 DS18S20

Te dejo este ejemplo de hacktronics, espero que te sirva

// This Arduino sketch reads DS18B20 "1-Wire" digital
// temperature sensors.
// Tutorial:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress insideThermometer = { 0x28, 0x94, 0xE2, 0xDF, 0x02, 0x00, 0x00, 0xFE };
DeviceAddress outsideThermometer = { 0x28, 0x6B, 0xDF, 0xDF, 0x02, 0x00, 0x00, 0xC0 };
DeviceAddress dogHouseThermometer = { 0x28, 0x59, 0xBE, 0xDF, 0x02, 0x00, 0x00, 0x9F };

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  // Start up the library
  sensors.begin();
  // set the resolution to 10 bit (good enough?)
  sensors.setResolution(insideThermometer, 10);
  sensors.setResolution(outsideThermometer, 10);
  sensors.setResolution(dogHouseThermometer, 10);
}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.print("Error getting temperature");
  } else {
    Serial.print("C: ");
    Serial.print(tempC);
    Serial.print(" F: ");
    Serial.print(DallasTemperature::toFahrenheit(tempC));
  }
}

void loop(void)
{ 
  delay(2000);
  Serial.print("Getting temperatures...\n\r");
  sensors.requestTemperatures();
  
  Serial.print("Inside temperature is: ");
  printTemperature(insideThermometer);
  Serial.print("\n\r");
  Serial.print("Outside temperature is: ");
  printTemperature(outsideThermometer);
  Serial.print("\n\r");
  Serial.print("Dog House temperature is: ");
  printTemperature(dogHouseThermometer);
  Serial.print("\n\r\n\r");
}

Gracias, Heke y flico

De acuerdo, no importa el orden en que yo coloque los sensores. Creo que me lié un poco al explicar antes: todavía quedo con la duda, ¿el orden en que sensors.getAddress() me los presenta, ¿siempre es el mismo, o es aleatorio? Si fuera aleatorio, tendría que recoger en el log mac+valor cada vez; si siempre salieran en el mismo orden, sabiendo el orden en que salen, solo anotaría el valor.

He visto que en la librería DallasTemperature (con la que también está hecho el ejemplo que menciona flico) al hacer begin se buscan los devices

while (_wire->search(deviceAddress))
{
    if (validAddress(deviceAddress))
    {
       // ...
        devices++;
    }

Está llamando iterativamente a un _wire->search() que es una función de la librería OneWire , en cuyas fuentes casi me ahogo...

en cuyas fuentes casi me ahogo...

No eres el unico que le ha pasado.

Hola,
sigo intentando establecer el orden de mis sensores: son 10 sensores que van colocados en fila entre los panales de una colmena, de izquierda a derecha. La librería produce una lista de los sensores que detecta.
En más de un lugar he hallado esto:

The order is deterministic. You will always get the same devices in the same order

Como no puedo establecer a partir de su ID el orden en que aparecerán en la lista, voy a hacer esto:

  • conectar los 10 sensores al arduino, sacar la lista de los sensores
  • mientras estoy viendo las temperaturas en la consola, ir calentando uno a uno los sensores (apretando entre dos dedos), y ver cuál de ellos sube la temperatura, y marcarlo con el nº de orden que tiene en la lista.
  • desconectarlos, y volver a conectarlos en el orden que se les ha asignado.
    Así en el log sabré que el primer registro corresponde al primer sensor de la izquierda, y así sucesivamente.

El problema: mi aplicación servirá solo para esos sensores colocados de esa manera. El día que uno se estropee y tenga que cambiarlo, tendría que rehacer todo el proceso de identificación.
La alternativa no me gusta: guardar en el log cada registro de temperatura asociado a su ID (16 caracteres), y luego reordenar los registros según el orden físico de los sensores.

Curro92

Me parece recordar que habia un sketch para identificar la MAC de cada dispositivo conectado...

Si es asi, solo tendrias que antes de sustituir un sensor cambiar en las variables o definiciones del programa su valor, pero la posicion seria la misma.

Me refiero a algo asi:

define sensor 1 = mac... la que sea o numero de orden el que sea..

define sensor 2 = mac... la que sea o numero de orden el que sea..

define sensor 10 = mac... la que sea o numero de orden el que sea..

y en tu programa seguirias leyendo el sensor 1 o 2 o 3 solo que la mac o numero de orden habria cambiado.

Mira a ver si lo encuentras, yo hare lo mismo y si lo veo te lo posteo.

He encontrado de momento estos enlaces que te identifican el adress (yo lo llamo la mac)

http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20#mult
http://tutorialpedia.org/tutorials/Working+with+Dallas+DS18S20+and+DS18B20+temperature+sensors+from+Arduino.html

Aqui el codigo que emplean para identificar el adress:

// This sketch looks for 1-wire devices and
// prints their addresses (serial number) to
// the UART, in a format that is useful in Arduino sketches
// Tutorial: 
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

#include <OneWire.h>

OneWire  ds(3);  // Connect your 1-wire device to pin 3

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

void discoverOneWireDevices(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  
  Serial.print("Looking for 1-Wire devices...\n\r");
  while(ds.search(addr)) {
    Serial.print("\n\rFound \'1-Wire\' device with address:\n\r");
    for( i = 0; i < 8; i++) {
      Serial.print("0x");
      if (addr[i] < 16) {
        Serial.print('0');
      }
      Serial.print(addr[i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    if ( OneWire::crc8( addr, 7) != addr[7]) {
        Serial.print("CRC is not valid!\n");
        return;
    }
  }
  Serial.print("\n\r\n\rThat's it.\r\n");
  ds.reset_search();
  return;
}

void loop(void) {
  // nothing to see here
}

PD: Upsss..... creo que Flico ya te habia dirigido a hackatronics.... sorry... no lo habia visto.