Delphi vs. Arduino: Soros kommunikációs hiba

Delphi vs. Arduino: Soros kommunikációs hiba
2018-06-03T02:49:42+02:00
2018-06-19T20:46:25+02:00
2022-12-05T10:15:35+01:00
Stella_209
- PC-n fut egy Delphi alkalmazás. 
- USB kábelkapcsolat Arduino-val.
- Mindkettőn roppant egyszerű program ami a soros kapcsolat ellenőrzésére szolgát.
1. Arduino program jó, mert soros monitorban rendesen kommunikál.
2. Kapcsolat jó,
3. Delphi program a várt string válasz helyett csak üres stringet kap, vagy zagyvaságot. Egy örökölt függvénykönyvtárat használ, ami win API hívásokkal operál.
Miért nem működik helyesen?


Arduinó program: (A PC-ről érkező parancsnak # karakterrel kell végződnie!)

String myString; void setup() { Serial.begin(9600); myString = ""; } void loop() { if (Serial.available() > 0) { myString = ""; myString = Serial.readStringUntil("#"); String Comm = myString.substring(0,3); String Parameter = myString.substring(2,20); if (Comm == ":GR") { String s = "06:32:01"; Serial.println(s); } else { Serial.println(123,DEC);} } }
Delphi oldalon: http://stella.kojot.co.hu/Progs/Serial.pas

Soros port olvasás:

procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); Var Count: integer; var buf: string; begin if Key=VK_RETURN then begin buf := Edit1.Text; count := Length(buf); PurgeBuffer(BTH); WriteCOM(BTH,buf,Count); Memo1.Lines.Add(buf); buf := ReadText(BTH); Memo1.Lines.Add(buf); Memo1.Lines.Add('----------'); end; end;
Egyszerű win API hívások és még se!
Üres stringet ad.
Pl. TComPort komponens-el menne, de engem az érdekel, hogy a szimpla API hívásokkal miért nem ad helyes választ.
Mutasd a teljes hozzászólást!
Nézd meg jobban SerialEvent-et. Pont hogy karakterenként ragaszt össze egy stringet. Szépen látni a sample-ban is. Vagy 400 eszközömön megy a SerialEventes megoldás. Ez a legjobb, és egyetlen megoldás is ami (nekem) működik.

Delphi oldalon ne találd fel újra a melegvizet, több, ingyenes komponens is van a soros port olvasására. Én Tcomportot használom, egy db unit az egész. Annak van egy ReceiveCallBack eseménye, és mindjárt egy "Data" nevű stringben meg is adja a bejövő szöveget. FileReadban nem akkor van adat, amikor te kedved szerint olvasgatod. Ne úgy gondolj a soros porta, mint egy "fizikai" file-ra. Tcomportban egyébként szintén beállítható, hogy milyen zárókarakter érkezése esetén jöjjön létre az esemény.

