Serial Monitor gibt nur zufällige Zahlen aus (HC-12 Kommunkation)

Ich habe 2 Arduinos (1x MEGA2560 und 1x Nano). An den MEGA ist ein Keypad, ein LCD 16x2 mit I2C, ein HC-12 Modul und ein Knopf angeschlossen. An den Nano ist nur ein HC-12 Modul angeschlossen. Dem Plan nach sollte es so gehen: Ich gebe eine Zahl mit dem Keypad bei dem MEGA ein und kann diese Zahl durch drücken des Knopfes über das HC-12 Modul an den Nano schicken. Der Nano soll mir dann diese Zahl über den Seriellen Monitor ausgeben. Bei mir zeigt der serielle Monitor des Nanos (bei egal welcher durch den MEGA abgeschickten Zahl) das an:


Hier ist der Code vom MEGA:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <SoftwareSerial.h>

SoftwareSerial hc12(10,11);

#define BUTTON_PIN 1

LiquidCrystal_I2C lcd(0x27, 16, 2);  // initialize the library with the I2C address and dimensions
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};  // connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9};  // connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
String input[3] = {"", "", ""};
int currentMenu = 0;



void setup() {
  Serial.begin(9600);
  hc12.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.print("Manual Mode:");
  Serial.println("Hallo");
  delay(500);
}

void loop() {
  char key = keypad.getKey();
  int Btn = digitalRead(BUTTON_PIN);
    
  if (digitalRead(Btn) != 1) {
    Serial.println(input[0]);    
    hc12.println(Serial.read());
    Btn = digitalRead(BUTTON_PIN);
}
  if (key != NO_KEY) {
    if (key == 'D') {
      input[currentMenu] = "";
      lcd.setCursor(0, 1);
      lcd.print("     ");
    } else if (key == 'A') {
      if (currentMenu > 0) {
        currentMenu--;
        lcd.setCursor(0, 0);
        lcd.print("Manual Mode:");
        lcd.setCursor(0, 1);
        lcd.print(input[currentMenu]);
      }
    } else if (key == 'C') {
      if (currentMenu < 1) {
        currentMenu++;
        lcd.setCursor(0, 0);
        lcd.print("DMX-Mode:    ");
        lcd.setCursor(0, 1);
        lcd.print(input[currentMenu]);
      }
    } else if (input[currentMenu].length() < 3) {
      input[currentMenu] += key;
      lcd.setCursor(0, 1);
      lcd.print(input[currentMenu]);
    }
  }
}

und hier vom Nano:

/*    Arduino Long Range Wireless Communication using HC-12
                      Example 01
   by Dejan Nedelkovski, www.HowToMechatronics.com
*/

#include <SoftwareSerial.h>

SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12

}

void loop() {
  while (HC12.available()) {        // If HC-12 has data
    Serial.println(HC12.read());      // Send the data to Serial monitor
  }
  while (Serial.available()) {      // If Serial monitor has data
    HC12.write(Serial.read());      // Send that data to HC-12
  }
}

Vielen Dank in Voraus!

Der Mega hat 3 x Serial wozu Software Serial?

Habe nicht gewusst, dass es unnötig ist. Ich habe einfach nach einem Tutorial gehandelt. Könnte es daran liegen oder ist das nur eine Empfehlung?

45 49 13 10 ist dasselbe wie 0x2D 0x31 0x0D 0x0A oder "-1" mit nachfolgender neuer Zeile (cr / lf)

Wenn du etwas Empfangenes unverändert zurücksenden willst, musst du read mit write (nicht print) kombinieren.

int Btn = digitalRead(BUTTON_PIN);
    
  if (digitalRead(Btn) != 1) {  // Hier liest du entweder von Pin 0 oder 1  ? ? ? 
    Serial.println(input[0]);    
    hc12.println(Serial.read()); // Hier sendest du "-1\n", weil im Serial-Empfangspuffer nichts ist
    Btn = digitalRead(BUTTON_PIN);
}

Der Code sieht dort jetzt so aus:

  int Btn = digitalRead(BUTTON_PIN);
    
  if (digitalRead(Btn) != 1) {
    Serial.println(input[0]);    
    hc12.write(Serial.read());
    Btn = digitalRead(BUTTON_PIN);
}

(Ich habe prinln durch write ersetzt)
Jedoch gibt es diesen Output:


(Die Zahlen bei den roten Pfeilen sind die Werte die eigentlich ankommen müssten)

Denk nochmal über digitalRead(Btn) nach.

hc12.write(Serial.read());
liefert nun 255 statt dem text "-1".

Das ist alles ok.

Wie kommst du auf die Idee, dass Serial.read() etwas außer "nichts angekommen" liefern könnte?

Was denkst Du, was da passiert, wenn Du den seriellen Monitor aufmachst?

