Sida 1 av 1
Avkoda Nexa med enklast möjliga kod/Problem med RF-mottagare
Postat: 31 oktober 2012, 16:30:46
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?
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 16:50:32
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.
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 17:05:40
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
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 17:13:16
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.
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 17:29:25
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.
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 21:46:06
av PHermansson
Wedge: Har du lust att dela med dig av koden?

Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 22:48:33
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
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 31 oktober 2012, 22:50:28
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.
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 1 november 2012, 16:55:57
av Wedge
PHermansson skrev:Wedge: Har du lust att dela med dig av koden?

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...
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 1 november 2012, 19:34:25
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.
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 1 november 2012, 21:06:45
av DeeJayPA2
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 2 november 2012, 08:07:13
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
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 2 november 2012, 08:33:28
av Kaggen
Har du läst och följt instruktionerna vart du skall lägga alla filer / bibliotek t.ex. RemoteSwitch mappen?
Re: Avkoda Nexa med enklast möjliga kod/Problem med RF-motta
Postat: 18 december 2012, 19:56:31
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.