interrupts

Goeie! dag.

ik heb een probleem wat steeds terug blijft komen en waar ik niet egt een makkelijke (wat volgens mij moet lukken) oplossing voor heb. veelal van de projecktjes die ik heb heeft een LCD of TFT. LCD valt dan nog wel mee. maar een TFT, als je veel update kan dat ook wel effe duren voordat de arduino klaar is. en heb ik het probleem dat bepaalde code niet vaak genoeg worden geupdate. omdat het aan het wachten is op de TFT code.

maar ik kan/mag de code ook weer niet 1:1 in een interrupt stoppen. zodat de tijd kritieke dingen goed lopen. en de TFT op de achtergrond.

EDIT!: geen 2 seconden oke! het gaat er om dat de rest van de code vertraging op loopt van de TFT.

ik heb al een project waar ik 2 unos gebruik 1 voor lcd en 1 voor tijd kritieke code. en ik heb een code waar ik een interrupt true set en als hij true is stop met TFT update en elke tft element heeft een variable zo dat ik het niet 2x update. en Run tijd krietike code. maar dit klinkt heel omslachtig.

meschien dat jullie mij een idee (voorbleed, heel simpel) kunnen geven.

momenteel gebruik ik een DUE. also ik zet meestal alle interrupt uit! alleen Millis/Micros staat aan. en als ik een interrupt nodig heb zet ik hem aan. weet ook niet echt of dit goed is, maarja als ik geen PWM,Servo,Pizzo,enz nodig heb kan het uit. maar ik weet niet precies wat de compiler doet. als je geen PWM gebruikt staat het automatisch uit. geen idee.

Hoi.

Ik vind het lastig om uit je post een vraag te destilleren en precies te begrijpen wat je wil.

Maar de Due is veel sneller dan een andere Arduino variant, dus als die je probleem nog niet oplost dan is het toch het beste om het met 2 controllers te doen. 2 Uno's is dan misschien een beetje te lomp, je kunt hetzelfde bereiken met een Uno en een pro mini (sterker nog, een pro mini heeft zelfs 2 extra analoge ingangen).

Om je een echt goed antwoord te kunnen geven, is de code belangrijk. Anders blijft het gokken waar het over gaat.

goeidag en bedankt voor reply.

sorry dat ik niet echt duidelijk ben.

ik heb een DUE + TFT(HXD8357D 8bit mode + touchscreen) + ENCODER + SENSOR (HIGH/LOW). voor de TFT heb ik een Menu lib gemaakt.

dit alles kom in een "insert machine" waar 6000 producten per/uur door heen gaat. dus 1.6 product per/sec en het idee is dat een Trigger alleen mag gebeuren op bepaalde encoder posities. en als er een trigger op een verkeerde encoder positie komt dan moet de machine stoppen.

Maar!!! zodra ik een "pagina" verander op de TFT blokkeert alles voor 1 a 2 sec. hij update wel de encoder en triggers. omdat dit interrupts zijn. maar er word niet vergeleken of de trigger op de goeie encoder moment plaats vind. dit is geen! interrupt, omdat er altijd word gezecht dat een interrupt zo klein mogelijk moet zijn.

Q: hoe los ik op dat de TFT de rest(meer belangrijke code) van de code niet blokeert. de rekenkracht is er wel alleen weet ik het niet goed teverdelen.

en het idee is om 2x Light Barrier sensors, 2x pressure sensor en 3x solenoid, doormiddel van de encoder tebesturren.

Indien het noodzakelijk is, kun je langere interrupt routines gebruiken. Je kunt b.v. twee variabelen vergelijken en gebaseerd op het result aktie ondernemen. Het is (waarschijnlijk) veel belangrijker om ravage te voorkomen dan om je interrupt routine kort te houden.

Hoe stop je de insert machine? Als dat gebeurt met een simpele digitalWrite(), kun je dat doen in interrupt routine. Als dat gebeurt via b.v. Serial.print heb je een probleem aangezien Serial.print gebruikt maakt van interrupts. Als de AdaFruit libraries interrupts gebruiken heb je ook probleem.

Ik heb geen ervaring met TFT, maar misschien kun je het verversen van de TFT opsplitsen in een aantal 'blokken' die ieder b.v. 500ms (of korter duren). Het niet gebruiken van graphics maar alleen tekst kan misschien alles ook wat versnellen.

bedankt voor deze duidelijke antwoord!

Indien het noodzakelijk is, kun je langere interrupt routines gebruiken. Je kunt b.v. twee variabelen vergelijken en gebaseerd op het result aktie ondernemen.

