Funksteckdose ansteuern über Kapazitiven Sensor (Capacitive Sensor)

Nabend,
wir müssen für eine Ausstellung 230V sicher schalten. Da ich kein Elektroniker bin, darf kein Soldid State Relais oder ähnliches verbauen. Deshalb habe ich eine Funksteckdose besorgt bei der ich den Sender über das Arduino Board ansteuern möchte.
Die Ansteuerung ansich funtkioniert einwandfrei, dazu verwende ich zwei reed Relais typ Meder DIP05-1A72-12D welche wenn geschaltet jeweils den ein oder aus Taster der Funkvernbedienung brücken.

Als Grundlage für meinen Sketch verwende ich den Beispiel sketch welchen ich wie folgt modifiziert habe:

#include <CapacitiveSensor.h>

/*
 * CapitiveSense Library Demo Sketch
 * Paul Badger 2008
 * Uses a high value resistor e.g. 10 megohm between send pin and receive pin
 * Resistor effects sensitivity, experiment with values, 50 kilohm - 50 megohm. Larger resistor values yield larger sensor values.
 * Receive pin is the sensor pin - try different amounts of foil/metal on this pin
 * Best results are obtained if sensor foil and wire is covered with an insulator such as paper or plastic sheet
 */

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int dosean = 13;
int doseaus = 10;

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()                    
{

   cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
   Serial.begin(9600);
   // initialize the digital pin as an output.
  pinMode(dosean, OUTPUT);  
  pinMode(doseaus, OUTPUT);  

}


void loop()                    
{
    long start = millis();
    long total1 =  cs_4_2.capacitiveSensor(30);
    if (total1 > 100) { digitalWrite(dosean, HIGH); delay(100);
    } else {
      digitalWrite(dosean, LOW);
    }
     if (total1 < 100) { digitalWrite(doseaus, HIGH); delay(100);
    } else {
      digitalWrite(doseaus, LOW);
    }
    Serial.print(millis() - start);        // check on performance in milliseconds
    Serial.print("\t");                    // tab character for debug window spacing

    Serial.print(total1);                  // print sensor output 1
    Serial.print("\t");

    delay(250);                             // arbitrary delay to limit data to serial port 
}

Das Ergebnis ist dabei folgendes:

Ich Berühre den Kapazitven Sensor, der zwischen Pin 2 und 4 ausgelesene Wert geht über 100 worauf Pin 13 auf High geht und das Relais für Funksteckdose an schaltet und die Dose geht an.
Entferne ich meine Hand vom Sensor geht der Wert unter 100 worauf Pin 10 auf High geht und das Relais für Funksteckdose aus schaltet und die Dose aus geht.
Das Problem ist jedoch, dass das Funkmodul streikt, wenn eine Taste länger als 5 Sekunden gedrückt ist (was zwangsläufig passiert da der Wert häufig unter 100 liegt und so das Relais Funksteckdose aus permanent Schaltet).

Was muss ich am Code ändern damit das Relais nur einmal geschaltet wird wenn der Wert unter 100 fällt? Steigt der Wert anschließend wieder über 100 und fällt dann wieder darunter soll das Relai natürlich wieder genau einmal schalten.

Eine andere denkbare Variante wäre, den Sensor als Taster zu verwenden:
Geht der vom Sensor gelesenen Wert über 100 dann soll Pin 13 für die eingestellte Delay Zeit auf high gehen. Geht der Sensorwert anschließend wieder über 100, soll Pin 10 für die eingestellte Delay zeit auf High gehen. Danach dann wieder Pin 13 und so weiter. Wie müsste der Code da aussehen?

Grüße,

Jan

Benutze Flags. Einfache Variablen in denen Du den Zustand des kapazitiven Sensors zwischenspeicherst. Dann verwende millis() un die Dauer des Impulses auf der Fernsteuerung zu definieren.

int dosean = 13;
int doseaus = 10;
int Statusan = 0;
int Statusaus = 0;
unsigned long Zeitan = 0; 
int Dauer = 500; // Zeitdauer Taste gedrückt 

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()                    
{

   cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
   Serial.begin(9600);
   // initialize the digital pin as an output.
  pinMode(dosean, OUTPUT);  
  pinMode(doseaus, OUTPUT);  
  Zeitan = millis(); 

}


void loop()                    
{
    long start = millis();
    long total1 =  cs_4_2.capacitiveSensor(30);
    if (total1 > 100 && Statusan == 0) { 
	digitalWrite(dosean, HIGH); 
	statoan = 1;
	delay(100);
    } 
	if ((total1 < 100 && Statusan == 1) || (millis() - Zeitan > Dauer)) 
	{
      digitalWrite(dosean, LOW);
	  statoan = 0;
    }
     ..... usw mit dem Ausschalttaster
}

Ich würde aber nicht Pin 13 verwenden da es beim Einschalten des Arduino aufleuchtet und somit die Steckdose eingeschaltet wird.

Grüße Uwe

Vielen Dank Uwe,
habe das mal wie folgt vervollständigt:

#include <CapacitiveSensor.h>
int dosean = 13;
int doseaus = 10;
int Statusan = 0;
int Statusaus = 0;
unsigned long Zeitan = 0; 
int Dauer = 1000; // Zeitdauer Taste gedrückt 

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()                    
{

   cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
   Serial.begin(9600);
   // initialize the digital pin as an output.
  pinMode(dosean, OUTPUT);  
  pinMode(doseaus, OUTPUT);  
  Zeitan = millis(); 

}


void loop()                    
{
    long start = millis();
    long total1 =  cs_4_2.capacitiveSensor(30);
    if (total1 > 100 && Statusan == 0) { 
	digitalWrite(dosean, HIGH); 
	Statusan = 1;
	delay(100);
    } 
	if ((total1 < 100 && Statusan == 1) || (millis() - Zeitan > Dauer)) 
	{
      digitalWrite(dosean, LOW);
	  Statusan = 0;
    }
    if (total1 < 100 && Statusaus == 0) { 
	digitalWrite(doseaus, HIGH); 
	Statusan = 1;
	delay(100);
    } 
	if ((total1 > 100 && Statusaus == 1) || (millis() - Zeitan > Dauer)) 
	{
      digitalWrite(doseaus, LOW);
	  Statusan = 0;
    }
    
}

Das ganze funktioniert jetzt einwandfrei aber es gibt folgendes Problem:

Das momentan aktive Relais (meist doseaus) öffnet und schließt permanent. Da das Teil tagelang im Dauerbetrieb laufen muss glaube ich nicht, dass es das lange mitmacht. Zudem läuft dann natürlich auch die Fernbedienung auf Dauerfeuer, wie die das verträgt kann ich nicht einschätzen. Gibt es eine Möglichkeit das zu unterbinden?

Grüße,

Jan

Nabend,
ich habe jetzt eine funktionierendes Programm mit Hilfe eines Programmierers hier vor Ort auf Basis von Uwes Sketch hinbekommen:

#include <CapacitiveSensor.h>
int dosean = 13;
int doseaus = 10;
int Statusan = 0;
int Statusaus = 0;
unsigned long Zeitan = 0; 
int Dauer = 100; // Zeitdauer Taste gedrückt 

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()                    
{

  cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
  Serial.begin(9600);
  // initialize the digital pin as an output.
  pinMode(dosean, OUTPUT);  
  pinMode(doseaus, OUTPUT);  
  Zeitan = millis(); 
  Serial.begin(9600);

}


void loop()                    
{
  long start = millis();
  long total1 =  cs_4_2.capacitiveSensor(30);
  if( (total1 > 100 )&&(Statusan == 0) ){ 
    digitalWrite(dosean, HIGH); 
    Statusan = 1;
    Statusaus = 0;
    delay(500);
    digitalWrite(dosean, LOW); 
  } 
  if ( (total1 < 100) && (Statusaus == 0) ) { 
    digitalWrite(doseaus, HIGH); 
    Statusaus = 1;
    Statusan = 0;
    delay(500);
    digitalWrite(doseaus, LOW); 
  } 
  Serial.println(total1);   // print sensor output 1

}

Vielleicht kann es ja mal wer brauchen.

Grüße,

Jan

Hallo,
ich nochmal. Ich habe jetzt aauch eine Version die den Sensor als richtigen Taster verwendet also:

Sensor berühren: Licht an
Sensor erneut berühren: Licht aus usw.

Der Code sieht dazu wie folgt aus:

#include <CapacitiveSensor.h>
int dosean = 12;
int doseaus = 10;
int Statusreset = 0;
int Statusanaus = 0;
unsigned long Zeitan = 0; 
int Dauer = 100; // Zeitdauer Taste gedrückt 

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()                    
{
  Serial.begin(9600);
  // initialize the digital pin as an output.
  pinMode(dosean, OUTPUT);  
  pinMode(doseaus, OUTPUT);  
  Zeitan = millis(); 
  cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // Kalibrierung Sensor 4,2 aus
  Serial.begin(9600);
}


void loop()                    
{
  // an
  long start = millis();
  long total1 =  cs_4_2.capacitiveSensor(30);
  if( (total1 > 1000 )&&(Statusreset == 0)&&(Statusanaus == 0) ){ 
    digitalWrite(dosean, HIGH); 
    Statusanaus = 1;
    Statusreset = 1;
    delay(500);
    digitalWrite(dosean, LOW); 
    Serial.println("an");
  } 


  start = millis();
  total1 =  cs_4_2.capacitiveSensor(30);
  if( (total1 > 1000 )&&(Statusreset == 0)&&(Statusanaus == 1) ){ 
    digitalWrite(doseaus, HIGH); 
    Statusanaus = 0;
    Statusreset = 1;
    delay(500);
    digitalWrite(doseaus, LOW); 
    Serial.println("aus");
  } 

  // reset an aus
  start = millis();
  total1 =  cs_4_2.capacitiveSensor(30);
  if(total1 < 800 ){ 
    Statusreset = 0;
    Serial.println("reset");
  } 


  Serial.println(total1);   // print sensor output 1
  delay(500);                             // arbitrary delay to limit data to serial port 
}

Funktioniert an sich auch wunderbar nur habe ich das Problem, dass die Sensorwerte im Lauf der Zeit immer über meinen schwellenwert ansteigen, so dass der Sensor nach z.B. 2 Stunden nicht mehr schaltet bzw. dauerhaft auf ein steht.
Wenn ich das Arduino Resette funktioniert wieder alles für eine gewisse Zeit einwandfrei. Ob ich die automatische Kalibrierung ein oder ausgeschaltet habe ändert an diesem Verhalten nichts.

Am liebsten würde ich daher einen reset z.B. alle 15 Minuten automatisch durchführen lassen. Ein automatischer reset über den reset Pin ist ja nicht empfehlenswert soweit ich das raus gelesen habe. Ich habe diesen Threat gefunden http://forum.arduino.cc/index.php/topic,37855.0.html wie würde das in meinem Code aussehen wenn ich das Programm alle 15 Minuten neustarten wollte?

Grüße,

Jan

Edit: Ich meine diesen Teil aus dem verlinkten Threat:

void(* resetFunc) (void) = 0; //declare reset function @ address 0

resetFunc(); //call reset

Ob ich die automatische Kalibrierung ein oder ausgeschaltet habe ändert an diesem Verhalten nichts.

Wie hast Du die automatische Kalibrierung eingeschaltet? Grüße Uwe

Ich dachte die ist automatisch eingeschaltet? Bzw. schaltet man sie nicht über folgenden Befehl aus?

 cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // Kalibrierung Sensor 4,2 aus

Oder muss ich die über

void reset_CS_AutoCal()

Neuaktivieren.

Grüße,

Jan

Edit: Bin mir jetzt eigentlich sicher, das ich das über reset_CS_AutoCal() machen muss. Wie muss mein Code aussehen, damit das alle 15 Minuten passiert?

Grüße,

Jan

Gibst Du uns den Link auf die Bibliothek CapacitiveSensor.h die Du verwendest? Grüße Uwe

Hallo Uwe
gerne, sollte diese hier sein: https://github.com/arduino-libraries/CapacitiveSensor/zipball/master

Ich habe mich jetzt mal eben hier eingelesen http://playground.arduino.cc/Learning/BlinkWithoutDelayDe#.UwUnLYWc6M8 und den code wie folgt abgeändert (teile die die ich abgeändert habe sind fett markiert):

#include <CapacitiveSensor.h>
int dosean = 12;
int doseaus = 10;
int Statusreset = 0;
int Statusanaus = 0;
unsigned long Zeitan = 0;
int Dauer = 100; // Zeitdauer Taste gedrückt
unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 90000; // Kalibrierungsinterval

CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2); // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()
{
Serial.begin(9600);
// initialize the digital pin as an output.
pinMode(dosean, OUTPUT);
pinMode(doseaus, OUTPUT);
Zeitan = millis();
cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // Kalibrierung Sensor 4,2 aus
Serial.begin(9600);
}

