Redfly und Dallas OneWire TempSensor

Hallo zusammen,
ich versuche gerade ein Projekt zu basteln, in welchem ich die Temperatur über OneWire an 2 Orten messe und über das RedFly auf eine Seite schreibe. Zumindest soll das so vereinfacht erstmal aussehen.

Ich habe in dem Projekt nen LCD-Display, RTC-Modul und eben die 2 Sensoren hintereinander.
Das läuft auch ohne Probleme "offline".
Das Testprogramm mit dem RedFlyServer bekomme ich auch zum laufen und kann die Seite im Browser öffnen.
Nun zum Problem:
Wenn ich beides zusammenbastel, dann hängt sich der Arduino auf, sobald ich den Browserzugriff starte.

Ich habe das Problem soweit eingegrenzt, dass sich der Arduino nur aufhängt, sobald ich irgendwie auf die Sensoren zugreife.
Also wenn ein Befehl wie "sensors.requestTemperatures();" auftaucht, hängt sich der Arduino beim Browserzugriff auf.

Ich vermute das Problem irgendwo in den Bibliotheken. Ist dazu vielleicht schon was bekannt?

#include <RedFly.h>
#include <RedFlyServer.h>
#include <Wire.h>
#include <RTClib.h>
#include <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>

Arduino Uno R3
Dallas Sensor DS18B20

Liebe Grüße

Ist genügend RAM für dein Programm übrig?
Benutze mal diesen Code Arduino Playground - AvailableMemory

Addi

oder Versuch Dein Programm auf einem Arduino MEGA; der hat mehr RAM.

Hast Du das F()- Makro für Texte verwendet?

Grüße Uwe

sensors.requestTemperatures

Ist wahrscheinlich im loop drinnen, was bedeutet dass der Arduino überfordert ist mit den Ergebnissen zu liefern.
Eine Sekunde pause wäre schon ganz gut.

Also hat das ganze Problem nichts mit den Librarys zu tun?!
Und ich weiß leider nicht genau, was du mit F()-Makros meinst.
Ich sende mit dem RedFly bisher nichts, außer einem Text mit ,Hallo'.
Und das available Memory Programm einfach noch hinten anhängen um mir das anzuzeigen?
Wieviel Memory sollte denn übrig sein?

Ansonsten ist das requestTemperatures wirklich im Loop, allerdings läuft es ohne Probleme, bis ich das RedFly anspreche ohne Delay. Ich steh nicht auf Delays, denn dann hängt immer alles für die Zeit.
Werde das morgen aber mal ausprobieren.

Hilft es, wenn ich den ganzen Code poste?! Ist relativ lang ^^

Delays kann man auch ohne Blockierung machen. Schau dir das Beispiel BlinkWithoutDelay an. Kurz gesagt ließt man da die aktuelle zeit mit millis() aus und vergleicht sie mit einer alten Zeit + Delay-Zeit.

z.B.:

unsigned long _previousMillis = 0;
unsigned long _currentMillis = 0;

void loop()
{	
	_currentMillis = millis();

	if(_currentMillis - _previousMillis > 1000) 
	{
		_previousMillis = _currentMillis;


                //Code der jede Sekunde ausgeführt wird
        }
}

Serenifly:
Delays kann man auch ohne Blockierung machen. Schau dir das Beispiel BlinkWithoutDelay an.

Das stimmt, das kenne ich auch, aber dann habe ich ja, soweit ich weiß, nicht den Effekt, dass der Arduino die Zeit hat, die Ergebnisse zu liefern. Denn dann arbeitet er ja weiter.

Er soll ja weiter arbeiten. Nämlich mit dem Webserver. Wenn du aber ständig den Sensor abfragst (was alleine durch die OneWire Lib wahrscheinlich ein paar Millisekunden dauert) lässt du ihm keine Zeit für andere Dinge.

Serenifly:
Er soll ja weiter arbeiten. Nämlich mit dem Webserver. Wenn du aber ständig den Sensor abfragst (was alleine durch die OneWire Lib wahrscheinlich ein paar Millisekunden dauert) lässt du ihm keine Zeit für andere Dinge.

Also du meinst ich soll keinen Delay einsetzen, durch den er wartet, sondern das requestTemperatures in eine Schleife (zB mit den millis) setzen, sodass er nur noch 1x pro Sekunde die Temperaturen erfragt?
Und dadurch, dass er sonst so oft abfragt und viele Daten verarbeitet, hängt er sich sonst auf?
Klingt schlüssig :smiley:
Mach ich morgen, jetzt erstmal ins Bett! :smiley:

Also das Delay(1000):
unsigned long currentMillis = millis();

  • if(currentMillis - previousMillis > interval) {*
  • previousMillis = currentMillis; *
  • sensors.requestTemperatures();*
  • }*
    bringt nicht wirklich einen Fortschritt.

Bis er sich aufhängt habe ich:
freeMemory()=1163

EDIT:
Also wenn ich das interval auf 10000 (10sek.) stelle, hängt er sich unregelmäßig beim Browserzugriff auf.
bzw. ich hab das gefühl, der schnelle zugriff (1-2x direkt nach hochfahren) klappt, danach hängt er sich auf.

TrunX:
Bis er sich aufhängt habe ich:
freeMemory()=1163

EDIT:
Also wenn ich das interval auf 10000 (10sek.) stelle, hängt er sich unregelmäßig beim Browserzugriff auf.
bzw. ich hab das gefühl, der schnelle zugriff (1-2x direkt nach hochfahren) klappt, danach hängt er sich auf.

Verwendest Du String-Objekte in Deinem Programm?

String-Objekte sind wegen eines Fehlers in der Speicherverwaltung erst ab der Version 1.0.5 so halbwegs problemlos verwendbar, ohne dass ein Programm sich früher oder später aufhängt, das intensiv mit String-Objekten arbeitet.

Also entweder Arduino 1.0.5 verwenden, oder auf String-Objekte im Programm komplett verzichten (was sowieso immer besser ist) und C-Strings/Char-Arrays stattdessen verwenden.

#include <RedFly.h>
#include <RedFlyServer.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RTClib.h>
#include <SoftwareSerial.h>        //LCD
#include <MemoryFree.h>

#define RELAY 11

SoftwareSerial mySerial(3,8);    // pin 8 = TX, pin 3 = RX (unused)

#define ONE_WIRE_BUS 10          // DS18B20 an Pin 10 angeschlossen
// Pass our oneWire reference to Dallas Temperature. 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

RTC_DS1307 RTC;

int buttonPin = 12;
int warte = 0;
long previousMillis = 0; //für millis-delay
int interval = 10000;

byte ip[]      = { 192,168,178,111 }; //ip from shield (server)
byte netmask[] = { 255,255,255,0 }; //netmask

//initialize the server library with the port 
//you want to use (port 80 is default for HTTP)
RedFlyServer server(80);


//debug output functions (9600 Baud, 8N2)
//Leonardo boards use USB for communication, so we dont need to disable the RedFly
void debugout(char *s)
{
#if defined(__AVR_ATmega32U4__)
  Serial.print(s);
#else
  RedFly.disable();
  Serial.print(s);
  RedFly.enable();
#endif
}

void debugoutln(char *s)
{
#if defined(__AVR_ATmega32U4__)
  Serial.println(s);
#else
  RedFly.disable();
  Serial.println(s);
  RedFly.enable();
#endif
}