dit is idd precies wat ik wil doen.

Hoe stop je de insert machine? Als dat gebeurt met een simpele digitalWrite(), kun je dat doen in interrupt routine.

ook precies dit is mijn idee.

Als de AdaFruit libraries interrupts gebruiken heb je ook probleem.

Uhmmm dat heb ik niet specifiek bekeken. zo ver ik weet is het gewoon een 8bit protocal zo als een 8bit LCD. alleen zijn er iets meer commands. om dingen aan tepassen in de register van de TFT. en er word gebruik gemaakt van een "pinmagic.h" zo dat er geen gebruik word gemaakt van "digitalWrite/digitalRead" maar de registers/port worden aangepast. wat een stukje ;) sneller gaat.

Ik heb geen ervaring met TFT, maar misschien kun je het verversen van de TFT opsplitsen in een aantal 'blokken' die ieder b.v. 500ms (of korter duren).

zo iets heb ik ook al geprobeert maar ik vind het een beetje omslachtig. Q: of is het juist een slecht gewoonte om teveel code in een ISR testoppen

Het niet gebruiken van graphics maar alleen tekst kan misschien alles ook wat versnellen.

tekst printen is juist het gene wat traag gaat. de graphics zijn al heel minimaal gewoon simpele vierkantjes waar je op kan drukken en dan verandert bv de page en krijg je een andere pagina.

Q: heeft het zin om ISR's uitzetten die je toch niet gebruikt. of doet de compiler dit. en kunnnen ze in uberhoud wel uit?

2 seconden om een tft te refreshen op een due?????? Ik zou daar eens grondig naar kijken.

Jantje: 2 seconden om een tft te refreshen op een due?????? Ik zou daar eens grondig naar kijken.

ja pffff beetje erger laten lijken dan dat het is. het gaat gewoon om het feit dat als ik de tft refresh dat de rest dus danig word geblokeerd en niet meer acuraat is.

