serieele comunicatie loopt soms "vast"

trix

Golden Member

Kort omdat het vanaf mijn telefoon moet,
Het is data afkomstig van een "scanner" als daarvoor b.v. een hoofdletter P passeert zie je in die te verzenden data die letter terug, wanneer je de bytes op de juiste volgorde legt.
Er mag best ergens een bitje verkeerd staan. Kabellengte is ca. 10 mrt. Geen opstartende motoren in de buurt. De kans op storingen van buiten af lijkt mij vrij klein.

eigenwijs = ook wijs
EricP

mét CE

kans is niet zo groot dat dit gebeurdt,...maar het gaat een keer gebeuren.

Och... de kans is ongeveer 1... :)

hoe los je dit dan op ? ik moet tot 300 kunnen tellen dus 16 bits.

Je blijft maar volhouden aan tellen in een ISR en er gaat niks fout enzo he! DAT WERKT DUS NIET.

ik heb een boaudrate van 9600, dat betekent volgens mij dat er elke milli seconde 1 byte binnen komt. dus mijn bewerkingen in de ISR mogen nooit langer duren dan 1 milli seconden, hoe controleer ik of dit ook het geval is ?

Maak de ISR kort. Dan hoef je daar niet over na te denken. Maar je blijft volhouden om het ingewikkeld te doen met alle ellende die dat tot gevolg heeft...
Kort door de bocht: op 16MHz zal een AVR een kleine 16 miljoen instructies per seconde uitvoeren (niet alles is single-cycle). Met 1000 characters per seconde, kun je dus 16000 instructies uitvoeren. Een beetje ISR is met 50-100 instructies wel klaar, zelf als je die in C schrijft. Dan heb ik een factor 160 over. Zelfs als ik in mijn inschatting een factor 2 verkeerd zit, dan heb ik nog steeds een factor 80 over: dat gaat zonder er over na te denken wel lukken hoor!

ik moet nog even nadenken en lezen over een protocol, hoe dat het best gaat in mijn niet veel eisende specifieke situatie.

Lompe variant: stuur van elke byte de hex representatie. Ja, het wordt 2x zoveel data. En je hebt ruimte voor wat control characters. Zit de bitrate 2x zo hoog en 2x zoveel data is er net zo snel...

Er mag best ergens een bitje verkeerd staan. Kabellengte is ca. 10 mrt. Geen opstartende motoren in de buurt. De kans op storingen van buiten af lijkt mij vrij klein.

En nou zet je het ding aan. Die lijnen klapperen wat... Er komt bij je ontvanger 1 byte binnen (het zien van een startbit is tenslotte genoeg voor de UART). De boel is out-of-sync en nu? Alles resetten? Kom, dat maak je toch niet zo!

Arco

Special Member

Als je geen protocol wilt gebruiken, kun je iets simpels als een time-out gebruiken. Als er langer als xxx mS niks meer binnenkomt de code als compleet zien.
Bij nieuwe data gewoon buffer resetten en opnieuw beginnen. Je zult op een of andere manier moeten synchroniseren, anders gaat 't nooit (goed) werken.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
EricP

mét CE

Dat is OOK een vorm van protocol... Beetje wonky, maar hey...

Tja, heb je ueberhaupt invloed op de te verzenden dataset ?
- Kun je bijv. start-of-message/end-of-message karakters toevoegen ?
- Kun je een sumcheck toevoegen ?
- zijn er bytewaardes die niet/nooit kunnen/mogen voorkomen
- worden de 300 bytes achterelkaar gestuurd of kunnen er onderbrekingen voorkomen ?
- hoeveel tijd zit er tussen twee van die opvolgende berichten?
Zomaar een paar vragen om te kijken wat er dan wel mogelijk is als je geen echt protocol wilt of kunt gebruiken.
Nou ga ik morgen een week op vakantie met nauwelijks serieuze mogelijkheden om te te reageren. Maar daarna wil ik er best wat verder over nadenken. In mijn werkzame verleden heb ik letterlijk tientallen protocollen moeten implementeren om data uit randapparatuur in onze dataloggers in te lezen.

trix

Golden Member

Ik zit nu op een telefoon te "pielen" ik reageer woensdag inhoudelijk, bedankt voor de reacties _/-\o_

eigenwijs = ook wijs

Om de teller in de mainloop uit te lezen kun je een botte interrupt disable / lees teller / interrupt enable doen.

Zoiets dus:

c code:



 int atomic_teller;

 cli();
 atomic_teller = TSOP_byte_transfer_counter;
 sei();

 ... doe nu alle compares etc op "atomic_teller"

Met een echt O/S doe je dat met semaphores of mutexes oid.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
EricP

mét CE

Hoe bedoel je... een ECHT OS? Er IS helemaal geen OS!

Ik heb er nog ff over na zitten denken, en ik denk dat een werkbare oplossing iets als volgt zou kunnen zijn:

Je maakt een ringbuffer van je 300 bytes. De UART-ISR mikt daar braaf elk volgend character in wat binnen komt tenzij de 'status' flag 'complete' is. Dan doe je helemaal niks (nou ja, UART uitlezen, omdat-ie dat fijn vindt als-ie een IRQ geeft).
Tevens zet je (als je wat doet) de timerCounter variabele op 0 als je een character in de buffer mietert en zet de status op 'reading'.

