Toon posts:

C# serialPort.Readline() ofwel RX

Pagina: 1
Acties:

Onderwerpen


  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
Hallo,

Ik probeer een soort debug applicatie te maken voor mijn ATmega88.
Helaas krijg ik via Visual Studio C# (windows forms) niet een volledig functioneel geheel met het Readline commando.

De ATmega88 stuurt nu continu een integer16 (16 bit integer) weg, dit gebeurt als Ascii (BCD dus).

Nu is het probleem dat wanneer ik zelf het commando serialPort.ReadLine() gebruik hij na verloop van tijd hangt.
Of hij pakt de 1e 3 integers die hij krijgt en dan blijft hij die herhalen. Andere input dringt dan pas na 2 minuten door in het programma. Alsof hij een te groot buffer heeft.

Ook het voorbeeld op de website van Visual Studio heeft dit probleem.

Dus heb ik serialPort.DiscarInBuffer gebruikt, maar dan word het helemaal feest en pakt hij halve woorden. (4 van de 8 bit dus)

Hoe kan ik gewoonweg maken dat hij de input leest en laat zien zonder dat hij vastloopt.

iemand een suggestie?

  • RxB
  • Registratie: september 2001
  • Laatst online: 07-02-2017
Het probleem is meestal dat de microcontroller te snel verstuurd achter elkaar.
en de serial port dan niet altijd events gooid. google maar eens op slow serial port

wat ik meestal doe bufferr klein houden van je poort.

in je event van je serialport.

while(comport.BytesToRead>0 )
{
addtobuffer(comport.ReadByte());
}


in je addtobuffer verwerk je de bytes pas als alles binnen is.

[Voor 12% gewijzigd door RxB op 28-10-2010 23:59]


  • Guldan
  • Registratie: juli 2002
  • Laatst online: 13:01

Guldan

Thee-Nerd

Een ander hulpmiddel is om aan te geven wanneer je bericht gestart/gestopt is. Nu ziet (versimpeld) je seriële poort:
1616161616161616161616161616
of 161 616 161 616 (of nog meer combinaties)
ipv 16 16 16 16 16 16 16 16 16 16 16

De seriële poort houdt geen rekening mee dat soms tijdens het ontvangen de bytes al uitgelezen worden. Dit dien je zelf nog op te vangen. Meestal word dit gedaan door start en een eind bericht (teken) mee te geven.
dus bijv. |16!|16!|16!|16|!. Hierbij is de start het pipe teken en het eind teken een uitroepteken.

You know, I used to think it was awful that life was so unfair. Then I thought, wouldn't it be much worse if life were fair, and all the terrible things that happen to us come because we actually deserve them?


  • farlane
  • Registratie: maart 2000
  • Laatst online: 20-09 22:56
ReadLine werk alleen als er CR/LF's in de data zit, wat betekent dat er al delimiters zijn.

Ik zou zeggen als de uP constant data verstuurd en je X tijd geen data meer binnenkrijgt je de poort moet gaan flushen en/of opnieuw initialiseren.

Naast events zou ik ook een timer laten lopen om te pollen of er toch nog wat in de poortbuffer zit, aangezien er situaties zijn te bedenken waarbij er geen event komt maar er toch data aanwezig is.

@hieronder:
De ATmega88 stuurt nu continu een integer16 (16 bit integer) weg, dit gebeurt als Ascii (BCD dus).

[Voor 14% gewijzigd door farlane op 30-10-2010 15:29]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Vinnienerd
  • Registratie: juli 2000
  • Laatst online: 17:56
TS, wat probeer je precies uit te lezen? Een ASCII character of een 16-bit (unsigned) int?

  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
Ik probeer niet meer een unsigned int 16 uit te lezen. Het is gelukt.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   switch (whichbit)
   {
       case 0:
            rdata1 = serialPort1.ReadByte();
            whichbit++;
            break;
        case 1:
            rdata2 = serialPort1.ReadByte();
            whichbit--;
            printok++;
            break;
    }           
}
private void timer1_Tick(object sender, EventArgs e)
{
    rdata = (rdata1 * 256) + rdata2;
    textBox1.Text = rdata.ToString();
}


Ik wist niet dat ik een event moest gebruiken totdat ik linux_freak zijn post zag.
En inderdaad guldan, ik verstuurde het eerst minder handig met ascii. Want 16 zou dit zijn: 49 54 49 54 49 54
Nu stuurt hij 2 keer een 8 bit reeks die plakt ie aan elkaar en laat hij zien.

Het enige probleem wat er nu nog speelt is synchronisatie, want hij kan ook beginnen met het lezen van "deel1" als "deel2" wordt verzonden.

Edit: dat is niet het enige probleem
Er zit een 15 sec vertraging tussen de data die erheen gaat, en de data die wordt weergeven...
En het buffer staat op 8. Erg vreemd

[Voor 14% gewijzigd door jeroen3 op 30-10-2010 18:04]


  • farlane
  • Registratie: maart 2000
  • Laatst online: 20-09 22:56