my 2cent Ik heb een vol automatische robot met 4 motoren, 8+ sensoren, gps, kompas, ... en een loop duurt minder dan 1ms. Als hij al zijn data naar een seriele poort schrijft (dat zijn meerdere html pagina's die een volledige memory dump van de robot geeft) duurt dat 400ms. En dat op een mega.

Ik weet niet wat een tft is maar 2 seconden is een eeuwigheid in elektronica wereld. Met een 8 bitter zou ik nog kunnen denken.... maar met een 32 bit arm processor die real-time video beelden kan verwerken .......

Die 2 seconden veroorzaakt dat problemen. Als je dat niet aanpakt ben je de symptomen aan het bestrijden en niet het probleem.

Dat is dus ook mijn punt in de post hierboven, en de reden waarom er naar de code word gevraagd. Het is heel goed mogelijk dat er teveel dingen tegelijk gedaan moeten worden en dat er daarom iets in de knoop geraakt, of dat het gewoon veel efficiënter kan. Vaak is het dan ook nog eens zo dat degene die dat gemaakt heeft, de fout er niet uitpikt, omdat ie zeker weet dat ie het op de juiste manier doet. Je geeft ook aan dat je er al aan gedacht hebt om efficiënt te werken. Maar toch is het wel verstandig er een ander naar te laten kijken. Ik begrijp uit je reacties wel dat het om een project gaat waar een machine bediend word (mogelijk eentje uit een productielijn). En dat het daarmee mogelijk om een commercieel project gaat waar je het idee en de software niet van zou willen publiceren. Maar toch is het een goed idee er eens een ander naar te laten kijken die niet met dezelfde gedachtegang aan dat project bezig is.

Kan gewoon programmeurs blindheid zijn. Dan ben je zeker niet de eerste en zeker niet de laatste. En ik spreek uit ervaring. Na een paar dagen zie je het nog niet. Een ander kijkt mee en binnen een paar minuten opgelost.

Gebruik voor je detectie en stoppen gewoon een simpel arduinotje, maakt niet uit, de encoder op de interupt, en dus elke puls kijken of je iets ziet, zo nee dan een uitgang om de machine te stoppen, en een uitgang naar een andere arduino, waar je het scherm mee aanstuurt, om het scherm te vertellen dat er gestopt is door de encoder. is bij elkaar veel goedkoper. en lekker simpel te programmeren. Ook op de scherm kan een uitgang zitten om de zaak te stoppen, en die kun je dus meenemen op de encodermachine, en in de interupt kijk je dan ook naar die ingang en stop je de machine, ook het starten kan dan vanuit deze.

Een interupt moet zo kort zijn om te voorkomen dat je pulsen mist. Maar mag zo lang zijn dat op de hoogste snelheid je klaar bent met de interupt als er een nieuwe puls komt. stel even je hebt een encoder van 1 Mhz (dat is natuurlijk belachelijk hoog, maar als voorbeeld zelfs dan heb je nog 12 regels die je kunt doen in een ISR.

In een PLC is dat een heel ander verhaal, want die kent cycli van > 2 ms.

Ik ken het probleem wel. Ik heb ooit een applicatie met een Adafruit RGB/LCD gemaakt, die met die 5 buttons eronder. Het updaten van die - toch simpele - display duurde ook te lang, lang geen 2 seconden, maar wel zolang dat andere processen erdoor verstoord werden en begonnen te haperen, erg onprofessioneel.

Toen ik er een Automaton state machine voor bouwde moest ik dat oplossen want het moet natuurlijk allemaal smooth blijven werken.

De oplossing hield in:

  • Ik buffer de display data dubbel (double buffering: schrijven doe je naar een array (buf1) en daarnaast heb je een array (buf2) met een exacte kopie van het scherm, de schermupdatecode update buf2 vanuit buf1 en schrijft daarnaast direct naar het fysieke display)

  • De display update code schrijft iedere cycle van de state machine (dit kun je natuurlijk ook door een interrupt laten doen) een x aantal bytes van buf1 naar buf2 en het fysieke display.

  • Als buf1 gelijk is aan buf2 kun je ophouden met updates.

De display blijft traag, maar de rest van het systeem lijdt er een stuk minder onder.

Met enige aarzeling doe ik er een link naar de LCD 'driver' machine bij, deels omdat men het misschien als eigen promotie zal zien, en deels omdat het niet het de meest toegankelijke stuk Automaton-code is. Je moet natuurlijk zo'n shield hebben om het te kunnen gebruiken.

https://github.com/tinkerspy/Automaton_Adafruit_RGBLCDShield

Bedankt allen voor de reacties.

het is geen!!! commercieel project het gaat gewoon om een machine die op me werk staat en de fabriekant lijkt niet egt mee tewillen werken. wat ik aan de ene kant ook totaal! niet erg vind, want als je de software ziet die er nu op zit schrik je al dood hoe slecht het is. het enige wat ze echt heel goed hebben gedaan is het mechanische gedeelte en een bepaalde trucje, wat de reden is waarom we deze machine hebben gekocht. alleen word er niet gekeken of dat trucje wel goed zijn werk doet. en dat is dus wat ik er op wil zetten.

Code mogen jullie ook zien het is nog totaal NIET!!! af maar meschien is dat wel goed op deze manier kan alles op de goeie manier gedaan worden zonder dat ik het 10x over moet doen.

en voordat iedereen gaat gillen, ik weet dat de numpad niet helemaal klopt, en dat ik beter een interval of != kan gebruiken voor het weergeven van variable.

tot nu toe ben ik alleen bezig geweest met de TFT menu. omdat dat het meeste werk is. en keep in mind ik ben een amateur(27jaar) die de afgelopen 3 jaar C code zich zelf heeft aangeleerd. uiteraard wel via tutorials.

Filmpje hier een filmpje zo dat je kan zien hoe het er nu uit ziet. en dit is gewoon een test sketch.

en de sketch. het is meer dan 9000 charecters dus hier een rar skecth

en meschien wel goed om te weten. als de tft minder snel werkt dat maakt mij niets uit. het gaat mij er gewoon om dat de tft code niet in de weg zit van de belangerijke code.

Ik weet het niet; zoals gezegd, geen ervaring met dit en geen idee hoe het werkt.

Maar om in loop() constant hetzelfde menu op te bouwen lijkt me een beetje overdreven. Zou dat niet werken als je het eenmalig in setup() doet?

sterretje: Ik weet het niet; zoals gezegd, geen ervaring met dit en geen idee hoe het werkt.

Maar om in loop() constant hetzelfde menu op te bouwen lijkt me een beetje overdreven. Zou dat niet werken als je het eenmalig in setup() doet?

Ik ben het helemaal met je eens. Maar uberhaupt schermen aansturen moet je splitsen in de achtergrond met alle toeters en bellen die in feite niet veranderen en de velden en plaatjes die daadwerkelijk veranderen. Het plaatje moet je dan ook alleen veranderen als deze dan ook veranderd. Dat gaat de performance drastisch verbeteren. Ik zou functies maken als: a) ToonScherm() b) updateVelden(0 als je die allemaal tegelijk wil bijwerken of updateVeld(veld) oid c) bouwMenu() als je wisselende menu structuren nodig hebt,

