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
// 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;
}