|
961
|
International / Deutsch / Re: Lesetipp: c't - Arduino im AVR-Studio programmieren
|
on: April 20, 2012, 02:44:01 am
|
Das macht die Datei "main.cpp" welche die IDE mitbringt: #include <Arduino.h>
int main(void) { init();
#if defined(USBCON) USB.attach(); #endif
setup();
for (;;) { loop(); if (serialEventRun) serialEventRun(); }
return 0; }
Die kapselt das eigentliche main() und einige spezielle Setup-Geschichten.
|
|
|
|
|
962
|
International / Deutsch / Re: Temperatur Logger, mit DS18B20... Brauche Hilfe bitte...
|
on: April 20, 2012, 02:28:24 am
|
|
Dafür ist ja die SD-Karte da, dort werden die Daten lokal gespeichert. Der Zugriff selbst kann auch wieder indirekt erfolgen. z.B. durch aufrufen eine URL http://<synologyIP>/service.php Das kann der Arduino regelmäßig pollen und dort stehen z.B. Befehle wie "send 2012-04-19.csv" drin. Damit kann der Arduino in einer "Messpause" die Datei von der SD-Karte per HTTP-Post an den Webserver hochladen. Das kann man sicher auch alles anders lösen. Es gibt immer verschiedene Wege zum Ziel. Bei meiner Lösung war mir wichtig, das der Arduino Wetterdaten sammelt und nicht die meiste Zeit damit verbringt auf einen HTTP-Request zu warten, oder von einem Request im ungünsitgen Zeitraum erwischt wird.
|
|
|
|
|
963
|
International / Deutsch / Re: VirtualWire
|
on: April 19, 2012, 11:29:56 pm
|
|
Aber das ist genau der Punkt. Du überträgst ein struct von einem System auf ein anderes. Die Wahrscheinlichkeit, das Du auf dem 2. System das gleiche Speicherlayout hast und damit der Pointer aus dem struct auf Deine eigene Memory-Page zeigt ist verschwindend gering. Somit hättest Du gute Chancen, das der Speicherschutz zuschlägt, sobald Du den String aus dem struct verwenden willst. Beim Arduino gibt es keine Pages, der Speicher wird linear adressiert. Dazu kommt, das bei den meisten µControllern eine Harvard-Architektur eingesetzt wird, also getrennter Programm und Datenspeicher. Beim Arduino / Atmel ist das Flash-Ram für den Code und SRAM für die Daten. Moderne PCs setzen auf die von Neumann-Architektur, bei der Programm und Daten in einem gemeinsamen Speicher liegen. Somit kann man sich durch falsche Pointer auf dem Arduino zumindest nicht den eigenen Programmcode zerstören.
|
|
|
|
|
964
|
International / Deutsch / Re: Temperatur Logger, mit DS18B20... Brauche Hilfe bitte...
|
on: April 19, 2012, 11:23:14 pm
|
|
Dann mach doch aus dem Arduino einen Webclient, keinen Webserver. Der Arduino misst die Temperatur und ruft auf Deinem Webserver eine URL (z.B. http://<synology-IP>/senddata.php?temp1=10.3&temp2=23) auf. Der Synology-Webserver kann auch PHP, Du kannst dort also ohne Probleme die Daten verarbeiten und in eine Datei schreiben. Außerdem sparst Du Dir so den Cronjob auf dem NAS das alle X Minuten den Arduino abfragt. Meine Arduino-Wetterstation funktioniert auf diese Weise sehr stabil seit einem halben Jahr. Ich habe mir sogar die RTC gespart und frage einmal täglich über eine spezielle URL von Webserver die Zeit ab. Das spart den Code für eine NTP-Funktion, denn ein HTTP-Get musste ich ja eh bauen. Ein weiterer Vorteil ist, das der Arduino den Zeitpunkt zum Senden der Daten bestimmen kann und nicht immer auf ankommende Requests warten muss.
|
|
|
|
|
966
|
International / Deutsch / Re: Arduino GSM shield http Get Verbindung
|
on: April 19, 2012, 02:00:08 pm
|
|
Ich habe mir gerade mal den Code der aktuellen Version der GSM-Lib angesehen. Beim httpGet() wird der "Host:" Parameter mitgesendet. Welche Version der Lib setzt Du ein? Evtl. fehlt das ja bei Deiner Version.
|
|
|
|
|
967
|
International / Deutsch / Re: Arduino GSM shield http Get Verbindung
|
on: April 19, 2012, 01:49:03 pm
|
Mehrere Sachen in Deinem Code fallen mir auf. 1.) Du definierst ein Array char msg[20], übergibst aber beim Aufruf "numdata=inet.httpGET(" www.google.de", 80, "/", msg, 50);" eine Puffergröße von 50 Bytes, statt der 20 Bytes des Arrays. Damit überschreibt die Funktion alle 30 Bytes hinter dem Array im Speicher. Das kann zu sehr spannenden Ergebnissen führen. 2.) Die Ausgabe der empfangenen Zeichen ist deutlich mehr als 50 Zeichen, von welchem Code werden die denn ausgegeben? 3.) Warum sollte das Programm mit DNS nicht klar kommen? Du bekommst eine Antwort vom Google-Webserver, also klappt DNS doch, sonst würde gar nix zurück kommen. Die Antwort ist ein HTTP 302 Redirect auf http://www.google.de. Das passiert z.B. auch wenn man einen HTTP-Request per telnet simuliert: telnet www.google.de 80 Trying 209.85.147.94... Connected to www-cctld.l.google.com. Escape character is '^]'. GET / HTTP/1.0 HTTP/1.0 302 Found Location: http://www.google.de/Cache-Control: private Content-Type: text/html; charset=UTF-8 Set-Cookie: PREF=ID=be4d6a2fb8e1fc75:FF=0:TM=1334861125:LM=1334861125:S=lkBvT9ZrB0NjYAxk; expires=Sat, 19-Apr-2014 18:45:25 GMT; path=/; domain=.google.com Set-Cookie: NID=58=to_a07wmRSi1obtjhkconKlD46PR7rgfSwy1T4kgZVbztkFfyPWgozoACZ1fvEh5GzrZ9s8sBewpmsbGGK5PcV6RQp8Cowl-C6y4aQao16a6CdLXU_DTxlaLjBbIz3hc; expires=Fri, 19-Oct-2012 18:45:25 GMT; path=/; domain=.google.com; HttpOnly P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." Date: Thu, 19 Apr 2012 18:45:25 GMT Server: gws Content-Length: 218 X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF=" http://www.google.de/">here</A>. </BODY></HTML> Das passiert deshalb, weil beim HTTP-Request der Parameter "Host: www.google.de" nicht mitgesendet wird. Damit anwortet Google mit dem Redirect. Was bei Deinem Beispiel fehlt ist ein Teil vom HTTP-Header, da bei Dir nach 20 Zeichen Schluss ist. Mach mal den msg[] Puffer deutlich größer und übergib bei inet.httpGET() die Größe die der Puffer hat. Mario.
|
|
|
|
|
968
|
International / Deutsch / Re: Arduino GSM shield http Get Verbindung
|
on: April 19, 2012, 01:29:22 pm
|
Ich hab den Code mal in die passenden Tags gepackt, sonst kann das ja keiner lesen. #include "SIM900.h" #include <SoftwareSerial.h> #include "inetGSM.h"
InetGSM inet;
char msg[20]; int numdata; char inSerial[50]; int i=0; boolean started=false;
void setup() { //Serial connection. Serial.begin(9600); Serial.println("GSM Shield testing."); //Start configuration of shield with baudrate. //For http uses is raccomanded to use 4800 or slower. if (gsm.begin(2400)){ Serial.println("\nstatus=READY"); started=true; } else Serial.println("\nstatus=IDLE"); if(started){ //GPRS attach, put in order APN, username and password. //If no needed auth let them blank. if (gsm.attachGPRS("internet.eplus.de", "eplus", "internet")) Serial.println("status=ATTACHED"); else Serial.println("status=ERROR"); delay(1000); //Read IP address. gsm.SimpleWrite("AT+CIFSR"); delay(5000); //Read until serial buffer is empty. gsm.WhileSimpleRead(); //TCP Client GET, send a GET request to the server and save the reply. numdata=inet.httpGET("www.google.de", 80, "/", msg, 50); //Print the results. Serial.println("\nNumber of data received:"); Serial.println(numdata); Serial.println("\nData received:"); Serial.println(msg); } };
void loop() { //Read for new byte on serial hardware, //and write them on NewSoftSerial. serialhwread(); //Read for new byte on NewSoftSerial. serialswread(); };
void serialhwread(){ i=0; if (Serial.available() > 0){ while (Serial.available() > 0) { inSerial=(Serial.read()); delay(10); i++; } inSerial='\0'; if(!strcmp(inSerial,"/END")){ Serial.println("_"); inSerial[0]=0x1a; inSerial[1]='\0'; gsm.SimpleWrite(inSerial); } //Send a saved AT command using serial port. if(!strcmp(inSerial,"TEST")){ gsm.SendATCmdWaitResp("ATE0", 500, 50, "OK", 5); Serial.println("SIGNAL QUALITY"); gsm.SimpleWrite("AT+CSQ");
} //Read last message saved. if(!strcmp(inSerial,"MSG")){ Serial.println(msg); } else{ Serial.println(inSerial); gsm.SimpleWrite(inSerial); } inSerial[0]='\0'; } }
void serialswread(){ gsm.SimpleRead(); }
|
|
|
|
|
969
|
International / Deutsch / Re: VirtualWire
|
on: April 19, 2012, 01:06:48 pm
|
und da auch bei modernen Betriebssystemen normalerweise malloc nicht direkt den Speicher vom Betriebssystem anfordert, sondern seine eigene Speicherverwaltung implementiert, ist das auch dort nicht unbedingt gewährleistet. Das bezweifle ich aber mal ganz stark. Das wäre ja das Sicherheitsloch, um als normales Programm auf den Speicher anderer Prozesse zugreifen zu können. Für den "Schutz" des Speichers sorgt die libc, soweit ich weiss. Schaut man sich z.B. unter Linux den Ablauf des folgenden simplen Programms an, sieht man z.B. die "mprotect()" Aufrufe: #include <stdlib.h> #define MEMSIZE 102400 void main(int argc, char** argv) { void* pdata = malloc(MEMSIZE); }
strace ./memtest execve("./memtest", ["./memtest"], [/* 14 vars */]) = 0 brk(0) = 0x8758000 uname({sys="Linux", node="c473s06", ...}) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f2000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=20200, ...}) = 0 mmap2(NULL, 20200, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76ed000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220o\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1442372, ...}) = 0 mmap2(NULL, 1448456, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb758b000 mmap2(0xb76e7000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15c) = 0xb76e7000 mmap2(0xb76ea000, 10760, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb76ea000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb758a000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb758a6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 open("/dev/urandom", O_RDONLY) = 3 read(3, "\23\341\276", 3) = 3 close(3) = 0 mprotect(0xb76e7000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0xb7710000, 4096, PROT_READ) = 0 munmap(0xb76ed000, 20200) = 0 brk(0) = 0x8758000 brk(0x8792000) = 0x8792000 exit_group(141918216) = ?
|
|
|
|
|
970
|
International / Deutsch / Re: VirtualWire
|
on: April 19, 2012, 11:38:05 am
|
Aber du hast ja schon schön vorgemacht, wie man Strings als char[] mit fester Länge speichern kann - das sollte eigentlich ausreichen.
Das ist richtig, aber ein "char* text" ist auch in einem struct schnell geschrieben, weil man das halt immer so macht. Dann später den Fehler zu finden ist um so schwerer. Zumal es beim Arduino kein Memoryprotection gibt und der Zeiger auf dem empfangenden Arduino zwar in die Wüste zeigt, aber durchaus gültig ist. Mario.
|
|
|
|
|
973
|
International / Deutsch / Re: Temperatur Logger, mit DS18B20... Brauche Hilfe bitte...
|
on: April 18, 2012, 02:11:46 pm
|
Hallo, ich habe da nochmal eine Verständnis Frage, folgendes Szenario: Der Arduino misst die Temperatur und schreibt sie eine Logdatei, ohne sie auf einer Webseite wieder zugeben. Kann ich dann ohne Problem die Daten per FTP oder telnet abrufen ? Arduino -->Logfile -->Ethernet
Dann musst Du Deinem Arduino aber auch FTP oder telnet beibringen. Denn so wie Du es beschreibst, ist der Arduino der Server, denn der loggt ja die Daten. Das Problem bleibt aber das Gleiche, Dein Arduino hat die Daten und Du musst sie per Ethernet abholen. Dabei ist dann HTTP immer noch viel einfacher als telnet oder ftp. Wo ist denn Dein Problem, wenn Du den Webserver schon hast. Du musst lediglich noch die Datei auf der SD-Karte öffnen und dann die Daten in einen Puffer lesen und den dann an den verbundenen Webclient (Browser, wget etc.) ausgeben.
|
|
|
|
|
974
|
International / Deutsch / Re: VirtualWire
|
on: April 18, 2012, 08:49:11 am
|
Schön, das es klappt. Wenn Du beliebige Daten übertragen willst, erzeugst Du Dir am besten ein "struct" (siehe http://www.proggen.org/doku.php?id=c:tutorial:struct) Dessen Länge und den Zeiger auf eine Instanz des struct kannst Du dann der Sendefunktion geben. struct Data{ unsigned int zahl1; float x; char[5]; };
Auf der Empfangsseite bekommst Du ja wieder einen Buffer der gleichen Länge wie das gesendete struct. Damit kannst Du diesen Buffer dann einfach auf den Typ Deines structs casten. struct Data *data = (struct Data*)buf;
Aufpassen muss man aber bei Strings (char*) im struct. Hier steht dann nicht der String direkt drin, sondern nur der Zeiger auf den eigentlichen String. Hier ist dann zusätzlicher Aufwand nötig-
|
|
|
|
|
975
|
International / Deutsch / Re: Temperatur Logger, mit DS18B20... Brauche Hilfe bitte...
|
on: April 18, 2012, 08:40:00 am
|
client.println(); die Datei (DATALOG.TXT) angeben, damit ich sie runterladen kann, Oder föllig miss verstanden?  Noch eine Frage,habe bei google irgendwie nix gefunden, kann den Sketch/Code auf die SD-Karte packen? Mein Sketch hat jetzt schon 29660bytes von max 32256bytes Im Prinzip schon, aber nicht die Datei gibst Du an, sondern Du musst diese Schrittweise einlesen und an den Client ausgeben. Datei auf der SD-Card öffnen, Daten aus der Datei lesen und per client.print() an den Client schicken. Und hier greift dann ggf. das Problem des gleichzeitigen Lesens von SD und Senden per Ethernet. Achtung, das leere client.println(); ist wichtig. Damit weiss der Browser (wget) das der HTTP-Header zuende ist und die Daten anfangen. Also erst nach dem leeren client.println(); Deine Ausgabe einbauen.
|
|
|
|
|