DS18S20 - Sensor an und ausschalten; liefert falschen Wert zurück?

Hallo,

ich bastel gerade an einem Funksensor auf ATTiny84-Basis, an den ein 433 Mhz Sender und ein DS18S20-OneWire-Sensor angeschlossen ist.
Nun schaue ich mir ein paar Sachen vom TinyTX-Code ab; u.A. das man Sensoren an einen ATTiny-Pin hängt, und diesen nur dann Saft gibt, wenn man Werte ausliest, um den Stromverbrauch zu minimieren.

Ich habe mein Script entsprechend umgemodelt; als erstes in der loop() wird der Dallas-Pin mit Strom beschaltet; danach die Temperatur ausgelesen.

Jetzt das, was ich mir nicht erklären kann: Schalte ich den PIN nicht aus, erhalte ich per 433 einen korrekten Temperatur-Wert. Wenn ich aber NACH dem Versand der Daten per 433 den Pin auf LOW schalte, bekomme ich nurnoch "85.00" als Temperatur-Wert per 433 geliefert.

Ich hänge mal das ganze Script an und hoffe es ist übersichtlich.

Momentan behelfe ich mir eben so, dass ich den Ausgang, an dem der Tempsensor hängt, nicht ausschalte. Aber egal, ob ich den Ausgang direkt nach dem Temperatur-Auslesen, nach einem Delay von 10 Sekunden oder am Ende vom Script auf LOW schalte, ab dann bekomme ich nurnoch 85.00 als Temperatur geliefert :confused:

// 433 Mhz-Sender angeschlossen an PIN 7
// DS18S20 angeschlossen an PIN 8

#include <VirtualWire.h>
#include <OneWire.h>
#include <JeeLib.h>

ISR(WDT_vect) { 
  Sleepy::watchdogEvent(); 
}

// Die ID des Sensor-Nodes. Dienst zur Identifizierung der Daten.
char NODEID = '1';

// PIN, an den das DATA-Beinchen des Temperatur-Sensor angeschlossen ist
int DS18S20_DATA_Pin = 2;

// PIN, an den das VCC-Beinchen des Temperatur-Sensors angeschlossen ist
int DS18S20_VCC_Pin = 9;

// PIN, an den der 433 Mhz Sender angeschlossen ist
int TX_Pin = 3;

// Temperatur-Variable deklarieren
float temp1;

OneWire ds(DS18S20_DATA_Pin);

void setup()
{
  // Initialise the IO and ISR
  vw_setup(2000);                 // Bits per sec
  vw_set_tx_pin(TX_Pin);          // pin 3 is used as the transmit data out into the TX Link module, change this as per your needs  

  // Set the aref to the internal 1.1V reference
  analogReference(INTERNAL);  

  pinMode(DS18S20_VCC_Pin, OUTPUT); // set power pin for DS18S20 to output

  ADCSRA &= ~ bit(ADEN); 
  bitSet(PRR, PRADC); // Disable the ADC to save power
}

void loop()
{
  digitalWrite(DS18S20_VCC_Pin, HIGH); // turn DS18S20 sensor on
  delay(10);

  // Temperatur Temp1 auslesen
  temp1 = getTemp();

  // Temperatur-String zum Versand initialisieren
  char temp1msg[24];

  // Node-ID an erste Stelle schreiben, durch ; separiert von den Nutzdaten
  temp1msg[0] = NODEID; // setzt einen Buchstaben an den Anfang
  temp1msg[1] = ';';
  temp1msg[2] = 'T';
  temp1msg[3] = 'E';
  temp1msg[4] = 'M';
  temp1msg[5] = 'P';
  temp1msg[6] = '1';
  temp1msg[7] = ':';

  // Float in Char umwandeln
  // dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);
  // +8 um die Daten an die 8. Stelle im Array zu schreiben
  dtostrf(temp1, 2, 2, temp1msg+8);

  // Datagramm verschicken
  vw_send((uint8_t *)temp1msg, strlen(temp1msg));

  // Auf kompletten Versandt warten
  vw_wait_tx();

  // VCC-String zum Versand initialisieren
  char vccmsg[24];
  vccmsg[0] = NODEID;
  vccmsg[1] = ';';
  vccmsg[2] = 'V';
  vccmsg[3] = 'C';
  vccmsg[4] = 'C';
  vccmsg[5] = ':';

  // Long in Char umwandeln
  // +6 um die Daten an die 6. Stelle im Char-Array zu schreiben
  ltoa(readVcc(), vccmsg+6, 10);

  vw_send((uint8_t *)vccmsg, strlen(vccmsg));
  vw_wait_tx(); 

  delay(100);
  digitalWrite(DS18S20_VCC_Pin, LOW);

  Sleepy::loseSomeTime(4000);
}


float getTemp(){
  //returns the temperature from one DS18S20 in DEG Celsius

  byte data[12];
  byte addr[8];

  if ( !ds.search(addr)) {
    //no more sensors on chain, reset search
    ds.reset_search();
    return -1000;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end

  byte present = ds.reset();
  ds.select(addr);
  ds.write(0xBE); // Read Scratchpad


  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }

  ds.reset_search();

  byte MSB = data[1];
  byte LSB = data[0];

  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;

  return TemperatureSum;
}

// readVcc()-Lib von Nathan Chantrell
// https://github.com/nathanchantrell/TinyTX/blob/master/TinyTX_DS18B20/TinyTX_DS18B20.ino
long readVcc() {
  bitClear(PRR, PRADC); 
  ADCSRA |= bit(ADEN); // Enable the ADC
  long result;
  // Read 1.1V reference against Vcc
#if defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328
#endif
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;

  // Kalibrierung der VCC-Anzeige
  // http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
  // Abschnitt: Improving Accuracy
  // scale_constant = internal1.1Ref * 1023 * 1000
  // internal1.1Ref = 1.1 * Vcc1 (per voltmeter) / Vcc2 (per readVcc() function)
  // Default: 1125300L
  // Meine Konstante: 1070860L, errechnet mit 3x1,5V Batterien als VCC
  result = 1070860L / result; // Back-calculate Vcc in mV; Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  ADCSRA &= ~ bit(ADEN); 
  bitSet(PRR, PRADC); // Disable the ADC to save power
  return result;
}

Hallo,
ich hab mir den Code nicht komplett durchgelesen, aber meine Erfahrung ist folgende.
Wenn du den DS18B20 auf High setzt und dann sofort ausliest, ich nenne es mal, dann ist der DS18B20 noch
nicht "ready". delay(10) ist vermutlich zu kurz.
Das ist bei meiner Steuerung genau so, ich habe 10 Sensoren verbaut. Wenn ich resette ist der erste Wert für
alle Sensoren 85°, das nächste auslesen stimmt dann.
Die 85° werden vom Sensor geliefert, wenn noch nicht korrekt ausgelesen wurde.
Vergrößere mal dein delay, dann sollte es vermutlich gehen.
gruß

Hi,

ich werde das mal versuchen.
Was ich dann aber trotzdem nicht ganz verstehe:

Ich setze den PIN des Sensors auf HIGH, und bekomme direkt den richtigen Wert.
Füge ich nach dem Auslesen eine Zeile hinzu, um den Sensor auf LOW zu setzen, bekomme ich 85.

Das würde doch dann bedeuten, dass der Pin grundsätzlich auf HIGH steht, wenn ich keine Bedingung an anderer Stelle mit LOW hinzufüge ?!

Moin Moin,

neovanmatix:
Das würde doch dann bedeuten, dass der Pin grundsätzlich auf HIGH steht, wenn ich keine Bedingung an anderer Stelle mit LOW hinzufüge ?!

genau so ist es.
Das Licht im Wohnzimmer ist so lange eingeschaltet, bis es jemand wieder ausschaltet.
Das entspricht dem Setzten und Rücksetzen eines Pins ( Ausgang )

Gruss
Kurti

Hmmm... okay, dann mal eine allgemeine Frage:

pinMode(DS18S20_VCC_Pin, OUTPUT); // set power pin for DS18S20 to output

Wird der PIN standardmäßig auf HIGH gesetzt, wenn ich einen Pin als Ausgang definiere?

Ich kann's mir halt einfach nicht erklären, weil...:

  1. Wenn der Pin standardmäßig auf HIGH steht, wird in der Loop der Pin nochmal auf High gesetzt (hat ja keine Auswirkung). Ich bekomme ein Temperatursignal das stimmt.
  2. Wenn ich ein LOW NACH dem Auslesen der Temperatur hinzufüge, bekomme ich nurnoch 85.00° geliefert. Nichts desto trotz war der PIN von Anfang an auf HIGH - sollte also auch genug Zeit gehabt haben, um Daten auszulesen.

Ich teste heute Abend mal was passiert, wenn ich ein delay(1000) nach dem HIGH-Setzen des Pins hinzufüge.