[ARDUINO] flankdetectie programmeren

Pagina: 1
Acties:

Onderwerpen


  • QuuN..
  • Registratie: Augustus 2009
  • Laatst online: 28-11-2024
Ik werk met een arduinobordje. De programmeertaal lijkt erg veel op C.
De bedoeling is dat ik een verandering waarneem. Ik lees waarden uit via een COM poort. Als 1 van deze ingangen met minimaal 30 verandert, dan wordt (alleen) dit signaal geregistreerd als hoog. Let op! De beginwaarde is dus niet 0!

Omdat er 9 ingangen worden uitgelezen, mag het programma niet wachten in een while lus, aangezien de rest ook tegelijk uitgelezen moet kunnen worden. De beginwaarde is niet vast, dus er moet echt naar het verschil gekeken worden. Omdat het realtime moet worden uitgelezen, mag er ook niet teveel vertraging in zitten.

Iemand een idee hoe ik dit kan oplossen? Hoeft niet per se in code, functioneel is ook goed.

Alvast bedankt

QuuN

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Het is me niet helemaal duidelijk wat je bedoeld.
Je leest waarden in via een COM poort. Bedoel je dat je 9 COM-poorten uitleest? Dit lijkt me nogal veel..
Of komen er 9 waarden achtereenvolgens over de COM-poort binnenrennen?

In dit laatste geval is er geen probleem. Een circulaire buffer maken m.b.v een interrupt op de COM poort, en 1 voor 1 de waarden afgaan.

edit: ah zoals CIStem zegt kan je natuurlijk ook bedoelen dat je analoge waarde van de 9 pinnen wilt lezen (max 8 vanwege de GND/REF?).
Ik ken het bordje niet, maar het lijkt me inderdaad sterk dat er zoveel ADC inputs opzitten, en dan zul je moeten multiplexen.

[ Voor 26% gewijzigd door EddoH op 12-08-2010 15:25 ]


  • gibraltar
  • Registratie: Augustus 2004
  • Laatst online: 17:59
Dat is afhankelijk van "minimaal 30". Als dat gaat inhouden dat je een analoog signaal moet omzetten met de ADC dan heb je sowieso een probleem omdat de package op de Arduino maar 6 kanalen heeft voor het aansluiten van analoge signalen. Zelfs al had je een package waar de pinnen wel op zaten, dan had je er nog maar 8, en geen 9. Dit kun je allemaal teruglezen in de datasheet op pagina 4 en pagina 250 - 262.

Daarnaast gok ik zomaar dat de Arduino (eigenlijk Wiring) dat helemaal niet ondersteund omdat ze daar bepaalde pinnen voor bepaalde functionaliteit claimen. Dan moet je toch even gaan kijken naar avr-libc, GCC en consorten. De "arduino-taal" is overigens C++ en is erg langzaam als je naar performance aan het zoeken bent.

Als het de belangrijkste taak van de microcontroller gaat zijn, dan is de ongeschreven regel dat je gebruik maakt van interrupts. Maar dat is erg afhankelijk van het signaal wat je uitleest en de toepassing zelf.

Om enige hulp te kunnen bieden moet je eigenlijk het volgende nog even verduidelijken:
  • Hoe ontvang je precies die waarden? Via 1 COM-poort/serieel/UART of op losse IO pinnen?
  • Hoe snel/langzaam moet je de verandering kunnen waarnemen? Wat is teveel vertraging?

[ Voor 38% gewijzigd door gibraltar op 12-08-2010 15:43 ]


  • QuuN..
  • Registratie: Augustus 2009
  • Laatst online: 28-11-2024
Dat via de com poort klopte niet helemaal. Ik gebruik nu 9 analoge pinnen. Deze waarde wil ik omzetten naar een binaire reeks van 9 getallen, en die versturen via usb (die wordt gedetecteerd als COM poort), om vervolgens een Java test interface hieraan te koppelen waarop ik dus wat visualiseer.