Ne Delphivel, hanem vmilyen terminálprogrammal (pl. Termite) küldözgess először, és szépen küldesd vissza Arduinoval.  (amolyan echo, mint a példában). Ha ez 100%-os, akkor vágj bele a Delphis oldalba.
Mutasd a teljes hozzászólást!

  • Nem ertek a Delphi hez, de ott is a megfelelo baudrate van beallitva(9600)?
    Mutasd a teljes hozzászólást!
  • A FILE_FLAG_OVERLAPPED flag a soros port megnyitásánál azt jelenti hogy asszinkron módban nyitottad meg. A ReadText függvény asszinkron handle esetén azonnal visszatér ha nincs semmi olvasnivalója. Az olvasást szálba vagy timer rutinba kellene helyezni.
    Mutasd a teljes hozzászólást!
  • én a TComPortot használom, de mint látom ez nem egy túlbonyolított vasziszdasz.
    Amit nem látok a programodban, már persze a port inicializációján kívül, hogy az Aurdinonak szükséges "#" karakter hogy kerül a küldött string végére. Mert ha kézzel nem adod meg, a programod nem teszi oda. Anélkül meg nem fog válaszolni.
    Mutasd a teljes hozzászólást!
  • elméletileg várnia kéne a timeoutok leteltéig.
    Mutasd a teljes hozzászólást!
  • Közben nézem az unitot, amit belinkeltél, kéne látni a programod azon részét, ahol inicializálod a portot (Opencom). Milyen timeoutokat adtál meg.
    Továbbá, ha az unit végére példának odabuggyesztet ReadText függvényt használod átalakítás nélkül, az bizony elég szegényes. Hibás olvasás esetén üres stringet ad vissza, mert nincs megárva az exception.
    Amúgy az egész úgy néz ki, mintha valaki Turbo Pascalból delphisítette volna
    Ha megvan a CPort miért nem azt használod, ott mindent úgy állítasz, ahogy a kedved tartja, ráadásul még úgy is működik.
    Mutasd a teljes hozzászólást!
  • Minden Arduino-nak küldött parancs utolsó karaktere #. És a Delphiben nem állítom a Baudot, mert ez a port alapértelmezése. (9600)
    Mutasd a teljes hozzászólást!
  • Ezt nem értem, a portot inicializálnod kell, az OpenCom pedig kéri a paramétert, mert nincs megadva a fejlécben default érték.
    Mutasd a teljes hozzászólást!
  • 1, a com portot az OpenCom fv szerint inicializálni kéne.
    2, A soros monitor ki van kapcsolva?
    3, Ha minden működik, akkor valahogy meg kell oldanod, hogy a válasz üzenetről ne maradj le ezért a port olvasását egy külön szálban kellene oldanod  -> Quetzelcoatl
    4, Amikor a PC-n adás van, akkor villog az RX LED  neg a TX LED az arduino-n?
    Mutasd a teljes hozzászólást!
  • TComPort-al simán megy minden, csak Windows API hívásokkal nem. És izgat, hogy miért nem.
    Ha valakinek már sikerült, kérem tegye ide a forráskódot tanulságképen.
    Mutasd a teljes hozzászólást!
  • Vagy szálat készítesz az olvasáshoz vagy hozzáadsz egy Timert a formhoz

    procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); Var Count: integer; var buf: string; begin if Key=VK_RETURN then begin buf := Edit1.Text; count := Length(buf); PurgeBuffer(BTH); WriteCOM(BTH,buf,Count); Memo1.Lines.Add(buf); end; end; procedure TForm1.Timer1Timer(Sender: TObject); var buf: string; begin buf := ReadText(BTH); Memo1.Text:=Memo1.Text+buf; if pos(#10,buf)>0 then Memo1.Lines.Add('----------'); end;
    Mutasd a teljes hozzászólást!
  • Már mondtam, tedd fel azt is, ahogy inicializálod  a portot. Miért kéne találgatnunk vaktában, hogy mi lehet a hiba?
    Mutasd a teljes hozzászólást!
  • Azt hiszem megtaláltam a megoldást: a mellékelt Serial1.pas unit tökéletes működik

    (* How to write/read a string to/from the serial port Title: How to write/read a string to/from the serial port *) unit Serial1; interface uses Windows, Messages, SysUtils; Type ComStateRecord = record CommHandle : THandle; Com_opened : boolean; Port : integer; end; Var // Tömbök az 1..255 portok kezelését tenné lehetővé ComFile: array[1..255] of THandle; ComState: array[1..255] of ComStateRecord; Com_opened : boolean = false; function OpenCOMPort( var fh: THandle; Port: integer): Boolean; function SetupCOMPort( var fh: THandle; baud: longint): Boolean; procedure ClearBuffer( var fh: THandle ); procedure SendText( var fh: THandle; s: string); function ReadText( var fh: THandle ): string; procedure CloseCOMPort( var fh: THandle ); implementation function OpenCOMPort( var fh: THandle; Port: integer): Boolean; var DeviceName: array[0..80] of Char; begin { First step is to open the communications device for read/write. This is achieved using the Win32 'CreateFile' function. If it fails, the function returns false. } StrPCopy( DeviceName, '\.\COM'+inttostr(Port) ); fh := CreateFile(DeviceName, GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Com_opened := not (fh = INVALID_HANDLE_VALUE); Result := Com_opened; end; function SetupCOMPort( var fh: THandle; baud: longint): Boolean; const RxBufferSize = 256; TxBufferSize = 256; var DCB: TDCB; Config: string; CommTimeouts: TCommTimeouts; begin { We assume that the setup to configure the setup works fine. Otherwise the function returns false. } Result := True; if not SetupComm(fh, RxBufferSize, TxBufferSize) then Result := False; if not GetCommState(fh, DCB) then Result := False; // define the baudrate, parity,... Config := 'baud=9600 parity=n data=8 stop=1'; if not BuildCommDCB(@Config[1], DCB) then Result := False; if not SetCommState(fh, DCB) then Result := False; with CommTimeouts do begin ReadIntervalTimeout := 0; ReadTotalTimeoutMultiplier := 0; ReadTotalTimeoutConstant := 1000; WriteTotalTimeoutMultiplier := 0; WriteTotalTimeoutConstant := 1000; end; if not SetCommTimeouts(fh, CommTimeouts) then Result := False; end; procedure ClearBuffer( var fh: THandle ); begin PurgeComm( fh, PURGE_TXCLEAR ); PurgeComm( fh, PURGE_RXCLEAR ); SetupCOMPort( fh, 9600); end; { The following is an example of using the 'WriteFile' function to write data to the serial port. } procedure SendText( var fh: THandle; s: string); var BytesWritten: DWORD; begin { Add a word-wrap (#13 + #10) to the string } s := s + #13 + #10; WriteFile(fh, s[1], Length(s), BytesWritten, nil); end; { The following is an example of using the 'ReadFile' function to read data from the serial port. } function ReadText( var fh: THandle ): string; var d: array[1..80] of Char; s: string; BytesRead, i: Cardinal; begin Result := ''; if not ReadFile(fh, d, SizeOf(d), BytesRead, nil) then begin { Raise an exception } end; s := ''; for i := 1 to BytesRead do s := s + d[I]; Result := s; end; procedure CloseCOMPort( var fh: THandle ); begin // finally close the COM Port! if Com_opened then begin CloseHandle(fh); Com_opened := False; end; end; end.
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • És az Arduino-n futó kis teszt program:
    Ilyen utasítások adhatók ki=  :GR# vagy :GD#

    (A teljes project mellékelve)

    String myString; void setup() { Serial.begin(9600); myString = ""; } void loop() { if (Serial.available() > 0) { myString = ""; myString = Serial.readStringUntil("#"); String Comm = myString.substring(0,3); String Parameter = myString.substring(2,20); if (Comm == ":GR") { String s = "06:32:01#"; Serial.print(s); } if (Comm == ":GD") { Serial.print("-002:12:34#");} Serial.flush(); } }
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • Az a sleep(1000) az unit4.pas-ban az asszinkron válasz visszaolvasása előtt roppant tudományos. Ha az Arduinonak valami időigényes művelet kell végrehajtani a válaszadáshoz majd megnöveled a csodakonstansod értékét 10000-re, 100000-re, stb ? 
    Mutasd a teljes hozzászólást!
  • Nem találtad meg a megoldást, hanem megkerülted a problémát. Ha rendesen meginicializáltad volna az előzőt, akkor nagy valószínűséggel az is működött volna. De ez is ezer sebből végzik, és akkor csak átfutottam lóugrásban a dolgaid. Pl. ha az a szerencsétlen Arduino 80 bájtnál hosszabb dolgot akarna küldeni - szerncsédre nem akar - úgy halna le az egész, hogy nem bírnál csodálkozni
    A sleep egy tipikus gányolás.Nem ezzel kell várakoztatni a programot a válaszra, hanem a port timeoutjait kell rendesen beállítani és akkor megvárja, amíg megjön az adat, nem többet mint amennyi az adatoknak kell, tehát akár azonnal is,  de nem többet. mint a maximum. A tiéd így max 2 mp-t vár, ha a readtotaltimeoutot 2000-re állítottad vona, ugyanezt éred el sleep nélkül is. De még így is lehalhat. Mivel a readintervaltimeout 0-ra van állítva, ha az Aurdino elmélázik két byte küldése közben, akkor lehal a kommunikáció.
    Mutasd a teljes hozzászólást!
  • Akkor most már konkrétan: szerintetek max. 20 karakter fogadásra, hogyan konfiguráljam fel a COM portot, hogy a PC szinte azonnal fogadja?
    Mutasd a teljes hozzászólást!
  • Ha már ilyen egyszálas programozó vagy akkor legalább ne egy sleep-el várakoztasd az olvasó függvényt az unit4-ben hanem egy waitforsingleobject függvénnyel egy ciklusban mondjuk 1ms -s timeout értékekkel.
    Ha a függvény visszatérési értéke WAIT_OBJECT_0 akkor lehet olvasni (s:=s+ReadText( CF ); )
    Ha az s változóban megtalálod a #-t akkor kész vagy és kiléphetsz a ciklusból

    var ret:DWORD; s:string; begin s:=''; .... //sleep(1000); repeat ret := WaitForSingleObject(CF,1); if ret=WAIT_OBJECT_0 then s:=s+ReadText( CF ); // mert ugye nem biztos hogy 1 szuszra küldi a választ if ret=WAIT_FAILED then begin showmessage('Handle error'); exit; end; until pos('#',s)>0;
    ....
    Mutasd a teljes hozzászólást!
  • Arduinoval SOSE hasznalj Stringet!
    01. Mit ne használjunk Arduino projektekben - String osztály
    The Evils of Arduino Strings

    Itt egy pelda, hogy lehet nelkule megoldani:

    int serial_timeout = 200; // ms int blink_interval = 1000; // ms char readed_char = 0; char serial_buf[129] = {0}; unsigned long start_millis = 0; int serial_buf_size = 0; int serial_buf_char_counter = 0; int led_pin = 13; unsigned long last_blink = 0; boolean blink_state = false; void setup() { pinMode(led_pin, OUTPUT); Serial.begin(9600); serial_buf_size = sizeof(serial_buf); } void loop() { serial_handle(); blink_led(); } void serial_handle() { if (Serial.available()) { start_millis = millis(); serial_buf_char_counter = 0; memset(serial_buf, 0, serial_buf_size); while (true) { if (millis() - start_millis > serial_timeout) { Serial.println("Timeout"); return; } if (Serial.available()) { readed_char = Serial.read(); serial_buf[serial_buf_char_counter++] = readed_char; if (serial_buf_char_counter == serial_buf_size) { Serial.println("Serial buffer overflow"); return; } if (readed_char == '\n') { if (strstr(serial_buf, "getver") == serial_buf) { Serial.println("$firmware_version;20.001*"); return; } else if (strstr(serial_buf, "reset") == serial_buf) { Serial.println("programming mode..."); delay(100); return; } else { Serial.println("Unkown command"); return; } } } } } } void blink_led() { if ((millis() - last_blink) > blink_interval) { blink_state = !blink_state; digitalWrite(led_pin, blink_state); last_blink = millis(); } }
    Mutasd a teljes hozzászólást!
  • Miután ilyen "egyszálas programozó" vagyok, kérek szépen egy minta program részletet arra, hogyan lehetne TThread szálon lekövetni a soros porti beolvasást.
    Mutasd a teljes hozzászólást!
  • blink_led funciton: az osi/legegyszerubb megoldas (jelenlegi tudasom szerint) a delay helyett:

    unsigned long last_blink = 0; boolean blink_state = false; void setup() { pinMode(13, OUTPUT); } void loop() { blink_led(); // program tovabbi resze ami szinte megallas nelkul fut le } void blink_led() { if ((millis() - last_blink) > 1000) { blink_state = !blink_state; digitalWrite(led_pin, blink_state); last_blink = millis(); } }
    Helytelem:

    int led_pin = 13; void setup() { pinMode(led_pin, OUTPUT); } void loop() { blink_led(); // program tovabbi resze ami csak ket masodpercenkent fut le egyszer } void blink_led() { digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW); delay(1000); }
    SOHA ne feledd: ha millis()-t mented valtozoba, a valtozo tipusa unsigned long legyen, kulonben hamar tulcsordul..
    Mutasd a teljes hozzászólást!
  • type TComreadThread = class(TThread) PComhandle:Thandle; private protected procedure Execute; override; procedure Readcomm; public property Comhandle:Thandle read PComhandle write PComhandle; end; ... var Form1: TForm1; ... ComreadThread:TComreadThread; implementation procedure TForm1.FormCreate(Sender: TObject); begin ... ComreadThread:=TComreadThread.Create(true); ComreadThread.FreeOnTerminate:=true; ComreadThread.Comhandle:=CF; ComreadThread.Resume; end; procedure TComreadThread.Readcomm; var s:string; begin Form1.Memo1.text:=Form1.Memo1.text +ReadText( Comhandle ); end; procedure TComreadThread.Execute; begin While not Terminated do begin Synchronize(Readcomm); sleep(10); end; end;
    Mutasd a teljes hozzászólást!
  • Sajnos ez a thread-es megoldás nem működik. Nem olvas, pedig maga a thread elszalad ReadText rutinba, amit direkt módosítottam, hogy debug-olni tudjam: a töréspontot az if BytesRead ... után tettem, de soha nem megy bele.

    Viszont a CPort komponens-el megy a dolog. Ez itt miért nem olvas?

    function ReadText( fh: THandle ): string; var d: array[1..80] of Char; s: string; BytesRead, i: Cardinal; begin Result := ''; if not ReadFile(fh, d, SizeOf(d), BytesRead, nil) then begin s := ''; end; if BytesRead>0 then begin s := ''; for i := 1 to BytesRead do s := s + d[I]; Result := s; end; end;
    Mutasd a teljes hozzászólást!
  • Mutasd a teljes hozzászólást!
  • Vagy megadod, hogy hány bájtot akarsz beolvasni és ha a timeoutok összege alatt nem érkezik be a megfelelő számú, akkor timeoutot dob, vagy egy szál aszinkron figyeli a portot, és ha adat érkezik, akkor elmenti és bekiabál.
    Ha megvan a ComPort könyvtár - gondolom megvan, hisz az elején hivatkoztál rá, hogy azzal működik - mindkét tipusra találsz demot.
    Én csak egy kasszagéppel tudnám kipróbálni a cuccaidat, de emiatt nem fogok leállítani egy kasszát.
    Ja és ahogy mindjárt az elején mondtam, INICIALIZÁLÁS. Ha a sleep 1000-rel ment, anélkül meg nem, akkor az azt jelenti, hogy a default 1000 ms kevés. Állítsd 2000-re, vagy 3000-re, de ne sleeppel operálj.
    Mutasd a teljes hozzászólást!
  • Szia! 

    Nálam ez a kód simán megy, igaz VB.Net. Az Arduino program egy korábbi átalakított távolságszenzor teszt volt.  Hátha segít valamit.

    Option Explicit On Imports System Imports System.ComponentModel Imports System.Threading Imports System.IO.Ports Public Class Form1 Delegate Sub SetTextCallback(ByVal [text] As String) Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim Portok As String() = IO.Ports.SerialPort.GetPortNames() Adatot_kuld_button.Enabled = False Kapcsol_Button.Enabled = False Adatot_kuld_button.Enabled = False For i = 0 To UBound(Portok) Portok_kombo.Items.Add(Portok(i)) Next i Baudrate_Kombo.Items.Add(9600) Baudrate_Kombo.Items.Add(14400) Baudrate_Kombo.Items.Add(19200) Baudrate_Kombo.Items.Add(28800) Baudrate_Kombo.Items.Add(38400) Baudrate_Kombo.Items.Add(56000) Baudrate_Kombo.Items.Add(57600) Baudrate_Kombo.Items.Add(115200) If UBound(Portok) = 0 Then Portok_kombo.Text = Portok_kombo.Items.Item(0) Kapcsol_Button.Enabled = True Else MsgBox("Nincs csatlakoztatva") End If Baudrate_Kombo.Text = Baudrate_Kombo.Items.Item(0) Szetkapcsol_Button.Enabled = False End Sub Private Sub Kapcsol_Button_Click(sender As Object, e As EventArgs) Handles Kapcsol_Button.Click SerialPort1.PortName = Portok_kombo.Text SerialPort1.BaudRate = Baudrate_Kombo.Text 'Használni kívánt port beállításai SerialPort1.Parity = IO.Ports.Parity.None SerialPort1.StopBits = IO.Ports.StopBits.One SerialPort1.DataBits = 8 'Port megnyitása SerialPort1.Open() Kapcsol_Button.Enabled = False Szetkapcsol_Button.Enabled = True Adatot_kuld_button.Enabled = True End Sub Private Sub Szetkapcsol_Button_Click(sender As Object, e As EventArgs) Handles Szetkapcsol_Button.Click SerialPort1.Close() Kapcsol_Button.Enabled = True Szetkapcsol_Button.Enabled = False End Sub Private Sub Adatot_kuld_button_Click(sender As Object, e As EventArgs) Handles Adatot_kuld_button.Click If Me.Adatot_kuld_textbox.Text <> "" Then SerialPort1.Write(Me.Adatot_kuld_textbox.Text) Else MsgBox("Üres!") End If End Sub Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived ReceivedText(SerialPort1.ReadExisting()) End Sub Private Sub ReceivedText(ByVal [text] As String) If Me.RichTextBox1.InvokeRequired Then Dim x As New SetTextCallback(AddressOf ReceivedText) Me.Invoke(x, New Object() {(text)}) Else Me.RichTextBox1.Text &= [text] End If End Sub Private Sub Portok_kombo_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Portok_kombo.SelectedIndexChanged If SerialPort1.IsOpen = False Then SerialPort1.PortName = Portok_kombo.Text Else MsgBox("Csak akkor lehet váltani, ha a meglévő kapcsolatot bontod!", vbCritical) End If End Sub Private Sub Baudrate_Kombo_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Baudrate_Kombo.SelectedIndexChanged If SerialPort1.IsOpen = False Then SerialPort1.BaudRate = Baudrate_Kombo.Text Else MsgBox("Csak akkor lehet váltani, ha a meglévő kapcsolatot bontod!", vbCritical) End If End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Me.RichTextBox1.Text = "" End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Me.RichTextBox1.SaveFile(Application.StartupPath & "\Arduinobo_adat.txt", RichTextBoxStreamType.PlainText) End Sub End Class
    Tényleg csak teszt volt.
    Kb 1.5-2 óra az Arduino kóddal együtt. (örömködés is benne volt ebben az időben, illetve a stressz teszt is! )
    A com-port kiválasztásánál azt kell választani, mint ami az Arduino IDE monitorában be lett állítva és megy. Baudrate-t az Arduino kódba bevarrtam a lehető legkisebbre (9600) majd a program indításakor azt választottam természetesen.
    Mutasd a teljes hozzászólást!
  • Az Arduino kód sem olyan mint nekem. A string osztályt lehet mellőzni, de nem minden esetben kell szerintem. Kódrészlet:

    void loop() { double duration; double Tav; //Hangsebesség double c; //Hőmérséklet Celsiusban double T; while(Serial.available()) { Utasitas= Serial.readString(); } //Serial.print (Utasitas); if (Utasitas.equals("start")) { futhat=true; } else { futhat=false; }
    Mutasd a teljes hozzászólást!
  • Miután ilyen "egyszálas programozó" vagyok, kérek szépen egy minta program részletet arra, hogyan lehetne TThread szálon lekövetni a soros porti beolvasást.

    Tele a net c# programpéldákkal. Haladni kellene a korral, és normális nyelven fejleszteni 
    Mutasd a teljes hozzászólást!
  • Tudod Barátom: 60 éves vagyok. Fejlesztettem már Basic-től kezdve Z80 Assembler-en át, GWBasic, Clipper, DBase, Pascal és az utóbbi 30 évben Delphiben. Ez utóbbit nagyon szeretem, mert sokkal áttekinthetőbb és számomra egyszerűbb a szintaktikája, mint a C-nek. Most viszont az Arduino őrület kapcsán mégis csak rászántam magam a C-re, de szenvedek. Jobban szeretem az ismert hazai pálya előnyeit élvezni.
    Mutasd a teljes hozzászólást!
  • Most már Arduino oldalon kikisérleteztem egy szuper gyors és megbízható rutint a parancsok fogadására.

    const byte numChars = 40; char charBuffer[numChars]; // an array to store the received data boolean newData = false; //for general loop bool debug = false; String myString; boolean stringComplete = false; String Command; String Parameter; void loop() { // SERIAL INPUT if (readSerial()) { String remainString = ""; for (int i=0; i<30; i++) { if (charBuffer[i]==0) { break; } else { remainString += String(charBuffer[i]); } } stringComplete = false; // This cycle is able to separate the sripped commands (LX200 style) // Eg.: #:GR01:12:23#:GD12:23:34#:GR01:12:23#:GD12:23:34# while (!stringComplete) { if (String(remainString[0]) == "#") { remainString = remainString.substring(1,100); } int n = remainString.indexOf("#"); Command = remainString.substring(1,3); Parameter = remainString.substring(3,n); remainString = remainString.substring(n+1,100); remainString.trim(); if (debug) { Serial.println(Command); Serial.println(Parameter); Serial.println("|"+remainString+"|"); } if (!doCommand(Command,Parameter) || (String(remainString[0]) != ":")) { stringComplete = true; } } // while } } boolean readSerial() { static byte index; while (Serial.available() > 0) { // Does serial1 have characters available? char rc = Serial.read(); // Read a character if (rc == '\n') { // Is it newline? charBuffer[index] = 0; // Yes, so terminate char array with 0 index = 0; // Reset array index newData = true; return true; // Return true (we have a full line) } else { charBuffer[index++] = rc; // Yes, so store it and increment index if (index > numChars) { // Have we filled the buffer? index--; // Yes, so decrement index } } } return false; // Return false (we don't have a full line) } bool doCommand(String Comm, String Par) .....
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd