Problem[GSM Shield + Arduino Uno + Sparkfun microSD Shield= Alarmanlagenprojekt]

Hallo zusammen,

ich hab's ja bereits erwähnt dass ich zur Zeit an einem interessanten Alarmanlagenprojekt sitze. Ich stell euch am besten kurz mein Setup vor, wie oben schon erwähnt :

ein Arduino GSM Shield
ein Arduino Uno
neuerding ein Sparkfun microSD Shield
und ein PIR Sensor
eine RGB LED
und ein paar Kabel

et voila, das soll meine neue "WG" Alarmanlage werden.

Background : Bei uns wurde eingebrochen und ich dachte ich bau uns 3en in der WG mal eine interessante Lösung hierzu, ich rechne zwar nicht wirklich damit dass sich irgendwelche Herrschaften wieder hier rein verirren aber ich habe große Lust dieses Projekt zu verwirklichen und hierzu ne kleine Anleitung eventuell zu schreiben.

Es klappt auch alles wunderbar, der PIR Sensor erfasst Bewegungen, ne SMS wird gesendet, die RGB LED gibt mir den aktuellen Status an der kleinen Anlage aber das Abspeichern der Bewegungen in einer Textdatei klappt nicht so wirklich :frowning: Ich habe mir dazu extra einen Sparkfun microSD Shield besorgt. Der funktioniert zwar wunderbar wenn ich ihn mit dem Arduino alleine betreibe. Aber sobald ich ihn in mein System integriere dann spinnt er beim booten etwas rum. Genauer gesagt zeigt mir der Serial Monitor etwas verwirrendes auf ( Siehe Anhang )

An was könnte dies liegen ? Im Anhang befinden sich noch weitere Bilder meines kleinen Setups.

#include <GSM.h>

#include <SPI.h>
#include <SD.h>

File myFile;

#define PINNUMBER "6915"
GSM gsmAccess;
GSM_SMS sms;

const int chipSelect = 8;

int redPin = 11;
int greenPin = 5;
int bluePin = 9;
int anode = 6;
int dimmer = 20;
int ledtimer = 500;

int inputPin = 4;
int pirState = LOW;
int val = 0;
int freezetime;

char remoteNumber[20];

void setColor(int red, int green, int blue)
{

red = 255 - red;
green = 255 - green;
blue = 255 - blue;

analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}

void setup() {

Serial.begin(9600);

pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);

pinMode(inputPin, INPUT);

Serial.println("Alarmanlage startet...");

Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin alizing SD card...");
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(SS, OUTPUT);

if (!SD.begin(chipSelect)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");

myFile = SD.open("logger.txt", FILE_WRITE);

// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to logger.txt...");
myFile.println("Starte Aufzeichnung.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}

boolean notConnected = true;
while(notConnected)
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Nicht verbunden.");
delay(1000);
}
}

Serial.println("GSM online.");
Serial.println("System bereit.");

setColor(0, 255, 0); // green

}

void loop(){

val = digitalRead(inputPin);
if (val == HIGH) {

// hier LED

if (pirState == LOW) {

setColor(0, 255, 255);
Serial.println("Bewegung erfasst!");

if (myFile) {
Serial.print("Writing to logger.txt...");
myFile.println("Bewegung registriert und gespeichert.");

myFile.close();
Serial.println("done.");
} else {

Serial.println("error opening test.txt");
}

sms.beginSMS("0157XXXXXXXXX);
sms.print("Bewegung im Zimmer!");
sms.endSMS();

Serial.println("SMS wurde gesendet.");
Serial.println("Bewegungssensor wird fuer :");
Serial.println(freezetime/1000);
Serial.println("s eingefroren.");
delay(freezetime);
Serial.println("Bewegungssensor ist wieder aktiv.");

pirState = HIGH;
}
} else {

// hier LED

if (pirState == HIGH){
// we have just turned of
setColor(0, 255, 0); // green
Serial.println("Keine Bewegung.");

pirState = LOW;

}
}
}

Wäre für jede Hilfe, Tipp oder Verbesserungsvorschlag sehr dankbar.

Beste Grüße

Don

PS : Und kann mir mal einer Please sagen wie ich den Code hier richtig einfügen kann ? =)