Je maakt een timer-ISR die zeg elke 100μS ofzo loopt. Die doet iets als: if timerCounter<255 timerCounter++ ofzo.
Verder doet die: if (status=='reading') && (timerCounter>timeout) status='complete'

In je main loop kijk je alleen naar status. Zodra die 'complete' wordt, hebben we blijkbaar een time-out. De laatste 300 bytes zijn blijkbaar mijn data. Je kijkt waar het begin van de ringbuffer zit, doet wat leuks met je data. Let wel: alles wat op dit moment binnen komt wordt naar /dev/null gerouteerd.

Als je data 'veilig' is (of verwerkt...) dan zet je status op 'waiting'. Vanaf nu kan er weer in de buffer geschreven worden en is de data daarin dus 'instabiel'.

De waarden van 'status' zijn iets van 'reading', 'complete' en 'waiting' ofzo. Ik zou daar defines van maken om de code wat leesbaarder te houden.

Door dit foefje voorkom je ook het 16-bit variabele probleem. Immers, OF de ISR zit aan de buffer OF iets wat vanuit main aangeroepen is. Ofwel: als 'main' aan je buffer zit, dan blijft de ISR er vanaf. Als de ISR er aan zit, dan wordt main geacht niks te doen.

Daarnaast zou je kunnen overwegen om met je 300 bytes iets als CRC ofzo mee te sturen. Dat worden dan gewoon een paar bytes extra.

Voorwaarde is wel dat de zendende kant iets met die timing kan. Als timing daar absoluut niet kritisch is, dan zou ik het verzenden gewoon lekker vanuit de main doen. Daarna een delay van 100mS ofzo. En dan ga je weer wat doen. Lomp, maar simpel en effectief.

Maar Eric, Een "300 byte buffer" is voor een ATMEGA328 een behoorlijke aanslag op het geheugen.

Dit project wordt zonder "architectuur" aan mekaar geprutst waardoor er steeds weer nieuwe problemen opduiken die met een beetje "vooraf nadenken" makkelijk voorkomen hadden kunnen worden.

Extern RAM? WTF? jaren zeventig technologie! (ok, jaren tachtig dan!). (Huidige, 2020 technologie is: 256Mb onchip RAM, maar dat is een beetje "state of the art" en nog niet makkelijk te verwerken voor hobbyisten.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
trix

Golden Member

Nog steeds vanaf de telefoon:
het is een atmega 2560.

eigenwijs = ook wijs
EricP

mét CE

Kom, dat ding van trix heeft 8k. Dat moet met die 300 bytes toch wel lukken?

Op 1 september 2020 07:13:28 schreef EricP:
Hoe bedoel je... een ECHT OS? Er IS helemaal geen OS!

Weet is dat het er niet is, dus "echt" mag er tussen uit.

Ook dat gedoe met flags en die 100us timer is absoluut niet thread safe. Je verschuift het probleem van de atomic compare van je "main" naar je timer ISR en wint er dus niks mee.

@trix: Het wordt misschien tijd dat ik weer eens een bakkie koffie kom drinken?

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
EricP

mét CE

Ook dat gedoe met flags en die 100us timer is absoluut niet thread safe. Je verschuift het probleem van de atomic compare van je "main" naar je timer ISR en wint er dus niks mee.

Het grappige is... dat dat dus WEL safe is. Om te beginnen werk je overal waar mogelijk meerdere 'threads' tegelijk in roeren met 8-bits variabelen. Die compare is daarmee atomair. En dus thread safe. Daarnaast doen AVRs - tenzij je echt gaat trucen - niet aan interruptable interrupts. Dus er KAN maar 1 ISR tegelijk in zitten roeren - waarmee een atomaire compare dus niet eens meer nodig is. Let wel: het is geen OS met pre-emtive multi-tasking. Het gaat over een ISR op een μC.

trix

Golden Member

Op 1 september 2020 20:35:29 schreef henri62:
@trix: Het wordt misschien tijd dat ik weer eens een bakkie koffie kom drinken?

dat mag altijd natuurlijk, graag.

eigenwijs = ook wijs

Op 1 september 2020 21:23:18 schreef EricP:
[...]Het grappige is... dat dat dus WEL safe is. Om te beginnen werk je overal waar mogelijk meerdere 'threads' tegelijk in roeren met 8-bits variabelen. Die compare is daarmee atomair. En dus thread safe.

Je moet ergens die 300 comparen, dat is per definitie 2 bytes dus niet atomic. Die bewering klopt niet.

Daarnaast doen AVRs - tenzij je echt gaat trucen - niet aan interruptable interrupts. Dus er KAN maar 1 ISR tegelijk in zitten roeren - waarmee een atomaire compare dus niet eens meer nodig is.

Inderdaad, het lijkt erop dat de atmega2560 niet aan nested interrupts doet, dan is het inderdaad safe om dat te doen. Ik ging er vanuit dat de atmega dat wel doet (zoals heel veel cpu's en controllers). Dus daarmee kom je dus weg.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.