Ich habe es zwar immer noch nicht zu 100% verstanden, aber ich habe jetzt den Code etwas abgeändert und der Nano erhält jetzt die eingetippte Zahl. Jetzt habe ich aber ein anderes Problem: Alle Zahlen über 255, werden als eine Andere bei dem Nano angezeigt.


MEGA Code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <SoftwareSerial.h>

SoftwareSerial hc12(10,11);

LiquidCrystal_I2C lcd(0x27, 16, 2);  // initialize the library with the I2C address and dimensions
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};  // connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9};  // connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
String input[3] = {"", "", ""};
int currentMenu = 0;



void setup() {
  Serial.begin(9600);
  hc12.begin(9600);
  pinMode(0, INPUT);
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.print("Manual Mode:");
  Serial.println("Hallo");
  delay(500);
}

void loop() {
  char key = keypad.getKey();
    
  if (digitalRead(0) != 1) {
    int tCh = input[0].toInt();
    Serial.println(tCh);    
    hc12.write(tCh);
    digitalRead(0);
}
  if (key != NO_KEY) {
    if (key == 'D') {
      input[currentMenu] = "";
      lcd.setCursor(0, 1);
      lcd.print("     ");
    } else if (key == 'A') {
      if (currentMenu > 0) {
        currentMenu--;
        lcd.setCursor(0, 0);
        lcd.print("Manual Mode:");
        lcd.setCursor(0, 1);
        lcd.print(input[currentMenu]);
      }
    } else if (key == 'C') {
      if (currentMenu < 1) {
        currentMenu++;
        lcd.setCursor(0, 0);
        lcd.print("DMX-Mode:    ");
        lcd.setCursor(0, 1);
        lcd.print(input[currentMenu]);
      }
    } else if (input[currentMenu].length() < 3) {
      input[currentMenu] += key;
      lcd.setCursor(0, 1);
      lcd.print(input[currentMenu]);
    }
  }
}

Nano Code:

#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12
}
void loop() {
  while (HC12.available()) {
      Serial.println(HC12.read());      // Send the data to Serial monitor
  }  
}

Is auch klar!
Ein byte kann nur 0 bis 255 groß werden

Du belegst noch immer die serielle Schnittstelle mit der Du den seriellen Monitor bedienst mit deinem Taster.

Tut mir leid falls ich sowas dummes fragen muss, aber ich bin ziemlich neu im Thema Arduino: Könntest du mir vielleicht sagen wie es möglich wäre die eingegebene Zahl (beim MEGA), egal wie groß diese ist (höchstens 3 Stellig) auf den Nano zu übertragen?

Ich habe den Knopf auf anderen Pins ausprobiert und der Knopf hat da nicht funktioniert.

Ok.
Wie hast Du den angeschlossen?
Die einfachste Verbindung ist den PIN A0 zu nehmen.

Dann von dort eine verbindung zum Taster.
Vom Taster eine Verbindung nach GND vom Arduino.

Dann legst Du eine Variable const byte tasterPin = A0; an.
Im setup() änderst Du die Zeile auf pinMode(tasterPin, INPUT_PULLUP);
Und überall im Code änderst Du Deine magische Zahl 0 auf tasterPin.

Um nun festzustellen, ob die Taste gedrückt wurde, fragst Du wie folgt ab:
if (digitalRead(tasterPin) == LOW))

Damit bist Du dann schon auf der richtigen Spur.
Bis zur Vollendung wird noch etwas fehlen, aber damit störst Du die Kommunikation nicht mehr.

Und dann mal Bettlektüreempfehlung zum durchlesen. Nur durchlesen. Nicht auswendig lernen. Und am Anfang beginnen. Das liest sich weg.
Lade Dir hier das pdf runter. Das ist Einsteigerfreundlich geschrieben und macht Lust auf mehr.

Ein Protokoll erfinden, oder ein vorhandenes nutzen.
evt. kannst du dir beim CMDMessenger was abschauen.....

Schreibt ein byte / char. Das sind 8 bit, die einen Wert 0 .. 255 (byte) oder -128 .. 127 (char) darstellen können. ( Als Text max. ein Buchstabe, wobei es Buchstaben gibt, die je nach Codierung auch mehr als ein byte/char brauchen )

Da du von dreistelligen Zahlen schreibst, meinst du vermutlich einen Text wie "345".
Dessen Nachteil ist, dass du beim Empfang eines Zeichens nicht weißt, ob die Zahl schon fertig ist.

Eine Möglichkeit wäre, beim Senden noch eins der übrigen Zeichen des Keypads ( "* #" ) einzutippen und mitzusenden, oder beim Senden per
hc12.println(input[0]);
noch ein Zeilenende mitzuschicken.
Beim Empfangen kannst du ausprobieren, welche der Varianten von HC12.parseInt am besten passen.

