Pages: 1 [2]   Go Down
Author Topic: Wireless doorbell  (Read 3357 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Could it be that the two radio devices aren't on quite the right frequency/channel or using different encoding? It's pure speculation, but perhaps the radio link would be able to work despite the mismatch if the signal was extremely strong, but not when it is at normal levels.

Okey, and where/what would you modify to get it straight?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've spend the last week figuring out what was wrong with my approch.

I've ruled out some other hardware aspects like voltage, batteries, reciever used. (I've tried several RX868 recievers).

I've also tested the wireless doorbell, the FS20 TK my a FS20 hardware power switch. And it works, even 3 floors away. So it's not the FS20 TK.

And I've started to study, and break down the code to the bare minimum that I need. (I'm only gonna use FS20) Also I've added some comments, I'm not a native 'C' speaker, I speak assembler and basic, so it took me some time to figure out some of the syntax.

And this is the resulting code;

Code:
// The basic idea is to measure pulse widths between 0/1 and 1/0 transitions,
// and to keep track of pulse width sequences in a state machine.
// can't just change these pin definitions, PIN_868 uses interrupts
#define PIN_868 14  // the 868 MHz receiver is connected to AIO1

enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };

// track bit-by-bit reception using multiple independent state machines
struct { char bits; byte state; uint32_t prev; uint64_t data; } FS20;

static byte FS20_bit (char value) {
    FS20.data = (FS20.data << 1) | value;  // shift left one, and AND with value
    if (FS20.bits < 0 && (byte) FS20.data != 0x01)
        return OK;
    if (++FS20.bits == 45 && ((FS20.data >> 15) & 1) == 0 ||
          FS20.bits == 54 && ((FS20.data >> 24) & 1))
        return DONE;
    return OK;
}

    byte zerosfound;
    
static void ook868interrupt () {
  // the ook interrupt occours on a FS20 protocol split, so on 300usec for a 0, and on 500ms for a 1
    // count is the pulse length in units of 4 usecs
    byte count = TCNT2;
    TCNT2 = 0; // reset the timer to 0
    // FS20 pulse widths are 400 and 600 usec (split on 300, 500, and 700)
    // see http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol
    if (FS20.state != DONE) {
        switch ((count - 25) / 50) {  
          // count values from 75 to 124 are considered a '0'
          // count values 125 to 174 are considered a '1'
            case 1:  FS20.state = FS20.state == T0 ? FS20_bit(0) : T0; break;
            case 2:  FS20.state = FS20.state == T1 ? FS20_bit(1) : T1; break;
            default: FS20.state = UNKNOWN;
      
          }
    }
}

static void reset_FS20 () {
    FS20.bits = -1;
    FS20.data = 0xFF;
    FS20.state = UNKNOWN;
}

static void ook868timeout () {
    if (FS20.state != DONE) {
        reset_FS20();
        //Serial.print(TCNT1);
        //Serial.println();
    }
}

static void ook868setup () {
    pinMode(PIN_868, INPUT);
    digitalWrite(PIN_868, 1); // pull-up
    
  
    // enable pin change interrupts on PC0
    PCMSK1 = bit(0);
    PCICR |= bit(PCIE1);

    /* prescaler 64 -> 250 KHz = 4 usec/count, max 1.024 msec (16 MHz clock) */
    // prescaler 32 -> 500 KHz = 2 usec/count
    TCNT2 = 0;
    TCCR2A = 0;
    TCCR2B = _BV(CS22);
    //TCCR2B = _BV(CS21) | _BV(CS20);
    TIMSK2 = _BV(TOIE2);  // set the 6th bit to true, enabling overflow interrupt
    
    reset_FS20();
}

// Poll and return a count > 0 when a valid packet has been received:
//  4 = S300
//  5 = FS20
//  6 = FS20 extended
//  7 = KS300
//  9 = EM10*

static byte ook868poll (byte* buf) {
    if (FS20.state == DONE) {  
        uint32_t since = millis() - FS20.prev;
      if (since > 150) {
        byte len = FS20.bits / 9;
        byte sum = 6;
        for (byte i = 0; i < len; ++i) {
            byte b = FS20.data >> (1 + 9 * i);
            buf[len-i-1] = b;
            if (i > 0)
                sum += b;
        }
        if (sum == buf[len-1]) {

            FS20.prev = millis();
            reset_FS20();
            return len;
        }
      }
      reset_FS20();
    }
      
    return 0;
}

ISR(TIMER2_OVF_vect)    { ook868timeout(); }
ISR(PCINT1_vect)        { ook868interrupt(); }

void setup () {
    Serial.begin(115200);
    Serial.println("FS20 Test\n");
    ook868setup();
}

void loop () {
    byte buf[10];
    byte len = ook868poll(buf);
    if (len != 0) {

        Serial.print("Time: ");
        Serial.println(millis() / 1000);
        
        Serial.print("FS20:");
        for (byte i = 0; i < len; ++i) {
            Serial.print(' ');
            Serial.print(buf[i], DEC);
        }
        Serial.println();

    }

}

Using this code the symtons are still what they where in the beginning; only when I hold the FS20 TK in less than 20 centimeter of the reciever, I get valid FS20 packages. Which really amazes me, because the type of FS20 reciever I use should be an extra sensitive one (RX868-SH-C3, chip; http://www.alldatasheet.com/view.jsp?Searchword=TH71111.2)

I've also expiremented with removing the check sum from the code, and I then do recieve packages over longer distance, but they are all crippled. Wrong house code, wrong checksum, wrong command.

So at this point I'm really amazed about this code ever working for anyone. Because to me it looks to fuzzy and to incedental, counting the time to determine the code...
« Last Edit: November 17, 2012, 03:50:14 pm by Lectere » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48569
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I can't find anything wrong with the code.
Really? You mean it works with all those smiley faces?
Logged

Pages: 1 [2]   Go Up
Jump to: