Programm läuft mit Arduino, jedoch nicht korrekt auf dem Attiny85

Ich möchte eine intelligente Klingel erstellen. Das Programm habe ich aus 2 verschiedenen zusammengestiefelt (Morsecode von

und DFPlayer von

Funktion: Bei langem Drücken der Taste spielt DFPlayer spielt Sounddatei 4 aus Ordner 2, bei falschem Code Sounddatei 3 und bei richtigem Code 2. Auf dem Breadboard mit einem Nano funktioniert alles tadellos. Wenn ich das Ganze auf einen Attiny85 übertrage (mit entsprechender Pinänderung), ist die richtige Codeeingabe nicht möglich, es kommt immer falscher Code=Sounddatei 3, jedoch Sounddatei 4 läuft wunschgemäss.

Wie kann ich den Fehler eingrenzen?

Noch eine Bemerkung: Bei der seriellen Übertragung verzichte ich (wegen der begrenzten Füsse des Attiny) auf das TX-Kabel - funktioniert auch beim Nano auf dem Steckbrett.

Hier der Code:

// Attiny dp-Player immer on
#include "SoftwareSerial.h"

const int ledPin =  3;  //Nano 6
const int buttonPin =  0; // Nano 8
const int magnetPin = 4; // orange LED Nano 4
const int schaltPin = 2; // Nano 2

SoftwareSerial mySerial(5,1); //5 brauchts nicht
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
# define ACTIVATED LOW

const unsigned long dotInterval = 60;
const unsigned long dashInterval = 200;
const unsigned long letterInterval = 900;
const unsigned long wordInterval = 1400;

unsigned long currentMillis;
unsigned long prevMillis;

int millisFlag;
int letterFlag;
int wordFlag;
int wordBreak;
int Zeit;

String wordFull;
String satz;

void setup()
  {
  mySerial.begin (9600);
 
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(magnetPin, OUTPUT);
  pinMode(schaltPin, OUTPUT);

  digitalWrite(schaltPin, HIGH);

  digitalWrite(ledPin, LOW);
  
  millisFlag = 0;
  prevMillis = 0;
  
  wordFull = "";
  wordBreak = 0;
 }

void loop()
{
int buttonState = digitalRead(buttonPin);
  
if (buttonState == HIGH)
   {
   digitalWrite(ledPin, HIGH);
   delay (10);
   ++Zeit;
   if (millisFlag == 0)
      {
      prevMillis = millis();
      millisFlag = 1;
      }
   } 
else
  {
  currentMillis = millis();
  digitalWrite(ledPin, LOW);

  long diff = currentMillis - prevMillis;
    
  if (wordFlag == 1 && diff >= wordInterval)
     {
         
  if (satz == "$")  //richtiger Code 3x tue mr uf
          {
          digitalWrite(magnetPin, HIGH);
          execute_CMD(0x0F,2,2);   //Ton: richtiger Code
          delay (9000);
          digitalWrite(magnetPin, LOW);
          delay (400);
          }
      else  //falscher Code
        {
        execute_CMD(0x0F,2,3);  //Ton: falscher Code
        digitalWrite(ledPin, HIGH);  // 2x blinken
        delay (400);
        digitalWrite(ledPin, LOW);
        delay (400);
        digitalWrite(ledPin, HIGH);
        delay (400);
        digitalWrite(ledPin, LOW);
        delay (400);
        digitalWrite(ledPin, HIGH);
        delay (400);
        digitalWrite(ledPin, LOW);
        delay (400);
        digitalWrite(ledPin, HIGH);
        delay (400);
        digitalWrite(ledPin, LOW);
        }
      
      satz = "";
      // self
      wordFlag = 0;
      wordFull = "";
      
      // lower ones
      letterFlag = 0;
      wordBreak = 0;
      prevMillis = millis();
      millisFlag = 0;
    }
    
  if (letterFlag == 1 && (wordBreak == 5 || diff >= letterInterval)) //wordBreak normal bei 4 --> keine längeren Morsewörter für $ --> 9
     {
     satz = satz + getLetter(wordFull);
     wordFull = "";
      
     // upper ones
     wordFlag = 1;
      
     //self
     letterFlag = 0;
     wordBreak = 0;
      
     // lower ones
     prevMillis = millis();
     millisFlag = 0;
     }
    
  if (millisFlag == 1)
     {
     if (diff >= dashInterval)
        {
        wordFull += "dash";
        wordBreak++;
        }
     else if (diff >= dotInterval)
        {
        wordFull += "dot";
        wordBreak++;
        }
        
      Zeit = 0;
      // upper ones
      letterFlag = 1;
      
      // self
      prevMillis = millis();
      millisFlag = 0;
     }
  }
  if(Zeit > 37)  // Zählergrösse ab wann geläutet wird
     {
     execute_CMD(0x0F,2,4); // Ton: läuten
     delay(9000);
     Zeit = 0 ;
     letterFlag = 0;
     wordBreak = 0;
     prevMillis = millis();
     millisFlag = 0;
     }

}
void execute_CMD(byte CMD, byte Par1, byte Par2)
{
word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte};
for (byte k=0; k<10; k++)
 {
mySerial.write( Command_line[k]);
 }
     
}