Sinnvoll wäre auf jeden Fall, den Unterschied zwischen Zahlen und Text zu verstehen.

Erstmal vielen Dank für alle Antworten! Ich brauche eigentlich doch nur 2-Stellige Zahlen, also brauche ich gar kein Protokoll. Jetzt funktioniert die Verbindung, aber ich habe jetzt ein anderes Problem... Wenn ich mein Relais über den Nano, welcher das Signal empfängt ansteuern will, aktiviert es alle 4 Kanäle mit den Zahlen 1 bis 3, jedoch bei der Zahl 4 wird keines der Relais aktiviert. Ich habe auch mit einer externen Stromquelle versucht die Relais Pins mit 5V kurzzuschließen und da hat es einzeln funktioniert. Beim NANO habe ich alle Pins (bis auf die Analogen) durchprobiert und der Fehler ist immer noch da. Der Serielle Monitor des Nanos zeigt ordnungsgemäß alle Zahlen die er empfangen soll an (1 => 1 Kanal, 2 => 2 Kanal..., 200 => OFF Alles Signal) Im folgenden Video sieht man wie es aussieht: https://youtube.com/shorts/RBA9xjD0R-c

Nano:

#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

const byte Ch1 = 6;
const byte Ch2 = 7;
const byte Ch3 = 8;
const byte Ch4 = 9;

void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12
  pinMode(Ch1, OUTPUT);
  pinMode(Ch2, OUTPUT);
  pinMode(Ch3, OUTPUT);
  pinMode(Ch4, OUTPUT);
}
void loop() {
  while (HC12.available()) {
    Serial.println(HC12.read());
if (HC12.read() == 200) {
digitalWrite(Ch1, LOW);
digitalWrite(Ch2, LOW);
digitalWrite(Ch3, LOW);
digitalWrite(Ch4, LOW);
  }
  
  if (HC12.read() == 1) {
digitalWrite(Ch1, HIGH);
  }
  
  else if (HC12.read() == 2) {
digitalWrite(Ch2, HIGH);
  }
  
  else if (HC12.read() == 3) {
digitalWrite(Ch3, HIGH);
  }

  else if (HC12.read() == 4) {
digitalWrite(Ch4, HIGH);
  }
  }
}

MEGA:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <SoftwareSerial.h>

SoftwareSerial hc12(10,11);

LiquidCrystal_I2C lcd(0x27, 16, 2);  // initialize the library with the I2C address and dimensions
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};  // connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9};  // connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
String input[3] = {"", "", ""};
int currentMenu = 0;

const byte tasterPin = A0;


void setup() {
  Serial.begin(9600);
  hc12.begin(9600);
  pinMode(tasterPin, INPUT_PULLUP);
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.print("Manual Mode:");
  Serial.println("Hallo");
  delay(500);
}

void loop() {
  char key = keypad.getKey();

  if (digitalRead(tasterPin) == HIGH) {
    Serial.println(200);    
    hc12.write(200);
    digitalRead(tasterPin);
}
  else if (digitalRead(tasterPin) == LOW) {
    int tCh = input[0].toInt();
    Serial.println(tCh);    
    hc12.write(tCh);
    digitalRead(tasterPin);
}
  if (key != NO_KEY) {
    if (key == 'D') {
      input[currentMenu] = "";
      lcd.setCursor(0, 1);
      lcd.print("     ");
    } else if (key == 'A') {
      if (currentMenu > 0) {
        currentMenu--;
        lcd.setCursor(0, 0);
        lcd.print("Manual Mode:");
        lcd.setCursor(0, 1);
        lcd.print(input[currentMenu]);
      }
    } else if (key == 'C') {
      if (currentMenu < 1) {
        currentMenu++;
        lcd.setCursor(0, 0);
        lcd.print("DMX-Mode:    ");
        lcd.setCursor(0, 1);
        lcd.print(input[currentMenu]);
      }
    } else if (input[currentMenu].length() < 3) {
      input[currentMenu] += key;
      lcd.setCursor(0, 1);
      lcd.print(input[currentMenu]);
    }
  }
}

Ich glaube dir nicht!

Ich will ja keine 100-irgendwas Relais ansteuern. Wieso ich das mit der 3 stelligen Zahl gemeint habe, war deswegen weil ich warum auch immer gedacht habe, dass ich DMX (512 Kanäle) kabellos übertragen will, aber DMX wird kabelgebunden sein.

Ich denke Du hast ein Verständnisproblem.

Das sind wieviele Lesevorgänge?
Wenn der erste Lesevorgang die 4 enthalten hat, ist die weg, wenn Du sie brauchst.

Offensichtlich interessieren dich die -1 auch nicht wirklich....

Ist mir eigentlich auch egal....
Ich weiß, dass du ein Protokoll brauchst und auch einhalten musst.
Das reicht mir.