Probleme mit SoftwareSerial am 328P

Grüße,

ich muss mal ein par Basics zum SoftwareSerial abfragen, bzw. ob das was ich hier aufgebaut habe fehlerhaft ist.

Also,

Ich betreibe einen 328P mit 8MHZ Internal an 3,3V

Ich Möchte SoftwareSerial benutzen.

Soft TX ist pin 5
Soft RX ist pin 6

Ich benutze Gleichzeitig einen Drehencoder an Pin 3 und Pin 4
Der Drehencoder nutzt den INT1

das Problem ist das der Software entweder das senden nach kurzer zeit abbricht oder Unsinn sendet.

//Serial.print Output
21:05:28.833 -> 0TT11
21:05:28.930 -> 0TT11
21:05:29.032 -> 0TT11
21:05:29.134 -> 0TT11
21:05:29.239 -> 0TT11
21:05:29.340 -> 0TT11
21:05:29.441 -> 0TT11

//mySerial.print Output
21:05:32.111 -> �����������W����������������/�VWW���TT11
21:05:33.029 -> 0TT11�0TT1w�0t}���|���������������������}�����L����+�=��
21:05:34.215 -> ���R��T11
21:05:34.423 -> f���s�W��������������������]}���=������������������^��;����������>�?����~�����������������������������������������������=

Der Code ist für beide Prints der gleiche

void loop() {
mySerial.print(PoM);
mySerial.print("T");
mySerial.print('T');
                        char Buffer [2]{0,0};
                        sprintf(Buffer, "%02d",11);
mySerial.print(Buffer); 
mySerial.print('\n'); 

Serial.print(PoM);
Serial.print("T");
Serial.print('T');
Serial.print(Buffer); 
Serial.print('\n');  
}

Hier nochmal der Ganze Code (Bzw. das was davon noch abgefahren wird. Ich habe den gesamten Loop auskommentiert um mögliche Fehlerquellen zu reduzieren)

#include <Adafruit_MCP23X17.h>
#include <SoftwareSerial.h>





#define           TX                5//Blau
#define           RX                6//gelb
#define           WakePin           7
#define           LED_ID            9
#define           LED_MOIST        10 
#define           LED_HUM          11
#define           LED_MIN          12
#define           LED_MAX          13

#define           Button           A0
#define           DT               3
#define           CLK              4//4

/////TESTLIB
int DT_StateCrnt=LOW;
int DT_StateLst =LOW;
int BS=LOW;
/////TESTLIB
const byte numChars = 4;
char receivedChars[numChars]; 
bool newData=false;
int numBytes =0;
int32_t wait=0;




uint8_t           ledState        = LOW;
unsigned long     previousMillis  = 0;
bool              connect         = false;


int16_t           inputDelta      = 0; 
int               last           =0;
int               EPnow           =LOW;

SoftwareSerial    mySerial(RX,TX);
Adafruit_MCP23X17 mcp;
byte              MCPADR          = 0x20;

int8_t            PoM             = 0;
int8_t            PoMt            = 0;
byte              value           = 0;

byte              IDB             = 0;
byte              IDC             = 0;
byte              Moist           = 0;
byte              MoistMin        = 0;
byte              MoistMax        = 0;
byte              Hum             = 0;
byte              HumMin          = 0;
byte              HumMax          = 0;


void setup() {
  //Setup 328P-PU Pins
  pinMode(WakePin    , OUTPUT );
  pinMode(LED_ID     , OUTPUT );
  pinMode(LED_MOIST  , OUTPUT );
  pinMode(LED_HUM    , OUTPUT );
  pinMode(LED_MIN    , OUTPUT );
  pinMode(LED_MAX    , OUTPUT );
  pinMode(RX         , INPUT  );
  pinMode(TX         , OUTPUT );
  pinMode(Button     , INPUT  );
  pinMode(DT         , INPUT  );
  pinMode(CLK        , INPUT  );
  attachInterrupt(1,readEncoder, CHANGE); 
  //start Hard and Software Serial 
  mySerial.begin(9600);
    Serial.begin(9600);
  Serial.println("PROGRAMMER TEST");//debugline Programm begin

  //Test MCP23017 connection
  if (!mcp.begin_I2C()) {
                          Serial.println("Error.");//debugline
                          while (1);{
                                      Serial.print("Stuck");//debugline
                                      }  //while
                        }    //if
  //Setup MCP23017 Pins as Output
  for (int i = 0; i < 16; i++) {mcp.pinMode(i, OUTPUT);}

  //WakeUp TargetSensor

  digitalWrite(WakePin, LOW);
  delay(100);
  digitalWrite(WakePin, HIGH);
  mySerial.println("Myseril.Test");
  //inputDelta = 1; //Test nessesarry
}//Setup

void loop() {
mySerial.print(PoM);
mySerial.print("T");
mySerial.print('T');
                        char Buffer [2]{0,0};
                        sprintf(Buffer, "%02d",11);
  mySerial.print(Buffer); 
  mySerial.print('\n'); 

Serial.print(PoM);
Serial.print("T");
Serial.print('T');
Serial.print(Buffer); 
Serial.print('\n');  
}//Loop

Der IRQ unterbricht das Senden der SoftwareSerial.
Mein Tipp:
Verwender eine Library für den Encoder ohne IRQ, oder einen Controller mit einer 2. Hardware Seriellen.

Eigentlich schließen sich senden und der encoder gegenseitig aus

wird gedreht wird nichts gesendet
wird gesendet wird nichts gedreht

kann ich vllt bevor gesendet wird mit einem

noInterrupts(); 
mySerial.print("Message");
interrupts();   

die Sache klären, oder braucht der SoftwareSerial die Interrupts um zu funktionieren?

bringt es vllt was den INT1 statt INT0 zu verwenden?
EDIT:nein, das bringt es schonmal nicht

Ich habe schon einiges ohne Interpret probiert, aber der Code ist recht lang und sobald ich das ReadEncoderOhneInterrupt(); in den Code einfüge werden Positionen übersprungen. oder er dreht zwischenzeitlich mal in die Falsche Richtung.

Kannst du eine Lib empfehlen?

Ich muss nachschauen, bin aktuell nicht am Rechner.

Frage:
Was passiert mit den Daten, wenn kein Encoder angeschlossen ist.
Wie lang sind die Leitungen zwischen den Encoder und dem Atmega ?

Und nein, den IRQ darfst du nicht abschalten.

Ich habe gute Erfragung gemacht mit RotaryEncoder

Hast du den auch schon am ESP32 laufen ?

Ja.
Hat den Vorteil die vier "Sprunge" was der Encoder macht bei einem Tick, werden durch die Lib bereinigt, man muss nur einfach Drehrichtung auswerten. Jeder Tick gibt nur 1 oder -1 aus, also vereinfacht das Schreiben.
Habe einen Encoder was macht bei einem Tick 6 Impulse, mit dem kam die Encoder Lib vom Paul Stoffregen nicht parat.

Ja, das kann meine aktuelle Library auch.
Nur habe ich die bisher nur auf einem AVR genutzt.

ich habe jetzt das ganze nochmal außerhalb meiner Baugruppe mit nur dem nötigsten auf ein steckbrett gebaut, da sieht der Fehler beim drehen so aus

22:16:48.582 -> TestSoft
22:16:48.582 -> TestSoft
22:16:48.615 -> TestSoft
22:16:48.615 -> TestSoft
22:16:48.615 -> TestSoft
22:16:48.647 -> TestSoft
22:16:48.647 -> TestSoft
22:16:48.647 -> TestSoft��!Q5
22:16:48.679 -> 
22:16:48.679 -> TestSoft
��!Q5
22:16:48.679 -> 
22:16:48.711 -> TestSoft
22:16:48.711 -> T��!Q5
22:16:48.711 -> estSoft

und auch nur dann wenn ich drehe. ansonsten verhält er sich ruhig und gibt

22:16:47.972 -> TestSoft
22:16:47.972 -> TestSoft
22:16:48.005 -> TestSoft
22:16:48.005 -> TestSoft
22:16:48.005 -> TestSoft
22:16:48.037 -> TestSoft
22:16:48.037 -> TestSoft
22:16:48.037 -> TestSoft
22:16:48.069 -> TestSoft
22:16:48.069 -> TestSoft
22:16:48.069 -> TestSoft
22:16:48.101 -> TestSoft
22:16:48.101 -> TestSoft

aus

das ist der code

#include "SoftwareSerial.h"
#define RX  6
#define TX  5
#define DT  3
#define CLK 4

int DT_StateCrnt=HIGH;
int DT_StateLst=HIGH;
int inputDelta=0;

SoftwareSerial    mySerial(RX,TX);
void setup() {
  pinMode(DT, INPUT);
  pinMode(CLK,INPUT);
  // put your setup code here, to run once:
Serial.begin(9600);
mySerial.begin(9600);
attachInterrupt(1,readEncoder, CHANGE);
}

void loop() {
 // if(!digitalRead(A0)){
 Serial.println("TestHard");
 mySerial.println("TestSoft");
 // }
}
void readEncoder(){
DT_StateCrnt=digitalRead(DT);
if((DT_StateLst==LOW)&&(DT_StateCrnt==HIGH)){
  if (digitalRead(CLK)==HIGH )
  {
    mySerial.println("LEFT");
    inputDelta++;
  }
else{mySerial.println("RIGHT");
inputDelta--;
}

}
DT_StateLst=DT_StateCrnt;
}//readEncoder

Das ist auch ein Ergebnis mit dem ich definitiv leben könnte.

nun die frage warum das in der Baugruppe nicht der fall ist...

EDIT:....Masseprobleme....ich benutze einen MCP2221 um den softwareSerial auszulesen und der will unbedingt mit auf dem GND vom 328P hängen sonst gibt der Murks aus.
nachdem ich die GND vom 328 und vom 2221 verbunden hatte ging zumindest das oben gezeigt Beispiel.

ob das im Hauptprogramm auch hilft wird sich gleich zeigen

Serial sendet oder empfängt der muss ein Bezugspunkt haben.

Ja... das ist vor allem nciht das erste mal das ich das vergesse und ewig nciht drauf komme was das Problem ist....

wenn das einmal passier ist das ja ok ....

Nagt also der Sender sendet schonmal das was er soll. der Empfänger empfängt zwar noch nichts bei das ist dann ein anderes Problem.

Danke auf jeden fall für eure schnelle Hilfe !

Das sieht doch schon ganz gut aus.
Dennoch würde ich es mit der Library probieren, die @fony gezeigt hat.

es gibt noch eine Sache, die ich nicht verstehe.

Wenn ich meinen Software Serial Kommunikation starte.

Es gibt einen Sender und einen Empfänger der zurücksendet.

ist am Anfang beim Sender immer

obwohl der eigentlich leer sein sollte, da der Empfänger ja nur zurücksendet wenn er was vom Sender bekommen hat.

da steig ich noch nicht dahinter wo das herkommen soll. bzw gibt es eine Möglichkeit den Puffer einmal am Anfang des Codes Leer zu räumen? ich habe

mySeril.flush(); 

probiert, aber das hatte nicht den gewünschten Effekt
Ich könnt natürlich am Anfang einfach den ganzen Buffer in einer For schleife lesen, dann ist es ja auch weg aber ist das der weg das zu tun?

Das ist alles sehr verwirrend. "Sender, Empfänger der zurückdendet ?"

Wenn du mal eine Zeichnung lieferst, wie das funktionieren soll, dann verstehen wir das evtl.

Das stimmt, die Bezeichnung ist irreführend.

also so sieht der Ablauf auf


Das ganze Läut über Software.Serial und ist direkt verbunden TX 1->RX2; RX1->TX2

Teilnehmer zwei wartet nach dem Programmstart auf daten und macht derweil nichts.
Teilnehmer eins hat beim Programmstart aber auf einmal 63 Byte im Buffer

das ist die Routine von Teilnehmer 1


void loop() {


  //Serial.print("MENU== ");Serial.println(inputDelta);//debugline

  //Menu
  switch (PoM) {
    case 0:{//StartUP OnlyChange
            if(mySerial.available()){mySerial.read();}
           Serial.print("TryToRead avi: ");
                          Serial.println(mySerial.available());
            clamp(1,8);
            MenuLED(inputDelta);
            if (ButtonDown()) {
            PoM = inputDelta;
            switch (inputDelta) {
                                  case 3: {SendData(inputDelta,'H');break;}
                                  case 6: {SendData(inputDelta,'M');break;}
                                  default:{SendData(inputDelta,'G');break;}
                                }          
            
                              }//IF ButtonDown
            }//case0

es sendet also nur etwas, wenn der Button Down HIGH ist.
Das bedeutet nach Programmstart kann er keine Daten gesendet haben ohne das ich das mit dem Button bestätige.

Und das Wiederrum bedeutet das Teilnehmer zwei außer warten auch nichts macht.

Die Frage ist. warum habe ich dann immer 63 byte im Buffer

EDIT: Teilnehmer Zwei ist ein ESP8266 für den TX vom Softwareserial nutze ich GPIO0, ist das vllt ein Problem?

EDIT: ja, das war das Problem, aus Gründen sendet der ESP beim Booten scheinbar irgendwelchen Mist über GPIO0. Ich habe einfach ins Setup meines Teilnehmer eins das hier geschrieben

  delay(100);
  while(mySerial.available()){Serial.println(mySerial.read());}

mit dem Delay wird sichergestellt das der ESP fertig gebootet hat und den wird der Buffer einfach leergelesen.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.