void setup(){
  
  uint8_t ret;

  Serial.begin(9600); //init serial port and set baudrate
  while(!Serial); //wait for serial port to connect (needed for Leonardo only)

  //init the WiFi module on the shield
  // ret = RedFly.init(br, pwr) //br=9600|19200|38400|57600|115200|200000|230400, pwr=LOW_POWER|MED_POWER|HIGH_POWER
  // ret = RedFly.init(pwr) //9600 baud, pwr=LOW_POWER|MED_POWER|HIGH_POWER
  // ret = RedFly.init() //9600 baud, HIGH_POWER
  ret = RedFly.init();
  if(ret)
  {
    debugoutln("INIT ERR"); //there are problems with the communication between the Arduino and the RedFly
  }
  else
  {
    //scan for wireless networks (must be run before join command)
    RedFly.scan();

    //join network
    ret = RedFly.join(*SSID*, *PW*, INFRASTRUCTURE);
    if(ret)
    {
      debugoutln("JOIN ERR");
      for(;;); //do nothing forevermore
    }
    else
    {
      //set ip config
      ret = RedFly.begin(ip, 0, 0, netmask);
      if(ret)
      {
        debugoutln("BEGIN ERR");
        RedFly.disconnect();
        for(;;); //do nothing forevermore
      }
      else
      {
        RedFly.getlocalip(ip); //receive shield IP in case of DHCP/Auto-IP
        server.begin();
      }
    }
  }
  pinMode(RELAY, OUTPUT);
  digitalWrite(RELAY, HIGH);   // turn the relay on (HIGH is the voltage level)


  //LCD
    mySerial.begin(9600); // set up serial port for 9600 baud
    delay(500); // wait for display to boot up
    clearLCD();
    backlightOn();
  //RTC
    Wire.begin();
    RTC.begin();
    
  //Temperatur  
    sensors.begin();
    delay(1000);
 
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");  }
    
   // following line sets the RTC to the date & time this sketch was compiled 
   // RTC.adjust(DateTime(__DATE__, __TIME__));
   

}


void loop()
{
  long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;  
    sensors.requestTemperatures();
  }
int Temp1 = sensors.getTempCByIndex(0);
int Temp2 = sensors.getTempCByIndex(1);  
  
  
  //listen for incoming clients
  if(server.available())
  {
    //a http request ends with a blank line
    boolean currentLineIsBlank = true;
    while(server.available())
    {
      char c = server.read();
      //if you've gotten to the end of the line (received a newline
      //character) and the line is blank, the http request has ended,
      //so you can send a reply
      if(c == '\n' && currentLineIsBlank)
      {
        //clear input buffer
        server.flush(); 

        //send standard HTTP 200 header
        server.print_P(PSTR("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"));

        //send some text
        server.println_P(PSTR("Willkommen auf Steffens Terrarien-Server! 

"));
        server.println_P(PSTR("
Temperatur oben: "));
        server.print(Temp1, DEC);
        server.println_P(PSTR("&deg;C"));
        server.println_P(PSTR("
Temperatur unten: "));
        server.print(Temp2, DEC);
        server.println_P(PSTR("&deg;C"));
        server.println_P(PSTR("

"));


        //show IP address of RedFly
        server.println_P(PSTR("
<i>RedFly IP: "));
        server.print(ip[0], DEC); server.print(".");
        server.print(ip[1], DEC); server.print(".");
        server.print(ip[2], DEC); server.print(".");
        server.print(ip[3], DEC);
        server.println_P(PSTR("
</i>"));
        break;
      }
      if(c == '\n')
      {
        //you're starting a new line
        currentLineIsBlank = true;
      } 
      else if(c != '\r')
      {
        //you've gotten a character on the current line
        currentLineIsBlank = false;
      }
    }

    //close connection
    server.stop();
 }
  else if(!server.connected()) //listening port still open?
  {
    server.stop(); //stop and reset server
    server.begin(); //start server
  }
  
  
//starte offline Programm 


DateTime now = RTC.now();

// In Line 1 wird das Datum und die Uhrzeit geschrieben
selectLineOne();
    if (now.day() < 10) {mySerial.print('0');} 
    mySerial.print(now.day(), DEC);
    mySerial.print(".");
    if (now.month() < 10) {mySerial.print('0');}
    mySerial.print(now.month(), DEC);
    mySerial.print('.');
    if (now.year() < 10) {mySerial.print('0');}
    mySerial.print(now.year(), DEC);
    mySerial.print("  ");
    if (now.hour() < 10) {mySerial.print('0');}
    mySerial.print(now.hour(), DEC);
    mySerial.print(':');
    if (now.minute() < 10) {mySerial.print('0');}
    mySerial.print(now.minute(), DEC);
    mySerial.print(':');
    if (now.second() < 10) {mySerial.print('0');}
    mySerial.print(now.second(), DEC);
    
//In Line 2 wird geschrieben
selectLineTwo();
    mySerial.print("Temp. Oben:     ");
    mySerial.print(Temp1); // Warum "byIndex"? Man kann mehr, als nur einen IC auf dem gleichen bus haben. 0 bezieht sich auf den ersten IC.
    mySerial.print(char(223)); //°
    mySerial.print("C");
    
//In Line 3 wird geschrieben
selectLineThree();
    mySerial.print("Temp. Unten:    ");
    mySerial.print(Temp2); // Warum "byIndex"? Man kann mehr, als nur einen IC auf dem gleichen bus haben. 1 bezieht sich auf den zweiten IC.
    mySerial.print(char(223)); //°
    mySerial.print("C");
    
//In Line 4 wird geschrieben
selectLineFour();
  if (digitalRead(buttonPin)==HIGH){
    mySerial.print("gef");
    mySerial.print(char(245)); //ü
    mySerial.print("ttert:  ");
    if (now.day() < 10) {mySerial.print('0');} 
    mySerial.print(now.day(), DEC);
    mySerial.print(".");
    if (now.month() < 10) {mySerial.print('0');}
    mySerial.print(now.month(), DEC);
    mySerial.print(".");
    if (now.year() < 10) {mySerial.print('0');}
    mySerial.print(now.year()-2000, DEC);}
   
   
// Schaltung des Relais
  int Stunde = now.hour();
  int relais = 0;
  
   if (Stunde > 9 && Stunde < 21){
    relais = 1;}
   else {relais = 0;}
  
   if (relais == 1 && Temp1 < 34 && warte == 0){             // Schalte das Relais an, wenn Temp. Oben < 34°C
    digitalWrite(RELAY, HIGH);}                             // und Zeit zwischen 10 Uhr und 20 Uhr
   else if(relais == 1){                                    // Wartet nach 34°C auf Abkühlung bis 30°C
   
   if(Temp1 >= 34) {
    digitalWrite(RELAY, LOW);
    warte = 1;  }
   else if (Temp1 <= 29) {warte = 0;}}
   else{
    digitalWrite(RELAY, LOW);
    warte = 1;}

    Serial.print("freeMemory()=");
    Serial.println(freeMemory());
    
} //void loop Ende


//SerialLCD Functions
void selectLineOne(){  //puts the cursor at line 0 char 0.
   mySerial.write(0xFE);   //command flag
   mySerial.write(128);    //position
}
void selectLineTwo(){  //puts the cursor at line 2 char 0.
   mySerial.write(0xFE);   //command flag
   mySerial.write(192);    //position
}
void selectLineThree(){  //puts the cursor at line 3 char 0.
   mySerial.write(0xFE);   //command flag
   mySerial.write(148);    //position
}
void selectLineFour(){  //puts the cursor at line 4 char 0.
   mySerial.write(0xFE);   //command flag
   mySerial.write(212);    //position
}
void clearLCD(){
   mySerial.write(0xFE);   //command flag
   mySerial.write(0x01);   //clear command.
}
void backlightOn(){  //turns on the backlight
    mySerial.write(0x7C);   //command flag for backlight stuff
    mySerial.write(157);    //light level.
}
void backlightOff(){  //turns off the backlight
    mySerial.write(0x7C);   //command flag for backlight stuff
    mySerial.write(128);     //light level for off.
}
void backlight50(){  //sets the backlight at 50% brightness
    mySerial.write(0x7C);   //command flag for backlight stuff
    mySerial.write(150);     //light level for off.
}

Das ist das komplette Programm.
Ich verwende Arduino 1.0.5.
Damit habe ich auf einem LCD: Datum/Uhrzeit (aus dem RTC-Modul), Temp1 + Temp2 (vom Dallas Sensor über OneWire) und einen Button für die letzte Fütterung
Und ein Relais, welches eine Heizlampe an und Ausschaltet.

zusätzlich jetzt halt noch das RedFly-Shield.
Vielleicht hilft der Code ja, wenn sich da jemand drantraut :roll_eyes:

zu 90% hängt er sich auf, wenn ich den Browser zugriff starte, 8% danach, und 2% geht :wink:

EDIT:
pingen geht übrigens ohne Probleme

Ich habe den Code nur überflogen, aber ein Serial.print() darf man nur machen, wenn das RedFly vorher deaktiviert wird. Daher gibt es auch die debugout() Funktionen.

Der Pin 3 wird von der SoftwareSerial Lib und dem RedFly gleichzeitig belegt. Dies kann unter Umständen Probleme machen.

PS: Code bitte nicht als Zitat/Quote posten. Es gibt dafür separate [ code ] Tags.

Hab ich als Code geschrieben, kein Problem :wink:

Pin 3 wird ja nicht benutzt, soll ich den in der SoftwareSerial.h einfach ändern?

Reicht es, wenn ich vor den "Offline Teil" RedFly.disable(); und nach dem Teil RedFly.enable(); schreibe?
Oder meinst du damit was anderes?

EDIT:
Wenn ich das mache, hängt er sich nicht mehr auf, Ping geht auch, aber kein Browserzugriff mehr.

EDIT 2:
Ich habe es wieder rausgenommen und die Temperatur zuordnung auch in die millis schleife geschrieben.
Damit scheint es erstmal zu funktionieren, wenn ich das richtig sehe.

Pin 3 wird ja nicht benutzt, soll ich den in der SoftwareSerial.h einfach ändern?

Die SoftwareSerial Lib verwendet den Pin als Eingang und die RedFly Lib als Ausgang. Dies kann durchaus Probleme verursachen.

Reicht es, wenn ich vor den "Offline Teil" RedFly.disable(); und nach dem Teil RedFly.enable(); schreibe?
Oder meinst du damit was anderes?

Ich meine die freeMemory Ausgabe. Am besten den Teil kommentieren, da dies nur für Debugzwecke dient.
//Serial.print("freeMemory()=");
//Serial.println(freeMemory());

Wenn ich das mache, hängt er sich nicht mehr auf, Ping geht auch, aber kein Browserzugriff mehr.

Was wurde genau geändert und führt zu keinem Erreichen des RedFly-Shields?

Ich hatte vor und nach dem Offline Teil "RedFly.disable();" bzw. "RedFly.enable();" geschrieben.
Dadurch war es nicht mehr zu erreichen.

Merke ich nicht, die Pins sind auch alle nicht belegt, und verursachen bisher keine Fehler. Vielleicht hab ich Glück, oder irgendwann mal was geändert, woran ich mich nicht erinnere.

Habe aber jetzt einfach mal das "sensors.getTempCByIndex(0)" mit in die millis-warte-Schleife gepackt und im Moment scheint es zu funktionieren.

EDIT:
War wohl nur von kurzer Dauer. Leider hängt er nun wieder.

Was wurde genau geändert und führt zu keinem Erreichen des RedFly-Shields?

Ich hatte vor und nach dem Offline Teil "RedFly.disable();" bzw. "RedFly.enable();" geschrieben.
Dadurch war es nicht mehr zu erreichen.

Das ist zu viel bzw. zu lange, da während der Deaktivierung keine WLAN-Daten verarbeitet werden können und diese dann verloren gehen.
Bitte einfach die entsprechende Ausgabe kommentieren.

Habe aber jetzt einfach mal das "sensors.getTempCByIndex(0)" mit in die millis-warte-Schleife gepackt und im Moment scheint es zu funktionieren.

Am besten das ganze "offline Programm" nur jede Sekunde ausführen, da man an einem Display die Daten auch nicht schneller lesen kann.
Das Auslesen der Temperaturwerte kann hier (jede Sekunde) ebenfalls gemacht werden. Dafür die Variablen Temp1 und Temp2 als static deklarieren, so dass sie immer den letzten Wert halten.

Erm, das ist nicht was static macht. Static bedeutet, dass wenn du von einer Klasse mehrere Objekte instantiiert, diese alle die gleiche Variable verwenden und nicht jedes Objekt seine eigene Version hat. Das funktioniert genauso mit Methoden. Man kann auch ganze Klassen static machen, so dass man sie verwenden kann ohne überhaupt ein Objekt davon zu erstellen.

Variablen behalten ihren Werte solange sie im Scope sind (d.h. innerhalb geschweifter Klammern). Wenn du Variablen für alle Methoden sichtbar machen willst, deklariert man sie global.

Ich will hier keine C-Diskussion starten... Es geht hier um eine statische Variable (keine Klasse und kein Objekt) und eine statische Variable hat immer den selben Speicherbereich, daher bleibt der Inhalt in ihrem Verwendungsbereich (Skope) bestehen und geht nicht verloren.

http://de.wikibooks.org/wiki/C-Programmierung:_static_%26_Co.