433MHz Sender/Empfänger und digitale/analoge Pins

Hallo,
ich beschäftige mich seit einer Woche damit, zwei Arduino Nanos mit jeweils einem Sender- und Empfangsmodul (433MHz) miteinander kommunizieren zu lassen. Ich habe eine feste Station, die über ein Relais zwei Steckdosen ansteuert, und ein Funksender. Soweit hat alles gut geklappt, die Steckdosen lassen sich ferngesteuert ein- und ausschalten. Jetzt habe ich einen neuen Sender gebaut, der kompakter ist (lediglich ein Arduino Nano mit Sender/Empfänger und 6 Taster). 3 Taster sind auf die digitalen Pins 6, 7 und 8, die anderen 3 auf die analogen Pins 0, 1 und 2 gelegt. Auf dem neuen Sender läuft das gleiche Programm wie gewohnt wie auf dem Alten, mit einer Ausnahme: wenn ich einen Taster auf einem digitalen Pin betätige, reagiert der Nano zwar auf den Tastendruck, sendet aber kein Signal bzw. es wird kein Signal empfangen (bei keinem Empfänger den ich getestet habe). Wenn ich auf einen der an einem analogen Pin angeschlossenen Taster drücke, läuft alles ganz normal.

Frage: Warum wird kein Signal gesendet bzw. empfangen, wenn ich einen an einem digitalen Pin angeschlossenen Taster drücke?

Der Code des Empfängers funktioniert einwandfrei mit dem alten Sender.

Hier sind die Quellcodes:

Sender:

#include <RCSwitch.h>

RCSwitch snd = RCSwitch();
int val[] = {0, 0, 0, 0};     // 2: low > high, 1: high, 0: low, -1: high > low
int wert[] = {0, 0, 0, 0};   // 1: Taster gedrückt, 0: Taster nicht gedrückt

void setup() {
  snd.enableTransmit(3);
  snd.setProtocol(1);
  snd.setPulseLength(433);
  snd.setRepeatTransmit(10);    // Sender einstellen
  Serial.begin(9600);
}

void loop() {
  wert[0] = digitalRead(8);
  wert[1] = digitalRead(7);
  wert[2] = analogRead(0)>1000?1:0;
  wert[3] = analogRead(2)>1000?1:0;  // Pins auslesen
  String txt = "";
  for(int i=0;i<4;i++) {
    if (wert[i] == 1) {
      if (val[i] == 2) val[i] = 1;
      if (val[i] < 1) val[i] = 2;
    } else if (wert[i] == 0) {
      if (val[i] == -1) val[i] = 0;
      if (val[i] > 0) val[i] = -1;
    }
    if (val[i] == 2) snd.send((3 << 9) | i, 12);  // Senden, wenn Taster gedrückt wurde
    txt += String(wert[i]);
  }
  Serial.println(txt);  // Über Serial ausgeben
  delay(100);
}

Empfänger:

#include <RCSwitch.h>

RCSwitch rec = RCSwitch();
RCSwitch snd = RCSwitch();
int r[] = {0, 0};                    // Relais (0: Aus, 1: An)
boolean t[] = {false, false};       // aktuelle Tasterstellung
boolean talt[] = {false, false};   // alte Tasterstellung, zum Vergleichen
int active = 0;

const int led1 = 6;   // LED für Relais 1
const int led2 = 5;   // LED für Relais 2
const int tas1 = 3;   // Lokaler Stationstaster für Relais 1
const int tas2 = 4;   // Lokaler Stationstaster für Relais 2
const int prec = 2;   // Pin des Empfängermoduls
const int psnd = 9;   // Pin des Sendemoduls
const int rel1 = 8;    // Pin für Relais 1
const int rel2 = 7;    // Pin für Relais 2

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(tas1, INPUT);
  pinMode(tas2, INPUT);
  pinMode(psnd, OUTPUT);
  pinMode(rel1, OUTPUT);
  digitalWrite(rel1, HIGH);
  pinMode(rel2, OUTPUT);
  digitalWrite(rel2, HIGH);
  pinMode(13, OUTPUT);
  rec.enableReceive(0);
  rec.setProtocol(1);
  snd.enableTransmit(psnd);
  snd.setRepeatTransmit(5);
  snd.setPulseLength(433);
  snd.setProtocol(1);
  Serial.begin(9600);
}

