Freq drift vs Temp calibration - Eureka, we've struck gold

Started by john k2ox, September 26, 2013, 11:43:54 PM

john k2ox

It works!

In the plots below are are two traces one at -20C and another at +20C.  One plot with Moteino in standard form and the other with temperature compensation active.

The temp compensation routine holds it to a 100 Hz!!!!!      This just blows me away.   I can't wait to do the next drive test.

Three miles?

Felix

That's great news!  8)

A few thoughts ...

- Do you think moving away from center frequencies (hardcoded to 434, 868, 915) should also help?
- Any hope to share the code or modded lib used to achieve this?
- I would tend to think RFM12B radios suffer from the same freq shift problem since they are the same manufacturer, probly same cheap xtals. If so, and if those could also be tweaked, maybe they could go beyond the 150m of range they typically yield.

john k2ox

 Crystals are sold by grade they 100ppm, 50ppm 10ppm, etc.  What that means is at 1 MHz  the drift will be 100Hz, 50Hz and 10Hz respectively.  So lets take the 100ppm at 1 MHz the spec is worse case it will drift +/- 100Hz when measured at 1 Mhz.  Since we are using it at 915 MHz we have to multiply all the numbers by 915.
+/- 91.5KHz !!!  Wow, so as it turns out the crystal in the rfm is pretty darn good.  Much to my surprise.

That also means the 434M radio will have half the drift of one at 915.

Yes, the 12B can use the same technique.   BTW you asked once about compatabilty of the 12s with the 69s.  I looked into it and they should be able to talk to each other.  The only reason they might not is because the way the CRC is calculated might be different.  I tried a dozen different cals with the 69 and never got the same result as the 69.  I need to contact Semtech to find out whats up.

One final note.  If they change crystal manufacturer the polynomial coefficents may need to be adjusted.  With a better setup i.e. a real temperature chamber better measurements would yield even better results. <10Hz.


Here's the code:

    #define FREQ 915000000ul

    int x = radio.readTemp(0);   //takes 172uS 
    radio.setFreq(FREQ - (int)(0.0572*(x*x*x) - 3.8416*(x*x) - 104.73*x + 3400.2));



Pretty sweet huh?   The whole thing takes abt 328 uS.

    int temp = radio.readTemp(0);   //takes 170uS 
    int fCor = radio.tcfo(temp);    //tot t = 236uS
    radio.setFreq(FREQ + state.nvFCOR + fCor); //tot t = 328uS


john

Felix

Thanks for all your efforts. Excellent stuff, so perhaps the xtals are bad after all huh... looking forward to see what range you get now. A post on building an antenna that's better than the wire would be great, I have some people asking for that.

As far as 12b->69 compatibility, I would tend to think they should be able to talk as well. I spent some time when I developed the lib trying to get them to talk but no success, it was mere trial and error without tools such as your 30K analyzer. Also didn't have a deep understanding of all the parameters and settings so I could easily have missed the obvious. So I let that part an open ended quest for someone to try out. Maybe you would have more success at this.

Unfortunately the xtal source could change without it being obvious...

Is tcfo(...) in your example a new function you added to your RFM69NEW?
I'd like to eventually merge all these in the main code...

john k2ox


    int temp = radio.readTemp(0);   //takes 170uS
    int fCor = radio.tcfo(temp);    //tot t = 236uS
    radio.setFreq(FREQ + state.nvFCOR + fCor); //tot t = 328uS
--------------------

int RFM69NEW::tcfo(int x)
{
int fCorrection = -(int)(0.0572*(x*x*x) - 3.8416*(x*x) - 104.73*x + 3400.2);
return fCorrection;
}


'state.nvFCOR'  is the value needed to put the radio on freq at 22C.  Then 'tcfo(int x)' keeps it there as the temp
changes.

I've set the val of 'state.nvFCOR'  using instrumentation for now.  I did explain in another post how two Motes can be used to do it.  No code for that yet.

john k2ox

I've run into a problem.  I have two radios, one I'll refer to as sender and the other rcvr.

Sender uses your send command and every 1 second it sends its temp.  This works fine.

Rcvr uses the same 'readTemp(0)' command as Sender.  It is placed inside  ' if (radio.receiveDone()){}'.

Unfortunately the temperature it returns varies about 4 degrees.  I used another sketch that just reads the temp of this radio (no RX) and it is stable.  So, the good news is the radios are repeatable.

I think there is a prob with collisions on the SPI bus.  I had thought doing a temp read immediately after receiveDone returns true that I'd be OK with a less than 400uS read.  The next tx/read is 999.6mS away.

Any thoughts?

Felix

I've played a little with the temp function some time ago and I would get a stall sometimes and occasionally a freeze on the while inside it...

john k2ox

I've never run into any freezes.   I was thinking maybe my funtion call was interfearing with some other bus activity.  That can't be possible ther is no multi tasking.  One thing happens then the next.

If I add a delay(35) just befor readTemp it's OK (in rx).  BTW my bit rate is very slow 500bps.  100 bits at 500 takes 200mS. 

Hmmmmmmmm.

pavlos

Fascinating.

Great job John and Felix.

John did you get a chance to experiment with simple OOK modulation at these slow rates? If CRC/auto ACK is disabled do you have any data on observed error rates at distances out to 5km or more? I wish I had the time to experiment and answer some of these questions myself but this is currently not possible. In the meantime I am enjoying this by proxy!






john k2ox

No I haven't.  I don't feel OOK is as good as FSK so I haven't spent much time with it. 

May I ask what is your interest in OOK?

Thanks,
john

Felix

I think some commercial devices like of the shelf remote controlled outlets operate with OOK. I didn't have an interest in that so I haven't spent time exploring the OOK capabilities. The RFM12B library that was build upon the work from Jeelib has an OOK capability I think.

pavlos

Thank you both for the feedback.

I am interested in low rate, low power but long range RF communication. One of the important components in achieving long range is a good error correcting code and the known good ones generally do better with 'soft' symbols (an estimate as to how probable the transmitted symbol was an 1 vs 0 given the received signal) instead of the usual 1/0 hard decision. Some RF modules do provide an option to return soft symbols but  it all seems quite hard to program/setup. I am hoping that by running the receiver in OOK mode at a higher bps rate than the transmitter we may get such estimates in a simple way. For instance by running the receiver at 4x the transmission rate we may receive for a strong 1 -> '1111' and for a weak 1 something like '1011' or even '1001'. Not sure what the impact would be on the sync word etc and it may all be impossible in the end.

In any case it is not important at all at this stage, I just thought to ask in case anyone of you had done such experiments.

Your experiments are extremely interesting to me and I will be following closely. Good luck all! 

Felix

Maybe not really related but i know there's data whitening and manchester encoding which ensures the message is more probable to transmit over the RF medium (no long 0 or 1 gaps in the message). Otherwise my knowledge about OOK is limited.