void loop()
{
// an
long start = millis();
long total1 = cs_4_2.capacitiveSensor(30);
if( (total1 > 1000 )&&(Statusreset == 0)&&(Statusanaus == 0) ){
digitalWrite(dosean, HIGH);
Statusanaus = 1;
Statusreset = 1;
delay(500);
digitalWrite(dosean, LOW);
Serial.println(“an”);
}

// aus
start = millis();
total1 = cs_4_2.capacitiveSensor(30);
if( (total1 > 1000 )&&(Statusreset == 0)&&(Statusanaus == 1) ){
digitalWrite(doseaus, HIGH);
Statusanaus = 0;
Statusreset = 1;
delay(500);
digitalWrite(doseaus, LOW);
Serial.println(“aus”);
}

// reset an aus
start = millis();
total1 = cs_4_2.capacitiveSensor(30);
if(total1 < 800 ){
Statusreset = 0;
Serial.println(“reset”);
}
// kalibrierung alle 15 minuten
** if (millis() - previousMillis > interval) {**
** previousMillis = millis();**
** cs_4_2.reset_CS_AutoCal();**
** }**

Serial.println(total1); // print sensor output 1
delay(500); // arbitrary delay to limit data to serial port
}

Soll dazu führen, dass alle 15 Minuten neu Kalibriert wird, kann das so funktionieren?

Grüße,

Jan

Edit: Mir fällt gerade auf, dass ich folgendes dann wohl aus meinem code raus nehmen muss damit das mit der Kalibrierung einen Sinn hat:

 cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // Kalibrierung Sensor 4,2 aus

Ja, das geht so.

Für Status-Variablen die nur 0/1 sind verwendet man übrigens besser boolean und true/false. Und Konstanten die sich nie änderen (wie Pin-Definitionen und feste Zeiten) kann man als "const" deklarieren.

Ok,
habe es eben auf das Arduino geladen und der Code tut was er soll.
Etwas seltsam ist aber, dass die Kalibrierung in jedem fall nach der eingestellten Zeit geschieht (habe es mir serial Monitor angesehen), auch wenn folgendes im Code enthalten ist:

  cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // Kalibrierung Sensor 4,2 aus

Hat jemand eine Erklärung dazu?

Grüße,

Jan

Edit:

Hier noch fertige Code:

#include <CapacitiveSensor.h>
int dosean = 12;
int doseaus = 10;
int Statusreset = 0;
int Statusanaus = 0;
unsigned long Zeitan = 0; 
int Dauer = 100; // Zeitdauer Taste gedrückt 
unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 300000;    // Kalibrierungsinterval

CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup()                    
{
  Serial.begin(9600);
  // initialize the digital pin as an output.
  pinMode(dosean, OUTPUT);  
  pinMode(doseaus, OUTPUT);  
  Zeitan = millis(); 
  Serial.begin(9600);
}


void loop()                    
{
  // an
  long start = millis();
  long total1 =  cs_4_2.capacitiveSensor(30);
  if( (total1 > 1000 )&&(Statusreset == 0)&&(Statusanaus == 0) ){ 
    digitalWrite(dosean, HIGH); 
    Statusanaus = 1;
    Statusreset = 1;
    delay(500);
    digitalWrite(dosean, LOW); 
    Serial.println("an");
  } 

  //aus
  start = millis();
  total1 =  cs_4_2.capacitiveSensor(30);
  if( (total1 > 1000 )&&(Statusreset == 0)&&(Statusanaus == 1) ){ 
    digitalWrite(doseaus, HIGH); 
    Statusanaus = 0;
    Statusreset = 1;
    delay(500);
    digitalWrite(doseaus, LOW); 
    Serial.println("aus");
  } 

  // reset an aus
  start = millis();
  total1 =  cs_4_2.capacitiveSensor(30);
  if(total1 < 800 ){ 
    Statusreset = 0;
    Serial.println("reset");
  } 
  // kalibrierung alle 15 minuten
  if (millis() - previousMillis > interval) {
    previousMillis = millis();
    cs_4_2.reset_CS_AutoCal();
    Serial.println("kalibrierung");
  }


  Serial.println(total1);   // print sensor output 1
  delay(500);                             // arbitrary delay to limit data to serial port 
}

Vielleicht kann es ja mal wer brauchen.