De snelheid moet zodanig zijn dat de visualisatie nog vloeiend loopt. Stel je hebt 3 sensoren naast elkaar, en je gaat van de linker naar de rechter via de middelste, dan moet hij vrijwel realtime reageren op de beweging.

Aan interrupts zat ik ook te denken, maar dan kan hij toch niet tegelijk reageren op 2 flanken? En dan zou ik 9 interupts moeten hebben. Iets zegt met dat zoveel interrupts niet mogelijk zijn.

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Lukt het je dan al om 9 analoge waarden in te lezen?
Oftewel: heb je 9 analoge pinnen beschikbaar die je met de ADC kunt converteren naar een binaire waarde?

Zo ja: dan zul je de pinnen gewoon om de beurt af moeten gaan. De adc kan waarsch maar 1 input tegelijk samplen. Vaak is er een afweging te maken tussen de sampletijd en de precisie bij het instellen van de ADC.

  • Wolfboy
  • Registratie: Januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

gibraltar schreef op donderdag 12 augustus 2010 @ 15:13:
Dat is afhankelijk van "minimaal 30". Als dat gaat inhouden dat je een analoog signaal moet omzetten met de ADC dan heb je sowieso een probleem omdat de package op de Arduino maar 6 kanalen heeft voor het aansluiten van analoge signalen. Zelfs al had je een package waar de pinnen wel op zaten, dan had je er nog maar 8, en geen 9. Dit kun je allemaal teruglezen in de datasheet op pagina 4 en pagina 250 - 262.
Zoiets is natuurlijk wel te multiplexen. Maar of dat wenselijk is... beetje te weinig gegevens helaas.

Blog [Stackoverflow] [LinkedIn]


  • Armageddon_2k
  • Registratie: September 2002
  • Laatst online: 10-09 15:29

Armageddon_2k

Trotse eigenaar: Yamaha R6

Is helemaal afhankelijk wat de snelheid is waarmee je waarde verandert.
Meest Realtime oplossing zou zijn:

Pseudo code
code:
1
2
3
4
5
6
7
8
9
10
Global VorigeWaarde 

Loopje oneindig

IF (HuidigeWaarde - VorigeWaarde) > 30 then
Veranderd()
END IF

VorigeWaarde = HuidigeWaarde
einde loopje


Het nadeel hiervan is dat je ingang "direct" van bijvoorbeeld 50 naar 90 moet veranderen, als dit ook maar iets geleidelijk gaat, werkt dit niet meer.

[ Voor 23% gewijzigd door Armageddon_2k op 12-08-2010 16:03 ]


  • gibraltar
  • Registratie: Augustus 2004
  • Laatst online: 17:59
QuuN.. schreef op donderdag 12 augustus 2010 @ 15:40:
Dat via de com poort klopte niet helemaal. Ik gebruik nu 9 analoge pinnen.
Dan gaat het vast om een Arduino Mega en niet een Duemilanove. Dan is het inderdaad mogelijk om tot 16 analoge pinnen uit te lezen.
Aan interrupts zat ik ook te denken, maar dan kan hij toch niet tegelijk reageren op 2 flanken? En dan zou ik 9 interupts moeten hebben. Iets zegt met dat zoveel interrupts niet mogelijk zijn.
Ik denk dat je moet gaan voor pollen, en hopen dat je je onbekende sampletijd haalt. Zorg er in ieder geval voor dat je de datasheet doorleest voor een goed idee wat je kan instellen (pagina 275 - 290). Het is niets anders dan de 9 pinnen door de ADC halen en ze vergelijken met de vorige waarde. De round-trip daarvan is hopelijk kort genoeg om eventuele pulsen niet te missen. De combinatie met data over UART gaat hier misschien wel een probleem vormen.

[ Voor 4% gewijzigd door gibraltar op 12-08-2010 16:04 ]


  • QuuN..
  • Registratie: Augustus 2009
  • Laatst online: 28-11-2024
