Automatisch CRLF bei Print anhängen / bei Input abfragen

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Automatisch CRLF bei Print anhängen / bei Input abfragen

      Hallo zusammen

      Ich habe mir ESP-01 Module besorgt, die haben eine sogenannte AT-Firmware drauf.
      Das bedeutet, die Kommunikation wird über UART per AT-Kommandos (wie damals die Modems) abgewickelt.

      Ich möchte mir nun ein paar Routinen schreiben, damit ich nicht immer mit den AT-Befehlen rumhantieren muss.
      Ich will jetzt aber auch nicht in der Firmware der ESP-Module rumpfuschen und das so belassen wie es ist.

      Möchte man ein Kommando an das ESP senden, muss man immer ein CRLF (Carriage Return, Line Feed) anhängen (nur CR oder nur LF reicht nicht).
      Umgekehrt bekommt man auch immer eine Antwort mit angehängtem CRLF.

      Gibt es in Bascom eine Möglichkeit, dass bei Print "Text" automatisch ein CRLF (anstelle des CR) angehängt werden kann, und für Input, dass immer auf CRLF gewartet wird?
      Oder muss man das zu Fuß machen?

      Konkretes Beispiel
      Das möchte ich als Beispiel Senden "AT" CRLF
      Muss dazu Schreiben: Print "AT";chr(13);chr(10);

      Geht's auch nur mit Print ohne Chr() zu nutzen.

      Beim Empfang wird wohl nur auf CR geprüft. Ein Input variable wartet immer bis die Eingabe mit Return abgeschlossen wird.
      Für diesen Fall wäre aber CR und LF sinnvoll, damit man das LF nicht extra aus dem Puffer entfernen muss.

      Ich verwende Bascom Vollversion 2.0.8.2

      Hat das schon mal jemand gemacht?
    • Das ' ; ' an ende des Print befehls verhindert CrLF. z.B.
      Print "Hallo"
      Print "Test"
      ergibt
      Hallo<CrLf>
      Test<CrLf>
      während
      Print "Hallo";
      Print "Test";
      HalloTest(ohne weitere Zeichen)
      ausgibt

      Mitch64 wrote:

      Umgekehrt bekommt man auch immer eine Antwort mit angehängtem CRLF
      Leider nicht immer. Die "Sendeempfangsbereitschaft" signalisiert es nur mit einem ">"
      PS Es funktioniert unbefriedigend es einfach mit einem Timeout zu ignorieren.

      The post was edited 1 time, last by Pluto25 ().

    • Danke für die schnelle Antwort.

      Das muss ich erst mal testen, ob bei Print wirklich CRLF angehängt wird.
      (Im Simulator sieht man nur ein CR, kein LF ((Hexmode eingeschaltet).

      Bei Config Input hab ich aber das Problem mit dem ECHO.
      Ich will ja nichts zurück senden. Ohne Echo meckert der compiler.
      Mit Echo kann ich nur CR, LF und CRLF einstellen.

      Schickt das Echo dann an das ESP z.B. ein CRLF zurück, nachdem mit Input var der String eingelesen wurde?
      Oder wie ist das zu verstehen?

      Ich will ja nur den String einlesen, der mit CRLF abgeschlossen ist, nichts wieder zum ESP senden.
      Erst wenn es mit notwendig ist und dann mit Print.
    • Mitch64 wrote:

      Im Simulator sieht man nur ein CR, kein LF
      Macht der auch nur. X( Deshalb mußte ein #if _sim in die Empfangsroutine oder immer At+010 tippen.

      Michael wrote:

      Macht man besser mit dem URXC Interrupt
      Den Rat hatte ich zu Anfang aufgenommen. Hiermit bin ich viel zufriedener als mit dem "Wait-Input- Gedöhns"

      Source Code

      1. Dim inbuf(64) as byte
      2. dim rxstr as string at inbuf overlay
      3. Rx_rdy:
      4. U = Udr
      5. Inbuf(ein) = U
      6. #if _sim = 1
      7. If Ring = 1 Then Print Chr(u); 'Ring=Echo (Echo ist system besetzt)
      8. If U = 13 Then
      9. If Ring = 1 Then Print 'CrLf für hterm
      10. #else
      11. If U = 10 Then
      12. Decr Ein ' CR löschen
      13. #endif
      14. Inbuf(ein) = 0 ' Zum Stringabschluß
      15. Neu = 1
      16. Else
      17. If Ein < 63 Then Incr Ein
      18. End If
      19. Return
      Display All
      Für Deine zwecke muß noch eine ">" Erkennung rein. Ich find gerade meinen Experimentalcode nicht

      The post was edited 1 time, last by Pluto25 ().

    • Ich hatte gehofft, dass man das vom Prinzip her so machen kann:

      BASCOM Source Code

      1. Dim ESP_Response as String * 20
      2. Function ESP_Check() as Byte
      3. Print "AT"
      4. Input ESP_Response
      5. End Function
      An der Stelle mal noch eine Frage.

      Wenn ich ein $Timeout = irgendwas setze, bevor ich den Input verwende.
      Kann ich dann über das Err-Flag sehen, ob der Timeout zugeschlagen hat oder wird das ERR in dem Fall nicht auf 1 gesetzt?

      Ich weiß, dass dann ein chr(0) zurückgegeben wird. Aber wird auch ERR=1 gesetzt?
    • Mir ist schon klar, dass im Falle eines Timeout, das Ergebnis auch nicht falscher ist, wenn das Err=1 gesetzt ist.
      Auf der anderen Seite ist es ein Fehlerflag, das Fehler anzeigt. Das tut es auch z.B. bei I2C.
      Warum also nicht konsequenterweise auch beim UART?

      Abgesehen davon wird es nicht gesetzt.


      Pluto25 wrote:

      An welches timeout hast Du gedacht? 5Sekunden?
      Nein, 30 Sekunden.
      Nein, Spaß!

      Das Timeout immer neu setzen geht vermutlich nicht, weil es ja eine Direktive ist. Falls es dich geht umso besser!
      Und die Dauer hängt natürlich vom Befehl ab.

      Manche Befehle können länger dauern. Z.B. wenn man eine Verbindung zu einer IP aufbaut.
      Direkte Befehle an das Modul wie Version abfragen und einen Mode umschalten wird schneller gehen.
      Aber selbst da würden 5s nicht schaden.

      Welches Timeout sich da befehlsabhängig anbietet hängt von den Response-Zeiten ab. Vielleicht teilweise 500ms, teilweise wären aber bestimmt auch 5 Sekunden angebracht.

      Pluto25 wrote:

      Abgesehen von einem Absturz ist das ">" der einzige Fall wo es nicht mit <CrLf>
      Ja ich habe registriert, dass es da eine Ausnahme gibt. Und nicht immer mit einem CrLf zu rechnen ist.
      Das wäre der Fall, wenn ich Daten versenden will.
      Aber das wird dann in der Routine, mittels der die Daten versendet werden sollen entsprechend behandelt.
      Hat ja niemand behauptet, dass ich da auch mit Input-Befehl arbeiten möchte.

      Trotzdem danke für den Hinweis.
    • djmsc wrote:

      Warum nimmst du nicht einfach einen Buffer?
      Den benutze ich ja (Config SerialIn=Buffered, Size = 200).
      Aber im Buffer habe ich ja dann auch das CR und das LF.

      Und genau von da will ich das ja auch auslesen.


      Pluto25 wrote:

      Es summiert sich nicht hoch
      Korrekt!
      Wenn ich eine Variable z.B.

      BASCOM Source Code

      1. Dim tmpString as String*20


      dimensioniert habe und dann wie folgt einlese

      BASCOM Source Code

      1. Input StringVariable

      dann wird der Input dann abgebrochen, wenn ein Zeichen nicht innerhalb des Timeouts ankommt.

      Der Timeout soll ja nur dazu dienen, dass das Programm nicht hängen bleibt, wenn ich etwa so einlese:

      BASCOM Source Code

      1. Dim tmpString as String*20
      2. Dim tmpByte as Byte
      3. Config SerialIn = Buffered, Size = 200
      4. Function getResponse() as Byte
      5. Input tmpString ' Antwort einlesen (Entfernt das CR aus dem Buffer)
      6. InputBin tmpByte ' das LF aus dem Buffer entfernen
      7. If len(tmpString)>0 then
      8. getResponse = TRUE
      9. Else
      10. getResponse = FALSE
      11. End If
      12. End Function
      Display All
      Das Beispiel bezieht sich jetzt auf die Antwort von "AT"

      Wenn da erst Daten Kommen (mit CRLF) und dann noch ein String mit OK (mit CRLF), dann muss man das natürlich berücksichtigen.

      Das sind aber alles nur mal Denkansätze, damit man sich nicht mit den AT-Kommandos rumschlagen muss.

      Kann man an den Dingern (ESP-01) eigentlich die Baudrate etwas reduzieren?

      The post was edited 1 time, last by Mitch64 ().

    • Mitch64 wrote:

      eigentlich die Baudrate etwas reduzieren?
      Unterschiedlich. Einige lassen sich mit AT+IPR umschalten. Meins schoß ich damit auf unerreichbere
      7?000Baud. Erfolgreich war ich dann mit AT+CIOBAUD . Andere arbeiten mit AT+UARD_CUR für vorübergehen und AT+UARD_DEF für dauerhaft(auch nach Reset). Dann unterscheiden sie noch Klartext (2400,9600...) oder Kürzel (1=?,2=?...). Am sichersten vorher fragen. Gibt AT+CIOBAUD? die Antwort 9600 weiß man das es Klartext versteht.
    • Hallo
      wie gehts dem Projekt?
      Ich ab hier mal was zusammengefriemelt. Aber schon über 3k und nur rudimentär funktionsfähig. Würden alle Eventualitäten abgehakt reich vermutlich der Flash nicht.

      Source Code

      1. $regfile = "m8def.dat"
      2. $crystal = 1000000
      3. $hwstack = $40
      4. $swstack = $40
      5. $framesize = $100
      6. $eepleave
      7. $baud = 9600
      8. '$sim
      9. 'Portb.0 LCD db4 ,1=LCD db7 ,2=Bled ,3=Vo-/Mosi
      10. 'Portb.4=Db5/Miso ,5=RS/Clk ,6=FET 1 ,7=FET 2
      11. 'Portc.0= 1= ,2= ,3=
      12. 'Portc.4=SDA-nc ,5=Scl -nc ,6=/R ,7=ne
      13. 'Portd.0=RX ,1=TX ,2=nc ,3=nc
      14. 'Portd.4=nc ,5=Lcd RS ,6=Lcd E ,7 =LCD Db6
      15. Ddrb = $ff 'Alles Ausgang
      16. Portc = $70
      17. Ddrc = 0 'alles Eingang
      18. Ddrd = $e6 'LCD6,E, Pin5,Pin2,TX = Ausgang
      19. Config Base = 0
      20. Config Timer0 = Timer , Prescale = 1024 '250ms
      21. '---------------------- LCD config
      22. Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.4 , Db6 = Portd.7 , Db7 = Portd.5 , E = Portd.6 , Rs = Portb.5
      23. Config Lcd = 16 * 2
      24. Lcd_backlight Alias Portb.2 : Set Lcd_backlight
      25. Initlcd
      26. Cls
      27. Cursor Off Noblink
      28. Config Adc = Single , Prescaler = Auto , Reference = internal 'Aref ca 2,6V 'für PT1000 2,78V bei 5,1V(Poti)
      29. '------------------- RS232 config
      30. On Urxc Rx_rdy
      31. Enable Urxc 'set RXCIE
      32. Dim Inbuf(128) As Byte
      33. Dim Rwert As String * 128 At Inbuf Overlay
      34. Dim Ein As Byte , N As Byte , Neu As Byte , U As Byte
      35. Dim A As Byte , B As Byte , C As Byte , L As Byte , S As Word , X As Byte , Y As Byte , Z As Byte
      36. Dim Temp As Byte , Tempi As Integer , Tempw As Word , Tempstr As String * 8
      37. Dim Templ As Byte At Tempw Overlay
      38. Dim Temph As Byte At Tempw + 1 Overlay
      39. Dim Ok As Byte , Erro As Byte , Timerr As Byte , Timo As Word
      40. Dim Conn As Byte , Sendgo As Byte , Soc As Byte
      41. Dim Wlanin As String * 128 , Wlanant As String * 128
      42. Dim Wlanl As Word , Wlanantl As Word
      43. Dim T As Word , Portno As Word
      44. Portno = 50290
      45. Declare Sub Antwort
      46. Declare Sub Eingang
      47. Declare Sub Wait_ok
      48. Enable Interrupts
      49. If Mcusr.0 = 1 Then
      50. Readeeprom Tempw , 0
      51. Incr Tempw
      52. Writeeeprom Tempw , 0
      53. End If
      54. If Mcusr.1 = 1 Then
      55. Readeeprom Tempw , 2
      56. Incr Tempw
      57. Writeeeprom Tempw , 2
      58. End If
      59. If Mcusr.2 = 1 Then
      60. Readeeprom Tempw , 4
      61. Incr Tempw
      62. Writeeeprom Tempw , 4
      63. End If
      64. If Mcusr.3 = 1 Then
      65. Readeeprom Tempw , 6
      66. Incr Tempw
      67. Writeeeprom Tempw , 6
      68. End If
      69. Mcusr = 0
      70. Do
      71. Lcd "Erwarte Esp"
      72. Ok = 0
      73. Do
      74. Print "ATE0"
      75. Timo = 1000
      76. Call Wait_ok
      77. Incr Temp
      78. Loop Until Ok = 1 Or Temp > 10
      79. If Timerr = 1 Then
      80. Locate 2 , 1
      81. Lcd "nicht erreichbar"
      82. Goto Ende
      83. End If
      84. Ok = 0
      85. '(
      86. Locate 1 , 1
      87. Lcd "CWMODE=1 "
      88. Print "AT+CWMODE=1"
      89. Timo = 500
      90. Call Wait_ok
      91. If Timerr = 1 Then
      92. Locate 2 , 1
      93. Lcd "nicht erreichbar"
      94. Goto Ende
      95. End If
      96. ')
      97. Ok = 0
      98. Locate 1 , 1
      99. Lcd "CIPMUX=1 "
      100. Print "AT+CIPMUX=1"
      101. Timo = 500
      102. Call Wait_ok
      103. If Timerr = 1 Then
      104. Locate 2 , 1
      105. Lcd "nicht erreichbar"
      106. Goto Ende
      107. End If
      108. Ok = 0
      109. Locate 1 , 1
      110. Lcd "CIPSERVER=1, "
      111. Print "AT+CIPSERVER=1,";
      112. Print Portno
      113. Timo = 500
      114. Call Wait_ok
      115. If Timerr = 1 Then
      116. Tempstr = Left(rwert , 8)
      117. If Tempstr = "no chang" Then
      118. Ok = 1
      119. Else
      120. Locate 2 , 1
      121. Lcd "nicht erreichbar"
      122. Goto Ende
      123. End If
      124. Else
      125. Lcd Rwert
      126. End If
      127. Locate 1 , 1
      128. Lcd "Erwarte Verb."
      129. Do
      130. If Wlanl > 0 Then
      131. Tempstr = Left(wlanin , 8)
      132. Select Case Tempstr
      133. Case Is = "GETSTATU"
      134. Wlanant = "S" + Bin(portd)
      135. Case Is = "GETPORT "
      136. Wlanant = "A" + Bin(portb)
      137. Case Is = "GETADC A"
      138. Wlanant = ""
      139. For A = 0 To 5
      140. Tempw = Getadc(a)
      141. Tempi = Tempw - 330
      142. Wlanant = Wlanant + Str(tempi) + ","
      143. Next
      144. Case Else
      145. Wlanant = "Nack"
      146. End Select
      147. Wlanantl = Len(wlanant) + 2
      148. Sendgo = 0
      149. Locate 1 , 9
      150. Lcd "T:"
      151. Lcd Wlanantl
      152. Print "AT+CIPSEND=";
      153. Print Soc;
      154. Print ",";
      155. Print Wlanantl
      156. Do
      157. Incr T
      158. Loop Until Sendgo = 1 Or T = 0
      159. Print Wlanant
      160. Wlanl = 0
      161. End If
      162. Do
      163. If Neu = 1 Then Call Eingang
      164. If Wlanl > 0 Then Exit Do
      165. #if _sim = 0
      166. Loop Until Timer0 > 245 '0,25s
      167. #else
      168. Loop Until Timer0 > 8
      169. #endif
      170. Timer0 = 0
      171. Incr Z
      172. Locate 1 , 14
      173. If Timerr = 1 Then
      174. Lcd " To"
      175. Timerr = 0
      176. Elseif Erro = 1 Then
      177. Lcd "Err"
      178. Erro = 0
      179. Elseif Ok = 1 Then
      180. Lcd " Ok"
      181. Ok = 0
      182. End If
      183. If Z > 3 Then '1/4 Sec
      184. Z = 0
      185. Else
      186. Incr S
      187. End If
      188. Loop
      189. Ende:
      190. 'weterer Versuch? Reset? Netz suchen?
      191. ' Incr Errco
      192. ' Loop Until Erco > 1
      193. Cls
      194. Lcd "Neuversuch"
      195. Locate 2 , 1
      196. For A = 0 To 15
      197. Lcd Chr(inbuf(a))
      198. Next
      199. Temp = 0
      200. Loop
      201. End
      202. Sub Eingang
      203. L = Len(rwert)
      204. Locate 2 , 1
      205. If L > 0 Then
      206. Tempstr = Left(rwert , 5)
      207. Select Case Tempstr
      208. Case Is = "SEND "
      209. Ein = 0
      210. Case Is = "0,CON" 'NECT"
      211. Conn = 1
      212. Locate 1 , 1
      213. Lcd "Connect "
      214. Case Is = "0,CLO" 'SED"
      215. Conn = 0
      216. Locate 1 , 1
      217. Lcd "Closed "
      218. Case Is = "+IPD," 'SED"
      219. Soc = Inbuf(5) - $30
      220. A = Instr(7 , Rwert , ":")
      221. If A > 8 Then A = A - 8
      222. Tempstr = Mid(rwert , 8 , A)
      223. Wlanl = Val(tempstr)
      224. Locate 1 , 9
      225. Lcd "Ein: "
      226. Lcd Tempstr
      227. Lcd " "
      228. Locate 2 , 1
      229. A = A + 8
      230. C = L - A
      231. Incr A
      232. Wlanin = Mid(rwert , A , C)
      233. Lcd Wlanin
      234. For A = C To 15
      235. Lcd " "
      236. Next
      237. Case Else
      238. If L > 15 Then Rwert = Left(rwert , 16)
      239. Lcd Rwert
      240. End Select
      241. End If
      242. Ein = 0
      243. Neu = 0
      244. End Sub
      245. Sub Wait_ok
      246. Timerr = 0
      247. T = 0
      248. Do
      249. If Neu = 1 Then Call Eingang
      250. Incr T
      251. Waitms 1
      252. Loop Until Ok = 1 Or T > Timo
      253. If T > Timo Then
      254. Timerr = 1
      255. End If
      256. Neu = 0
      257. Ein = 0
      258. End Sub
      259. Rx_rdy:
      260. U = Udr
      261. Inbuf(ein) = U
      262. If U = $3e Then
      263. Sendgo = 1
      264. #if _sim = 0
      265. Elseif U = 10 Then
      266. Decr Ein
      267. #else
      268. Elseif U = 13 Then
      269. #endif
      270. If Ein < 2 Then
      271. Ein = 0
      272. Else
      273. Inbuf(ein) = 0
      274. Neu = 1
      275. If Rwert = "OK" Then
      276. Ein = 0
      277. Ok = 1
      278. Neu = 0
      279. ' Elseif Rwert = "ERROR" Then
      280. ' Ein = 0
      281. ' Erro = 1
      282. ' Neu = 0
      283. ' Ok = 0
      284. End If
      285. End If
      286. Else
      287. If Ein < 128 Then Incr Ein
      288. End If
      289. Return
      Display All
    • Projekt ist das nicht.
      Es geht hier eher um erste Gehversuche mit dem Modul.

      Aber das Response ist ziemlich wirr.
      Das kann man schlecht nach Schema F abvespern.
      Jeder Befehl ist da anders.

      Mal OK, dann ein Rückgabewert, man anders rum.
      Mal kommt nur Wert ohne OK, mal nur ein OK.
      Mal kommt Error anstelle von OK usw.
      Das hängt immer vom Befehl ab und vom Betriebszustand, zumindest bei einigen Befehlen.

      Wenn ich da an eine Initialisierung denke, die mit einem Aufruf erledigt werden soll,
      wird es schwierig. Denn mein Modul baut nach dem Einschalten sofort die letzte Verbindung auf.

      Also müsste ich zuerst den Resetvorgang abwarten (der anders verläuft, als bei einem neuen Modul) und dann prüfen, ob eine Verbindung hergestellt wurde.
      Dann ob das überhaupt die gewünschte ist und ggf. die Verbindung Trennen und neu aufbauen.

      Wie du schon festgestellt hast, wird der Code schnell recht groß. Und ist ein ziemliches Gefrickel!
      Um aber nun alle Eventualitäten abzudecken, also welche möglichen Antworten (und Zeilen bzw. Strings) eine Anfrage bringt, müsste man alles durchtesten, bei allen Betriebsmodes.

      Und dazu fehlt mir gerade der Nerv.

      Und einfach nur Befehle schicken, ohne die Antwort auszuwerten und darauf zu reagieren finde ich persönlich unprofessionell. Das führt dann dazu, dass das Ding evtl nicht korrekt initialisiert ist und dann rumspinnt oder einfach nicht das tut was man erwartet.

      Ich hab noch keine Idee, wie man das am besten lösen kann. Schließlich sollte dann die Initialisierung auch mit einem Brandneuen Modul genauso funktionieren, wie mit einem bereits initialisierten Modul, also einem, das z.B. völlig anders konfiguriert war (als AP z.B. und soll als Station konfiguriert werden).

      Also nicht so ganz trivial.
    • Ich muss nochmal auf den Befehl
      Config Input = <term>, ECHO = <echo>
      zurück kommen.

      In der Bascom-Hilfe steht, dass für <echo> folgende Werte eingegeben werden können.
      CR, LF, CRLF, LFCR (siehe Tabelle)

      Weiter unten steht dann noch der Hinweis mit Ausrufezeichen:
      When NOECHO is used, NO characters are sent back even while configured with CONFIG INPUT

      Demnach geht es wohl doch, dass man kein Echo zurück sendet. Das ist auch das was ich anwenden möchte.

      Aber was heißt das nun genau?

      Muss ich jetzt schreiben

      a) Config Input = CRLF , ECHO = noecho

      oder

      b) Config Input = CRLF

      oder

      c) Config Input = CRLF , noecho

      ???

      Alle Varianten lösen bei meiner Version 2.0.8.2 einen Compiler-Fehler aus.

      Wie muss ich das konfigurieren, dass kein Echo zurück gesendet wird?
      Weiß das jemand?
    • Michael wrote:

      Config Input = Crlf , Echo = Crlf
      Echo Off

      stefanhamburg wrote:

      Input C Noecho 'supress echo
      Beide Varianten scheitern am Simulator, der hängt sich auf.

      Ich werde es später ausprobieren mit einer realen Schaltung.

      @stefanhamburg
      Sollte denn in der Bascomhilfe bei Input der Syntax dann nicht so angegeben werden:

      Input <var> [NoEcho]

      @Michael
      Und bei Config Input in der Tabelle NoEcho ergänzt werden, sofern es funktioniert?