MakeMagazinDE / KIschreibmaschine

4 stars 1 forks source link

ESP32 Restarted nach Eingabe einer Anfrage #1

Open ghost opened 1 year ago

ghost commented 1 year ago

Hallo Zusammen,

Ich habe das Projekt aus dem make:Magazin nachgebaut, mit einer typengleichen Schreibmaschine, der Privileg electronic 1200. Nach etwas experimentieren habe ich einen ESP32-S erfolgreich an die serielle Schnittstelle anschließen können. (Die Privileg verwendet ein leicht anderes Board)

Nachdem ich den bereitgestellten Code etwas angepasst hatte (WLAN Settings werden von MultiWlan nicht angenommen, war aber leicht zu beheben), habe ich die Maschine getestet.

Wenn ich also nun eine Eingabe tätige, wird mir diese auf dem Seriellen Monitor auch angezeigt, soweit so gut. Auch das "Drucken" der Warte-Punkte funktioniert.

Aber sobald ich über den Seriellen Monitor sehe, dass eine Antwort eingegangen ist, startet sich der ESP neu mit folgender Fehlermeldung:

ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13864
load:0x40080400,len:3608
entry 0x400805f0
geht los ...
Connecting to WiFi 
WiFi connected
Connected to Black Box
IP address: 192.168.10.119
Sending API Request...
request: {"model":"text-davinci-003","prompt":"Wass Isst 2+2?","temperature":0.7,"max_tokens":256,"frequency_penalty":0,"presence_penalty":0.6,"top_p":1.0}
.
Nachricht_len: 10
Nachricht_array: 
2+2 is 4.
CORRUPT HEAP: Bad head at 0x3ffcfc84. Expected 0xabba1234 got 0x3ffc88fc

assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)

Backtrace:0x40083a35:0x3ffb24e00x4008b909:0x3ffb2500 0x40090bc5:0x3ffb2520 0x4009080b:0x3ffb2650 0x40083e99:0x3ffb2670 0x40090bf5:0x3ffb2690 0x4014a761:0x3ffb26b0 0x400d595c:0x3ffb26d0 0x400d2e65:0x3ffb26f0 0x400d30be:0x3ffb27c0 0x400d7c95:0x3ffb2820 

ELF file SHA256: 0000000000000000

Rebooting...

Ich bin die meisten Zuweisungen der Arrays und anderen Variablen durchgegangen, und auch nach dem Fehler habe ich viel gesucht (Tag 3 im Moment..), aber nur Heap Allocation Probleme gefunden, also Versuche, etwas im Heap abzulegen, dessen Platz wohl bereits belegt ist.

Was kann ich hier tun?

DiWa2194 commented 1 year ago

Hallo,

probier bitte mal Folgendes:

  1. Im Hauptprogramm "ERIKA3004" ganz unten den Befehl "Serial.println(openAI_text(Eingabe));" ersetzen durch "openAI_text(Eingabe);"
  2. Im Unterprogramm "Request" ganz oben den Befehl "String openAI_text(String request) {" ersetzen durch "void openAI_text(String request) {"

Geht es dann?

Fantomas200 commented 1 year ago

Hallo Gregorius,

Nachdem ich den bereitgestellten Code etwas angepasst hatte (WLAN Settings werden von MultiWlan nicht angenommen, war aber leicht zu beheben)

Magst du die Lösung/Anpassung für das Problem bitte hier auch mit posten :) MNY TNX

DiWa2194 commented 1 year ago

Hallo, probiere einfach mal das setup mit folgenden Code zu ersetzen:

void setup() { delay(1000); Serial.begin(115200); delay(100); Serial.println("geht los ..."); pinMode(RTS_PIN, INPUT); erika.begin(ERIKA_BAUD); // Mit dem WLan verbinden WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); // EDIT 16.04.2023, DiWa Serial.print("Connecting to WiFi .."); while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(1000); } Serial.println(WiFi.localIP());
//WiFi_Init(); while (erika.read() > 0) Serial.println("Startup Zeichen leeren"); erika.write(ascii2ddr['\n']); }

chs-59 commented 1 year ago

Leider ist der Code bei diesem ziemlich geilen Projekt tatsächlich seltsam vermurkst. Vermutlich hat Dirk Wahl hier aus Versehen eine veraltete Version hochgeladen, anders ist das eigentlich nicht zu erklären.

Das Passwort kann so nicht funktionieren. Zur Korrektur sind in Erika3004.ino Z.24 ff zu ändern:

const char* ssid_1     = "XXXX"; // hier eigenen WLan_Namen eintragen 
const char* password_1 = "XXXXXX"; // hier eigenes WLan_Passwort eintragen 
const char* ssid_2     = "XXXX"; // hier eigenen WLan_Namen eintragen 
const char* password_2 = "XXXXX"; // hier eigenes WLan_Passwort eintragen 

In der Datei WiFi.ino sind in den Zeilen 4+5 alle Anführungszeichen zu entfernen! Sofern man nur ein einziges Wlan eintragen will, sind die ssid_2/password_2-Zeilen in Erika3004.ino und WiFi.ino zu löschen. Umgekehrt kann man natürlich weitere Wlans ergänzen.

Um das Heap-Problem zu lösen, ist der Code aus Request.ino in Erika3004.ino zu übertragen und Request.ino zu löschen. Die von DiWa2194 genannten Korrekturen sind natürlich auch sehr richtig, haben bei mir allein aber das Heap-Problem nicht gelöst.

In der zum Download verlinkten ddr2ascii.h fehlt das "i"; es ist dort im Index 5 nachzutragen (Zeile 7). (Wahrscheinlich ein Hinweis auf die allgemein schlechte Versorgungslage damals in der DDR...)

Der Code für die Tastatur-Eingabe funktionierte auf meiner Sigma 8200i auch nicht. Die Anfrage an OpenAI war mit Steuerzeichen verseucht und produzierte deshalb nur Fehlermeldungen als Antwort. Auch die Umsetzung der Sonderzeichen war missglückt.

Hier mein geänderter Code der letzten if-Anweisung im loop (ca. ab Zeile 100) :

  if (erika.available())
  {
    int Zeichen_nummer = erika.read();

    char Zeichen = ' ';
    Zeichen = ddr2ascii[Zeichen_nummer];  // In der ddr2ascii.h das i an Index 5 ergänzen!

      switch (Zeichen_nummer) {
      case 71:  { Eingabe = Eingabe + "ss"; break; } // Eszett zu ss
      case 101: { Eingabe = Eingabe + "ae"; break; } // ä zu ae
      case 102: { Eingabe = Eingabe + "oe"; break; } // ö zu oe
      case 103: { Eingabe = Eingabe + "ue"; break; } // ü zu ue
      case 114: { break; }                           // Backtab ignorierenn
      case 117: { break; }                           // Einzug ignorieren
      case 118: { break; }                           // Papier zurück ignorieren
      case 121: { break; }                           // Tab ignorieren
      case 119: { break; }                           // Newline hier ignorieren
      default: {                                   // Druckbare Zeichen anhängen 
        if (Zeichen_nummer > 127) {} // do nothing
        else {Eingabe = Eingabe + Zeichen; }
        break;
      }
    }
    if (Zeichen == '\n') {
      Serial.println(Eingabe);
      openAI_text(Eingabe);
      Eingabe = "";
    }

  }

So funktioniert bei mir alles, wie es sollte – jedenfalls fast. Einige von OpenAI gesendete (seltene) Sonderzeichen werden noch falsch umgesetzt.

Eine Ergänzung für jene, die auch eine Sima 8200i erwerben: Die interne Schnittstelle sieht deutlich anders aus als auf der Skizze im Make-Magazin. Sie hat 26 Pole, von denen nur sechs genutzt werden und führt zu einer (offenbar DDR-typischen) EFS26-Buchse. Die Belegung ist hier zu sehen.

DiWa2194 commented 1 year ago

Ich habe den Code umgeschrieben, neue Version zum Download. Die Unterprogramme wurde ersetzt und der Code entsprechend ins Hauptprogramm übernommen.

ddr2ascii.h hat nun auch ein "i" und weitere Zahlen. Neue Version im Downloadbereich.

Danke auch an chs-59: Deinen switch habe ich übernommen.

ghost commented 1 year ago

Heyho, entschuldigt meine Abwesenheit, ich habe gerade den geupdateten Code getestet. Er funktioniert schon deutlich zuverlässiger, allerdings sind mir noch zwei Probleme aufgefallen.

  1. Lange Zeilen (Die über die gesammte Breite des papieres gehen) werden am ende Abgeschnitten, die letzten vier Zeichen fehlen.
  2. Bei langen API Responses gibt es noch abstürze. (Das Nachrichten Array mit einer Länge von 256 ist zu Klein)
    
    Sending API Request...
    request: {"model":"text-davinci-003","prompt":"Was ist der sinn des lebensss","temperature":0.7,"max_tokens":256,"frequency_penalty":0,"presence_penalty":0.6,"top_p":1.0}
    ........
    Nachricht_len: 418
    Nachricht_array: 
    Der Sinn des Lebens ist eine Frage, die jeder Einzelne für sich
    selbst beantworten muss. Es gibt keine universell definierte Antwort
    darauf. Jeder Mensch hat andere Ziele und Werte, die sein Leben
    bestimmen. Einige Menschen suchen nach Glück und Erfüllung, andere
    nach Reichtum und Macht, wieder andere nach Sinn und Bedeutung. Der
    Sinn des Lebens liegt in den individuellen Zielen und Werten eines
    jeden Menschen.
    Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.

Core 1 register dump: PC : 0x00000000 PS : 0x00060b30 A0 : 0x800d2c6a A1 : 0x3ffb2180
A2 : 0x3ffc41e8 A3 : 0x00000014 A4 : 0x00000001 A5 : 0x00000001
A6 : 0x3ffc40c4 A7 : 0x00060023 A8 : 0x8015e138 A9 : 0x3ffb2160
A10 : 0x3ffc41e8 A11 : 0x3ffb218c A12 : 0x00000001 A13 : 0x6562654c
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000017 EXCCAUSE: 0x00000014
EXCVADDR: 0x00000000 LBEG : 0x400848b9 LEND : 0x400848c1 LCOUNT : 0x00000027

Backtrace: 0xfffffffd:0x3ffb2180 0x400d2c67:0x3ffb21b0 0x400d7b6d:0x3ffb2290```

gasmaennchen commented 1 year ago

Vielen Dank für die tolle Idee, eine Erika mit einem ESP32 zu verheiraten.

Das Abschneiden von Text am Zeilenende trat bei mir ebenfalls auf. Durch Anpassen der Zeilenlänge auf 66 Zeichen funktioniert es jetzt besser.

Leider ist heute der Test beim Ausdrucken eines Rezeptes für Nudelsuppe abgebrochen, weil die Netzsicherung der Schreibmaschine durchgebrannt ist. 🥲

chs-59 commented 1 year ago

@BackyardScientist: Die Zeilenlänge variiert mit der Schriftweiteneinstellung. Bei meiner Maschine kann man mit dem Schieberegler links unten zwischen 10 und 12 wählen, wobei 12 überraschender Weise der enge Zeichenabstand ist, 10 der weite. Mit 12 passt es bei der Sigma 8200i gut. Wenn Dein Nachrichten-Array nur 256 Byte groß ist, musst Du da was verändert haben. In der ersten Version von Dirk Wahl waren's 5000, jetzt 4096. Bei mir (5000) passen bislang alle Antworten rein.

Schade, vor allem bei englischer Textausgabe, ist noch die (u.a.) fehlende Konvertierung des Apostroph, was z.B. bei "don't" zur Ausgabe von "donWCot" führt. Falls sich jemand dieses Problems annimmt und hier ein Update postet, wäre ihr mein ewiger Dank gewiss.

In meinem Code habe ich noch zwei kleine Feature ergänzt: Durch Eingabe von AI-/AI+ sowie Absatztaste lässt sich die Verbindung zur AI aus- und einschalten, falls man die Maschine mal normal verwenden möchte. Außerdem werden kleine Anfragen unter 10 Zeichen ignoriert. Sie führen in der Regel zu sehr erratischen und langen Antworten.

// im Anfangsbereich Deklaration ergänzen:
bool AISwitch = true; // Senden an Open AI aktivieren 
.......
// im loop() diese if-Abfrage ersetzen
// ACHTUNG: Ich benutze der besseren Übersichtlichkeit wegen noch den Funktionsaufruf openAI_text aus Version 1
// In der aktuellen Version ist der Aufruf von openAI_text durch den Funktionscode ersetzt (Z. 89 - 189). Der muss dann
// ggf. auch hier statt openAI... zwischen die geschweiften Klammern

    if (Zeichen == '\n') {
      Serial.println(Eingabe);
      if ( Eingabe.equals("AI-") ) { AISwitch = false; Serial.println("AI off");  }      
      if (AISwitch && Eingabe.length() > 10 ){ openAI_text(Eingabe); } 
      if ( Eingabe.equals("AI+") ) { AISwitch = true;  Serial.println("AI on");   }
      Eingabe = "";
    }
drkrebs commented 12 months ago

@chs-59: Vielen Dank für die nützlichen Verbesserungen; die habe ich bei mir gleich eingebaut. PS: 10 und 12 bei Schreibmaschinen bedeuten 10 bzw 12 cpi (characters per inch); das ist die Laufweite. Bei 12 cpi passen also mehr Buchstaben auf einen Inch, drum ist das auch der enge Zeichenabstand.