char getLetter(String checkWord) {
  if (checkWord == "dot") {
    return 'E';
  } else if (checkWord == "dotdot") {
    return 'I';
  } else if (checkWord == "dash") {
    return 'T';
  } else if (checkWord == "dotdotdot") {
    return 'S';
  } else if (checkWord == "dotdash") {
    return 'A';
  } else if (checkWord == "dashdot") {
    return 'N';
  } else if (checkWord == "dotdotdotdot") {
    return 'H';
  } else if (checkWord == "dotdotdash") {
    return 'U';
  } else if (checkWord == "dotdashdot") {
    return 'R';
  } else if (checkWord == "dashdotdot") {
    return 'D';
  } else if (checkWord == "dashdash") {
    return 'M';
  } else if (checkWord == "dotdashdash") {
    return 'W';
  } else if (checkWord == "dashdashdot") {
    return 'G';
  } else if (checkWord == "dotdotdotdash") {
    return 'V';
  } else if (checkWord == "dotdashdotdot") {
    return 'L';
  } else if (checkWord == "dotdotdashdot") {
    return 'F';
  } else if (checkWord == "dashdotdotdot") {
    return 'B';
  } else if (checkWord == "dashdotdash") {
    return 'K';
  } else if (checkWord == "dotdotdotdotdash") {
    return '$';
  } else if (checkWord == "dashdashdash") {
    return 'O';
  } else if (checkWord == "dotdashdashdot") {
    return 'P';
  } else if (checkWord == "dashdotdotdash") {
    return 'X';
  } else if (checkWord == "dashdotdashdot") {
    return 'C';
  } else if (checkWord == "dashdashdotdot") {
    return 'Z';
  } else if (checkWord == "dotdashdashdash") {
    return 'J';
  } else if (checkWord == "dashdotdashdash") {
    return 'Y';
  } else if (checkWord == "dashdashdotdash") {
    return 'Q';
  } else {
    return '_';
  }
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Ich verstehe nicht, wass du in deiner Funktion mit dem Morsecode anfangen willst.
Der Zusammenhang erschließt sich mir nicht, auch wei du fast keine Dokumentation im Sketch mit lieferst.

Das geht doch ohne die String Krücke. Dot/Dash kann man auch anders abspeichern. Da reicht bestenfalls ein einzelnes Bit pro Zeichen. Die Strings sind falsch verwendet (z.B. keine Speicherreservierung, und Call by Value) und nicht gut für den RAM Verbrauch.

Was wunderst Du Dich? Du willst den Sketch auf einem System mit einem Achtel des Flash und RAM zum laufen bringen?
Das Ram ist zwar nicht voll aber 150Byte frei sind wenig weil während der Ausführung noch mehr RAm gebraucht wird.
Wieso verwendest Du strings für die Morsezeichen. Statt "dot" und "dash" könnten Ziffern zB 1 und 2 verwendet werden, numerische Vergleiche und so viel Speicher gespart werden.

Grüße Uwe

wie gesagt sind es Codeschnipsel von 2 Codes und da ich Anfänger bin, brauche ich Codes, die schon laufen

Danke für den Hinweis. Ich versuche mal mit das Programm mit numerischen Variablen umzuschreiben - bin aber noch blutiger Anfänger. Muss ich Speicher reservieren? Melde mich in einigen Tagen wieder.

Hallo zusammen
Habe mal zum Testen etwa 6 else if-Zeilen gelöscht und siehe es funktioniert mal so!
Eigentlich habe ich gedacht, die Arduino-Software schützt vor übermässigem RAM-Verbrauch.

Vielen Dank für euer Mitdenken!

Während der Laufzeit geht das nicht...

Du solltest unbedingt DATEI - VOREINSTELLUNGEN - Ausführliche Warnungen während [x] Kompilierung einschalten und darunter auf ALLE stellen.

Dann: wenn Du flags setzen willst, warum verbrauchst Du dafür ein INT?
Mach daraus ein boolean.
Wenn Du Pins benennst, mach daraus ein byte.

Deine Blink falscher Code...
Wenn es schon delay() sein muss, würde ich das so bauen:

      else  //falscher Code
      {
        execute_CMD(0x0F, 2, 3); //Ton: falscher Code
        digitalWrite(ledPin, HIGH);
        for (byte b = 0; b < 8; b++)
        {
          delay (400);
          digitalWrite(ledPin, !digitalRead(ledPin));
        }
      }

Allein das macht bei mir für einen Attiny85 mit Optiboot aus Deinen 5206/346 bytes bei mir 4912/339 bytes

Ich frage mich, ob Du die Variable currentMillis brauchst.

Und wenn Du die Funktion getLetter() auf switch/case umstellst und das mit den Strings änderst, dann hat das zweimal Platz :wink:

Normalerweise nicht, aber Ausnahmen bestätigen die Regel :slightly_smiling_face:

Nein, das ist Programmieren mit allen Risiken und Nebenwirkungen :crazy_face:

Wie schiebst Du das Programm auf den ATtiny85?

Ich nutze dazu einen UNO, der einen beim Debuggen unterstützen kann. Dein Nano könnte das auch.

Auch ein Arduino MINI oder PRO MINI mit ATmega328 wären eine Wahl

Grüße Uwe

Man muss es nicht tun. Und es ist hier sicherlich auch nicht die Lösung. Aber in Extrem-Situationen hilft es wahrscheinlich schon wenn nicht dauernd neuer Speicher reserviert wird, sondern man das einmal am Anfang tut.

Aber wie gesagt, sowas macht man sowas nicht mit Strings. Schon ein byte/bool Array würde das Speicherproblem lösen. Die Werte in Bits speichern macht aber die Vergleiche am einfachsten.

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