ich betreibe den Arduino als Webserver für eine Temperaturanzeige. Das funtioniert auch.
Dazu möchte ich noch die aktuelle Zeit darstellen und da beginnen die Probleme.
Das funktioniert auch. Nur wenn ich**"0000-00-00 00:00:00"** durch strZeit ersetze gebt es einen Fehler. fctGetCurTime() liefert genau den gleichen String.
cannot pass objects of non-trivially-copyable type 'class String' through '...'
Da der Fehler meistens im geheimen Teil des Codes liegt, wäre es sinnvoll, den kompletten Sketch zu posten.
Welcher Typ ist strZeit? Ich vermute Klasse String und das dürfte das Problem sein.
Danke an alle
und JA ich bin ein blutiger Anfänger. Ich habe einige Erfahrung mit VBA und deshalb macht mir auch das Konzept des char-Array in C einige Schwierigkeiten. Mit viel Mühe habe ich das Ziffern Datum in ein Array bekommen, wenngleich mir das nötige '0'+ in RtcIs[8] = '0'+newDay/10 nicht klar ist.
Die Funktion fctGetCurTime gibt aber einen String zurück und damit scheint der Ärger zu beginnen.
Ich weiß aber nicht, wie ich das behebe.
Ich poste mal den ges. Code ohne die void setup - damit es kürzer wird.
Im Setup wird das ENC28J60 per DHCP intitialisiert und die RTC per NTP gestellt.
// from Arduino demo sketch for testing the DHCP client code // Original author: Andrew Lindsay
// Major rewrite and API overhaul by jcw, 2011-06-07 // Copyright: GPL V2
// See http://www.gnu.org/licenses/gpl.html // See http://www.wennekes.info
/*-----( Import needed libraries )-----*/
#include <EtherCard.h>
#include <Wire.h>
#include "RTClib.h" // Adafruit + add RTC.getTemperature()
/*-----( Declare Constants and Pin Numbers )-----*/
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 }; //Change this in a unique mac adres for your network
static byte ntpServer[] = {192, 53, 103, 103}; //ptbtime3.ptb.de but you can cange in any public ntp server.
uint8_t ntpMyPort = 123;
long timeZoneOffset = 3600L; //Winter (original) time Europe
boolean networkConnection = true;
int pinCS = 10; // Pin zum CS des ENC28J60
byte Ethernet::buffer[700];
/*-----( Declare Global Variables )-----*/
word rh, rt; // make global
String strZeit;
BufferFiller bfill;
/*-----( Declare objects )-----*/
RTC_DS3231 RTC;
word homePage() {
strZeit = (fctGetCurTime());
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n"
"\r\n"
"<meta http-equiv='refresh' content='10'/>"
"<title>Tempanzeige</title>"
"<h1>DS3231 Temp Sensor</h1>"
"<h2>Temp aus DS3231: $D °C</h2>"
"<h2>Platzhalter: $D %</h2>"
"<h2>Uhrzeit: $S </h2>"), rt, 0, strZeit); //<==PROBLEM===
return bfill.position();
}
void setup ()
{
//### ENC28J60 per DHCP intitialisiert und die RTC per NTP ###
}
void loop () {
// Get the current time
Serial.print (fctGetCurTime());
Serial.print (" ");
Serial.print(RTC.getTemperature());
Serial.println(" C");
rt = RTC.getTemperature();
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if (isnan(rt)) {Serial.println("Failed to read from Sensor");}
// check if valid tcp data is received and send web page date
if (pos) ether.httpServerReply(homePage());
}
String fctGetCurTime(){
char RtcIs[]= "0000-00-00 00:00:00";
DateTime now = RTC.now();
unsigned long newHour = now.hour();
unsigned long newMinute = now.minute();
unsigned long newSecond = now.second();
unsigned long newYear = now.year();
unsigned long newMonth = now.month();
unsigned long newDay = now.day();
RtcIs[0] = '0'+newYear / 1000;
RtcIs[1] = '0'+((newYear / 100) % 10);
RtcIs[2] = '0'+((newYear / 10 ) % 10);
RtcIs[3] = '0'+newYear % 10;
RtcIs[5] = '0'+newMonth / 10;
RtcIs[6] = '0'+newMonth % 10;
RtcIs[8] = '0'+newDay / 10;
RtcIs[9] = '0'+newDay % 10;
RtcIs[11] = '0'+newHour / 10;
RtcIs[12] = '0'+newHour % 10;
RtcIs[14] = '0'+newMinute / 10;
RtcIs[15] = '0'+newMinute % 10;
RtcIs[17] = '0'+newSecond / 10;
RtcIs[18] = '0'+newSecond % 10;
return RtcIs;
}
Der Rückgabewert ist ein String Objekt. Dann sollte auch eins erstellt werden. Aber man kann weder String Objekte, noch char Arrays so ins PROGMEM schreiben!!
doch die Funktion liefert einen String, so ist sie ja deklariert: String fctGetCurTime().... und char RtcIs[] brauche ich ja auch nur bis zum return.
Ich habe char RtcIs[] aber wirklich mal global definiert - das allein brachte aber keinen Erfolg sondern der Hinweis von
Serenifly:
... Aber man kann weder String Objekte, noch char Arrays so ins PROGMEM schreiben!!
Ich habe mir gedacht, probiers lieber mal aus und so lautet die Zeile jetzt: "
Moment. Ich lag falsch
Die PSTR Klammer geht ja nicht bis zu Ende. Da hatte ich mich total verguckt.
Dann liegt es daran, dass die Funktion wohl keine String Objekte als Parameter nimmt. Sondern ein char Array erwartet. Was sehr häufig vorkommt. Auf String Objekte kann man i.d.R. komplett verzichten. Am besten gleich char Arrays verwenden. Ansonsten bekommt man mit c_str() Lesezugriff auf das interne Array.
Das könnte man auch als Rückgabewert char* umbauen.
Vorsicht. Du kannst keine Zeiger auf lokale Variablen zurückgeben. Also müsste man das Array als Parameter übergeben. Für Anfänger ist es da einfacher wenn es global ist
Das die Umwandlung in den String das lokale charArray persistiert, wußte ich nicht.
Das lokale Array hört schon auf zu existieren. Aber bei der Rückgabe wird über den Konstruktor des String Objekts vorher kopiert.
Wie ich schrieb, habe ich einige Probleme das C Konzept der Strings, oder besser, dass es sie so wie in VB/ VBA nicht gibt, zu verstehen.
Mit char* habe ich versucht zu arbeiten, aber so richtig ist mir nicht klar wann ein Zeiger und wann das Array selber verwandt wird.
Allein das zusammensetzten des arrays hat mich einen halben Tag gekostet. Ich habe es jetzt so gemacht, dass ich ein Array definiere "char RtcIs[]= "0000-00-00 00:00:00" und anschließend die einzelnen Zeichen austausche.
Aber warum reicht dazu nicht: "RtcIs[0] = newYear / 1000;"?
Warum muss es "RtcIs[0] = '0'+newYear / 1000;" sein?
jetzt wird es heller. In C ist ein String eine Byte-Kette von ASCII-Codes, um die ich mich kümmern muss/ kann. Der Name ist eine Zeiger auf das 0. Element. Wenn man eine '2' schreiben will so muss man ASCII-Code 50 dez schreiben. Würde man 2 schreiben, dann hätte man ein Steuercode hinterlegt.
So richtig?
@Tommy: sehr gut erklärt auf deiner Seite. Mit Namen und Zeigern muss ich mich noch beschäftigen.
In VB ist ein String ein String und ich mache mir keine Gedanken, wie er verwaltet wird - unter der Haube muss das VB aber genauso machen.