ik ben het helemaal met jullie eens!!!

dat is ook de rede dat zo iets er ook al in zit. schijnbaar niet op gevallen.

alleen doe ik het een beetje anders ipv toon dit en dat. is het als Page != prevpage update alles en als hij dat gedaan heeft stop hij met updaten(stopRefresh()). alleen variable zo als het getal dat op loopt wat je op het filmpje kan zien heeft dat nog niet. daar moet ik een interval of iets in stoppen.

maar back to the point. het probleem wat ik voor zie is dit:
de producten worden vervoert door een ketting met nokken(vingers) die is 80CM lang en heeft 84 schakels.
de encoder die ik heb heeft 96 pulsen per/omwenteling en er zit een tandwiel op met 12 tanden.
dus dat maakt 672 pulsen per product. als de machine 6000 p/uur doet is dat 1.6 p/sec
is 1075.2 pulsen per seconde.

dus wil ik dat de DUE ±1075 keer per sec gaat na kijken of alles wel goed gaat.
door middel van zo iets:

// voor 4 sensoren
if(encoderPositie > minCheck1 && encoderPositie < maxCheck1){
  //lees pin
  if (pin == LOW){
    //STOP machine
  } //else {
    //niets aan de hand, ga door.
  //}
}


// de 2 solenoids
if(encoderPositie > minCheck2 && encoderPositie < maxCheck2){
  //zet pin HIGH
} else {
  //zet pin low
}

en het punt is dat de tft dus niet in de weg mag zitten. hoe verdeel je dit goed.

Wees voorzichtig met digitalReads en Writes in een interrupt routine. Dan kun je beter fastIO gebruiken die al gauw een factor 50 sneller is. En als je alleen dat vlaggetje zet is dat voldoende. In de loop hoef je dan alleen dat vlaggetje af te testen of je de machine moet uitzetten.

Je zou het controleren kunnen uitbesteden aan bijv. een attiny85. Dat ding kan full speed cheken of de pulsen wel binnenkomen en als er een probleem optreedt een signaallijn laag trekken die dan door de DUE wordt opgepikt. Zou net moeten kunnen met met de pins van een attiny85. (2 EUR/stuk of zo?)

Als het multitasken in software onvoldoende lukt doe je het gewoon in hardware...

Wees voorzichtig met digitalReads en Writes in een interrupt routine

Waarvoor moet ik voorzichtig zijn?

Dan kun je beter fastIO gebruiken die al gauw een factor 50 sneller is

ja, wat was ik ook al van plan.

Je zou het controleren kunnen uitbesteden aan bijv. een attiny85

ja maar ik wil juist de min + max variable door middel van de tft veranderen ;-)

als ik de timing dingen in een ISR kan stoppen en de TFT + allemaal andere dingen waar ik het nog niet over heb gehad gewoon in de loop() ben ik helemaal gelukkig.

OK, 'point taken'.

Statemachientje is waarschijnlijk de elegantste oplossing (eigenlijk een sequencer (weet het Nederlandse woord niet)).

int currenState = 0;

void loop() {
  val++;
  analogWrite(LCD_LED, 128);

  switch(currentState)
  {
    case 0:
      menu.run();
      tft.setTextSize(2);
      tft.setTextColor(WHITE);
      break;
    case 1:
       menu.submenuButton(0, 1,  page1, page1txt);
       currentState++;
       break;
    case 2:
       menu.submenuButton(0, 2,  page2, page2txt);
       currentState++;
       break;
    case 3:
       menu.toggle(1, 0, button3, toggle1);
       currentState++;
       break;
    case 4:
       tft.setTextColor(WHITE, BLACK);
       currentState++;
       break;


iedera aparte stap in je huidige code voor het scherm in een 'case'
beetje werk, maar niet echt

    default:
      // terug naar de eerste stap
      currentState = 0;
  }
}

Iedere keer dat loop() wordt uitgevoerd doe je nu slechts een klein stukje van de scherm opbouw (zoals ik al in een eerder antwoord aangaf). Je hebt nu een hele hoop (relatief misschien) tijd om andere dingen te doen.

Als je een interrupt moet gebruiken, kun je een 'global volatile' variabele gebruiken (bv een teller) die je nu in loop() kunt controleren zonder al te veel vertraging.