1.jpg

2.jpg

3.jpg

Du gehst recht verschwenderisch mit dem begrenzten RAM um. Alle String-Literale landen im RAM.

Mach mal bei den println()-Ausgaben, das F()-Makro drum herum:

Serial.println(F("Text"));

Das geht glaube auch beir der File-Klasse. Dann bleiben die im Flash.

Diese Funktion hilft da auch:

int getFreeRAM() 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Du bit ein Schatz Serenify, das hat geklappt !!!

Kannst du mir das nochmal ganz kurz im Prinzip erklären, was da genau abläuft, damit ich wieder was gelernt habe und mich nicht nur freuen kann dass es funktioniert.

Beste

Don

Der AVR hat eine modifizierte Harvard-Architektur (wie viele andere µC auch). Anders als bei der von-Neumann-Architektur auf dem PC haben ROM und RAM getrennte Adress- und Daten-Räume und -Busse. Die normalen Funktionen sind i.d.R. für Adressen im RAM gedacht und können daher keine Adressen im Flash verarbeiten.

Daher werden beim Booten des Controllers alle Variablen aus dem Flash in das RAM kopiert. Große Arrays und viele String-Literale müllen als das RAM voll, auch wenn man sie nie verändert.

AVR gcc bietet aber eine ganze Reihe Makros und Hilfs-Funktionen um Daten direkt im Flash zu verarbeiten. Das F()-Makro stammt von der Arduino IDE und funktioniert mit print() und println(). Das alles kostet natürlich etwas Performance, da jedes Byte erst kopiert werden muss. Aber meistens ist das vertretbar.

Es gibt dazu auch noch PROGMEM:

Das geht auch für nicht-Strings, z.B. große Integer Arrays wie Tabellen. Man muss diese dann nur durch eine spezielle Funktion aus dem Flash kopieren.

Außerdem gibt es in avr/pgmspace.h noch weitere Makros und Funktionen. So gibt es z.B. von den meisten String Funktionen _P Versionen, die einen String direkt im Flash verarbeiten (z.B. strcmp, strcat, strcpy, strchr, strstr, sprintf (für den Format String)). Und das PSTR() Makro um die PROGMEM Deklaration direkt in den Funktions-Aufruf zu packen. Damit geht dann sowas:

#include <avr/pgmspace.h>

char stringBuffer[21];
#define P(str) strcpy_P(stringBuffer, PSTR(str))

P() geht dann mit allen Funktionen, da strcpy() einen Zeiger auf den Puffer zurückgibt. Das Makro kopiert einfach den String aus dem Flash in den Puffer ins RAM. Damit braucht man dann für alle String-Konstanten nur noch einen Puffer (der dann groß genug sein muss!).

Oder man machst sowas (hier für ein TFT):

void displayPrint_P(const char* str, int x, int y)
{
	strncpy_P(stringBuffer, str, STRING_BUFFER_SIZE);
	display.print(stringBuffer, x, y);
}

Und ruft das so auf:

displayPrint_P(PSTR("Text"), 10, 20);

Wenn du nur die Arduino print() Funktion nimmst, ist das nicht nötig, aber mit anderen Libs geht F() nicht. Außerdem ist sprintf_P() praktisch. Vor allem wenn man größere Format-Strings hat.

Merci

DonQuijote:
Hallo zusammen,

PS : Und kann mir mal einer Please sagen wie ich den Code hier richtig einfügen kann ? =)

Paar Beiträge vor deinem....
http://forum.arduino.cc/index.php?topic=227116.0
die letzten drei Beiträge auf der ersten Seite lesen.