[Intro]: So I would like to build an APRS demodulator/decoder it is an Audio FSK signal. I have the basic idea of what I need to do, and right now I am focusing on the detection of the mark and space [1, 0] respectively, essentially working on this project in "blocks".
[Requirements]: I need to capture the frequency either 1200/2200Hz signals and report them as either 1, or 0. At 1200baud the signal will need to be read every 0.83 milliseconds. The signal coming in will be a sine wave of variable amplitude so it is my understanding that I cannot use an interrupt to signal the high/low transition of a pin especially since the signal will be centered at 2.5v to prevent the signal from going negative.
[Code Explanation & Issues]: I wrote a small bit of code which uses the ADC to trigger on zero crossings and uses the millis() function to time the interval. This works alright at frequencies <100Hz, but tends to lock on random frequencies as well and is only accurate +/- 3 Hz at low frequencies. This accuracy would be fine if we were only comparing 1200/2200Hz but it will not count that high. I searched through some frequency measurement code like FreqCount, and a few other ARPS TNC/demodulation but do not understand how to properly "read" their code and understand it.
int millisValues[3];
int increment = 0;
int i = 0;
int wait = 0;
int values = 0;
float freq = 0;
void setup() {
pinMode(A0, INPUT);
Serial.begin(9600);
}
void loop() {
values = analogRead(A0);
// Serial.println(values);
if (values < 512 && wait == 0){ //Check for zero crossing, wait if we passed it.
millisValues[i] = millis();
i++;
wait = 1;
// Serial.println(i);
}
if (values >= 512){
wait = 0;
}
if (i == 2){
i = 0;
float freq = (millisValues[1] - millisValues[0]); //determine time between zero crossings
Serial.print("Frequency is ");
Serial.print(1/freq*1000); //conversion to frequency
Serial.println(" Hz");
delay(50); //added for readability. Would not need this in final code
}
}
[Request]: I hope to find some suggestions on how to approach this project, and find a general intuition on how to solve these problems with my level of understanding of programming. My idea is that if I change the frequency divider of which the Arduino samples at that I could improve the accuracy of the timing since it will measure faster. This is the only idea I have at this point so any feedback would be appreciated. As I mentioned earlier I am focusing only on the conversion of the 1200/2200Hz signal into the binary equivalent.
Can you show a screen capture of the signal. How many 1200 Hz pulses are there ? sometimes just one ?
The Arduino can measure a pulse length, either with a Arduino function ( https://www.arduino.cc/en/Reference/PulseIn ) or with a hardware timer.
What about the duty cycle ? and how does it change from 1200 Hz to 2200Hz ?
[Requirements]: I need to capture the frequency either 1200/2200Hz signals and report them as either 1, or 0. At 1200baud the signal will need to be read every 0.83 milliseconds. The signal coming in will be a sine wave of variable amplitude so it is my understanding that I cannot use an interrupt to signal the high/low transition of a pin especially since the signal will be centered at 2.5v to prevent the signal from going negative.
I believe the analog comparator will suit your needs. It has an interrupt and an output that can trigger a timer/counter. Check it out in section 22 of the datasheet if you're using the ATmega328P.
Most APRS stations use the modulation scheme known as Bell 202 1200 baud AFSK. There is plenty of code around to demodulate AFSK signals, for example here is one written in C and then in assembly language for an ATtiny10.
Basically, the algorithm is a 2 point Fourier transform.
I guess Google was hating me today. I fished around for 20 minutes and gave up, had to leave anyway. I found references to the Bell 202 spec, but I was curious about the details. Never found them. I guess it's all dinosaur stuff now anyway.
Here is an arduino library Arduino APRS Library | unsigned.io for AFSK demodulation ( BELL 202). There are also designs for his ATMEGA328P based "micromodem" for APRS stuff. You can even buy a ready made modem there.
I have an open question with him about using his AFSK demodulator for telephone caller ID processing.
Analog FSK demodulator chips are getting quite rare now.