My son recently returned from a holiday in China. His biggest complaint was the blocking of FaceBook!
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
BandpassCoefficientFinderNew.xlsxA better method using Newton's method to solve the biquad response equation.sheet - 17.74 kB - 02/12/2017 at 12:33 |
|
|
BandpassCoefficientFinder.xlsxA quick integer coefficient finder for biquad bandpass filterssheet - 70.86 kB - 02/12/2017 at 04:05 |
|
I have been on holidays and busy working on a couple of other projects.
Anyway I fired up the CNC and made three more wooden slices for the modem case.
Just one more wooden slice and the strip-board to go.
I have to have a look at the strip-board layout and how I am going to route the USB cable.
Also some code to communicate to the host computer and to set the modem as originate or answer.
The other problem is that I will need to make a second modem to talk to!
Here is the completed modem box (top view):
No iPhone:
Bottom view:
Disassembled:
So work remaining is to design the strip-board, the USB cable route and perhaps a varnish.
AlanX
I had some problems with the audio loopback so I had to drop back to a direct loopback.
Here is the signal from the first stage lowpass:
Not pretty but functional. Some noise is probably a good idea for testing and optimising.
Here is the demodulator output:
Basically identical results for Answer or Originate configuration. What is not shown here is the decoder jitter.
The jitter associated with the baud rate generator was the main problem. It was missing the timeout flag. Fixed. It now only misses the occasion interrupt tick from the sample clock.
The jitter associated with demodulator is likely to be jitter from the sine wave generator and/or from the phase transition. Suppressing the high frequency noise by adding an additional low pass had no effect:
The only real hint is that jitter is much worse (x4?) with the higher frequencies suggesting jitter is from the sine wave generator.
Turned off the binary signal (i.e. a single tone) and the jitter is clearly visible and in tune with the demodulator jitter. Here is the signal, even in this image you can see this signal moves around:
Before I found the baud rate generator problem I reduced the band pass filter Q to good effect. After minimising the remaining jitter I will have to rework the band pass filters to see if I can increase the Q as I think suppressing the opposite channel still has merit.
Tried a 62.5kHz Fast PWM, 32 bit maths and a 256 sine wave lookup table (and variations in between). The sine wave looks great but slowly oscillates. The demodulator hates it! After double checking I find the frequency is off which means the Arduino cannot keep up (even with just the sine wave generator running). Back to 31.37 kHz.
Now I was caught out in that I thought the Phase Correct PWM frequency is half of the Fast PWM frequency of 62500 Hz. It is not! It is actually 31372.5 Hz. It pays to check the manual.
I have come to the conclusion that the jitter is mostly due to background interrupts by the Arduino bootloader. This probably means that I am losing interrupt ticks. I did drop the PWM to 7813 Hz to have a look, but the wave form was pretty poor:
Here is the Data In (blue) versus Data Out (yellow). Note that Data Out is delayed by about a bit:
You might say what jitter? That was the low channel (1170 Hz), the high channel (2125 Hz) is not so good:
In reality the background jitter is just like a noise floor. It just sets a minimum for degradation by the telephone system. I could spend weeks investigating jitter and trying solutions but I feel I have a fair solution right now so I will move on.
Now that I think I have the code working properly, here is the results of the audio (speaker and microphone) loopback for the low channel:
The signal looks to be all over the place but it detects okay with the usual jitter.
Here is the high channel:
Detection is good with the speaker to about 30 cm away. Without the speaker connected you get the usual spike chatter.
The microphone gain is far too high, someone talking in the room is stronger than the signal. But the next circuit board iteration has that fixed.
---
So lots of progress today! A working modem!
Alanx
I have been searching for magic numbers. Yes I use Excel to help (i.e. goal seek, solver, macros (mostly brute-force) and data tables).
Basically matching up the timer divider (i.e. Fsample = 16,000,000/64/n) and the delay number to find a correlation null at the centre frequency. We want a sample frequency that is between 7000 Hz and 10000 Hz to avoid aliasing within the telephone bandwidth and enough time for processing the signal between timer ticks. The correlation null need not be exactly zero. Here is the table for the 1170 Hz centre frequency:
The frequency number (n) is at the top and the delay number (d) is on the left. The band is from 175 Hz to 250 Hz bandwidth. I have selected a cell near the middle (sample frequency 8069 Hz and a delay of 19). I chose this cell over the others as the table for the 12125 Hz centre frequency has a matching sample frequency (delay 18):
Here I used a brute-force Excel macro. I decide to use three stages and wanted a pretty close match in performance for the two centre frequencies. Here are the coefficients that I found:
Modem | Answer | Originate | Units |
Fsample | 8069 | 8069 | Hz |
Fcentre | 1170 | 2225 | Hz |
Divisor | 8 | 8 | |
Q | 1.78 | 2.16 | |
Gain | 1.3 | 1.3 | |
A0 | 2 | 2 | |
A1 | 0 | 0 | |
A2 | -2 | -2 | |
B1 | 8 | -1 | |
B2 | -5 | -5 | |
Other channel suppression | -29 | -36 | dB |
When considering filter coefficients you must avoid division by using arithmetic shift right. Therefore the divisor must be a power of 2. A low divisor reduces the risk of integer overflow.
These filters should reject the other channel by about 30dB. This should be enough. Here is the answer modem (i.e. Fc = 1170 Hz) calculated response:
And the originate modem (i.e. Fc = 2125 Hz) calculated response:
Note the alias above 5000 Hz.
You may have noticed I have been using a really cool graphs of the bandpass frequency response. Here is where I got it from:
The guy/gal who worked this out deserves a medal!
To date I have been using a brute-force (i.e. a dumb grid search) macro to find the integer parameters for my bandpass filters. If you don't know, integer problems are very hard (actually NP Complete). While it works, it is slow and being a bit of a perfectionist (it a genetic disorder) I have eventually got a quick spreadsheet method working. While it finds the best solution available, determining the quality of that solution (in practice the filter Q) is a bit difficult (there is a way but even a perfectionist can say why bother as it is a case of "take it" or "leave it" for the filter). Here is what it looks like:
I used biquad frequency response as a check:
You may be able to see that the filter Q is closer to 3.6 than the design of 2.2.
I have posted the spreadsheet to the project if your interested.
Notes:
Update the Arduino code the test. If all good then finish off the case.
AlanX
Who thought this would be hard?
I have spent a week trying to work this out. Here is the pseudo code so far:
Calculate the Mark and Space ratios:
Find the lowest common multiple N of A and B:
Where N is the sine (iSin[]) lookup array size.
To generated the sine wave step through the array using Phase:
Note: B=N/A
So:
or
The Phase needs to roll back to the start on overflow:
The sine wave is:
To reduce the sine look up array size by a constant (C) we can divide the Phase by the constant (C):
or
The sample frequency is restricted and depends on the Arduino clock (16 MHz), the pre-scaler (timer dependent) and the PWM type.
So I have spent a day trying different combinations of Fsample and M to minimise the array size and the error. Nothing great found!
---
I thinks I need help (at least my partner thinks so)!
I found a paper (http://www.analog.com/static/imported-files/tutorials/MT-085.pdf) that although a bit complicated, shows a way out of this mess:
Set N to a power of 2, say 65536 (an unsigned int):
Then phase is:
or
Choose a sine array size that is a power of 2 , say 64.
or
Phase rollover is implicit with an unsigned int.
Here is the code for the ISR:
// TRANSMIT:
// Phase Correct PWM frequency 31250 Hz
// Originate modem Mark frequency 1270 Hz (=2244)
// Originate modem Space frequency 1070 Hz (=2663)
// Answer modem Mark frequency 2225 Hz (=4666)
// Answer modem Space frequency 2025 Hz (=4247)
const byte iSin[64] = {
128,140,153,165,177,188,199,209,
218,226,234,240,245,250,253,254,
255,254,253,250,245,240,234,226,
218,209,199,188,177,165,153,140,
128,116,103, 91, 79, 68, 57, 47,
38, 30, 22, 16, 11, 6, 3, 2,
1, 2, 3, 6, 11, 16, 22, 30,
38, 47, 57, 68, 79, 91,103,116
};
volatile byte DataOut=0;
ISR(TIMER2_OVF_vect) {
static unsigned int phase=0;
OCR2A = iSin[(phase>>10)]; // Output on D11
if (true) { // Set true for Originate Modem
if (DataOut==0) {
phase+=2244; // Fspace (Originate modem)
} else {
phase+=2663; // Fmark (Originate modem)
}
} else {
if (DataOut==0) {
phase+=4247; // Fspace (Answer modem)
} else {
phase+=4666; // Fmark (Answer modem)
}
}
}
Now is that not sweet code!
---
I used Phase Correct PWM instead of Fast PWM as it generates less interrupts rather than the phase correct feature.
Final note, don't put the iSin array inside the ISR like I did! It took ages to workout why the PWM was off frequency!
AlanX
I have simulated many options but I have not really done much better than the current setup. The backward channel without any additional filtering is suppressed nearly 20 dB. Really I have to wait until I physically test the modem with the presence of the backward channel before spending too much more time.
The backward channel is 387 Hz (space) and 487 Hz (mark). If I lowpass the signal (e.g. 585 Hz) and then down sample to 3300 Hz (from 13200 Hz) then the existing modem code will work fine for backward channel. The main problem is that the 2200 Hz frequency is aliased as 500 Hz. So I will need a good lowpass filter before the down sampling.
More thought is required.
Spent a lot of time playing with filter parameters to avoid proper division (can only use arithmetic shift right). Looking at cascading single pole filters. Easier to design, numerically efficient and works more or less the same. Here is a 5 single pole versus the current two pole lowpass:
Code for the 558 Hz 2 pole lowpass:
And for the 5 single pole version:
So the five single poles works better and is faster!
If I want to configure the modem for both forward and backward output then I will need to review the output filter. One option is to increase the number of steps for the DAC for the backward channel.
More thought is required.
Rewrote the code so the the modem can be send mode or answer mode. I have not tested it yet but I need to consider the digital to analog conversion (DAC) and the output lowpass filter. The question is do I really need to try so hard to filter out the DAC quantization. Here is the what I am thinking:
At 2 bit 2200 Hz is fine:
And at 1200 Hz the wave form is still okay:
But at 387 Hz:
This will probably not work will (but I have not tried).
But if I use three bit, the wave form is greatly improved:
So perhaps 4 bit is the way to go. The advantage of the above circuit is that the amplitude does not vary very much and the power level is probably about right (125 uW) but can be increased in necessary.
Here is a four bit version showing 387 Hz and 2200 Hz:
With the four bit version the resistor ladder network does not have to compensate for the lack of bits. The 25 R resistors are the uP source impedance. The power level is about 0.1 mW which will probably need to be scaled back.
Just to double check, I reconsidered PWM. First the ripple was about the same for the same RC values using a PWM frequency of 31.25 kHz for only the 387 Hz case. However, ripple frequency for the PWM much higher will present as a 4850 Hz alias for the answer modem (i.e. 2200/1200 Hz) and a 1750 Hz alias for the send modem (i.e. 487/387 Hz) so will not present a problem (if any gets through the phone line filters). For the answer modem the sensitivity to the 4850 Hz signal is attenuated about 20 dB (the attenuation is similar for the send modem). So the PWM option will work as well.
Now at this time you may be wondering why I did not go with PWM in the first place? Well basically I could not model the PWM frequency affect on the modem response then!
I like simple so back to PWM:
The PWM filter works for low frequencies but the ISR generates a square wave for 2.2kHz. Pretty ugly. Added another capacitor across the speaker to clean it up. Looks more like a triangle wave but good enough. Here is the PWM circuit:
I had a play with the decoder and reworked it as an AM demodulator:
If I wanted to create my own protocol I could mix binary FSK with binary ASK!
The first observation is that there are a number of configurations that need to be tested and it is rather a headache! First is to determine suitable sampling rates for the originate and answer decoders. Integer multiplies work best and the sample rates determined were: 22 kHz (2200/2000 Hz)...
Read more »Spent the day designing a case for the modem. Basically a piece of 18 mm thick MDF.
I chose MDF as it has a soft edge when cut and should suit this application. The design consists of a top layer for the iPhone and mounts for the microphone and speaker. The second layer (to do) will hold the electronics etc. The iPhone will be fully below the top of the MDF so that the modem case can have a lid. Here is the top layer:
This morning I backed out of the "carved" modem case and redesigned a plywood version:
Th disks are temporary feet.
Here are the cut pieces:
And assembled with the microphone and speaker in place (to be glued later):
And the iPhone happily sitting on top:
Now to design the electronics compartment. The simplest power supply and serial interface is to use the Arduino/Nano USB plug and a USB cable. I will also need a switch (on the base) for send or receive mode.
Half duplex means you need two modems and iPhones on each end (unless I can get the back channel to work).
Even though I have made the top of the case for the small speaker I had not actually tested the speaker. I assumed that the smaller speaker with less inertial would be better - wrong!
Here is the small (26.7 mm diameter) speaker signal as recorded by the Nano:
Looks good except for the AM modulation. Here is the signal after the bandpass:
Looks even better except for the AM modulations. Here is the signal after the lowpass:
See how the AM modulation upsets the decode and in fact the decode fails (repeatedly at this point). Here the medium (39.5 mm) speaker signal:
It looks worse but look at the signal after the bandpass:
It is pretty good. Here is the signal after the lowpass:
No problems. All of the above is repeatable. No difference with a Zobel network and no hint of issues when measuring the speaker terminals.
So I will have to rework the case for the larger speaker.
---
I have some 6.4 mm thick plywood in the shed so I will cut the electronics enclosure and the base tomorrow. I will cut the strip-board the same size as the other pieces and sandwich it near the base.
I don't have bolts long enough for the complete sandwich pile but that can be fixed later.
Designed the rest of the case. Decided to glue the top sandwiches and conceal the bolts for the bottom sandwiches.
---
I have a cheap Chinese CNC machine, so I can make neat little wooden objects (such as the modem case) but I can tell you these machines are hard to use and are very slow:
On the user side:
So tonight I had one success out of three attempts. Not happy! I will have another go tomorrow, five pieces remain. Here is the stack so far:
I have re-cut the speaker hole to fit the 40 mm diameter speaker and added a 6.4 mm thick cover to hide the assembly bolts. The iPhone will now sit just below the top of the case.
I tested the modem at 1200/2200 Hz and not too bad.
Tested the modem at 400/500 Hz and evidence of strong AM modulation upsetting the demodulator:
I suppose it is too much to ask for a speaker not to resonated at any frequency of interest. Not keen on a two speaker design.
I wonder if paper cone speakers are better? I will have to buy a couple and try them.
I suspect stopping the speaker from resonating may be a bit of an ask so I need to look at suppressing AM modulation in software or going directly to a FM discriminator. Looking at he above, it looks like close to 100% AM modulation, that may be difficult to remove.
Unsoldered a small paper speaker from my 2 transistor...
Read more »Optimising the code is tricky as there are so many parameters. One approach is to extract the data from the Arduino and model the code in Excel. Once the Excel model faithfully mirrors the Arduino the the parameters can be tested. Here are some examples (cut down to fit the Hackaday webpage width):
First the input signal recorded from the Arduino (note the pre-amplifier bias shift):
Now with the bias removed:
Now mixed:
Now after the LP filter (and this still amazing me):
Now with the DC bias removed:
Now after non-return to zero detection:
You will note that the out put data is delayed by about 1 bit and the duty cycle is somewhat jittery, That is because the signal is 100mv pp and the background noise is about 50mv pp. If the signal is higher the duty cycle jitter disappears. The main problem with the detector is that it is sensitive to background impulse noise (false highs).
Spent the last few days testing code. I think I am at the end (can't think of anything else to try). The final version consists of a bandpass, switching mixer and a low pass:
The DC bias problems at the switching mixer are solved by the bandpass filter much better than the DC bias filter.
The DC bias problems after the low pass was solved by increasing the gain (i.e. an integer maths problem).
Here are the signals:
The input signal:
After the bandpass filter:
After switch mixing:
After the lowpass filter:
And finally the demodulated signal (shown against the buad clock):
The input signal about 0.77v pp and the demodulator works down to 0.001mv pp (+/1 LSB of the ADC!).
The measured execution time of the ISR (including the ISR overhead of 2.6 us) was:
The total time between interrupts is 75.7 us.
A very tight fit if I want to use a 150 baud back channel as per the specification.
Here is the current code:
// Bell 202 modem
#define Fspace 1200
#define Fmark 2200
#define Fsample 13200
#define Baud 1200
#define sampleTicks 66 // sampleTicks = Fsample / Fmark * Fsample / Fspace
// 2 bit Sine table for Fsample equal to 13200 Hz
const byte sin2Bit[sampleTicks] = {
2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
2,2,2,2,2,2,2,2,
1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1
};
// Define various ADC prescaler
const byte PS_16=(1<<ADPS2);
const byte PS_32=(1<<ADPS2)|(1<<ADPS0);
const byte PS_64=(1<<ADPS2)|(1<<ADPS1);
const byte PS_128=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
void setup() {
pinMode(A0,INPUT); // Audio input
pinMode(12,OUTPUT); // Digital data output
pinMode(11,OUTPUT); // Audio output bit 1
pinMode(10,OUTPUT); // Audio output bit 0
pinMode(LED_BUILTIN,OUTPUT); // Test loop speed
Serial.begin(9600);
// Set ADC prescaler (assume a 16 MHz clock)
ADCSRA&=~PS_128; // Remove bits set by Arduino library
ADCSRA|=PS_16; // 16 prescaler (1 MHz)
// About 17.2 us to return an ADC value but only good for 6 bits (probably more)
cli(); // Disable interrupts
// ATmega48A/PA/88A/PA/168A/PA/328/P
// Use Timer 0 for sample rate (13.2 kHz)
// Note delay() and millis() will no longer work (use microseconds() instead)
TIMSK0 = 0; // Timer interrupts OFF
TCCR0A = (2 << WGM00); // CTC mode
TCCR0B = (2 << CS00); // prescaler 8, 2 MHz clock
TIMSK0 = (1 << OCIE0A); // COMPA interrupt
OCR0A = 151; // Sample rate: 2 MHz/152 = 13.2 kHz
sei(); // Enable interrupts
}
// Total execution time 33.3 us including interrupt overhead of 2.6us
volatile byte DataIn=0;
volatile byte DataOut=1;
volatile byte baudTick=11;
ISR(TIMER0_COMPA_vect) {
static byte Phase=0;
static int SX0=0,SX1=0,SX2=0;
static int BP0=0,BP1=0,BP2=0,BP3=0,BP4=0,BP5=0,BP6=0;
static int MX0=0,MX1=0,MX2=0;
static int LP0=0,LP1=0,LP2=0;
// Audio output (8.6 us)
PORTB=(PORTB&0b11110011)|(sin2Bit[Phase]<<2...
Read more »
Here it is:
Here is a 1200Hz output at the DAC:
An after the low pass filter:
The designed peak to peak voltage is 3v. The output is offset to maximise the emitter follower voltage swing.
Same again for 2200Hz:
And after the low pass filter:
The designed peak to peak voltage is 2v.
Here is a binary signal after the low pass filter:
Here is a random signal after the low pass filter:
The modem did pick up and demodulate a 500 uW audio signal from the speaker at about 1 cm away from the microphone but the microphone and transistor amplifier are rather non-linear with 1 to 2 volt voltage swings and is demodulating the amplitude modulation on the input signal:
Note that the top of the signal has less range than the bottom of the signal.
Had some problems demodulating the audio signal. Found some coding errors introduced in the last code update. Fixed. I also reworked the high pass to more aggressively remove the DC bias and to undo the low pass mark/space amplitude differences.
Here is the audio signal (~0.7 vpp) after the pre-amp and the demodulated signal (note that the demodulated signal is delayed by about 1 bit:
Have to be happy about this!
More work is required because demodulation fails at less than 0.5 vpp. With about 500 uW of speaker power and the speaker about 1 cm away from the microphone, the audio signal amplitude post the pre-amp is about 1 vpp (about where I want it).
Perhaps I need to consider some automatic gain control (AGC)?
Debugging interrupt service routines (ISR) on an Arduino is hard work. You cannot just print debug information from inside the ISR. There are ways around this.
Anyway, I exported the variable data, line by line, checking and correcting. Had to relearn operator precedence order, and changed the DC bias code to something I found on the Internet (thanks: sam-koblenski.blogspot.com.au/2015/11/everyday-dsp-for-programmers-dc-and.html). Added another DC bias adjustment to the correlation output. It works very well now, down to just above the noise level (i.e. the fan of my oscilloscope delivers 100 mV pp post the pre-amplifier). Here is the demodulator code:
// Decode the data
X1=X0;
Y6=Y5;Y5=Y4;Y4=Y3;Y3=Y2;Y2=Y1;Y1=Y0;
Z2=Z1;Z1=Z0;
F2=F1;F1=F0;
G1=G0;
Sx=analogRead(A0)-512; // 18 us
X0=Sx+(3*X1>>2);Y0=X0-X1; // Remove DC offset
Z0=(Y6>=0)?Y0:-Y0; // Switching mixer
F0=(Z0+Z1+Z1+Z2+F1*40-F2*12)>>5; // 600 Hz low pass filter (8 us)
G0=F0+(3*G1>>2);H=G0-G1; // Remove DC offset
DataIn=(H>0)?1:0; // Test correlation
Note: all variables are 16 bit integer.I don't think I need any more sensitivity but if I did, then filtering off of the high frequency noise would help (i.e. the demodulator is sensitive to any frequency above 1700 Hz as the mark frequency). I could roll off the microphone a little faster by adding a 2.2uF across the microphone pins. Actually, that did not work, it made it worse - parasitic oscillation? Here is the current strip-board layout:
TBC...
AlanX
Microphone Estimate Check
Here is my estimate for speaking into a microphone 25 mm away:
Speaking into a microphone Estimate | ||
Voice at 1 m | 60.0 | dB SPL (1 W / 1 m) |
No Power Adjustment | 0.0 | dB |
SPL (uP) -> V rms (the magic number!) | -74.0 | dB |
Microphone Sensitivity | -63.0 | dB |
Microphone Rated at 1k Load | 0.0 | dB |
Assume an effective 25 mm mouth to microphone spacing | 32.0 | dB |
Amplifier Gain (x1) | 0.0 | dB |
Voltage (rms) | -45.0 | dB |
Voltage (rms) | 5.623 | mV rms |
Voltage (pp) | 15.905 | mV pp |
So is the mathematics right?
Jack Smith (www.cliftonlaboratories.com/microphone_output_level.htm) piblished:
"The image below is at a speaking level more typical of what I would use in a normal QSO. Although there are a few peaks of 40 mV or more, the majority of the speech is around 20 mV peak-to-peak."
iPhone Output Level
Next, what is the output level of the iPhone in normal handset mode?
Hard to find on the Internet but a "dial tone" was quoted at 80 dB. This sounds okay, 80 dB is the level where you raise your voice to be heard and beyond that you risk long term hearing damage.
On that basis I can expect 4 vpp from the microphone (assuming I use the standard 1k load resistance, the microphone sensitivity is proportional to the load resistance within limits):
Dial Tone Estimate | ||
Telephone Dial Tone | 80.0 | dB SPL (1 W / 1 m) |
No Power Adjustment | 0.0 | dB |
SPL (uP) -> V rms | -74.0 | dB |
Microphone Sensitivity | -63.0 | dB |
Microphone rated at 1k load | 0.0 | dB |
Assume an effective 10 mm speaker to microphone spacing | 0.0 | dB |
Amplifier Gain (x1) | 0.0 | dB |
Voltage (rms) | -57.0 | dB |
Voltage (rms) | 1.413 | mV rms |
Voltage (pp) | 3.995 | mV pp |
Here I have had to assume an effective speaker to microphone distance of 10 mm.
Modem Speaker to iPhone Estimate
Here I have made two calculations: the first is normal speaking into an iPhone and the second the modem. The main difference is the power and distance from the "speaker" to the microphone:
Voice to Iphone | ||
Speaker Sensitivity | 60.0 | dB SPL (1 W / 1 m) |
No Power Adjustment | 0.0 | dB |
Distance Correction (50 mm) | 26.0 | dB |
Sound Level | 86.0 | dB |
Speaker to Iphone | ||
Speaker Sensitivity | 80.0 | dB SPL (1 W / 1 m) |
Power Adjustment (4 mW) | -48.0 | dB |
Distance Correction (10 mm) | 40.0 | dB |
Sound Level | 72.0 | dB |
There is a difference af 14 dB (x5) but this is well within the AGC range of the iPhone.
So the current design is workable.
iPhone to Modem Microphone Estimate
This question is more about the amount of gain required for the modem microphone:
Modem Receive Estimate | ||
iPhone Output | 80.0 | dB SPL (1 W / 1 m) |
No power adjustment | 0.0 | dB |
SPL (uP) -> V rms | -74.0 | dB |
Microphone Sensitivity | -63.0 | dB |
Microphone rated at 1k load | 0.0 | dB |
Assume an effective 10 mm speaker to microphone spacing | 0.0 | dB |
Amplifier Gain (x200) | 46.0 | dB |
Voltage (rms) | -11.0 | dB |
Voltage (rms) | 0.283 | V rms |
Voltage (pp) | 0.799 | V pp |
As the target average uP signal is about 0.7 vpp in order to maximise the dynamic range (5 v down to 0.1 v), a microphone gain of x200 is required. An LM386 would work well here.
Checking the bias current for the AM4011 microphone:
Voltage across microphone | Microphone Current |
2.2 v | 0.31 mA |
4.4 v | 0.32 mA |
7.7 v | 0.36 mA |
Based on the above measurements, a 5v supply and a 10k load resistor will work fine (approximately 2 volts across the microphone). This suggests a 20 dB gain improvement over the 1k load resistor test condition.
This suggest I will have to reduce the microphone amplifier back to maintain 1 vpp:
Modem Receive Estimate | ||
iPhone Output | 80.0 | dB SPL (1 W / 1 m) |
No power adjustment | 0.0 | dB |
SPL (uP) -> V rms | -74.0 | dB |
Microphone Sensitivity (rated at 1k load) | -63.0 | dB |
10k Microphone Load Resistor | 20.0 | dB |
Assume an effective 10 mm speaker to microphone spacing | 0.0 | dB |
Amplifier Gain (x25) | 28.0 | dB |
Voltage (rms) | -9.0 | dB |
Voltage (rms) | 0.353 | V rms |
Voltage (pp) | 0.999 | V pp |
We will see if the microphone amplifier can be dropped back to a gain of only 28 dB!
I assembled Modem V2 and checked the microphone circuit. The microphone worked well but only had 0.9v across it? Checked the circuit for wiring errors and incorrect component...
Read more »Connecting the microprocessor (uP) to an 8 ohm speaker and to an 8 ohm speaker used as a microphone is tricky. Tricky if you want it clean (no PWM in the out put) and simple (i.e. low part count and garden variety components).
Op Amps
The problems here are simple power supply, voltage swing, input noise and output current capacity (i.e. output impedance).
The old single supply contenders (from my local electronics store) are:
With a newer:
None of these are low noise but the LMC6482/4 is rail to rail and rated at 600 ohm output impedance. So none of them will drive an 8 ohm speaker directly.
One option is to add a push-pull transistor circuit to the output:
LM386
An LM386 will drive an 8 ohm speaker directly and has a 50k imput impedance, gain is programmable from 20 to 200.
For this application, an LM386 has merit. The gain bandwidth (5Mz) and input impedance is high enough for a multi-feedback band pass. Here is a schematic of a Sallen Key band pass:
I have used an ideal OpAmp instead of the real thing as TinaTi does not have it.
The gain of the 386 has been set to x20. As the 386 has an output voltage swing of the supply voltage less 2 volts, the 5v PWM input has been attenuated for an output of 2.5 volts peak to peak. I added a 1u capacitor to the attenuator network to roll off the high frequency faster. I have not shown the zobel network or the other 386 circuity.
Transistors
No problems, here is a narrow band speaker driver/buffer:
Note that the 25R is the atmega328p output impedance but the 100R is to limit the current to the maximum permitted.
And here is the frequency response:
The buffer has a -7bB loss but the 31kHz PWM frequency is attenuated a further -28dB.
Quiescent current is about 13 mA according to the simulation.
A speaker microphone input circuit would look like this:
Source: www.next.gr/uploads/51/sp_mic.gif
This image is a common base followed by a common collector (an emitter follower). (The emitter follower is rather useless here!)
Transformers and LC Filters
Good audio transformers are bulky and expensive.
I did spend some time looking at LC impedance matching but high Q (low resistance) components are also quite bulky. I have some suitable toroids (FT-68-??) that are good to 300kHz with an Al of 1.06 uH per turn.
Here is the type of design I have looked at:
Due to impedance matching the circuit delivers x3.4 the power to the speaker than using just a 100R to limit the current. Other than the steep high frequency roll off it does not seem worth it.
A good place to put the LC filter is on the output of the audio amp:
I have designed a transistor and a LM386 versions.
Here is the transistor version strip-board design:
Here is the final PWM buffer:
And the final pre-amp:
The problem with the transistor version is that at this level of complexity it will need to be debugged (built and tested in stages).
Back to the LM386 version:
Here is the PWM buffer (less the Zobel network):
The LM386 spice model came from https://hackaday.io/g4lvanix
(https://github.com/g4lvanix/Spice-models/blob/master/sub/LM386.sub), thanks.
The LM386 version is at the near foolproof stage, the lesson appears to be that PWM is a "tough nut to crack".
Two thoughts:
To solve this problem I created a simple spreadsheet and modelled a HP RC filter...
Read more »
Create an account to leave a comment. Already have an account? Log In.
Hi,
I am trying to build a navtex demodulator. I have built classic hardware demodulators with XR2211, pulse counting demodulators; used the CP-1 from AEA, the PK-232 also from AEA. The best demodulator used by me (excluding PC based solutions) was the one using Goertzel filters with ATmega328P (Arduino Uno) described here https://www.microchip.com/en-us/application-notes/an2701 (includes source code). I have seen that you have used Goertzel filters in another project. What do you think, shall I try this correlator? You have experience both with Goertzel filter and correlator demodulator. Which would be more suitable for navtex? Thanks.
interesting idea, but if you connect electrically to the phone (via the headphone/mic socket) you should be able to manage Bell 212A or V22, which are 1200 baud FSK protocols. Strap V42bis on top of that for error correction and compression and you should get to 2400 baud.
As an aside, you should probably shift to a 32 bit platform, something like the STM 32F412GDISCOVERY will give you a 100MHz ARM Cortex M4 (with 1MB of flash, 256KB of RAM, DSP and FP support) an I2S audio in and out codec and a small touch screen for about $20
This is great stuff. Here are some links for you I've found doing my own research into creating a software modem:
http://bellard.org/linmodem/ - Same guy who wrote the QEMU hypervisor wrote this long ago.
http://www.soft-switch.org/ - This is what is currently used for FoIP on Asterisk PBX. When I last looked at the code, it only lacked the code and logic for Bell 103/202.
https://github.com/arms22/SoftModem - just ran across this right now - looks similar to what you are doing.
Hi Don,
Thanks I will have a look. I have seen SoftModem.
---
I have two key problems:
1 Arduino Uno/Nano computational limitations (i.e. CPU bandwidth).
2 Modern high speed modems protocols don't work well with digital or VOIP phones.
---
My understanding is that digital phones and VOIP do not necessarily honour phase shifts (as the human ear does not know the difference).
I believe the 9600 baud rate uses a 2400 Hz carrier and uses QAM modulation.
QAM is a combination of phase and amplitude modulation. Thus the potential reason for the problems of analog modems over digital lines. How much of a problem depends of where you are in the world and the level of congestion.
I have found the Bell 202 is not sensitive to phase noise so it is a good candidate for congested digital/VOIP.
---
To date I have been able to code a one way Bell 202 protocol with less than half of the ATmega328P bandwidth in C code.
Encoding QAM would not be difficult but I am reasonable sure that decoding QAM would be beyond the bandwidth of the ATmega328P in C code (perhaps even in assembler). But I have not tried (yet!).
---
Regards AlanX
I think you're right in that the ATmega won't be able to keep up with QAM. Microchip has a line of DSP based PIC controllers and offer a free dsPIC Software modem which does have the v.32/v.32bis standards. It does mean rigging another chip and associated filtering into the circuit but totally doable.
Or... you can do 9600 baud FSK which is used in high speed amateur (HAM) radio applications. If the goal is to circumvent the great firewall of china, then it would suffice - at least far enough to get the signal out of china and somewhere that has a paired modem that can serve as it's "ISP".
But, it would be exciting to see a full implementation of this that can talk to a conventional PSTN modem bank. :)
As for whether or not Analog works well over digital/VoIP lines: The trick is to have zero/flat latency and not to compress an already compressed stream. Here is a talk I did several years ago at HOPE in NYC discussing how it can be done.
Incidently, around the time I did this talk, we did test going point-to-point over VoIP from West Coast USA to NE Australia using the Analog Modem on a ATA configuration and were able to regularly get 33.6kbps connections between them.
Hi Don,
I don't think you can get 9600 baud with just FSK. You could get 2400 baud by adding a two level AM signal over the top of the FSK.
The following shows a four bit QAM:
What is happening here is 2 bits are encoded in AM and 2 bits are encoded in phase shift. I assume the carrier is 2400 Hz and it takes two cycles (1200 Hz) to decode.
---
I have been working on this project for less than a week. To get fast progress I find it is best to start very simple and get something working before progressing on to the more complex options.
The next step for me is to design the audio interface as simply and cleanly as I can. I would like to get two Arduino's talking via two loud speakers.
Regards AlanX
Hi Don,
Good point, in not using compression.
Makes sense that a compressed signal needs more bandwidth on the telephones company's side of the fence and the compression may not be optimal on that side of the fence as well.
AlanX
You should be able to do better than Bell 103. I have sent quite a few 14.4 faxes using regular modems with ATA (Telephone adapter thingy) on VoIP with G.711 codec. Cellphone CODECs do have a lot more compression.
Hi Lee,
Did a quick search of the Internet and it appears to depend on where in the would you are. VOIP is pretty bad over here (Australia) even for voice (may improve with the National Broadband Network). It is also part of the local ISP's terms and conditions that you don't use their Internet for VOIP!
In any case that is the fun of the project, to explore the options.
Regards AlanX
All that for facebook! Great workaround, though.
But... isn't there lag with digital communication, slight delays from buffering, etc., isn't it compressed, and isn't the transmission of sound <s>somewhat unidirectional</s> half-duplex?
Hi Eric,
Bell 103A does work (I have seen a YouTube of it working) but I am not sure about Bell 202. The human ear is not sensitive to phase shift but the the demodulator is, it results in phase shift of the binary output. Up to a point this is tolerable. You should have noted that it works when I introduce phase, amplitude and gaussian noise in the Excel simulation. So I am confident.
---
The Bell protocols do not specify the data protocol but RS232 is asynchronous other than within the frame.
The Bell 103A is full duplex (i.e. bi-directional).
The Bell 202 is either half duplex (i.e. take turns) or 1200 baud one way and 150 baud the other way.
__
I think the key issue issue will be cleaning up the phase noise with an input filter (if that is possible) to help the demodulator.
---
The code I am coming up with for the Bell 202 is super simple so worth persisting before going back to the Bell 103A and for more robust frequency determination.
AlanX
Become a member to follow this project and never miss any updates
This is great stuff. Here are some links for you I've found doing my own research into creating a software modem:https://dotnewage.com/