I’m happy to announce that my new Arduino wind meter shield is ready. I had posted the design as well as a photo or two of the naked board in my last post but now I’ve placed and soldered all the numerous components and it’s ready to go.
My first wind meter prototype is kind of working. The software will need improvement to make this wind meter into something really useful. But both hardware and software are basically functional and can be built up upon.
The next thing I will do is re-design the entire hardware. Instead of two distinct boards with wires all over the place I will design a single, standard-sized Arduino Shield that can be stacked on an Arduino Uno. Just like any of those commercially available shields that add motor control, Ethernet or whatever. That will make the whole setup much smaller and simpler. And I hope this will also make it easier for others (like you?) who want to build their own.
This re-design is what I’m going to talk about today so I guess there won’t be much in the way of photos, just some schematics and board layouts. And I’ll put all the Eagle files on the overview page as a zip download. Here’s what I’ve changed and why:
The first version used the (unregulated) Vin of the Arduino so it had a linear 5V regulator of its own. On top of that there was also a flying capacitor type inverter to generate a -5V rail for the analog multiplexer. Both of these chips have been eliminated. I’m now using the the 5V rail straight from the Arduino, there is just a 100uF tantal input cap. The -5V is no longer needed by the multiplexer. I’ll later explain why.
Signal routing / pulse generation / drive
The drivers are entirely new: I’ve replaced the two 74HC368 inverters with a single 74HC126 non-inverting line driver / buffer. It has four 3-state buffers, one for each transducer. The negative pin of each transducer is simply grounded in the new design. That costs us half the signal amplitude but simplifies things greatly. And our two-stage amplifier should have more than enough gain to make up for that.
As suggested earlier, there is only a single 74HC4052 left (instead of 3). We will get some crosstalk issues but we’re always transmitting or receiving, never both at the same time. Plus, the tuned amplifier filters out most of that high frequency stuff (such as square waves). And we have the option to mute the amplifier, this time both at the input as well as on the output. Not sure if we’ll need it, I’ll check once everything else is working.
Permanently grounding the negative pin of the transducers means we only have four signals to worry about. So I’m only using half of the 4052 to chose exactly one of the four signals. Y0, Y1, Y2, Y3 as inputs from the four transducers and Y as output that goes to the amplifier.
But why don’t I need the -5V anymore? Here is why. In my first design I routed the signal from the transducers straight through the 4052. Because this signal swings around ground, it will be negative half of the time and positive the other half. So I needed both a negative and a positive supply. Later, that signal was capacitively coupled into the amplifier where it was biased so somewhere around 2.3 volts. Now I already do the biasing before the 4052. So the signal will be positive at all times and hence there’s no longer a need for a negative voltage. I find this a really elegant solution, I just hope it will work 😉
There is still an Axis and Direction signal controlling a 74HC139 encoder generating the enable signals for the transducer drivers / output buffers. I had LEDs on these enable signals in the first version, these are no longer present. The software changes the axis/direction every 2ms so you won’t be able to see anything now.
The 74HC126 has active high enable signals (as opposed to the 125 which is otherwise identical). Since all but one enable signals are high, only one transducer can float freely. That’s our receiving transducer. That also means that the other 3 transducers are actively driven so only one of them must receive the PWM signal.
This is how I’ve solved this: As I said, I only used half of the 4052 for the tranducer signals. So the other half can be used to route the PWM signal from the Arduino to the correct output buffer. So the signal from the Arduino is connected to the input X and the outputs X0, X1, X2, X3 carry the signal to the different gates of the 74HC126. There is one potential problem: The outputs that are not selected are floating freely so there are 10k pull-down resistors on X0, X1, X2 and X3.
So from the 8 large ICs on the first version, only 3 are left. That saves plenty of board space so we can fit our circuit on a standard sized Arduino shield.
The basic design with two stages of tuned common emitter amplifiers with NPN darlington pairs has worked well so I’ll stick to that.
The main shortcoming of my first version was the 47uH plus 330nF LC tank (see part 4) so I’m changing that to 1mH plus 15.82nF. Same resonant frequency but much higher impedance. The inductor I’ve chosen has a dc resistance of a bit more than 16 ohms which will give a Q-factor of around 15 – comfortable for our application.
The main change is the biasing. A wind meter will be deployed outside so it is likely to see great variation in temperature. So the biasing of our amplifier and thus the quiscent current need to be stable over a wide temperature range. Two things make this a difficult task here: First, we’re using darlington pairs which means twice the variation in base-emitter drop. Second, our rather low operating voltage of 5 volts.
A common solution for difficult biasing situations is the use of a matched transistor to generate the base biasing voltage. And that’s what I’ll do here. Each stage has an additional darlington pair with collector and base connected for this purpose. So the collector will always be 2 diode drops (around 1.3V at room temperature) above its emitter. I want the emitter to sit 1V above ground and 1mA of quiscent current. So I add a 1k emitter resistor and a 2.7k collector resistor and get just that.
Base emitter drop will change by about -2mV per degree per transistor. So for a 50 degree increase in change in temperature, the drop accross our darlington pair will change from 1.3V to 1.1V – quite substantial. But quiscent current will only increase to 1.054mA and the emitter will then sit 1.054V above ground. A 5.4% variation for a 50 degree change in temperature. Not bad at all I think.
The last change to the amplifier is that I’ve put the gain limitting resistors (R7 and R12) in series with only the bypass caps (C5 and C10). This will let me change the gain without affecting biasing which is given by R8 and R13.
Zero Crossing Detector (ZCD)
Almost no change here. I’ve only changed my comparator to be a Microchip MCP6561R. It has a worst-case propagation delay of only 80ns which is 100 times faster than the one I used last time. And it’s still cheap: CHF 0.43 at Farnell if you buy 10.
I told you earlier that I had some trouble with my last envelope detector which utilized a VCVS active low-pass filter. If I turned up the gain too much I got wild output swings. I found a screen shot of that:
Green is the amplifier output. We’re trying to get the envelope of that. But look what happens to the pink line when I turn up the gain. Nothing to do with an envelope. And I would like even more gain to make the envelope use (almost) all of the 0…5 volts range.
I haven’t really understood why that is. Suggestions anyone? The only thing I can think of is the rather narrow gain-bandwidth product of the op amp, 600kHz if I remember correctly.
So I’m using two op-amp buffers, each followed by a normal RC low-pass filter. So I can set any gain I want for the two buffers without affecting the signal shape. As an added benefit, I can now look at the signal after each buffer / filter. I’ve also changed the op-amps to be Microchip MCP601R. Less precise (we don’t need precision here) but fast (2.8MHz) and cheaper.
At the very input of the envelope detector I’m now using a second (not really matched but same type) diode (D2) to produce a bias voltage just a diode drop above ground to precisely compensate for the rectifying diode (D1) of the envelope detector.
The comparator at the output is now a MCP6561R as for the ZCD. Not that we need the speed here, just to use the same type.
Everything new here. LMT86 as a temperature sensor. Cheap, works from -50 to +150 degrees centigrade and is accurate to 0.4 degrees. Its output is between 1.5 and 2.5volts over the temperature of interest. It comes in a SC-70 package. That’s a bit small but still hand-solderable without problem.
There is no more op-amp to scale it up but I’ve added a rather precise 2.5V voltage reference, the ADR361. Quite an overkill maybe but I thought if you are measuring wind speed you are likely to also measure things like humidity, pressure, light intensity or something like that. So with the anemometer shield you get a precise and stable reference for all your measurements.
As you can see, I ended up changing quite a lot. When laying out the board I was surprised how easily everything fitted in. Not only did the fewer logic ICs save space themselves, it also greatly simplified signal routing. As you can see from the photos, I’ve already made a board. All the components have arrived as well so I’m ready to go ahead and build it up. I’m really looking forward to seeing how it will perform. I just hope everything works as planned.
All the board and schematic PDFs as well as the Eagle files can be found on the overview page as a .zip file: http://soldernerd.com/arduino-ultrasonic-anemometer/
In my last post I talked about how to get the Arduino to output bursts of 40kHz pulses. Today I’ll go through the rest of the software so by the end of this post we’ll have a very rudimentary but working sketch for our ultrasonic wind meter.
If you’ve read part 7 of this series you will have noticed that all the key tasks are handled not in the main code but in interrupt service routines (ISRs). That’s fairly typical for an application like this one.
In this project, there are 2 ISRs:
TIMER1_COMPB Interrupt: It is triggered by Timer/Counter1. It sends 15 PWM pulses every 2ms and takes care of the Axis, Direction and Mute signals. Named TMR_INT on the screen shots in this post. This is what I’ve covered last time.
TIMER1_CAPT Interrupt: This is where all the measurement takes place. It is triggered by the envelope detector and zero-crossing detectcor. It reads the current value of Timer/Counter1. Named CAPT_INT on the screen shots in this post. This is what I’ve covered last time. This is mainly what I’ll be covering today.
The basic Idea of the software is as follows:
Every measurement takes 2ms. It takes 375us (15 times 25us) to send the pulses plus 500us – 1500us for the pulses to arrive (assuming very extreme wind situations). So 2ms gives us plenty of time to finish our measurement.
Shortly after sending the pulses we start listening and wait for the envelope detector to trigger TIMER1_CAPT interrupt. We save the current value of timer1, this is our coarse measurement of time-of-flight. We then set up interrupts to capture a rising edge of our zero-crossing detector (ZCD).
A rising edge of our ZCD triggers TIMER_CAPT interrupt. We save the current value of timer1 and set up interrupts to capture a falling edge of the ZCD.
A falling edge of our ZCD triggers TIMER_CAPT interrupt. We save the current value of timer1 and set up interrupts to capture a rising edge of the ZCD.
Repeat steps 3 and 4 until we’ve captured 8 rising and 8 falling edges. Averaging these will give us a very precise measurement of the phase shift.
After every measurement we change the direction we measure: N->S, E->W, S->N, W->E, …
We measure each direction 32 times until we calculate the actual wind speed. So one full measurement will take 4 x 32 x 2ms = 256ms. So we take about 4 measurements per second.
The screen shot above shows how a measuement proceeds: AXIS and DIRECTION are set depending on the direction to be measured. MUTE is driven high and 15 PWM pulses are sent. TMR_INT triggers after every pulse in order to count them. After a short break, TMR_INT triggers again and turns MUTE off again. Eventually, the envelope detector (ENV_DETCT) triggers CAPT_INT. Shortly afterwards, CAPT_INT is triggered 16 more times by the zero-crossing detector (ZCD).
There are 2 sets of variables to save all the measurements from the envelope and zero-crossing detector: At any point in time, one is in use by the ongoing measurements, i.e. they’re being updated. The other set represents the last set of measurements and is static. This second set can be used by software in our main loop to calculate the wind speed and direction. As I’ve said, capturing one set of measurements takes 256ms. So we also have 256ms to do all the calculations, send data (via USB or whatever), write the new measurement to the display, do some data logging or whatever else we have in mind. There is likely to be some floating-point math, square roots and tigonometric functions going to be needed to arrive at the wind speed and direction but 256ms should be pretty comfortable even for that.
This is what I’ve tried to show in the screenshot above: There is a signal named CALC which is driven high when a new set of measuements becomes available and driven low when the calculations are finished. So this signal shows you how much time the Arduino’s Atmega328 spends processing the data and writing to the display. As you can see, it’s less than 25ms so there is ample of room for more complex calculations or other tasks. We’ll definitely need some of that head room since the calculations performed so far are really just the bare minimum.
There definitely is still a lot to be improved, mainly how the raw measurements are evaluated to get the actual wind speed. But what’s more important to me at this time is that the basic idea/setup works. With no wind, my measuements fluctuate somewhere between plus/minus 0.3 meters per second without having done any calibration. It also reacts nicely when I blow a bit of air towards it.
I’ve changed the pinout many times while developing this software but I’m confident that I won’t have to change the pinout any more. So my plan is to now build version 2 of the hardware first. The entire setup will be much less complex (and prone to errors) without all the lose wires going back and forth between the different boards. Then, with the updated and hopefully final (or nearly final) hardware I’ll go ahead and finish the software.
Speaking of software: You can download the Arduino sketch from the overview page where you also find the Eagle files for both boards: http://soldernerd.com/arduino-ultrasonic-anemometer/. I’ll make it a habit to post all the download material for this project on the overview page so people don’t need to go through all the posts trying to find a certain file.
The first thing we’ll need to archive is to send a series of pulses at 40kHz which is the frequency the ultrasonic transducers work. They must be as precise and repeatable as possible since all our measurements depend on them. Any jitter and the like will affect our measurements. And the duty cycle should be 50%. So you really want to do them in hardware. The Atmega328 comes with a single 16-bit counter/timer (Timer/Counter1) as well as two 8-bit counters (Timer/Counter 0 and 2). We’ll need the 16-bit resolution so the choice is clear: Timer1.
Well yes, you could easily use one of the 8-bit counters to generate your pulses but you’ll still need timer1 for measurement. I’ve decided to do everything with just one timer so it’s going to be timer1.
How many pulses we should send is not so clear. I’m working with 15 pulses which works quite well but I’m not claiming it’s an optimal choice. But it is short enough to make sure we’ve stopped transmitting before the first sound waves reach the opposite transducer, even with heavy tail wind.
Since we have such strict requirements for our pulses, we can’t rely on any of those convenient high-level functions to set up our timer but have to study the Atmega328 datasheet and do it ourselfs.
This is a short explanation of what it does: Set pin 10 as an output. Arduino pin10 is pin16 of the Atmega328. And that’s the pin connected to the output B of timer1. That’s line 1.
I then set up counter1 in FastPWM mode running at the full system clock frequency of 16MHz. Output B (that’s our pin 10 on the arduino) is set high when the counter starts at zero. It will be cleared (i.e. set low) when the timer reaches the value in output compare register B (OCR1B). The counter will be reset when (i.e.it will start at zero again) when it reaches the value in couput compare register A (OCR1A). I also enable an interrupt for when the timer overflows. More on that later. That’s lines 2 and 3.
Then comes the part where I actually set duty cycle and pulse with. I do that by setting the output compare registers. OCR1AH and OCR1AB are the high and low bytes of register OCR1A. So the final value in that register is 0x018F which equals to 399. That means counter 1 will count from 0 up to 399 before it starts again. That’s 400 steps. And here’s the math: The timer runs at 16MHz, our counter will overflow every 400 cycles. 16000000 / 400 = 40000. That’s exactly the 40kHz we’re looking for. The duty cycle is set to half that time by setting OCR1B to 199 or 0x00C7.
That’s it. We have a perfect PWM signal at exactly 40kHz and 50% duty cycle. Look at the screenshot above to convince you that this is exactly what we are getting.
But so far, the pulses go on forever. What we need is a way to turn the output signal off after 15 (say) pulses. One way of doing that is to count the pulses and turn the output off once the 15 pulses have been sent. That’s what the interrupt at overflow is used for.
In that ISR (interrupt service routine) I increment the variable pulse_count. Once pulse_count reaches 15 I know that all the pulses have been sent and turn the output off: TCCR1A = 0b00000011; The timer/counter will continue to run but the PWM output has been turned off.
For debugging/monitoring purposes, I set pin A5 high at the beginning of the ISR and low at the end. So I can tell when (and how long) the ISR is running by monitoring pin A5. Here’s what I get:
The yellow signal is the PWM output (pin10) as before. The blue line shows the time spent handling the interrupt. I could then continue counting without sending any pulses and turn the output back on when I reach 80 for example. And at the very beginning that’s exactly what I did. But then the microcontroller has to handle an interrupt every 25us (microseconds) even when not sending pulses. That’s quite wasteful so I set a longer time period by increasing the OCR1A and OCR1B registers seen above.
Actually, I’m using this interrupt to do some other things as well such as setting Axis and Direction as well as the Mute signal and some other housekeeping. That wide blue pulse you see at the left side of the screenshot above does most of that, that’s why it is so wide.
Speaking of time consumed handling interrupts. It’s quite significant as you can see here: About 5 microseconds for a normal (just counting) interrupt. That’s 20% of CPU time while sending pulses (5us every 25us). That’s muuuch more than I ever imagined it to be. That’s about 80 instructions. I’m writing in C so I’ll have to check the assember code produced by the compiler to see what’s going on.
If you’ve read through my previous posts of this series you know that here is an Arduino and two home-made PCBs together with 4 transducers waiting to work together as an ultrasonic wind meter. If you haven’t you may click here for an overview of posts on my anemometer project: https://soldernerd.com/arduino-ultrasonic-anemometer/https://soldernerd.com/2014/11/19/arduino-ultrasonic-anemometer-part-6-mechanical-design/
For this wind meter to work, the four transducers need to be held in place somehow. Even during testing and development I wanted some reliable mechanical setup so that I don’t need to worry about it all the time. For this prototype I don’t need anything waterproof that I can put outside for a prolonged period of time. Anyway it will be sitting on my bench most of the time so wood works just fine for me.
Here two videos of the CNC milling machine at work:
The transducers are 16mm in diameter. 16mm plastic pipes are readily available from hardware stores. They are intended for electrical wiring so you also get matching angles and the like. So I got myself 8 90-degree angles and a 2m pipe from a local hardware store. I think I’ve mentioned before that I want the transducers to sit in a 20cm distance so make the wind meter rather compact.
I’ve just recently attended a CNC machining course at the Zurich Fab Lab (http://zurich.fablab.ch/) so I decided to do my first CNC milling project and use my newly aquired knowledge to make a wooden base to hold the plastic tubes (and PCBs) in place.
I’ve used some left over 18mm melamine-coated multiplex. It’s extremely sturdy and has a nice smooth surface. I ran my first tests with a Arduino Mega so that’s what you see above but I’ve replaced that with a Uno by now. So all the software development will take place on an Arduino Uno and its Atmega328.
Besides the two boards you already know, there is a 2×16 characters LCD. I thought it would be nice to have a display connected to the Arduino when writing the software. Just to see what you’re doing. An easy way to drop some debugging output and of course display the measurements once we are ready to actually run this thing.
There is a little PCB attached to the LCD display. It mainly holds a trimmer to adjust the contrast as well as a resistor for the backlight LED. Since I had to make a board anyway I also included a 10uF plus 100nF ceramic capacitor as well as a protection diode.
As you can see from the photos above, there are definitely more and longer wires than necessary. But for a prototype I’m always reluctant to soldering things and cutting wires to their minimal or optimal length. I like to be able to just unplug a board and do some changes to it.
When I started writing my software I didn’t have a clue which signal will be on which pin. I just plugged them in as I went along. And I changed it several times until I was finally happy with it. So I do need some flexibility. But it also makes the setup a bit of a mess I must admit.
Ok, the hardware is working now. Time to write some software and see if we get it all up and running. See you next time.
In the last post I went through the analog board and showed what I had to do to get it working properly. Today I’ll do the same whith the digital board. Click here for an overview over this series of posts on the anemometer project: https://soldernerd.com/arduino-ultrasonic-anemometer/
So I plugged in the board for the first time and everything looked fine. The power LED came on, both the +5V and -5V rails worked as expected. But not everything worked that well.
I’ve explained in a previous post how the Arduino can control the direction by means of two lines: Axis and Direction. Here’s the meaning of these signals (L=low, H=high):
Axis=L, Direction=L -> North to South
Axis=L, Direction=H -> South to North
Axis=H, Direction=L -> East to West
Axis=H, Direction=H -> West to East
The first thing these two signals do is to control 74HC139 address decoder. The 139’s enable signal is grounded so its outputs are always on. Depending on Axis and Direction the 139 turns exactly one of the signals North_EN, South_EN, East_EN and West_EN on. EN stands for enable. As the bar over the signal name indicates, these are active-low signals. So zero volts means on and 5V means off. Each of these enable signals is connected to an LED. The other side of the LEDs is connected (via a resistor of course) to +5V so the LED is on when the signal is on despite the fact that it is active low. This part also worked.
Then we have two 74HC368 hex inverters. If you look at the 368s data sheet you’ll notice that it consists of 6 inverting buffers. But there are only two enable signals. As with most enable signals, these too are active-low. One enable signal controls 4 of the inverting buffers while the other one controls only 2. For us, this doesn’t matter since we need a total of 4 groups (one for each transducer) of 2 buffers each (one for each transducer pin). So we’ll only use two buffers of each group no matter if there are four.
Each group is controlled by one of the enable signals coming from the 139. The North_EN signal enables the buffers of the group connected to the North transducers and so forth. So exactly one group of buffers is on at any given time. That’s the transducer that is transmitting. All 4 buffer groups are connected to the same PWM signal (named Signal on the schematic) coming from the Arduino. But since only one buffer group is on, only that transducer is actually sending. The other buffer outputs are off and their transducer pins can float freely. Notice how the PWM signal is connected to the input of only one of the buffers in each group. The output of that buffer ist then connected a transducer pin as well as to the input of a second buffer. So one pins of the transmitting transducer are always in opposite states. When the first one is high, the second one is low and vice versa. There were no surprises here, everything worked as expected.
Here’s a little visualization of the 74HC139 in action. Note the glitches in the West_EN and East_EN signals. The Arduino can’t change both Axis and Direction perfectly simultaneously, there will always be at least one clock cycle in between the two commands. That’s why those glitches happen. But Axis and Direction are changed between measurements so nothing interesting is going on anyway. No need to worry about this here.
But then there is the task of selecting the right signal to listen to. And that’s where I’ve messed up just about everything. I guess I just wanted to build my first prototype as soon as possible and didn’t double-check everything as I should have. I probably also tried to be clever and use as few signals as possible and chose my inputs so that it simplifies the physical routing on the PCB. Anyway, I ended up with a design that doesn’t work. So if you want to build this circuit, look at the RevB board and schematics where I’ve corrected the mistakes.
As explained before, there are three 74HC4052 multiplexers to eliminate crosstalk. Like the 139, the 4052s are controlled by Axis and direction. But watch out: You need to select the transducer opposite from the one that is transmitting. So for example Axis=L and Direction=L means North to South. North_EN is low so the North buffer group is on and so North is transmitting. That means we have to chose the South transducer for receiving. Nothing complicated, really. But you have to concentrate and think carefully about which transducer has to connected to which of inputs. There are multiple solutions that work but many more that don’t.
My working solution is as follows: IC5 selects between North and East. So North is connected to input 1 while East is connected to input 3. When we want to listen to North, East is idle and vice versa. That’s why we get rid of crosstalk. The negative output of IC5 is grounded, the positive one is named NorthEast and routed to IC6. The second multiplexer, IC7 selects between South on input 0 and West on input 2. Again, the negative output is grounded and the positive output named SouthWest is connected to IC6. IC6 then only has the simple task of choosing between SouthWest and NorthEast. That’s why I only needed my Direction signal to control this multiplexer. The other address input can be left grounded.
I didn’t bother building another board so I’ve just used some pieces of wire to correct my mistakes. The corrected circuit is equivalent to what you see on the RevB schematic and works flawlessly.
This was definitely not my most interesting post so far. Lots of text and much in the way of photos or screenshots. Analog circuits are usually more fun to work with I find. Next time I’ll connect the Arduino to my two boards and show you how they perform. There will be some photos and screen shots again, promise.
Ok, so the the analog board is finally ready and all the components have been soldered into place. Time to see if it works as expected. My test setup looked as follows: I’ve programmed an Arduino (a Mega as you can see in the background, I didn’t have a Uno at that time but it doesn’t matter for what I’m doing here) to output 15 pulses at 40kHz from one of its pins (followed by a break of a few milliseconds). That pin was connected to one of the pins of a transducer while the other transducer pin was grounded. A second transducer was placed accross from the first one in a 20cm distance. That’s the distance/size I’m planning to use in the final design as it keeps the wind meter nice and compact. One pin of that second transducer was grounded while the other one was connected to the amplifier input of the analog board. So there are only 2 transducers at this time. One constantly transmitting, the other constantly receiving. Software is also minimal. Keep it simple for now, we’re just trying out the analog circuit.
Here we have the transmitted signal in red at the bottom left, together with the amplifier input (yellow), output of the first stage (green) and output of the second stage (purple). On the positive side, the received signal (amplifier input) is quite strong, around 350mV peak-to-peak. But the amplifier is barely working. At the output of the second stage we want a signal in the range of 5V pp but we get just a bit more than 700mV. We’re using a two-stage tuned amplifier and only double the signal amplitude. That’s hopeless.
As I’ve said in part 3, the root cause for this is my poor choice for the inductor/capacitor combination. 47uH or 330nF at 40kHz only give an impedance of 12 Ohms. Even with a decent Q-factor the impedance across the LC tank will never be high enough. I’d rather use something like 1mH / 15nF or 470uH / 33nF as as Carl did. But I didn’t have a inductor like that at hand so I had to change some other components to fix it.
First I changed the bypass capacitors (C5 and C10) from 100nF to 1uF. That makes the emitter ‘more grounded’ at signal frequencies (4 ohms instead of 40 ohms if you do the math). That did help but was not enough to save the show.
I then changed the emitter resistors (R8 and R13) from 330 ohms to only 47 ohms. The logic behind this is simple: The voltage across the LC tank is too small because the impedance is too low. Voltage is current times resistance (or impedance). I can’t change the impedance because I don’t have a suitable inductor so I have to increase the current. Changing the base resistors does just that.
Now I have plenty of gain at the price of a much-higher-than-planned quiescent current. Actually, gain was even a bit too high so I put in 15 ohms for R7 and R12 to slightly reducing the gain. Power consumption is not really a concern in this prototype so we’re fine for now. But if you’re going to build your own, use a big enough inductor in the first place and you won’t have to jerk up the current just to squeeze out enough gain.
Amplifier input (yellow), output of the second stage(green) and output of the second stage (purple). Note the different scales of 200mV, 1V and 2V per division. As you can see, the gain’s fine now. We’re getting a bit more than 4 Volts of amplitude peak-to-peak which is just what we need.
You can also see how much cleaner the output is compared to the input. The yellow signal has picked up quite a bit of noise gut the purple signal looks perfectly clean. That’s the benefit we get from the narrow bandwidth of the tuned amplifier. And that’s why you don’t want to just use an op-amp.
Let’s turn to the envelope detector now. Fortunately this part worked right from the start but that doesn’t mean it can’t be improved. I’ve used a voltage divider of 1M and 47k (R14 and R15) to get a voltage of 2.2 Volts which just about compensates for the drop over the schottky diode D1. Maybe I’ll use an identical diode in my next design to get a voltage exactly one diode drop above ground.
Here we see the transmitted signal (red) together with the amplifier output (purple), the output of the diode / input of the low-pass filter (green) and the filter output (yellow). Note how the filter makes the stairs in the green signal disapear. That’s exactly its purpose.
I found the envelope to be a bit slow so I’ve changed the resistors R16 and R17 from 47k to 22k. Together with the 1nF caps (C15 and C16) that gives a -3db point of 7.2kHz. That makes the envelope quite a bit faster which means the rising edge will also be steeper. That makes it easier to precisely trigger on it, provided it is still smooth. Obviously you have to strike some balance here. Not sure if my values now are perfect but they definitely do work ok.
One problem I’ve encountered is that I get some nasty oscillations in the envelope if I turn up the gain too high (via the pot R1). Making the envelope faster has made it even worse. I’m not quite sure why that is. It’s my first time to work with a VCVS (voltage controlled voltage source) circuit such as this active filter. I might use two stages of simple op-amp buffers and RC filters in my next design. That means I’ll need an extra op amp but anyway. For now, I just have to be modest with the gain setting and everything is fine.
This screenshot shows the envelope detector in action: Transmitted signal (red), amplifier output (purple), envelope (yellow) and output of the envelope detector (green). Note that this screenshot was taken before the changed cutoff frequency of the filter. The yellow curve is very smooth but doesn’t track the purple amplifier output very well. That’s why I thought it was a bit slow.
The green signal is the output of the comparator which is also the output of our envelope detector. It will be connected to the Arduino where it will trigger an interrupt and serve as a coarse measurement of the time-of-flight.
My zero-crossing detector is extremely simple. I set the inverting input of the comparator to half the supply rail by means of R23 and R24. The 100nF cap across R24 (C21) makes sure it stays there and doesn’t swing around itself. I bias the amplifier output to the very same 2.5 volts so I really trigger exactly when the sine wave crosses zero. R22 makes sure the non-inverting input to the comparator can swing freely and the input impedance is reasonably high.
Here we see the output of the amplifier / input to the zero-crossing detector (purple) together with the zero-crossing detector output. Everything seems to work fine. As expected, the detector also triggers on very small signals and potentially noise but that should not pose a problem.
These are the same two signals watched a bit more closely. You might notice that there is quite a bit of time delay from the actual zero-crossing to where the green signal changes. This won’t be a problem as long as the delay is constant but I’m planning to use a faster comparator in my next design. This one has a propagation delay of 8us according to its data sheet. You can get others that are two orders of magnitude faster for nearly the same price such as the MCP6561R with a propagation delay of only 80ns.
No surprises here. The output of the LM35 is 10mV per degree centigrade as expected and is amplified by a factor of 4.3 by the op amp. Can’t quite remember why I chose only 4.3, I might change that to 11 by changing R25 to 10k.
This is what I would consider the heart of this wind meter. This is where the received signal is amplified and processed so the overall accuracy and reliability of the entire project really depends on it. The functionality of this board can be summarized as follows:
Amplify the received signal
Generate a digital signal when the amplitude exceeds a given threshold (envelope detector)
Generate a digital signal every time the received signal crosses zero (zero crossing detector)
Measure the temperature
This circuit runs on the +5V rail generated on the digital board. There’s no need for a negative voltage here, the +5V is all we need. The input to the amplifier (i.e. the received signal) also comes straight from the digital circuit. The 3 outputs temperature (analog), zero-crossing detector (digital) and envelope detector (digital) are all connected to the Arduino Uno. I’ll go through each of the four parts now.
Just as Carl, I have used two tuned amplifier stages. Each stage uses a NPN darlington pair built from two discrete transistors. The parallel LC tank at the collector determines the resonant frequency of 40kHz as well as the bandwidth. Check out this wiki page http://en.wikipedia.org/wiki/Common_emitter or google for ‘degenerated common emitter amplifier’ if you’re not familiar with this topology.
The main difference to Carl’s design is that it’s running from 5 volts instead of 8 which eliminates the need for an extra rail.
I’ve added a 10k resistor from the emitter of the first transistor to the emitter of the second. This is often done to to enable Q1 to turn of Q2 faster. It’s probably not necessary at our low frequency but leaving it away later is much easier than adding it.
I’ve also added an extra resistor to the emitter degeneration. There is a bypassed resistor as with Carl’s design but I’ve added another resistor in series that can be used to reduce the gain. I’ll use a zero-ohm resistor at the beginning and replace that with whatever is needed to get just the right amount of gain. Thinking of it, it would have been smarter to put the gain setting resistor in series with the bypass capacitor only. That way I could adjust the gain without affecting the biasing. But that’s something for the next version.
For simplicity, I’ve biased the input of both stages to half the supply rail or 2.5 volts. The emitter will be two diode drops lower at around 1.2 volts. That should be sufficient to get a stable quiescent current over a reasonably wide temperature range. Speaking of quiescent current: The 330 ohms emitter resistor will yield a quiescent current of around 3.5mA.
I’ve made a rookie error on the LC tank. Carl had used a 470uH coil with a 33nF capacitor which gives just the right resonant frequency. He reports the DC resistance of his coil to be around 10 ohms which gives a Q-factor of around 10 – not great but sufficient. I didn’t have a 470uH inductor around but there were a few 47uH ones from a previous project. They had a DC resistance of slightly below 1 ohm so the Q-factor would also be just above 10. So I decided to use them, together with a 330nF cap to get the right frequency. Onetenth of the inductance, one tenth of the resistance, ten times the capacity. Same frequency, same Q, just perfect I thought. And yes, the resistance across the LC tank does have the same shape. But it only has one tenth of the value. So I got very little gain out of the amplifier when I first turned it on and had to correct this later. Lesson learned.
I’ve changed little for the envelope detector. It still uses a two-pole active low-pass filter. The values have changed somewhat but the time constants and cuttoff frequencies remain similar.
I’ve used a 1M plus 47k resistor at the input before the diode. At a 5V supply this yields a voltage of about 0.2 volts which just about compensates for the voltage drop over the schottky diode.
I’ve added a 10k pot to adjust the gain of the active filter. So there are two parameters you can adjust without grabbing your soldering iron: filter gain and threshold voltage.
I have included a (positive) feedback resistor across the comparator just in case I need some extra hysteris but don’t plan to use one unless tests show it’s really needed. I found that most of the time the comparator itself has enough hysteris of its own. But that remains to be seen, there is space on the board in case we need it.
About the components: The op-amp is a Microchip MCP6061, a precision op-amp. We don’t need this here but I happened to have some of them from a previous project. The comparator is a Microchip MCP6541. A bit slow (up to 8us of propagation delay) but as with the op-amp I already had some at hand.
I’ve simplified the zero-crossing detector somewhat. I want it to trigger every time the received signal crosses zero. When the signal is small it will most likely trigger on random noise but I’m not worried about that. I’m planning to average a number (say, 16) zero-crossings for each measurement. Exactly half of them shall be positive-to-negative and negative-to-positive. This will help to cancel some of the errors I hope. My plan is to set up my interrupts on the Arduino to trigger on the envelope detector first. Only after that I will enable the zero-crossing interrupts. Once I have captured all of my 16 (or whatever the number happens to be) zero-crossings, I’ll disable both time of interrupts until the next measurement. So this zero-crossing detector may random-trigger as much as it likes during all other times.
So I bias the signal at half the supply rail at 2.5 volts. The threshold is at 2.5 volts as well so I can even use the same resistive voltage divider.
As with the other comparator, I’ve included a feedback resistor across it but don’t plan to actually use it.
At the heart of the temperature measurement is a LM35 temperature sensor. It outputs a voltage of 10mV per degree centigrade. So there’s no way you can measure any temperatur below zero. That’s of course a problem depending on where you live but I see this version as a prototype and for testing it will do just fine.
There is also an op-amp that lets you scale up the rather small voltage of the LM35 to the 0…5V measurement range of the Arduino ADCs.
Here are the links to the board layout and the schematic as PDFs. As I’ve mentioned before I’m happy to share the Eagle files if anyone’s interested but at the moment I can’t upload them here. Seems you have to go premium to upload zip files and the like.
What is this cirquit supposed to do? It has 4 ultrasonic transducers attached to it. At any point in time, exactly one of them will be transmitting while the one accross from it will listen and receive the signal. For example, if the North transducers is sending then the South transducer needs to be listening. The other pair of transducers just sits there idle.
The signal to be sent is a series of PWM pulses with a frequency of 40kHz and a duty cycle of 50%. This signal will come from the Arduino, the circuit here just needs to route it to the correct transducers.
For the receiving transducer, one leg needs to be grounded while the other one must be allowed to float freely. The signal on this floating leg is what you are receiving. So this received signal needs to be routed to the analog part of the circuit where it will be amplified and processed. Here, we don’t need to worry about this yet, we just need to make sure, the signal is as strong and clean as possible. That means we will have to protect it from the much more powerful PWM signal.
The Arduino needs some way of telling this cirquit in which of the 4 possible directions to measure. I thought the easiest way of doing this is by means of two signals: Axis and Direction. Axis determines if we are dealing with the North/South or East/West axis. The Direction signal then determines which side is transmitting and which one is receiving.
But let’s start at the beginning. Most of the board is powered from a +5V rail but the multiplexers (more on them later) also need a -5V supply to do their job. So I’m using a linear regulator to make +5V from the Arduino’s Vin voltage. Vin is the voltage applied to the Arduino’ s DC jack.I’m using an LM2931 (pin compatible with the 7805) but you could use anything really. I then feed my +5V to a ICL7660 (the Microchip version of the 7660 but again, you could use anything) to get a -5V rail as well. Since the load on the -5V rail will be minimal I didn’t bother using tantalum caps but just used 10uF ceramics.
The transducers are driven by a pair of 74HC368, a classic hex inverter with tri-state outputs. This last part is important because like I said, we need to let the receiving transducer float freely (at least one leg), otherwise it won’t be able to receive anything. The inverting nature of this chip allowes us to generate a 180 degrees out-of-phase PWM signal easily. So when transmitting, one leg is always high while the other one is low and vice versa.
The buffers are enabled by a active low enable signal. So when the respective enable signal is low, the output buffer is on and the transducer can send. When the enable signal is high, the output buffer is off and the pins can float freely.
On the receiving side I’ve used three 74HC4052 multiplexers. They allow you to choose 1 out of 4 signal pairs and connect them with a common pair on the other side. Two address pins are used to decide which of the 4 pairs to connect. For this we can just our Axis and Direction signals from above. The 4052s can be turned on and off just like the 368s but we never need to turn them off so we can just ground the enable signal.
We have four transducers and the 4052 can handle 4 pairs of input signals. So yes, we could just use one. But there would be cross-talk from the (powerful) PWM signal to the (weak) received signal. So the solution is to cascade 3 of them in such a way that the receiving and transmitting signals never meet. So you can’t put North and South on one multiplexer (mux) and East and West on another. That won’t help. You have to include one from each axis so one of them is always idle.
I think once everything works as supposed, cross-talk won’t be a problem since we will stop sending before the signal arrives at the receiving transducer. But this is just a prototype anyway so I don’t mind some overkill that will probably save me some hassle during the testing/debugging phase. This way I can send and receive endless PWM signals (and not just bursts of them) while tuning the amplifier for example. But I’m planning to just use one in the next version.
Note that I’ve grounded one pin of the output signal on the first two multiplexers. So when I choose a transducer to receive, one of its legs is automatically grounded while the signal on the other one is routed to the 3rd and final mux.
There is one final thing to watch out for with these multiplexers: They have two supply rails (plus ground) and the signal you want to pass through the mux has to lay between those supply voltages at all time. In our case, the received signal will oscillate around zero volts so it will be negative half of the time. That means we need to provide a negative voltage as well. That’s why we need the -5V rail. It’s not exactly elegant having to generate a negative voltage just for that but the way the circuit works it is needed. In the next version I will probably bias the input signal to oscillate around some positive voltage so I won’t need the -5V any more.
If you have studied Carl’s circuit (highly recommended), most things will look familiar to you up to here. I’ve drawn my own schematic and have done some things somewhat differently but the general idea is really similar. Supply rails of plus/minus 5 volts, a pair of 368s to drive the transducers and cascaded 4052s to route the received signal.
Now there are two things where I’ve changed a bit more. The first is this Axis/Direction approach so I only need two control signals from the Arduino. It saves some pins on the Arduino and simplifies the software. If that’s necessary depends mainly on what else you want the Arduino to do. Carl has used a dedicated Atmega328 rather than an actual Arduino so there are plenty of I/O pins that serve no purpose otherwise. My goal is to (one day, hopefully) build a standard Arduino Uno shield that you can just stack of your Arduino Uno board. So who knows what other tasks that Arduino has to accomplish. That’s why I thought it wise to keep the task as simple and use as few pins as possible. The downside is that I had to use an 74HC139 to decode the Axis/Direction signal and generate the individual enable signals for the 368s. While I was at it, I decided to attach an LED on each of the enable signals. So you can see from where to where you are currently measuring. The final software will probably change that every few milliseconds so you won’t be able to tell anything but for testing and debugging I thought it might help.
One last thing that I’ve added was an NPN transistor that grounds the output signal to the amplifier when turned on. So with an optional mute signal I can turn the output off. Not sure if I will really use it. It’s completely optional but I’m already thinking about the next version and as I’ve mentioned I only want to use a single multiplexer. So I’m thinking about just grounding the output signal while transmitting pulses. A poor man’s RX/TX switching of sorts…
Here are the schematic and board layout as PDFs. I’d be happy to share the Eagle files as well but so far I haven’t managed to upload them here. Only a few file types are allowed here it seems. But let me know and I’ll send them to you.
This is the first of a series of posts to follow. I will describe my attempts to build an ultrasonic wind meter (anemometer) based on an Arduino Uno. By the time of writing, I have a working prototype but it will take me a while to catch up in this blog. So this is just the first post – more will follow soon.
Let me quickly outline the project: My aim is to build an ultrasonic anemometer based on a Arduino Uno board. Now what’s an anemometer? That’s just a fancy name for a wind meter. I want to be able to measure both wind speed and wind direction with high accuracy. Most wind meters are of the cup or vane variety. They turn wind into mechanical motion and then measure that motion to calculate wind speed and possibly direction. An ultrasonic anemometer on the other hand sends and receives ultrasonic pulses and measures the time-of-flight. From the time-of-flight (or the time difference, depending on your approach) you can then calculate the wind speed in a given direction. Add a second pair of senders and receivers at a 90-degree angle and you get both wind speed and direction. As so often, wikipedia gives a nice overview/introduction to the subject: http://en.wikipedia.org/wiki/Anemometer
Surprisingly, there seem to be very few people out there who have done this before. Basically, there is this one brave guy named Carl who has built such an anemometer from scratch and put all the relevant infomation online.His project was published on hackaday.com and this is where I found it: http://hackaday.com/2013/08/21/ultrasonic-anemometer-for-an-absurdly-accurate-weather-station/. All of his documentation can be found here: https://mysudoku.googlecode.com/files/UltrasonicAnemometer.zip. This material makes for an excellent starting point if you want to build your own. I’ve looked carefully at Carl’s schematics and have copied many of his ideas. I did end up changing quite a few things and will explain my reasons for doing so but the general approach is very much the same. Many thanks for sharing this with us, Carl.
The basic idea is simple: You send a ultrasonic pulse and measure the time until it arrives at a receiver located in some distance. Ultrasonic transducers often operate at 40kHz and so do mine. A transducer is a device capable of both sending and receiving a signal. It’s the kind of thing cars uses for their parking aids, telling you if there is an obstacle and at what distance.
In a 2-dimensional anemometer such as here, you will have 2 pairs of transducers for a total of 4. Let’s call them North, South, East and West for simplicity. You need to be able to send and receive pulses in all 4 directions: N->S, S->N, E->W and W->E. Not all at the same time but one after the other.
So you will need some kind of circuit to route your signals from and to any of the transducers. For example you want to send from the West transducers and receive from your East transducer or vice versa. Let’s call it the digital part even though the received signal is analog in nature. The PCB without components just above is the basis for this digital part. If you wonder who or what Jingling Ding is: That’s the name of my step daughter who helped me drawing and laying out this PCB in Eagle.
You will then need some more circuitry to process the received signal. This circuit is shared among the 4 transducers so only one can be listening at any point in time. That’s why the digital part needs to route the signal from the correct transducer to this signal processing circuit. The received signal is analog in nature and will be very weak compared to the transmitted one. So you will need quite a bit of amplification first. But this analog signal cannot directly be used by your arduino to measure the time of flight. You need some digital signal(s) that you can measure using the timer(s) on the arduino’s Atmega328 chip (in case of the Arduino Uno). Let’s call this the analog part. That’s what’s shown on the photo at the top of this page.