Spørsmål:
Ta utdata fra ekstern enhet ved hjelp av Arduino Uno
djthoms
2014-12-23 04:45:12 UTC
view on stackexchange narkive permalink

Jeg kunne ikke finne dette spørsmålet hvor som helst, men jeg vil bruke Arduino Uno til å fange utdataene fra et kode 39-signal som kommer ut av en separat enhet. For øyeblikket ligner oppsettet mitt på dette:

enter image description here

Jeg har en biometrisk håndleser som sender ut et kode 39-signal langs D1 mens D0 forblir med en konstant 0 som kan sees her:

enter image description here

Til slutt vil jeg bruke Arduino Uno til å ta inngangen fra datalinjen og konvertere Code 39-signalet til ASCII. Prosessen skal fungere slik:

  1. Brukeren legger inn koden sin i håndleseren og håndleseren måler hånden
  2. Leser utganger Kode 39-signal til Arduino og programvare på Arduino konverterer strekkodeformat til ASCII.
    • Merk: Jeg tror Code 39-signalet vil representere noe som ligner på denne * 12345 * . Bruker-ID-koden vil alltid være fem sifre. * representerer start- og stopptegnene for Code 39-strekkodeformat
  3. Arduino sender ASCII-kode til datamaskinen som sjekker ekstern database for å sikre at brukeren er gyldig

Jeg har mine riktige pinner satt som følger:

  #include <SoftwareSerial.h> # define D1 3 # define D0 2void setup () {pinMode (D1, INNGANG); pinMode (D0, INPUT);}  

Er det mulig å enten skrive ut den binære representasjonen av signalet via seriekonsollen eller skrive til en fil som jeg kan se senere? Tanken min er å bruke funksjonen loop til å lytte etter signalene via digitalRead()

  void loop () {digitalRead (D1) ; digitalRead (D0);}  

Den siste delen er det jeg har et problem med, siden jeg ikke ser ut til å få informasjonen skrevet ut på seriekonsollen eller skrevet til en fil . Jeg prøvde dette, men det fungerte ikke:

  void loop () {foo ();} void foo () {digitalRead (D1) == HIGH? Serial.print ("0"): Serial.print ("1"); Serial.println ("");
digitalRead (D0) == HØY? Serial.print ("0"): Serial.print ("1");}  

Noen ideer om hvordan du kan få dette til, eller er det umulig? Jeg vil se utdataene fra enheten slik at jeg kan bekrefte at den sender ut det jeg tror det er.

Til slutt bruker jeg Visual Studio med Visual Micro-pluginet, slik at jeg kan prøve å feilsøke koden min. Jeg har også en OS X-maskin som har Arduino IDE installert på den hvis jeg trenger en Mac for noe.

Tillegg: Jeg har ikke klar tilgang til et oscilloskop. Imidlertid har jeg testet denne enheten på et oscilloskop, og jeg hadde utgang som virket helt feil. Jeg vil se hva arduinoen sier det er å verifisere ting før jeg fortsetter med dette prosjektet.

Dette kommer til å være ekstraordinært vanskelig med mindre du har litt mer informasjon om den andre enheten.
Lagt til oppdateringer! Jeg forklarer hvordan alt skal fungere og inkluderte typen enheter jeg bruker. Gi meg beskjed hvis noe trenger avklaring!
Se om du kan finne eksisterende kode for å koble til en mag stripe-leser - selv om problemet ditt er enklere da de simulerte sveipene sannsynligvis har en jevn hastighet. Du kan også se på motta halvparten av programvarens serielle implementering for ideer, selv om signaliseringen du prøver å motta er forskjellig.
@ChrisStratton Jeg er enig. Jeg prøvde å lete etter konverteringer for kode 39 spesielt, men jeg fant klasser som inkluderte mange andre strekkodeformater. Konverteringen fra kode 39 til ASCII er ganske rett frem - 12 bits kan representere A-Z0-9% * \ - +. Takk for at du pekte meg i riktig retning!
Jeg fylte ut noen forklaringer på problemene dine i begynnelsen av svaret mitt. Hvis dette ikke fungerer for deg, kan vi finne bedre løsninger, f.eks. ved hjelp av en buffer.
En svar:
Ariser - reinstate Monica
2014-12-26 22:00:19 UTC
view on stackexchange narkive permalink