Het betreft inderdaad een Arduino mega, dus ik kan 16 analoge signalen tegelijk inlezen.
De code van armageddon had ik eerst ook in mijn hoofd. Echter zoals je in mijn 1e post kan lezen zorgt de while loop ervoor dat je maar signaal tegelijk kan uitlezen. Daarnaast stel je de nieuwe waarde gelijk aan de huidige, wat ervoro zorgt dat het signaal gelijk weer laag wordt. De bedoeling is echter dat het signaal hoog blijft zolang die iets detecteert.

@ CIStem
Ook hierbij geldt hetzelfde, misschien was flankdetectie niet het juiste woord, maar het signaal moet gewoon hoog blijven zolang de waarde nog steeds een groot genoeg verschil meet. Ik zal sowieso eens kijken in de datasheet om wat inspiratie op te doen.

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Wat bedoel je met 'zolang die iets detecteert' ?
Het is handiger als je wat duidelijker bent met betrekking tot de use case en de specifieke sensoren, aansluitingen en aansturing, en wat je uiteindelijk wilt bereiken, want zo blijft het een beetje gissen...


Voor zover ik het begrijp wil je gewoon een verschil van '30' (ik neem aan na conversie van de ADC, niet 30 mV oid) ten opzichte van de beginwaarde detecteren, en dan een andere uitgang hoog laten woorden, of iets anders doen. Hiervoor wil je 'realtime' weten of het signaal nog steeds '30' hoger is dan de beginwaarde.
Aan het 1 voor 1 inlezen doe je niks. De CPU opereert nu eenmaal serieel.
Wil je per se parallel zul je met een FPGA oid aan de gang moeten.

Dan is het vrij simpel:

- Een char/int/whatever array van 9 maken
- (Optioneel) een bool array maken. Op 0 setten (of een bitmask oid, naar voorkeur)).
- Eerste paar loops de waarde van de 9 pins lezen, resultaat opslaan in de array.
- Vervolgens constant de 9 inputs lezen en vergelijken met de beginwaarde uit de array.
- Verschil > 30? -> (Optioneel) bool op true setten in de bool array. Oid.
- (Optioneel) Mbv je bool array de correcte outputs setten (laag of hoog).