Je bent op de verkeerde weg, want je gaat er nu bv van uit dat je voor elk ontvangen character een event krijgt, waarvan ik je kan (nog een keer) garanderen dat dat niet het geval zal zijn.

Verder heb je wel een timer toegevoegd, maar die maakt alleen gebruik van het resultaat van je event gebaseerde constructie, en die is niet optimaal.

Dus erm in pseudo:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialRxHandler()
}

private void PollTimer_Tick(object sender, EventArgs e)
{
    SerialRxHandler()
}

private void SerialRxHandler()
{
    while( Data in PoortBuffer )
    {
        Buffer += Data;
        Restart Poll Timer
   }
   while( Bericht in Buffer Compleet )
   {
        Verwerk Bericht
        Adjust Buffer
    }
    if( Totaal de weg kwijt )
        Reset/Flush Poort/ Reset Buffer
}

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
De reden dat ik een losse timer gebruikte voor de textbox was omdat iets het niet toeliet om textbox1 te benaderen vanuit de event. En nu weer mag het niet vanuit SerialRxHandler.

  • RxB
  • Registratie: september 2001
  • Laatst online: 07-02-2017
je zal we de melding krijgen van dat je moet invoken.

hieronder op msdn de uitleg van hoe en wat je moet doen

http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx

  • CyBeR
  • Registratie: september 2001
  • Niet online

CyBeR

💩

Guldan schreef op vrijdag 29 oktober 2010 @ 13:36:
Een ander hulpmiddel is om aan te geven wanneer je bericht gestart/gestopt is. Nu ziet (versimpeld) je seriële poort:
1616161616161616161616161616
of 161 616 161 616 (of nog meer combinaties)
ipv 16 16 16 16 16 16 16 16 16 16 16

De seriële poort houdt geen rekening mee dat soms tijdens het ontvangen de bytes al uitgelezen worden. Dit dien je zelf nog op te vangen. Meestal word dit gedaan door start en een eind bericht (teken) mee te geven.
dus bijv. |16!|16!|16!|16|!. Hierbij is de start het pipe teken en het eind teken een uitroepteken.
Dat is nergens voor nodig -- hij stuurt fixed-length content van één 16-bit int, dus twee bytes. Jij maakt van elke verstuurde twee bytes, minimaal vier bytes en potientieel zelfs 7 bytes ('|65335!'), en daarmee de communicatie minimaal tweemaal zo langzaam.

In dit geval is het heel simpel te doen door gewoon steeds twee bytes te lezen en die in een int te proppen.

Overigens TS: je hebt hier wel potentieel een synch-probleem. Wat als je pas je UART aanslingert op het moment tussen byte 0 en byte 1? Dan ben je dus byte 1 als byte 0 aan het lezen, en byte 0 van je volgende resultaat als byte 1. Je moet een manier vinden om aan te geven welke byte, byte 0 is. Als je niet de volledige range van een 16-bit unsigned int nodig hebt maar genoeg hebt aan een kwart daarvan, kun je dat bijvoorbeeld doen door de twee most significant bits op te offeren voor dit doeleinde.

[Voor 7% gewijzigd door CyBeR op 30-10-2010 20:41]

All my posts are provided as-is. They come with NO WARRANTY at all.


  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
Jep ;) , dat had ik al gezien. Ik denk met CTS/RTS ofzo.
Maar dat zoeken ik later wel uit.

Ik zal morgen het Invoken uitzoeken.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 20-09 22:56
Jep ;) , dat had ik al gezien. Ik denk met CTS/RTS ofzo.
Dus ...
Ik zal morgen het Invoken uitzoeken.
'Het invoken' is niet een onderdeel van je probleem met de communicatie. Zorg nou dat je eerst het probleem oplost en dan pas de volgende erbij pakt.

[Voor 25% gewijzigd door farlane op 31-10-2010 01:18]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
Sorry voor de late reactie, maar ik heb de ATmega kapot gemaakt toen ik aan het klooien was met een LCD schermpje.
Wordt waarschijnlijk pas volgende week... dan heb ik nieuwe

[Voor 5% gewijzigd door jeroen3 op 05-11-2010 22:33]


  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
Ik heb ondertussen geleerd dat het anders moet.

De pc stuurt een commando, bijvoorbeeld "T".
De microcontroller weet dan dankzij een vooraf bedacht "protocol" dat na het ontvangen van "T" de waarde van variabele "temp" moet worden verzonden, als ascii. (5 stuurt hij dus als 00005, int16)
De pc kan voordat de T verstuurt wordt de receive buffer legen en na een event of vastgestelde tijd de data uit te lezen met "ReadExisting".

Alleen is de lengte van een event wat lastig is te stellen als je langere variabelen wilt ontvangen. (int32)
Geldt bij Visual C# ook dat 1 byte is 4 bits,? Dus 2 bytes is één zendcycle van de microcontroller.
En treedt de event dan altijd op?

  • CyBeR
  • Registratie: september 2001
  • Niet online

CyBeR

💩

Aangezien byte staat voor 'By Eight', ga je niet snel een byte vinden van minder dan 8 bits.

All my posts are provided as-is. They come with NO WARRANTY at all.


  • RobIII
  • Registratie: december 2001
  • Laatst online: 17:20

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

CyBeR schreef op woensdag 08 december 2010 @ 23:33:
Aangezien byte staat voor 'By Eight', ga je niet snel een byte vinden van minder dan 8 bits.
Even mierenneuken:
The byte (pronounced /ˈbaɪt/), is a unit of digital information in computing and telecommunications, that most commonly consists of eight bits. Historically, a byte was the number of bits used to encode a single character of text in a computer and it is for this reason the basic addressable element in many computer architectures.

The size of the byte has historically been hardware dependent and no definitive standards exist that mandate the size. The de facto standard of eight bits is a convenient power of two permitting the values 0 through 255 for one byte. Many types of applications use variables representable in eight or fewer bits, and processor designers optimize for this common usage. The byte size and byte addressing are often used in place of longer integers for size or speed optimizations in microcontrollers and CPUs. Floating point processors and signal processing applications tend to operate on larger values and some digital signal processors have 16 to 40 bits as the smallest unit of addressable storage. On such processors a byte may be defined to contain this number of bits. The popularity of major commercial computing architectures have aided in the ubiquitous acceptance of the 8-bit size.

The term octet was defined to explicitly denote a sequence of 8 bits because of the ambiguity associated with the term byte.
History
The term byte was coined by Dr. Werner Buchholz in July 1956, during the early design phase for the IBM Stretch computer. It is a respelling of bite to avoid accidental mutation to bit.
AFAIK is de "by eight" (wat mij overigens ook altijd geleerd is) niet veel meer dan een voor de hand liggende aanname. En puur voor de volledigheid: 4bits wordt ook wel nibble genoemd.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij


  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 16:34
Ow.. ja natuurlijk. Dat zou ik moeten kunnen dromen.

Het werkt nu redelijk goed. Alleen als ik elke 100 ms een "T" stuur, komt het wel eens voor dat hij teveel/te weinig ontvangt. Toch nog even verdiepen in die "serialPort" van C#.

  • Vinnienerd
  • Registratie: juli 2000
  • Laatst online: 17:56
Je kan ook afspreken dat elke message die je stuurt max x bytes lang is. Als dan je buffer <= x klaar heeft staan, kun je 1 byte uitlezen. Als dat je startbyte is, kun je x-1 bytes uitlezen. Zoniet, herhalen.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 20-09 22:56
Je hele probleem draait zoals altijd weer uit op het probleem vanhet herkennen van 'frames'.

Het vinden van het begin en einde van een frame kun je op meerdere manieren doen, waarvan een start en/of stop tekens er 1 is. Het probleem hierbij is echter dat deze characters niet in de data zelf mogen voorkomen omdat anders een frame niet correct wordt gedetecteerd. In dat geval moeten ze ge-escaped worden. Als er een escape character in je data zit moet die ook ge escaped worden. Messy dus.

Een andere manier is het detecteren van het begin/einde van een frame op basis van tijd. Bijvoorbeeld de afspraak dat als er X ms lang geen data binnenkomt dit het einde van een frame is.

Daarbij wordt nog vaak een controlegetal gebruikt om te kunnen controleren of het frame inderdaad goed binnenkomt.

Omdat het verwerken van berichten met een dergelijke timing op een niet-realtime OS als WIndows voor problemen kan zorgen, kun je ook net doen alsof en de data die je binnenkrijgt gewoon proberen te parsen. Dit doe je totdat:
A - Er geen data meer is. Klaar.
B - Er geen compleet bericht meer in je buffer staat. Wacht op meer data.
C - Er een niet compleet bericht te lang in je buffer staat. Flush je buffer.
D - Er een parsefout optreedt. Flush je buffer.

Voor B,C en D is het makkelijk om op een of andere manier te weten hoeveel data er eigenlijk moet komen en dat je kunt controleren dat er een parsefout is opgetreden door bijvoorbeeld een controlegetal ( bijvoorbeeld een CRC ) te gebruiken in je bericht.

Nogmaals: je constructie baseren op de alleen events van de SerialPort klasse is niet verstandig.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1


Nintendo Switch (OLED model) Apple iPhone 13 LG G1 Google Pixel 6 Call of Duty: Vanguard Samsung Galaxy S21 5G Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True

Tweakers maakt gebruik van cookies

Bij het bezoeken van het forum plaatst Tweakers alleen functionele en analytische cookies voor optimalisatie en analyse om de website-ervaring te verbeteren. Op het forum worden geen trackingcookies geplaatst. Voor het bekijken van video's en grafieken van derden vragen we je toestemming, we gebruiken daarvoor externe tooling die mogelijk cookies kunnen plaatsen.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Forum cookie-instellingen

Bekijk de onderstaande instellingen en maak je keuze. Meer informatie vind je in ons cookiebeleid.

Functionele en analytische cookies

Deze cookies helpen de website zijn functies uit te voeren en zijn verplicht. Meer details

janee

    Cookies van derden

    Deze cookies kunnen geplaatst worden door derde partijen via ingesloten content en om de gebruikerservaring van de website te verbeteren. Meer details

    janee