void loop() {
  t[0] = digitalRead(tas1)==HIGH;
  t[1] = digitalRead(tas2)==HIGH;   // Lokale Taster auslesen
  if (rec.available()) {
    long val = rec.getReceivedValue();    // Empfangenes speichern
    rec.resetAvailable();
    if ((val >> 9) == 3) {
      int data = val & 7;            // Hinteren 3 Bits ausschneiden
      if (data == 4) {
        int b = (val >> 5) & 7;
        snd.send(((b==0?5:b) << 9) | (r[0] << 1) | r[1], 12);    // aktuelle Stati zurücksenden
      } else {
        digitalWrite(13, HIGH);
        r[data>>1] = data & 1;      // neue Einstellung speichern ...
        active = (data >> 1) + 1;    // ... und später aktualisieren lassen
      }
    }
  }
  for(int i=0;i<2;i++) {
    if (talt[i] != t[i]) {
      if (t[i]) {
        r[i] = 1-r[i];
        digitalWrite(i==0?rel1:rel2, 1-r[i]);
        digitalWrite(i==0?led1:led2, r[i]);
      }
      delay(20);
    }
    talt[i] = t[i];
    if (active == i+1) {     // Aktualisierung
      active = 0;
      digitalWrite(i==0?rel1:rel2, 1-r[i]);   // Relais ist LOW-aktiv
      digitalWrite(i==0?led1:led2, r[i]);
      digitalWrite(13, LOW);
    }
  }
}

Danke im Voraus für Vorschläge und Lösungsansätze für mein Problem :wink:

  wert[2] = analogRead(0)>1000?1:0;

wieso liest Du diese Pins analog aus? Du kannst sie ja auch digital verwenden. Der Grenzwert 1000 bei 1023 Maximalwert ist meiner Meinung etwas zu hoch.
Bist Du sicher daß Du 2 dieser Sendemodule gleichzeitig betreiben kannst? Schalten die Die Sendefrequenz ab wenn sie nicht angesteuert werden?
Grüße Uwe

uwefed:
Der Grenzwert 1000 bei 1023 Maximalwert ist meiner Meinung etwas zu hoch.

Die analogen Pins sind ja nicht das Problem, sondern die Digitalen. Der Grenzwert spielt keine Rolle, habe ihn schon oft verwendet und noch nie Probleme bekommen (meinstens in Kombination mit einem 10k Pull-Up Widerstand und einem Taster).

uwefed:
Schalten die Die Sendefrequenz ab wenn sie nicht angesteuert werden?

Pro Arduino Nano habe ich jeweils nur einen Sender und einen Empfänger. Dass die Sender von verschiedenen Nanos sich gegenseitig blockieren schließe ich aus, da das nicht mein erstes Projekt mit Funksendern ist und ich bis jetzt in dieser Hinsicht keine Probleme hatte.

uwefed:

  wert[2] = analogRead(0)>1000?1:0;

wieso liest Du diese Pins analog aus? Du kannst sie ja auch digital verwenden.

Mir wäre neu, einen analogen Pin mit digitalRead() auslesen zu können.
Keine digitalen Pins sondern nur analoge Pins zu verwenden (da diese ja funktionieren) ist nur schwer umsetzbar, da durch den kompakten Aufbau der Fernsteuerung 3 Taster auf der Seite der digitalen Pins und 3 Taster auf der Seite der analogen Pins angebracht sind.
LG The Programmer

Mir wäre neu, einen analogen Pin mit digitalRead() auslesen zu können.

Funktioniert nicht mit allen Pins, aber in der Regel schon...
z.B. klappt es nicht mit A6 und A7 beim 328P

t[0] = digitalRead(tas1)==HIGH;

Ist das gleiche wie:

 t[0] = digitalRead(tas1);

The_Programmer:
Die analogen Pins sind ja nicht das Problem, sondern die Digitalen. Der Grenzwert spielt keine Rolle, habe ihn schon oft verwendet und noch nie Probleme bekommen (meinstens in Kombination mit einem 10k Pull-Up Widerstand und einem Taster).Pro Arduino Nano habe ich jeweils nur einen Sender und einen Empfänger. Dass die Sender von verschiedenen Nanos sich gegenseitig blockieren schließe ich aus, da das nicht mein erstes Projekt mit Funksendern ist und ich bis jetzt in dieser Hinsicht keine Probleme hatte.Mir wäre neu, einen analogen Pin mit digitalRead() auslesen zu können.

Auch wenn es keine Rolle spielt, kann dieses zu einem Problem führen.

Dass die Sender sich nicht gegenseitig stören, kannst du nicht ausschließen.
Auch wenn es bisher funktioniert hat. Wenn dies nicht "sicherheitsrelevant" ist, kann es natürlich so bleiben. Aber "sauber" ist es nicht.

Wenn es dir neu ist, einen analogen Pin mit "digitalRead();" zu lesen, heißt es nicht, dass dies dennoch möglich ist. Grundlagen!

Keine digitalen Pins sondern nur analoge Pins zu verwenden (da diese ja funktionieren) ist nur schwer umsetzbar, da durch den kompakten Aufbau der Fernsteuerung 3 Taster auf der Seite der digitalen Pins und 3 Taster auf der Seite der analogen Pins angebracht sind.
LG The Programmer

Wenn du es nur so umsetzen kannst, ist es auch ok, aber nimm "digitalRead();" dafür.

Warum es mit digitalen Pins nicht funktioniert, kann ich leider nicht erkennen, da dein Sketch für mich recht unübersichtlich ist.

HotSystems:
aber nimm "digitalRead();" dafür.

und definiere die Pins als Eingänge.
Grüße Uwe

uwefed:
und definiere die Pins als Eingänge.
Grüße Uwe

Stimmt...aber das habe ich einfach mal vorausgesetzt. :wink:

Trotz des Grenzwertes von 1000 und der Tatsache, dass man analoge Pins auch mit digitalRead() auslesen kann, sind diese nicht das Problem; sie funktionieren einwandfrei.

The_Programmer:
Frage: Warum wird kein Signal gesendet bzw. empfangen, wenn ich einen an einem digitalen Pin angeschlossenen Taster drücke?

Das Problem liegt nur an den digitalen Pins, die zwar ausgelesen werden, aber das Signal nicht (oder falsch) gesendet bzw. nicht (oder falsch) empfangen wird.

Der Sender an den stationären Relais wird nicht verwendet, nur initialisiert für eine spätere Funktion, d.h. es gibt nur einen Sender, der sendet.

Schade, dass du unsere Empfehlungen ignorierst.
Aber ok, ist dann so.

Hast du schon mal die Werte, die gesendet werden sollen, im SerialMonitor angesehen?

Was wird am seriellen Monitor ausgedruckt?

String txt = "";
  for(int i=0;i<4;i++) {
    ...
    txt += String(wert[i]);
  }
  Serial.println(txt);  // Über Serial ausgeben

Du macht ein Debug mit serial und sagst uns nicht was dabei herauskommt. Sollen wir hellsehen?

Grüße Uwe

Die Ausgabe im Serial Monitor sind lediglich die Tasterzustände, ob gedrückt oder nicht.
Es ist eine 4-stellige Binärzahl, die auch immer die aktuellen Tasterzustände richtig ausgibt.
Die gesendete Zahl ( (3 << 9) | i ) setzt sich aus der dreistelligen, gerätespezifische Zahl (in diesem Fall 3, also 011) und neun weiteren Datenbits zusammen (in diesem Fall der vorletzte Bit für Relais 1 oder 2 und der letzte Bit, ob dieses Relais ein- oder ausgeschaltet werden soll). Diese werden, wie ich mit dem Serial Monitor auch getestet habe, richtig codiert.

PS: ich ignoriere eure Kommentare nicht, sie helfen mir nur nicht mein Problem zu lösen.

EDIT: 011 anstatt 001

Wie schon geschrieben, lass dir doch die Werte anzeigen, die gesendet werden sollen.
Da kann doch nur eine Differenz sein.

The_Programmer:
Die Ausgabe im Serial Monitor sind lediglich die Tasterzustände, ob gedrückt oder nicht.

dann erweitere mal die Ausgabe mit den Zuständen der val[] Variablen bei jedem FOR Durchgang und zeig sie uns.
Grüße Uwe

HotSystems:
Wie schon geschrieben, lass dir doch die Werte anzeigen, die gesendet werden sollen.
Da kann doch nur eine Differenz sein.

The_Programmer:
Die gesendeten Zahlen [...] werden, wie ich mit dem Serial Monitor auch getestet habe, richtig codiert.

An den gesendeten Zahlen liegt es auch nicht.

Wenn ich

txt += String(val[i]);

anstatt

txt += String(wert[i]);

ans Ende der FOR-Schleife schreibe, gibt die Konsole

0000
0000
0200
0100
0100
0100
0100
0-100
0000
0000

nach dem Drücken des Tasters, der mit dem digitalen Pin 7 verbinden ist, aus.

Ganz schlau werde ich aus deinen Informationen nicht.
Du schreibst, der Empfänger ist ok. Funktioniert ja mit altem Sender.
Der gesendete Zahlenwert ist ok. Hast du ja im Monitor gesehen.