[ Voor 8% gewijzigd door EddoH op 12-08-2010 16:36 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 11-09 12:01
QuuN.. schreef op donderdag 12 augustus 2010 @ 16:21:
Het betreft inderdaad een Arduino mega, dus ik kan 16 analoge signalen tegelijk inlezen.
'Tegelijk' is ook maar relatief, waarschijnlijk worden die 16 ingangen gemultipexed op 1 ADC converter.
De code van armageddon had ik eerst ook in mijn hoofd. Echter zoals je in mijn 1e post kan lezen zorgt de while loop ervoor dat je maar signaal tegelijk kan uitlezen. Daarnaast stel je de nieuwe waarde gelijk aan de huidige, wat ervoro zorgt dat het signaal gelijk weer laag wordt.
Wat je dan moet doen is een reference niveau bepalen ( door te middelen gedurende een bepaalde tijd oid ) en de 'huidige waarde' ( Evt ook met een filter erop ) met die reference vergelijken. In pricipe verandert de reference dus niet meer.

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.


  • Springuin
  • Registratie: Juli 2002
  • Laatst online: 11-09 20:13
Je moet blijven uitlezen; hetzij in je normale programmaflow, hetzij via een timerinterrupt die op geregelde tijden je programma onderbreekt. Je kunt niet iets instellen zodat bij een wijziging van je analoge waarde een interrupt afgaat zodat je iets kunt doen.

Eventueel kun je het deels in hardware oplossen: je analoge signaal differentieren en vergelijken met een ingestelde waarde (dmv een comparator). Dan heb je een digitaal signaal en kun je een interrupt zetten op de flank van een digitale poort.

Je omschrijving is te abstract, vertel eens duidelijk wat je hardware doet, wat je code uiteindelijk wil doen en wat je aansluit. Dan krijgen wij een beter beeld van wat je wilt bereiken. Wellicht zijn er betere oplossingen.

Acties:
  • 0 Henk 'm!

  • QuuN..
  • Registratie: Augustus 2009
  • Laatst online: 28-11-2024
Ok ik zal even uitleggen wat de context is.

Ik ben bezig met een klein projectje om een multi touchscreen te maken.
Dit doe ik door een grid te maken van IR zenders en ontvangers die tegen elkaar zijn geplaatst. Dit principe werkt, en ik heb dus nu een testopstelling van 9 zenders + 9 ontvangers.

De ontvangers zijn aangesloten op de analoge ingangen van de arduino mega. Deze geeft een 10bits waarde terug (dus tussen 0 en 1023) per analoge ingang. Als er veel buitenlicht op de opstelling schijnt is de waarde hoger. Nu wil ik dat het daglicht geen invloed heeft op de meetwaarden. Hierdoor wil ik de verschillen meten tussen een situatie waarbij de sensoren niets detecteren, en natuurlijk waarbij ze wel wat detecteren. Hierdoor maakt de omgeving niet uit, omdat je toch telkens naar het verschil kijkt.

Uiteindelijk wil ik alles via een com poort naar een pc sturen, en dit uitlezen met java. Dit heeft verder geen invloed op het principe.

Omdat het multi-touch is, moet hij dus in een snel tempo alle sensoren kunnen uitlezen/detectie waarnemen. Ik hoop dat de situatie nu duidelijk is.


Bedankt voor de snelle reacties tot nu toe!

Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Ik denk persoonlijk dat die processor snel genoeg is om gewoon 1 voor 1 die sensoren uit te lezen. Dat kan je gewoon berekenen natuurlijk, er zijn specificaties hoelang een instructie duurt. In de praktijk zal je deze vertraging zo goed als niet merken.

Acties:
  • 0 Henk 'm!

  • gibraltar
  • Registratie: Augustus 2004
  • Laatst online: 17:59
Misschien is het handig als je eerst bepaald wat wél en wat niet een "event" is. Je bent op zoek naar iets als: x aantal verandering in y tijd. Die verandering in waarde kun je prima bepalen door de waarde te vergelijken met de vorige waarde. Die verandering in tijd kun je prima regelen met een timer, die je een interrupt kunt laten afvuren op vaste tijdstippen (eigenlijk een vaste frequentie).

Die waarden kun je denk ik het beste gewoon even in de praktijk meten met een enkele sensor. Daarna is het gewoon een beetje trial-and-error. Ik zou het ongeveer zo doen:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int sensor_values[9];
int sensor_states;
int sensor_read_flag;

ISR(TIMER0_OVF_vect)
{
  sensor_read_flag = 1;
}

int main(void)
{
  while(1) {
    if(sensor_read_flag) {
      /* lees sensoren uit met adc */
      /* vergelijk sensoren en zet sensor_states bitjes */
      /* stuur nieuwe status over indien anders dan vorige */
      /* sla sensor waarden op */
      sensor_read_flag = 0;
    }
  }
}


Code in je Interrupt Service Routine (ISR) dien je zo klein mogelijk te houden. Het uitlezen van ADC zal wel een aantal cycles in beslag nemen. Je kan het beste alleen veranderingen over de seriële lijn sturen, dus alleen als je daadwerkelijk een verandering waarneemt. Succes!

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

@CIStem: ipv die code kun je net zo goed in de loop de timer registers direct uitlezen. Zo heeft de ISR natuurlijk weinig nut ;)
QuuN.. schreef op vrijdag 13 augustus 2010 @ 08:18:
Uiteindelijk wil ik alles via een com poort naar een pc sturen, en dit uitlezen met java. Dit heeft verder geen invloed op het principe.

Omdat het multi-touch is, moet hij dus in een snel tempo alle sensoren kunnen uitlezen/detectie waarnemen. Ik hoop dat de situatie nu duidelijk is.
De beperkende factor is nu de COM poort geworden. Al lees je alles op lichtsnelheid in, de COM-poort zal waarschijnlijk altijd trager zijn.
Je hoeft alleen maar snel genoeg te zijn om de menselijke vinger te kunnen detecteren, dit zal geen probleem zijn.

[ Voor 7% gewijzigd door EddoH op 13-08-2010 10:26 ]

Pagina: 1