La oss først finne ut hva som er galt med metoden din. Du prøver å avstemme signalpinnene kontinuerlig og skrive dem ut til serie. Standard seriehastighet er 9600. Hvilket betyr at du kan sende ca. 900 tegn per sekund. Når vi ser på oscillogrammet ditt, kan vi fortelle at signalet du vil analysere har en baseklokke på omtrent 2,5 kHz. Hvilket betyr at du definitivt ikke vil kunne prøve alle nivåendringer med metoden din.

Du kan faktisk bruke loop () -funksjonen til å lytte etter endringer, dvs. polle signalet, når du øker den serielle baudhastigheten. Men jeg foreslår at du bruker avbrudd.

Mitt forslag er en tretrinnsprosess.

  1. få signalet grundig registrert med all relevant informasjon om signalet. Dette inkluderer overføring til PCen din via serielt grensesnitt.
  2. Analyser signalet offline. dvs. etter å ha mottatt den på PCen din
  3. Tilpass arduino-koden din for å dekode den videre før du overfører den til PCen

la oss komme til del 1): les Arduino-dokumentasjon om avbrudd avbruddet lar deg forhindre forstyrrelse av de to oppgavene dine (lese inngangene og skrive til seriell) .Hva er den interessante informasjonen? Jeg tror det er bølgeformen (dvs. signalet i beste oppløsning du kan levere). Du kan prøve bølgeformen din med høy hastighet, men det resulterende datavolumet vil overvelde seriell utgang. Heldigvis har signalet ditt noen åpenbare egenskaper. Hvilke er:

  • følger noen timing (dvs. en klokke)
  • har en begrenset overføringslengde (protokollramme)
  • har en begrenset overføringshastighet ( som kan sees fra oscillograf)

Den beste måten å beholde så mye av signalinformasjonen ved å redusere mengden seriell overføring er å registrere tiden for hvert nivåendring.

Oppdateringer: buffer brukt, bufret utgang etter mottak av tidsavbrudd

  #define RECVTIMEOUT 2000 // vi tror mer enn 2000 usec er slutt på overføring
#define MAXEVENTS 100 uint8_t inpin = 2; volatile usignert lang tidsstart = 0; uint8_t transmitLevel = LOW; volatile uint8_t state = 0; // liten tilstandsmaskin: 0 = ingenting skjedde ennå, 1 = motta data, 2 = motta timeoutvolatile uint16_t tstamps [MAXEVENTS]; // vi lagrer tidsstempler for mottatte symboler herflyktige uint16_t nivåer [MAXEVENTS]; // vi lagrer nivåer av mottatte symboler herflyktig uint8_t indeks = 0; // vi lagrer dataindeks her. uint8_t count = 0; // teller for senere bruk. flyktig bool-konflikt = falsk; // vil bli satt, hvis overføring er i konflikt med mottaksfunksjonen. unngå pinchange () // ISR (avbryte tjenestes rutine) {switch (state) {case 0: timestart = micros (); t-stempler [indeks] = 0; nivåer [indeks] = digitalRead (inpin); tilstand = 1; ++ indeks; gå i stykker; tilfelle 1: t-stempler [indeks] = mikro () - tidsstart; nivåer [indeks] = digitalRead (inpin); ++ indeks; gå i stykker; tilfelle 2: konflikt = sant; }} ugyldig oppsett () {Serial.begin (115200); // høy seriell rate. ikke glem å sette det samme i IDE attachInterrupt (0, &pinchange, CHANGE); // kontrolleren trenger å vite, hvor ISR-en din er.} ugyldig loop () {switch (state) {case 1: if (index > 20) {if (micros () - timestart > RECVTIMEOUT) {state = 2; }} hvis (indeks > = MAXEVENTS) {state = 2; }    gå i stykker; tilfelle 2: for (count = 0; count<index; ++ count) {Serial.print (tstamps [count]); Serial.print (";"); Serial.println (nivåer [count]); } hvis (konflikt) {Serial.println ("for kortere tid til å sende data"); } indeks = 0; konflikt = 0; tilstand = 0; }}  

Dette skal gi en fin csv med alle signalkantene dine i mikrosekunder, som du kan lime direkte inn i favoritt regnearkprogrammet. Dette er bare for ett signal. For å analysere begge deler, må du forbedre det tilsvarende.

Oppdater 1

del 2)

fra innhentede data fra vår forrige kodeversjon (kodebit for kortfattethet)

  tidssignal tidsforskjell2614592 0 4682615056 1 4642615524 0 4682616496 0 9722616960 1 4642617956 0 9962618960 1 10042620424 1 14642621352 1 9282622324 1 9722623320 0 996  
/ p>
  1. Koden i den første versjonen av svaret fungerte ikke ordentlig. Hver 1 skal følges av et 0 i kolonne 2 og omvendt. Dette stemmer tilsynelatende ikke, noe som fører oss til den konklusjonen at vi savnet noen hendelser.
  2. tidsforskjeller ser ut til å være multipler på omtrent 470 μs. Vi kan betrakte dette som lengden på et symbol.

Så hva er galt med koden? Jeg brukte noInterrupts () for å stoppe Interrupts for å kopiere dataene. Jeg håpet det vil ikke være nivåendringer i løpet av denne korte tidsperioden, men tilsynelatende var dette ikke sant. Hvordan fikser jeg det? Vi må bedre finne en annen måte å registrere begivenhetene og overføre dem. Jeg anbefaler å holde deg til avbruddsteknikken, men endre måten vi lagrer hendelsene på og leser den opp. La oss bruke en buffer som er stor nok til alle hendelser i en overføring. Etter en overføring kan vi sende all data uten problemer via seriell til PCen.

Hva kan vi forvente? 0 og 1 bør sendes vekselvis, med rimelig tid. Hvis vi kan bevise dette, kan vi endre hovedsløyfen igjen for dekoding av kode 39.

del 3)

  • skriv kode som lagrer et ord av kode 39 i en buffer
  • en annen kode som dekoder ordet til en byte når bufferen er full
  • overfører den byten via seriell

(mange forbedringer mulig).

Hei Ariser, noen få ting jeg ser: 1. Jeg satte overføringshastigheten og justerte den i den serielle skjermen, men jeg ser bare omtrent 57 endringer når jeg skal se, minst 60 endringer. Noen anelse om hvorfor det kan være tilfelle? Igjen er formatet kode 3 av 9. Utdataene skal være en brukers femsifrede brukerkode med start- og stopptegn. Slik: '* 12345 * `P.s. beklager det tok meg for alltid å svare! Jeg hadde ferie, og nå er jeg endelig tilbake på jobb
Humm, jeg fryktet det. Jeg trodde, anledningen til å motta en pin-endring mens du blokkerte avbrudd var veldig sjelden, men jeg har vist meg feil. Klarte du å trekke ut klokken fra de mottatte dataene? Jeg oppdaterer svaret mitt, men det tar litt tid å brygge noe brukbart.
Jeg vet ikke hva du mener med "trekk ut klokken fra mottatte data"
Hvis du får tidsinformasjonen via seriell skjerm, kan du beregne klokkefrekvensen, fordi tiden mellom to tilstøtende nivåendringer må være enten en eller to klokkesykluser. Når du har lengden på en klokkesyklus, er det lettere å bygge litt kode for å dekode dataene på arduinoen i stedet for å overføre hver bit til PCen.
Vel, jeg kopierte koden du hadde og brukte den. Jeg fikk utdata, men jeg kan ikke forstå det. Jeg vet at enheten som sender signalet overføres til 9600 baud. Her er disse dataene: [Trial 1] (http://pastebin.com/bWcdtrVb) og [Trial 2] (http://pastebin.com/YRSrj6k6). Jeg setter pris på all hjelpen din!
Ok, jeg kan forstå det. Jeg skriver for øyeblikket litt mer inn i svaret. Et annet spørsmål: Overføring av bruker-ID utløses direkte av din handling (godkjenning), ikke sant?
Ja. Bruker skriver inn koden og skanner hånden. Håndskanneren bekrefter bare brukerens hånddimensjoner kun for interne formål.
La oss [fortsette denne diskusjonen i chat] (http://chat.stackexchange.com/rooms/19836/discussion-between-ariser-and-djthoms).


Denne spørsmålet ble automatisk oversatt fra engelsk.Det opprinnelige innholdet er tilgjengelig på stackexchange, som vi takker for cc by-sa 3.0-lisensen den distribueres under.
Loading...