Avkoda Nexa med enklast möjliga kod/Problem med RF-mottagare

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
PHermansson
EF Sponsor
Inlägg: 4340
Blev medlem: 22 december 2004, 00:46:38
Ort: Särestad Grästorp
Kontakt:

Avkoda Nexa med enklast möjliga kod/Problem med RF-mottagare

Inlägg av PHermansson »

Jag har misslyckats med alla kodexempel jag hittat på nätet för att avkoda Nexa, HomeEasy och liknande med en Arduino. När jag försöker förstå hur koden fungerar (tex den på http://www.arduino.cc/playground/Code/HomeEasy) så blir jag snart förvirrad :)

Så jag försöker göra ett program som är så enkelt som möjligt. Programmet kör en loop och använder PulseIn-funktionen (http://www.arduino.cc/en/Reference/PulseIn) för att mäta hur länge ingången är hög (i mikrosekunder). Är ingången hög mellan 400 till 480 uS är det en godkänd puls. Samma sak om den är mellan 1349 och 1450 uS. Dessa värden har jag testat fram. Varje godkänd puls stegar upp en räknare, kommer det en puls utanför dessa gränser nollas räknaren, värdet på pulslängden och hur många pulser som godkänts innan skrivs ut på serieporten.
Med dessa intervall återstår bara problemet att pulseIn ibland rapporterar en tid på 0 mS. Filtreras dessa bort går det att få fram en sekvens av 25 godkända pulser. Men det mesta är nollor, inget som kan avkodas.
Jag får mycket störningar på rf-mottagaren, antar att det är här problemet finns. För hur ska mitt program veta var en sändning startar när det konstant kommer pulser som matchar den korta pulsen?
Användarvisningsbild
Icecap
Inlägg: 26638
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Icecap »

Konstigt - inte! Nu har jag ingen information om hur pulserna ser ut men just användandet av pulsein() är riklig anledning till att det inte fungerar!

Denna uppgift lösas med interrupt och en Capture-enhet, därifrån är resten skapligt enkelt.
Användarvisningsbild
PHermansson
EF Sponsor
Inlägg: 4340
Blev medlem: 22 december 2004, 00:46:38
Ort: Särestad Grästorp
Kontakt:

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av PHermansson »

Varför skulle det inte kunna fungera med pulsein? Man väntar på att ingången går hög, och mäter sedan hur länge den är hög.
"Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds. Gives up and returns 0 if no pulse starts within a specified time out."

Pulsein används i en av exempelkoderna på Arduino playground.
http://arduino.cc/playground/Code/HomeE ... lock&num=3
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Wedge »

Jag vet inte om jag krånglat till det, men jag satte upp ett timerinterrupt och samplade insignalen. Ofta. Tror det låg nånstans på 40 us. Och så en kodsnutt som filtrerade insignalen. Minst tre samples i rad höga innan data registrerades som hög och ettan gick vidare, och likadant med nollorna. Ett slags mjukvaruschmitt-trigger. På inpinnen filtrerade jag även med ett enkelt RC-filter först för att få bort skräp ur signalen.
Sen var det inga större problem att skilja databitar från start- och stoppmönstren. Innan startbiten (hög följt av ganska lång låg) struntar jag helt i vad som händer. Därefter tickar en statemaskin vidare.
Användarvisningsbild
Icecap
Inlägg: 26638
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Icecap »

Att det inte fungerar beror på att man inte kan göra värst mycket annat än att vänta på pulsein(), gör man något annat kan det blockera för start i tid. Med en ISR och en state-mashine blir det strax ganska annat. Om man sedan använder Capture eller timer är av mindre betydelse, det viktiga är att man har en pålitlig tidsupplösning vilket man per definition inte har med pulsein().

Detta är ytterligare ett exempel på att dessa färdiga funktioner förleder till snabba och enkla lösningar - som tyvärr bara fungerar ibland.
Användarvisningsbild
PHermansson
EF Sponsor
Inlägg: 4340
Blev medlem: 22 december 2004, 00:46:38
Ort: Särestad Grästorp
Kontakt:

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av PHermansson »

Wedge: Har du lust att dela med dig av koden? :wink:
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Swech »

Vad har du för mottagare?
en färdig mottagar ic?

Du behöver köra med timers och capture som Icecap påpekar

Swech
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Kaggen »

PHermansson skrev:... Gives up and returns 0 if no pulse starts within a specified time out."
Har du inte svaret på din fråga varför den returnerar noll i texten ovan som du citerade?

Du kan ju ändra tiden på timeouten vad jag förstår. default är ju 1 sekund.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Wedge »

PHermansson skrev:Wedge: Har du lust att dela med dig av koden? :wink:
Nån gång ska jag stuva om och separera decoderbiten från allt annat i projektet jag har den i. Men just nu... njae...
Användarvisningsbild
PHermansson
EF Sponsor
Inlägg: 4340
Blev medlem: 22 december 2004, 00:46:38
Ort: Särestad Grästorp
Kontakt:

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av PHermansson »

Jag använder två uppsättningar att testa med. Dels en Arduino Duemilanove med en okänd RF-mottagare. Denna uppsättning har jag inte fått att fungera med Adlers Esic-kod, den för att läsa av trådlösa temperatursändare. Sen använder jag en hembyggd klon med Atmega168 och en mottagare det står "CDR03A" på, tror jag köpt den från Sparkfun eller Seeed Studio. Denna uppsättning fungerar med Esic-koden så troligen är det en bättre konstruktion.

Jag har fortsatt idag med att modda en kod som ursprungligen användes för att avkoda RC-signaler till radiostyrda bilar och som använder interrupt vid ändring på Int0.
Har bara kört den med Duemilanoven och resultaten blir i alla fall bättre, men har inte testat med klonen än.
DeeJayPA2
Inlägg: 371
Blev medlem: 19 mars 2008, 19:20:25
Ort: Luleå

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av DeeJayPA2 »

Användarvisningsbild
PHermansson
EF Sponsor
Inlägg: 4340
Blev medlem: 22 december 2004, 00:46:38
Ort: Särestad Grästorp
Kontakt:

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av PHermansson »

Den lyckas jag inte kompilera, får skumma felmeddelanden:

Kod: Markera allt

Show_received_code.cpp.o: In function `loop':
Show_received_code.cpp:28: undefined reference to `RemoteReceiver::init(unsigned short, unsigned short, void (*)(unsigned long, unsigned int))'
collect2: error: ld returned 1 exit status
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av Kaggen »

Har du läst och följt instruktionerna vart du skall lägga alla filer / bibliotek t.ex. RemoteSwitch mappen?
Användarvisningsbild
PHermansson
EF Sponsor
Inlägg: 4340
Blev medlem: 22 december 2004, 00:46:38
Ort: Särestad Grästorp
Kontakt:

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta

Inlägg av PHermansson »

Nu efter _mycket_ om och men, forskande, funderande, knåpande och ett antal svordomar har jag fått till en kod som fungerar. Som så ofta annars vill jag ha en fungerande kod enligt KISS-principen att utgå från, och detta är nog as simple as it gets:

Kod: Markera allt

/* For decoding Nexa remotes, as simple as possible(?)

RF receiver connected to Arduino pin D2.

C Patrik Hermansson 20121218
GPL v2
*/ 
const byte LED = 13;

unsigned long timeOfLastPinChange=0;
long microsSinceLastChange,microsSinceLastChangeOld;
int startbit, c=0;
unsigned long message; 

void pinChange () {
  // Pin level has changed
  long currentTime = micros();
  microsSinceLastChange = (currentTime - timeOfLastPinChange);
  timeOfLastPinChange = currentTime;  
}

void setup()
{ 
  Serial.begin(9600);
  Serial.println("Start Nexa-decode");
  pinMode(LED, OUTPUT);
  attachInterrupt (0, pinChange, CHANGE);  // attach interrupt handler
}

void loop()
{
  if (microsSinceLastChangeOld != microsSinceLastChange) {   // Pin has changed since last time
    
    // Detect startbit
    if (microsSinceLastChange >=11100 && microsSinceLastChange <=11400 && startbit==0) 
    {
        startbit = 1;
        Serial.println("Startbit received ");
    }
    
    // Check for short and long pulses, add to message accordingly
    if (microsSinceLastChange < 700 && startbit==1) 
    {
      c++;
      message = message << 1;
    }
    else if (microsSinceLastChange > 700 && microsSinceLastChange < 1500 && startbit==1) 
    {
      c++;
      message = message << 1;
      message |= 1;
    } 
    
    // Save current time
    microsSinceLastChangeOld = microsSinceLastChange;
    
    // All pulses received, check if code is recognized and reset counters
    if (c>50 && startbit==1) {
       //Debug:
       //Serial.println(message);
       if (message==2863313713) {    // A1 on
           digitalWrite(LED, HIGH);
           Serial.println("A1 on");
       }
       else if (message==2863313705) { // A1 off
           digitalWrite(LED, LOW);
           Serial.println("A1 off");
       }   
       message=0;
       c=0;
       startbit=0;
    }
  }
}
Ni får gärna testa koden och se om den fungerar i fler uppsättningar. Här har jag använt en Arduino Duemilanove och en Rf-modul, tror den är från Sparkfun.
Skriv svar