Dann kann es ja nur am Sendermodul liegen.
Nur das unterscheidet nicht ob ein digitaler Pin oder analoger Pin betätigt wird.

Also irgend etwas ist da nicht ok.

Soweit bin ich auch gekommen, HotSystems. Deswegen habe ich ja auch einen neuen Post hier im Forum eröffnet.
Genau genommen funktioniert es nicht nur mit dem alten Sender, sondern auch mit dem neuen, aber nur mit den analogen Pins. Die gesendeten Zahlen (3 << 9) | i mit i = {0, 1, 2, 3} ergeben 1536, 1537, 1538 und 1539 (jeweils 1024 + 512 + i), wobei die ersten beide nicht gesendet und/oder nicht empfangen und die letzten beiden sowohl gesendet als auch empfangen werden.
Ich habe es nun auch mit anderen Zahlen probiert ( (3 << 9) | (1 << 8) | i ), immer das gleiche Ergebnis. Ich habe auch die Variablen zwischen analogen und digitalen Pins getauscht, stets das gleiche Resultat.
Ich hoffe, dass jemandem ein Detail auffällt, der mir bisher entgangen ist.

Wenn ich

txt += String(val[i]);

anstatt

txt += String(wert[i]);

ans Ende der FOR-Schleife schreibe,

Hatte ich Dich nicht gebeten ZUSÄTZLICH die Werte auszugeben?

Grüße Uwe

Du überträgst die Button-Nummer  snd.send((3 << 9) | i, 12);testest aber die Buttons als Bits

    if ((val >> 9) == 3) {
      int data = val & 7;            // Hinteren 3 Bits ausschneiden
      if (data == 4) {

Du solltest also vielleicht besser zum Senden  snd.send((3 << 9) | (1 << i), 12);verwenden, dann aber auch beim Empfang

    if ((val >> 9) == 3) {
      int data = val & 0xF;            // unterste 4 Bits ausschneiden
      if (data == 4) {

benutzen.

Whandall:
Du überträgst die Button-Nummer
testest aber die Buttons als Bits

Das Senden der Button-Nummer habe ich bewusst gewählt, da die Programmierung hierfür am einfachsten ist. Die Zahlen 0, 1, 2 und 3 binär ausgedrückt sind 00, 01, 10 und 11. Hierbei steht die erste Ziffer für das Relais, das angesprochen wird, und die zweite, ob dieses ein- bzw. ausgeschaltet werden soll. Deswegen werden die Zustände Taster zu Beginn auch in dieser Reihenfolge in das Array gelesen, da die Positionen im Array die zu sendenden Zahlen sind.

uwefed:
Hatte ich Dich nicht gebeten ZUSÄTZLICH die Werte auszugeben?

Mein Fehler :wink: hier sind die Zahlen, die die Konsole bei dem Druck des Tasters am digitalen Pin 7 ausgibt, wenn das

txt += String(val[i])+String(wert[i])+"  ";

am Ende der Schleife steht.

00  00  00  00  
00  00  00  00  
00  21  00  00  
00  11  00  00  
00  11  00  00  
00  11  00  00  
00  -10  00  00  
00  00  00  00  
00  00  00  00

The_Programmer:
Das Senden der Button-Nummer habe ich bewusst gewählt, da die Programmierung hierfür am einfachsten ist. Die Zahlen 0, 1, 2 und 3 binär ausgedrückt sind 00, 01, 10 und 11. Hierbei steht die erste Ziffer für das Relais, das angesprochen wird, und die zweite, ob dieses ein- bzw. ausgeschaltet werden soll. Deswegen werden die Zustände Taster zu Beginn auch in dieser Reihenfolge in das Array gelesen, da die Positionen im Array die zu sendenden Zahlen sind.

Soweit so gut. Wozu soll dann der Test auf Button == 4 gut sein?
Warum maskierst du drei Bits, obwohl nur zwei gesendet werden können?

Bei mir funktionieren alle Buttons (schließend nach GND) wenn ich sie mit INPUT_PULLUP benutze und umgekehrt abfrage, egal ob analog oder digital gelesen.

Alle Tasten nacheinander gedrückt ergeben bei mir als gesendete Werte

value = 0x600
value = 0x601
value = 0x602
value = 0x603

P.S. du brauchst mir nichts über Bits, Darstellungen etc zu erklären, das kann ich schon alles, seit etwa 40 Jahren. :wink: